Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f9c2905
Common changes for adding GCU MA/T2 support
okaravasi Oct 23, 2024
4289bbc
Merge branch 'sonic-net:master' into master-gcu_t2_support_common
okaravasi Oct 25, 2024
2947290
Adding an intermediate fixture to support generic_config_updater modu…
okaravasi Oct 31, 2024
77aaf0c
Removing duplicated copy
okaravasi Nov 13, 2024
c311296
Combining two new fixtures to a common
okaravasi Nov 28, 2024
1802727
Merge remote-tracking branch 'origin/master' into master-gcu_t2_suppo…
okaravasi Nov 29, 2024
857f1d2
Merge remote-tracking branch 'origin/master' into master-gcu_t2_suppo…
okaravasi Feb 4, 2025
7e4571a
Starting gcu feature support for t2 from 202405, Removing fixture ran…
okaravasi Feb 4, 2025
6443182
fix typo in release number
okaravasi Feb 4, 2025
3592a5a
Added fixture that transparently gets asic id from called fixture eit…
okaravasi Feb 4, 2025
d3012ce
Adding fixtures for namespace prefixes
okaravasi Feb 4, 2025
cba17e6
Refactoring wrapper fixture 'selected_asic_index' to explore if enum_…
okaravasi Feb 4, 2025
d65c0e3
modifying namespace_prefixes so that can be called without namespace …
okaravasi Feb 14, 2025
46daa53
Merge remote-tracking branch 'origin/master' into master-gcu_t2_suppo…
okaravasi Feb 14, 2025
540a050
adding t2 support in separate test suites under generic_config_updater
okaravasi Feb 14, 2025
3938f12
standalone definitions for ip_netns and cli prefix namespaces fixture…
okaravasi Feb 19, 2025
7e05c70
Merge branch 'master' into master-gcu_t2_support_common
okaravasi Feb 25, 2025
ef75d16
Merge branch 'master' into master-gcu_t2_support_common
okaravasi Apr 15, 2025
137c8c5
Eliminating repeated code based on review comment / Fixing merge conf…
okaravasi Apr 15, 2025
c89c9de
Adding back mark condition comment from merge
okaravasi Apr 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion tests/common/gu_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ def apply_patch(duthost, json_data, dest_file):
json_data: Source json patch to apply
dest_file: Destination file on duthost
"""
duthost.copy(content=json.dumps(json_data, indent=4), dest=dest_file)
patch_content = json.dumps(json_data, indent=4)
duthost.copy(content=patch_content, dest=dest_file)
logger.debug("Patch Content: {}".format(patch_content))

cmds = 'config apply-patch {}'.format(dest_file)

Expand Down Expand Up @@ -569,6 +571,56 @@ def expect_acl_rule_removed(duthost, rulename, setup):
pytest_assert(removed, "'{}' showed a rule, this following rule should have been removed".format(cmds))


def save_backup_test_config(duthost, file_postfix="bkp"):
"""Save test env before a test case starts.
Back up the existing config_db.json file(s).
Args:
duthost: Device Under Test (DUT)
file_postfix: Postfix string to be used for the backup files.
Returns:
None.
"""
CONFIG_DB = "/etc/sonic/config_db.json"
CONFIG_DB_BACKUP = "/etc/sonic/config_db.json.{}".format(file_postfix)

logger.info("Backup {} to {} on {}".format(
CONFIG_DB, CONFIG_DB_BACKUP, duthost.hostname))
duthost.shell("cp {} {}".format(CONFIG_DB, CONFIG_DB_BACKUP))
if duthost.is_multi_asic:
for n in range(len(duthost.asics)):
asic_config_db = "/etc/sonic/config_db{}.json".format(n)
asic_config_db_backup = "/etc/sonic/config_db{}.json.{}".format(n, file_postfix)
logger.info("Backup {} to {} on {}".format(
asic_config_db, asic_config_db_backup, duthost.hostname))
duthost.shell("cp {} {}".format(asic_config_db, asic_config_db_backup))


def restore_backup_test_config(duthost, file_postfix="bkp", config_reload=True):
"""Restore test env after a test case finishes.
Args:
duthost: Device Under Test (DUT)
file_postfix: Postfix string to be used for restoring the saved backup files.
Returns:
None.
"""
CONFIG_DB = "/etc/sonic/config_db.json"
CONFIG_DB_BACKUP = "/etc/sonic/config_db.json.{}".format(file_postfix)

logger.info("Restore {} with {} on {}".format(
CONFIG_DB, CONFIG_DB_BACKUP, duthost.hostname))
duthost.shell("mv {} {}".format(CONFIG_DB_BACKUP, CONFIG_DB))
if duthost.is_multi_asic:
for n in range(len(duthost.asics)):
asic_config_db = "/etc/sonic/config_db{}.json".format(n)
asic_config_db_backup = "/etc/sonic/config_db{}.json.{}".format(n, file_postfix)
logger.info("Restore {} with {} on {}".format(
asic_config_db, asic_config_db_backup, duthost.hostname))
duthost.shell("mv {} {}".format(asic_config_db_backup, asic_config_db))

if config_reload:
config_reload(duthost)


def get_bgp_speaker_runningconfig(duthost):
""" Get bgp speaker config that contains src_address and ip_range

Expand Down
31 changes: 13 additions & 18 deletions tests/common/plugins/conditional_mark/tests_mark_conditions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1008,9 +1008,9 @@ fib/test_fib.py::test_vxlan_hash:
#######################################
generic_config_updater:
skip:
reason: 'generic_config_updater is not a supported feature for T2'
reason: 'generic_config_updater is not a supported feature for T2 platform on older releases than 202405.'
conditions:
- "'t2' in topo_name"
- "('t2' in topo_name) and (release in ['201811', '201911', '202012', '202205', '202211', '202305', '202311'])"

generic_config_updater/test_bgp_prefix.py::test_bgp_prefix_tc1_suite:
skip:
Expand All @@ -1031,60 +1031,58 @@ generic_config_updater/test_dhcp_relay.py:
generic_config_updater/test_dynamic_acl.py:
skip:
reason: "Device SKUs do not support the custom ACL_TABLE_TYPE that we use in this test. Known log error unrelated to test
on m0-2vlan testbed causes consistent failures / generic_config_updater is not a supported feature for T2
on m0-2vlan testbed causes consistent failures
/ Dynamic ACL is not supported in Cisco Q200 based platforms"
conditions_logical_operator: "OR"
conditions:
- "platform in ['armhf-nokia_ixs7215_52x-r0']"
- "hwsku in ['Cisco-8111-O64']"
- "topo_name in ['m0-2vlan']"
- "'t2' in topo_name"
- "platform in ['x86_64-8101_32fh_o-r0', 'x86_64-8102_64h_o-r0', 'x86_64-8101_32fh_o_c01-r0']"

generic_config_updater/test_ecn_config_update.py::test_ecn_config_updates:
skip:
reason: "This test is not run on this asic type, topology, or version currently / generic_config_updater is not a supported feature for T2"
reason: "This test is not run on this asic type, topology, or version currently"
conditions_logical_operator: "OR"
conditions:
- "asic_type in ['cisco-8000']"
- "topo_type in ['m0', 'mx', 'm1', 'm2', 'm3']"
- "release in ['202211']"
- "'t2' in topo_name"

generic_config_updater/test_eth_interface.py::test_replace_fec:
skip:
reason: 'Skipping test on 7260/3800 platform due to bug of https://github.com/sonic-net/sonic-mgmt/issues/11237
/ generic_config_updater is not a supported feature for T2'
reason: 'Skipping test on 7260/3800 platform due to bug of https://github.com/sonic-net/sonic-mgmt/issues/11237'
conditions_logical_operator: "OR"
conditions:
- "hwsku in ['Arista-7260CX3-D108C8', 'Arista-7260CX3-D108C10', 'Arista-7260CX3-Q64', 'Mellanox-SN3800-D112C8'] and https://github.com/sonic-net/sonic-mgmt/issues/11237"
- "'t2' in topo_name"

generic_config_updater/test_eth_interface.py::test_toggle_pfc_asym:
skip:
reason: "Skip asym pfc on unsupported platforms"
conditions_logical_operator: "OR"
conditions:
- "asic_type in ['cisco-8000']"
- "'t2' in topo_name"

generic_config_updater/test_eth_interface.py::test_update_speed:
skip:
reason: 'Skip this script due to this not being a production scenario and misleading StateDB output for valid speed / generic_config_updater is not a supported feature for T2'
reason: 'Skip this script due to this not being a production scenario and misleading StateDB output for valid speed'
conditions_logical_operator: "OR"
conditions:
- https://github.com/sonic-net/sonic-mgmt/issues/8143
- https://github.com/sonic-net/sonic-buildimage/issues/13267
- "'t2' in topo_name"

generic_config_updater/test_incremental_qos.py:
skip:
reason: "Does not support dualtor right now, due to issue https://github.com/sonic-net/sonic-mgmt/issues/14865
/ generic_config_updater is not a supported feature for T2"
reason: "Does not support dualtor right now, due to issue https://github.com/sonic-net/sonic-mgmt/issues/14865"
conditions_logical_operator: "OR"
conditions:
- "'dualtor' in topo_name"
- "'t2' in topo_name"

generic_config_updater/test_incremental_qos.py::test_incremental_qos_config_updates:
skip:
reason: "This test is not run on this hwsku/asic type or version or topology currently"
conditions_logical_operator: "OR"
conditions:
- "not any(i in hwsku for i in ['2700', 'Arista-7170-64C', 'montara', 'newport']) and asic_type in ['broadcom', 'cisco-8000'] and release in ['202211']"

generic_config_updater/test_mmu_dynamic_threshold_config_update.py::test_dynamic_th_config_updates:
Expand All @@ -1093,7 +1091,6 @@ generic_config_updater/test_mmu_dynamic_threshold_config_update.py::test_dynamic
conditions_logical_operator: "OR"
conditions:
- "asic_type in ['broadcom', 'cisco-8000'] and release in ['202211']"
- "'t2' in topo_name"

generic_config_updater/test_multiasic_addcluster.py:
skip:
Expand Down Expand Up @@ -1127,15 +1124,13 @@ generic_config_updater/test_pfcwd_status.py:
conditions:
- "topo_type in ['m0', 'mx', 'm1', 'm2', 'm3']"
- "release in ['202211']"
- "'t2' in topo_name"

generic_config_updater/test_pg_headroom_update.py:
skip:
reason: "Unsupported topology."
conditions_logical_operator: "OR"
conditions:
- "topo_type in ['m0', 'mx', 'm1', 'm2', 'm3']"
- "'t2' in topo_name"

#######################################
##### gnmi #####
Expand Down
46 changes: 44 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
from tests.common.dualtor.dual_tor_utils import disable_timed_oscillation_active_standby # noqa: F401

from tests.common.helpers.constants import (
ASIC_PARAM_TYPE_ALL, ASIC_PARAM_TYPE_FRONTEND, DEFAULT_ASIC_ID, ASICS_PRESENT, DUT_CHECK_NAMESPACE
ASIC_PARAM_TYPE_ALL, ASIC_PARAM_TYPE_FRONTEND, DEFAULT_ASIC_ID, NAMESPACE_PREFIX,
ASICS_PRESENT, DUT_CHECK_NAMESPACE
)
from tests.common.helpers.custom_msg_utils import add_custom_msg
from tests.common.helpers.dut_ports import encode_dut_port_name
Expand Down Expand Up @@ -2222,7 +2223,7 @@ def dut_test_params_qos(duthosts, tbinfo, ptfhost, get_src_dst_asic_and_duts, lo
yield rtn_dict


@ pytest.fixture(scope='class')
@pytest.fixture(scope='class')
def dut_test_params(duthosts, enum_rand_one_per_hwsku_frontend_hostname, tbinfo,
ptf_portmap_file, lower_tor_host, creds): # noqa: F811
"""
Expand Down Expand Up @@ -2890,6 +2891,47 @@ def gnxi_path(ptfhost):
return gnxipath


@pytest.fixture(scope="module")
def selected_asic_index(request):
asic_index = DEFAULT_ASIC_ID
if "enum_asic_index" in request.fixturenames:
asic_index = request.getfixturevalue("enum_asic_index")
elif "enum_frontend_asic_index" in request.fixturenames:
asic_index = request.getfixturevalue("enum_frontend_asic_index")
elif "enum_backend_asic_index" in request.fixturenames:
asic_index = request.getfixturevalue("enum_backend_asic_index")
elif "enum_rand_one_asic_index" in request.fixturenames:
asic_index = request.getfixturevalue("enum_rand_one_asic_index")
elif "enum_rand_one_frontend_asic_index" in request.fixturenames:
asic_index = request.getfixturevalue("enum_rand_one_frontend_asic_index")
logger.info(f"Selected asic_index {asic_index}")
return asic_index


@pytest.fixture(scope="module")
def ip_netns_namespace_prefix(request, selected_asic_index):
"""
Construct the formatted namespace prefix for executed commands inside the specific
network namespace or for linux commands.
"""
if selected_asic_index == DEFAULT_ASIC_ID:
return ''
else:
return f'sudo ip netns exec {NAMESPACE_PREFIX}{selected_asic_index}'


@pytest.fixture(scope="module")
def cli_namespace_prefix(request, selected_asic_index):
"""
Construct the formatted namespace prefix for executed commands inside the specific
network namespace or for CLI commands.
"""
if selected_asic_index == DEFAULT_ASIC_ID:
return ''
else:
return f'-n {NAMESPACE_PREFIX}{selected_asic_index}'


def pytest_collection_modifyitems(config, items):
# Skip all stress_tests if --run-stress-test is not set
if not config.getoption("--run-stress-tests"):
Expand Down
57 changes: 34 additions & 23 deletions tests/generic_config_updater/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from tests.common.utilities import skip_release
from tests.common.config_reload import config_reload
from tests.common.gu_utils import apply_patch
from tests.common.gu_utils import apply_patch, restore_backup_test_config, save_backup_test_config
from tests.common.gu_utils import generate_tmpfile, delete_tmpfile

CONFIG_DB = "/etc/sonic/config_db.json"
Expand All @@ -12,48 +12,63 @@
logger = logging.getLogger(__name__)


@pytest.fixture(scope="module")
def selected_dut_hostname(request, rand_one_dut_hostname):
"""Fixture that returns either `rand_one_dut_hostname` or `rand_one_dut_front_end_hostname`
depending on availability."""
if "rand_one_dut_front_end_hostname" in request.fixturenames:
logger.info("Running on front end duthost")
return request.getfixturevalue("rand_one_dut_front_end_hostname")
else:
logger.info("Running on any type of duthost")
return rand_one_dut_hostname


# Module Fixture
@pytest.fixture(scope="module")
def cfg_facts(duthosts, rand_one_dut_hostname):
def cfg_facts(duthosts, selected_dut_hostname, selected_asic_index):
"""
Config facts for selected DUT
Args:
duthosts: list of DUTs.
rand_one_dut_hostname: Hostname of a random chosen dut
selected_dut_hostname: Hostname of a random chosen dut
selected_asic_index: Random selected asic id
"""
duthost = duthosts[rand_one_dut_hostname]
return duthost.config_facts(host=duthost.hostname, source="persistent")['ansible_facts']
duthost = duthosts[selected_dut_hostname]
asic_id = selected_asic_index
asic_namespace = duthost.get_namespace_from_asic_id(asic_id)
return duthost.config_facts(host=duthost.hostname, source="persistent", namespace=asic_namespace)['ansible_facts']


@pytest.fixture(scope="module", autouse=True)
def check_image_version(duthosts, rand_one_dut_hostname):
def check_image_version(duthosts, selected_dut_hostname):
"""Skips this test if the SONiC image installed on DUT is older than 202111

Args:
duthosts: list of DUTs.
rand_one_dut_hostname: Hostname of a random chosen dut
selected_dut_hostname: Hostname of a random chosen dut

Returns:
None.
"""
duthost = duthosts[rand_one_dut_hostname]
duthost = duthosts[selected_dut_hostname]
skip_release(duthost, ["201811", "201911", "202012", "202106", "202111"])


@pytest.fixture(scope="module", autouse=True)
def reset_and_restore_test_environment(duthosts, rand_one_dut_hostname):
def reset_and_restore_test_environment(duthosts, selected_dut_hostname):
"""Reset and restore test env if initial Config cannot pass Yang

Back up the existing config_db.json file and restore it once the test ends.

Args:
duthosts: list of DUTs.
rand_one_dut_hostname: Hostname of a random chosen dut
selected_dut_hostname: Hostname of a random chosen dut

Returns:
None.
"""
duthost = duthosts[rand_one_dut_hostname]
duthost = duthosts[selected_dut_hostname]
json_patch = []
tmpfile = generate_tmpfile(duthost)

Expand All @@ -62,9 +77,7 @@ def reset_and_restore_test_environment(duthosts, rand_one_dut_hostname):
finally:
delete_tmpfile(duthost, tmpfile)

logger.info("Backup {} to {} on {}".format(
CONFIG_DB, CONFIG_DB_BACKUP, duthost.hostname))
duthost.shell("cp {} {}".format(CONFIG_DB, CONFIG_DB_BACKUP))
save_backup_test_config(duthost, file_postfix="before_gcu_test")

if output['rc'] or "Patch applied successfully" not in output['stdout']:
logger.info("Running config failed SONiC Yang validation. Reload minigraph. config: {}"
Expand All @@ -73,27 +86,25 @@ def reset_and_restore_test_environment(duthosts, rand_one_dut_hostname):

yield

logger.info("Restore {} with {} on {}".format(
CONFIG_DB, CONFIG_DB_BACKUP, duthost.hostname))
duthost.shell("mv {} {}".format(CONFIG_DB_BACKUP, CONFIG_DB))
restore_backup_test_config(duthost, file_postfix="before_gcu_test", config_reload=False)

if output['rc'] or "Patch applied successfully" not in output['stdout']:
logger.info("Restore Config after GCU test.")
config_reload(duthost)


@pytest.fixture(scope="module", autouse=True)
def verify_configdb_with_empty_input(duthosts, rand_one_dut_hostname):
def verify_configdb_with_empty_input(duthosts, selected_dut_hostname):
"""Fail immediately if empty input test failure

Args:
duthosts: list of DUTs.
rand_one_dut_hostname: Hostname of a random chosen dut
selected_dut_hostname: Hostname of a random chosen dut

Returns:
None.
"""
duthost = duthosts[rand_one_dut_hostname]
duthost = duthosts[selected_dut_hostname]
json_patch = []
tmpfile = generate_tmpfile(duthost)

Expand All @@ -119,19 +130,19 @@ def skip_when_buffer_is_dynamic_model(duthost):

# Function Fixture
@pytest.fixture(autouse=True)
def ignore_expected_loganalyzer_exceptions(duthosts, rand_one_dut_hostname, loganalyzer):
def ignore_expected_loganalyzer_exceptions(duthosts, selected_dut_hostname, loganalyzer):
"""
Ignore expected yang validation failure during test execution

GCU will try several sortings of JsonPatch until the sorting passes yang validation

Args:
duthosts: list of DUTs.
rand_one_dut_hostname: Hostname of a random chosen dut
selected_dut_hostname: Hostname of a random chosen dut
loganalyzer: Loganalyzer utility fixture
"""
# When loganalyzer is disabled, the object could be None
duthost = duthosts[rand_one_dut_hostname]
duthost = duthosts[selected_dut_hostname]
if loganalyzer:
ignoreRegex = [
".*ERR sonic_yang.*",
Expand Down
Loading