diff --git a/tests/common/gu_utils.py b/tests/common/gu_utils.py index 07435568d5b..c9c7865f649 100644 --- a/tests/common/gu_utils.py +++ b/tests/common/gu_utils.py @@ -74,7 +74,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) @@ -512,6 +514,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 diff --git a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml index 2136552a0a1..fa91664a987 100644 --- a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml +++ b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml @@ -801,9 +801,9 @@ fib/test_fib.py::test_ipinip_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 202205.' conditions: - - "'t2' in topo_name" + - "('t2' in topo_name) and (release in ['201811', '201911', '202012', '202106', '202111'])" generic_config_updater/test_bgp_prefix.py::test_bgp_prefix_tc1_suite[empty]: skip: diff --git a/tests/conftest.py b/tests/conftest.py index bff93f580c3..93a9fdff6eb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -587,6 +587,29 @@ def rand_one_dut_lossless_prio(request): return lossless_prio_list[0] +@pytest.fixture(scope="module") +def rand_asic_namespace(request, duthosts, rand_one_dut_hostname): + """ + Return the randomly selected asic namespace in case of multi-asic duthost. + """ + + if "rand_one_dut_front_end_hostname" in request.fixturenames: + dut_hostname = request.getfixturevalue("rand_one_dut_front_end_hostname") + else: + dut_hostname = rand_one_dut_hostname + + duthost = duthosts[dut_hostname] + + asic_namespace = None + asic_index = None + if duthost.is_multi_asic: + namespace_list = duthost.get_asic_namespace_list() + asic_namespace = random.choice(namespace_list) + asic_index = duthost.get_asic_id_from_namespace(asic_namespace) + + return asic_namespace, asic_index + + @pytest.fixture(scope="module", autouse=True) def reset_critical_services_list(duthosts): """ @@ -2204,7 +2227,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 """ diff --git a/tests/generic_config_updater/conftest.py b/tests/generic_config_updater/conftest.py index 6e14fd1374e..e76ad4d47bf 100644 --- a/tests/generic_config_updater/conftest.py +++ b/tests/generic_config_updater/conftest.py @@ -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" @@ -12,48 +12,61 @@ 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, rand_asic_namespace): """ 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 """ - duthost = duthosts[rand_one_dut_hostname] - return duthost.config_facts(host=duthost.hostname, source="persistent")['ansible_facts'] + duthost = duthosts[selected_dut_hostname] + asic_namespace, asic_id = rand_asic_namespace + 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) @@ -62,9 +75,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: {}" @@ -73,9 +84,7 @@ 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.") @@ -83,17 +92,17 @@ def reset_and_restore_test_environment(duthosts, rand_one_dut_hostname): @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) @@ -119,7 +128,7 @@ 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 @@ -127,11 +136,11 @@ def ignore_expected_loganalyzer_exceptions(duthosts, rand_one_dut_hostname, loga 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.*",