Skip to content

[BMC] Add is_bmc() and get_bmc_host() SonicHost extensions#23199

Merged
yxieca merged 2 commits intosonic-net:masterfrom
Blueve:dev/jika/bmc2
Mar 26, 2026
Merged

[BMC] Add is_bmc() and get_bmc_host() SonicHost extensions#23199
yxieca merged 2 commits intosonic-net:masterfrom
Blueve:dev/jika/bmc2

Conversation

@Blueve
Copy link
Copy Markdown
Collaborator

@Blueve Blueve commented Mar 23, 2026

Description of PR

Summary:
Add is_bmc() and get_bmc_host() methods to support BMC test workflows, along with BMC-specific test fixtures. This enables test authors to identify BMC devices and interact with the associated host (CPU) side within the same test.

This is part of the SONiC BMC test framework as described in the BMC High-Level Test Plan.

Type of change

  • Testbed and Framework(new/improvement)

Back port request

Approach

What is the motivation for this PR?

BMC tests need to:

  1. Determine if a DUT is a BMC device (is_bmc())
  2. Access the associated host (CPU) side from BMC tests to verify cross-device behavior like power cycling, reboot cause, and service state (get_bmc_host())

How did you do it?

  1. is_bmc() on SonicHost (tests/common/devices/sonic.py): Checks DEVICE_METADATA.localhost.type == 'NetworkBmc' from the device's running config. Uses the already-cached get_running_config_facts() so no extra SSH calls are needed.

  2. get_bmc_host() on MultiAsicSonicHost (tests/common/devices/multi_asic.py): Reads the bmc_host hostname from the testbed YAML (tbinfo) and creates a SonicHost instance for the host (CPU) side. Placed as an explicit method on MultiAsicSonicHost (before __getattr__ delegation) since it needs access to duthosts.tbinfo and duthosts.ansible_adhoc.

  3. BMC test fixtures (tests/bmc/conftest.py):

    • bmc_duthost: Gets the BMC DUT host and asserts it is a BMC
    • bmc_host_side: Gets the host (CPU) side SonicHost via get_bmc_host()

How did you verify/test it?

  • Verified is_bmc() follows the same pattern as existing device type checks (e.g., switch_type == "dpu" in SonicHost __init__)
  • Verified get_bmc_host() follows cross-device access patterns (e.g., get_supervisor_for_linecard() in dut_utils.py)
  • Verified get_bmc_host() is defined before __getattr__ in MultiAsicSonicHost so it takes priority over SonicHost delegation

Any platform specific information?

Applies to platforms with a BMC running SONiC OS where DEVICE_METADATA.localhost.type is set to NetworkBmc.

Supported testbed topology if it is a new test case?

N/A - this PR adds framework utilities only. The bmc_duthost and bmc_host_side fixtures are available for BMC test modules under tests/bmc/.

Documentation

@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).

Copy link
Copy Markdown
Collaborator

@StormLiangMS StormLiangMS left a comment

Choose a reason for hiding this comment

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

@Blueve — A few issues to address:

  1. CI FAILED: Both Pre_test Static Analysis and Pre_test Validate Test Cases are failing. Must be fixed before merge.

  2. is_bmc() is not cached: Each call invokes self.get_running_config_facts() which runs a remote shell command. This gets called from get_bmc_host() and the bmc_duthost fixture. Consider using self.facts.get('platform') or a cached property to avoid repeated remote calls.

  3. get_bmc_host() returns bare SonicHost: SonicHost(self.duthosts.ansible_adhoc, bmc_host_hostname) creates a host without going through the DutHosts factory, so it won't have duthosts/tbinfo context and won't be wrapped as MultiAsicSonicHost even if applicable. Consider reusing a host from self.duthosts if available.

  4. DEFAULT_ASIC_SERVICES mutation risk: .remove("teamd") on the class-level list could raise ValueError if it was already removed (e.g., by BackEndToRRouter init). A defensive if "teamd" in self.DEFAULT_ASIC_SERVICES guard would be safer.

@mssonicbld
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@Blueve Blueve marked this pull request as ready for review March 24, 2026 15:13
@Blueve
Copy link
Copy Markdown
Collaborator Author

Blueve commented Mar 25, 2026

/azpw run

@mssonicbld
Copy link
Copy Markdown
Collaborator

⚠️ Notice: /azpw run only runs failed jobs now. If you want to trigger a whole pipline run, please rebase your branch or close and reopen the PR.
💡 Tip: You can also use /azpw retry to retry failed jobs directly.

Retrying failed(or canceled) jobs...

@Blueve Blueve closed this Mar 25, 2026
@Blueve Blueve reopened this Mar 25, 2026
@Blueve Blueve closed this Mar 25, 2026
@Blueve Blueve reopened this Mar 25, 2026
@mssonicbld
Copy link
Copy Markdown
Collaborator

/azp run

1 similar comment
@mssonicbld
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

1 similar comment
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Blueve and others added 2 commits March 26, 2026 14:23
- Add is_bmc() to SonicHost: checks DEVICE_METADATA.localhost.type
  for 'NetworkBmc' (cached via get_running_config_facts)
- Add get_bmc_host() to MultiAsicSonicHost: resolves the host (CPU)
  side device from the 'bmc_host' field in testbed YAML and returns
  a SonicHost instance for cross-device verification in BMC tests
- Create tests/bmc/ package with conftest.py providing bmc_duthost
  and bmc_host_side fixtures for BMC-specific test modules

Co-authored-by: Copilot <[email protected]>
Signed-off-by: Jing Kan <[email protected]>
BMC has no ASIC or data-plane, so remove bgp, swss, syncd and teamd
from DEFAULT_ASIC_SERVICES when device_type is NetworkBmc. Remaining
ASIC services: database, lldp. Host-level services (pmon, snmp) are
handled by MultiAsicSonicHost._DEFAULT_SERVICES.

Co-authored-by: Copilot <[email protected]>
Signed-off-by: Jing Kan <[email protected]>
@mssonicbld
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@yxieca yxieca merged commit e71985a into sonic-net:master Mar 26, 2026
18 of 19 checks passed
ravaliyel pushed a commit to ravaliyel/sonic-mgmt that referenced this pull request Mar 27, 2026
…#23199)

What is the motivation for this PR?\nBMC tests need to:\n1. Determine if a DUT is a BMC device (is_bmc())\n2. Access the associated host (CPU) side from BMC tests to verify cross-device behavior like power cycling, reboot cause, and service state (get_bmc_host())\n\nHow did you do it?\n1. is_bmc() on SonicHost (tests/common/devices/sonic.py): Checks DEVICE_METADATA.localhost.type == 'NetworkBmc' from the device's running config. Uses the already-cached get_running_config_facts() so no extra SSH calls are needed.\n2. get_bmc_host() on MultiAsicSonicHost (tests/common/devices/multi_asic.py): Reads the bmc_host hostname from the testbed YAML (tbinfo) and creates a SonicHost instance for the host (CPU) side. Placed as an explicit method on MultiAsicSonicHost (before __getattr__ delegation) since it needs access to duthosts.tbinfo and duthosts.ansible_adhoc.\n3. BMC test fixtures (tests/bmc/conftest.py):\n   - bmc_duthost: Gets the BMC DUT host and asserts it is a BMC\n   - bmc_host_side: Gets the host (CPU) side SonicHost via get_bmc_host()\n\nHow did you verify/test it?\n- Verified is_bmc() follows the same pattern as existing device type checks (e.g., switch_type == "dpu" in SonicHost __init__)\n- Verified get_bmc_host() follows cross-device access patterns (e.g., get_supervisor_for_linecard() in dut_utils.py)\n- Verified get_bmc_host() is defined before __getattr__ in MultiAsicSonicHost so it takes priority over SonicHost delegation\n\nSigned-off-by:\nJing Kan <[email protected]>
selldinesh pushed a commit to selldinesh/sonic-mgmt that referenced this pull request Apr 1, 2026
…#23199)

What is the motivation for this PR?\nBMC tests need to:\n1. Determine if a DUT is a BMC device (is_bmc())\n2. Access the associated host (CPU) side from BMC tests to verify cross-device behavior like power cycling, reboot cause, and service state (get_bmc_host())\n\nHow did you do it?\n1. is_bmc() on SonicHost (tests/common/devices/sonic.py): Checks DEVICE_METADATA.localhost.type == 'NetworkBmc' from the device's running config. Uses the already-cached get_running_config_facts() so no extra SSH calls are needed.\n2. get_bmc_host() on MultiAsicSonicHost (tests/common/devices/multi_asic.py): Reads the bmc_host hostname from the testbed YAML (tbinfo) and creates a SonicHost instance for the host (CPU) side. Placed as an explicit method on MultiAsicSonicHost (before __getattr__ delegation) since it needs access to duthosts.tbinfo and duthosts.ansible_adhoc.\n3. BMC test fixtures (tests/bmc/conftest.py):\n   - bmc_duthost: Gets the BMC DUT host and asserts it is a BMC\n   - bmc_host_side: Gets the host (CPU) side SonicHost via get_bmc_host()\n\nHow did you verify/test it?\n- Verified is_bmc() follows the same pattern as existing device type checks (e.g., switch_type == "dpu" in SonicHost __init__)\n- Verified get_bmc_host() follows cross-device access patterns (e.g., get_supervisor_for_linecard() in dut_utils.py)\n- Verified get_bmc_host() is defined before __getattr__ in MultiAsicSonicHost so it takes priority over SonicHost delegation\n\nSigned-off-by:\nJing Kan <[email protected]>

Signed-off-by: selldinesh <[email protected]>
albertovillarreal-keys pushed a commit to albertovillarreal-keys/sonic-mgmt that referenced this pull request Apr 3, 2026
…#23199)

What is the motivation for this PR?\nBMC tests need to:\n1. Determine if a DUT is a BMC device (is_bmc())\n2. Access the associated host (CPU) side from BMC tests to verify cross-device behavior like power cycling, reboot cause, and service state (get_bmc_host())\n\nHow did you do it?\n1. is_bmc() on SonicHost (tests/common/devices/sonic.py): Checks DEVICE_METADATA.localhost.type == 'NetworkBmc' from the device's running config. Uses the already-cached get_running_config_facts() so no extra SSH calls are needed.\n2. get_bmc_host() on MultiAsicSonicHost (tests/common/devices/multi_asic.py): Reads the bmc_host hostname from the testbed YAML (tbinfo) and creates a SonicHost instance for the host (CPU) side. Placed as an explicit method on MultiAsicSonicHost (before __getattr__ delegation) since it needs access to duthosts.tbinfo and duthosts.ansible_adhoc.\n3. BMC test fixtures (tests/bmc/conftest.py):\n   - bmc_duthost: Gets the BMC DUT host and asserts it is a BMC\n   - bmc_host_side: Gets the host (CPU) side SonicHost via get_bmc_host()\n\nHow did you verify/test it?\n- Verified is_bmc() follows the same pattern as existing device type checks (e.g., switch_type == "dpu" in SonicHost __init__)\n- Verified get_bmc_host() follows cross-device access patterns (e.g., get_supervisor_for_linecard() in dut_utils.py)\n- Verified get_bmc_host() is defined before __getattr__ in MultiAsicSonicHost so it takes priority over SonicHost delegation\n\nSigned-off-by:\nJing Kan <[email protected]>
opcoder0 pushed a commit to opcoder0/sonic-mgmt that referenced this pull request Apr 13, 2026
…#23199)

What is the motivation for this PR?\nBMC tests need to:\n1. Determine if a DUT is a BMC device (is_bmc())\n2. Access the associated host (CPU) side from BMC tests to verify cross-device behavior like power cycling, reboot cause, and service state (get_bmc_host())\n\nHow did you do it?\n1. is_bmc() on SonicHost (tests/common/devices/sonic.py): Checks DEVICE_METADATA.localhost.type == 'NetworkBmc' from the device's running config. Uses the already-cached get_running_config_facts() so no extra SSH calls are needed.\n2. get_bmc_host() on MultiAsicSonicHost (tests/common/devices/multi_asic.py): Reads the bmc_host hostname from the testbed YAML (tbinfo) and creates a SonicHost instance for the host (CPU) side. Placed as an explicit method on MultiAsicSonicHost (before __getattr__ delegation) since it needs access to duthosts.tbinfo and duthosts.ansible_adhoc.\n3. BMC test fixtures (tests/bmc/conftest.py):\n   - bmc_duthost: Gets the BMC DUT host and asserts it is a BMC\n   - bmc_host_side: Gets the host (CPU) side SonicHost via get_bmc_host()\n\nHow did you verify/test it?\n- Verified is_bmc() follows the same pattern as existing device type checks (e.g., switch_type == "dpu" in SonicHost __init__)\n- Verified get_bmc_host() follows cross-device access patterns (e.g., get_supervisor_for_linecard() in dut_utils.py)\n- Verified get_bmc_host() is defined before __getattr__ in MultiAsicSonicHost so it takes priority over SonicHost delegation\n\nSigned-off-by:\nJing Kan <[email protected]>

Signed-off-by: opcoder0 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants