Skip to content

[config reload] Skip swss readiness check when swss is not present#4606

Merged
liat-grozovik merged 2 commits into
sonic-net:masterfrom
william8545:bmc_config_reload
Jun 14, 2026
Merged

[config reload] Skip swss readiness check when swss is not present#4606
liat-grozovik merged 2 commits into
sonic-net:masterfrom
william8545:bmc_config_reload

Conversation

@william8545

Copy link
Copy Markdown
Contributor

What I did

config reload (without -f) fails on platforms that do not ship the swss container (e.g. BMC) with swss container is not ready. Retry later or use -f to avoid system checks. The readiness gate waits on a swss.service that does not exist on such images, so reload can never proceed without -f. This makes the gate skip the wait when swss is not present.

How I did it

In _per_namespace_swss_ready(), check the service's systemd LoadState first. If it is not-found (service not built into the image) or masked, return ready — there is no swss to wait for. Platforms that ship swss read LoadState=loaded, so the existing active/120s-settle checks are unchanged. Added unit tests for the not-found/masked paths and regression guards for the loaded/inactive and active/settle behavior.

How to verify it

  • pytest tests/config_test.py::TestSwssReady
  • On a platform without swss (swss.service is not-found): config reload -y proceeds instead of aborting.
  • On a switch that ships swss: behavior is unchanged (still waits until swss has been active for >120s).

Previous command output (if the output of a command-line utility has changed)

root@sonic:~# config reload -y
Acquired lock on /etc/sonic/reload.lock
swss container is not ready. Retry later or use -f to avoid system checks
Released lock on /etc/sonic/reload.lock

New command output (if the output of a command-line utility has changed)

root@sonic:~# config reload -y
Acquired lock on /etc/sonic/reload.lock
Running command: ...   # reload proceeds normally
Released lock on /etc/sonic/reload.lock

config reload's pre-flight gate calls _swss_ready(), which fails on
platforms that do not ship the swss container (e.g. BMC): swss.service
reads LoadState=not-found, so the gate blocks reload unless -f is passed.

Treat a swss service whose LoadState is not-found or masked as "nothing
to wait for" in _per_namespace_swss_ready(), so config reload proceeds
without -f. No behavior change on platforms that ship swss, where
swss.service is loaded and the existing active/settle checks still apply.

Add unit tests for the not-found/masked (ready) paths and regression
guards for the loaded/inactive and active/settle behavior.

Signed-off-by: William Tsai <willtsai@nvidia.com>
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

…ready

Signed-off-by: William Tsai <willtsai@nvidia.com>
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@yxieca yxieca left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, well-targeted fix. config reload without -f was effectively deadlocked on platforms that don't ship the swss container (BMC), since the readiness gate waited on a swss.service that doesn't exist. Checking systemd LoadState first and treating not-found/masked as "nothing to wait for" is the right call, and it's at the correct abstraction layer — the function that probes the service decides from systemd ground truth, rather than threading a platform conditional through the reload path.

I verified the important properties:

  • Switch behavior is provably unchanged. The change is purely additive (+5/-0, no existing line touched). A swss-shipping switch reports LoadState=loaded, so the new branch is skipped and the existing ActiveState=="active" + 120s-settle logic runs verbatim.
  • Failure modes fail safe. Empty/garbage/failed-systemctl output (out.strip() not in the tuple) falls through to the existing ActiveState check → != active → not ready. So there's no path where a switch that should have swss wrongly skips the wait. not-found also can't transiently fire on a real switch — an installed unit file reports loaded long before config reload runs.
  • Including masked is correct, not scope creep — it's the same deadlock class (a masked unit can never become active).
  • Tests are great for a 5-line change: both new paths (with call_count == 1 asserting the short-circuit) plus regression guards for the loaded/inactive/active/settle behavior, and the settle-math mocks match the production formula.

Two small, non-blocking suggestions:

  • Optional multi-ASIC not-found test. _swss_ready() already has a single-ASIC not-found end-to-end case; a get_num_asics() == 2 case with both swss@0/1 reporting not-found would round out coverage. The multi-ASIC iteration itself is unchanged code, so this is belt-and-suspenders rather than a gap.

  • Docstring on the overloaded return. _per_namespace_swss_ready() now returns True for both "swss active and settled" and "swss absent." That's exactly right for this gate (both mean "safe to proceed"), but a one-line docstring noting the contract is "safe to proceed past the swss gate" (not "swss is active") would prevent a future caller from misreading it.

Neither blocks. Approving.

AI agent on behalf of Ying.

@mssonicbld

Copy link
Copy Markdown
Collaborator

Cherry-pick PR to msft-202608: Azure/sonic-utilities.msft#384

Yogapriya-cisco pushed a commit to vrajeshe/sonic-utilities that referenced this pull request Jul 10, 2026
…onic-net#4606)

- What I did
config reload (without -f) fails on platforms that do not ship the swss container (e.g. BMC) with swss container is not ready. Retry later or use -f to avoid system checks. The readiness gate waits on a swss.service that does not exist on such images, so reload can never proceed without -f. This makes the gate skip the wait when swss is not present.

- How I did it
In _per_namespace_swss_ready(), check the service's systemd LoadState first. If it is not-found (service not built into the image) or masked, return ready — there is no swss to wait for. Platforms that ship swss read LoadState=loaded, so the existing active/120s-settle checks are unchanged. Added unit tests for the not-found/masked paths and regression guards for the loaded/inactive and active/settle behavior.

- How to verify it
pytest tests/config_test.py::TestSwssReady
On a platform without swss (swss.service is not-found): config reload -y proceeds instead of aborting.
On a switch that ships swss: behavior is unchanged (still waits until swss has been active for >120s).
Previous command output (if the output of a command-line utility has changed)
root@sonic:~# config reload -y
Acquired lock on /etc/sonic/reload.lock
swss container is not ready. Retry later or use -f to avoid system checks
Released lock on /etc/sonic/reload.lock
New command output (if the output of a command-line utility has changed)
root@sonic:~# config reload -y
Acquired lock on /etc/sonic/reload.lock
Running command: ...   # reload proceeds normally
Released lock on /etc/sonic/reload.lock

Signed-off-by: William Tsai <willtsai@nvidia.com>
Signed-off-by: Yogapriya Mohankumar <ymohanku@cisco.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants