From 95de8f2cc810055aac458b4a7aaa1c7f78833532 Mon Sep 17 00:00:00 2001 From: Jingwen Xie Date: Thu, 18 Nov 2021 08:02:30 +0000 Subject: [PATCH 1/7] Cover service start-limit-hit case. Return True after service start and verify that in tests --- tests/generic_config_updater/gu_utils.py | 36 +++++++++++++----------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/tests/generic_config_updater/gu_utils.py b/tests/generic_config_updater/gu_utils.py index 6cf4637c006..9f20c2f44c9 100644 --- a/tests/generic_config_updater/gu_utils.py +++ b/tests/generic_config_updater/gu_utils.py @@ -6,6 +6,8 @@ logger = logging.getLogger(__name__) +CONTAINER_SERVICES_LIST = ["swss", "syncd", "radv", "lldp", "dhcp_relay", "teamd", "bgp", "pmon", "telemetry", "acms"] + def generate_tmpfile(duthost): return duthost.shell('mktemp')['stdout'] @@ -29,12 +31,12 @@ def expect_op_success(duthost, output): "Please check if json file is validate" ) -def expect_op_success_and_reset_check(duthost, output, container_name, threshold, interval, delay): +def expect_op_success_and_reset_check(duthost, output, service_name, threshold, interval, delay): '''Add contianer reset check after op success ''' expect_op_success(duthost, output) - if start_limit_hit(duthost, container_name): - reset_start_limit_hit(duthost, container_name, threshold, interval, delay) + if start_limit_hit(duthost, service_name): + reset_start_limit_hit(duthost, service_name, threshold, interval, delay) def expect_res_success(duthost, output, expected_content_list, unexpected_content_list): for expected_content in expected_content_list: @@ -56,13 +58,13 @@ def expect_op_failure(output): "The command should fail with non zero return code" ) -def start_limit_hit(duthost, container_name): +def start_limit_hit(duthost, service_name): """If start-limit-hit is hit, the service will not start anyway. """ - service_status = duthost.shell("sudo systemctl status {}.service | grep 'Active'".format(container_name)) + service_status = duthost.shell("sudo systemctl status {}.service | grep 'Active'".format(service_name)) pytest_assert( not service_status['rc'], - "{} service status cannot be found".format(container_name) + "{} service status cannot be found".format(service_name) ) for line in service_status["stdout_lines"]: @@ -71,29 +73,31 @@ def start_limit_hit(duthost, container_name): return False -def reset_start_limit_hit(duthost, container_name, threshold, interval, delay): - """Reset container if hit start-limit-hit +def reset_start_limit_hit(duthost, service_name, threshold, interval, delay): + """Reset service if hit start-limit-hit """ - logger.info("Reset container '{}' due to start-limit-hit".format(container_name)) + logger.info("Reset service '{}' due to start-limit-hit".format(service_name)) - service_reset_failed = duthost.shell("sudo systemctl reset-failed {}.service".format(container_name)) + service_reset_failed = duthost.shell("sudo systemctl reset-failed {}.service".format(service_name)) pytest_assert( not service_reset_failed['rc'], "{} systemctl reset-failed service fails" ) - service_start = duthost.shell("sudo systemctl start {}.service".format(container_name)) + service_start = duthost.shell("sudo systemctl start {}.service".format(service_name)) pytest_assert( not service_start['rc'], "{} systemctl start service fails" ) - reset_container = wait_until(threshold, + is_container = service_name in CONTAINER_SERVICES_LIST + + reset_service = wait_until(threshold, interval, delay, - duthost.is_service_fully_started, - container_name) + duthost.is_service_fully_started if is_container else True, + service_name) pytest_assert( - reset_container, - "Failed to reset container '{}' due to start-limit-hit".format(container_name) + reset_service, + "Failed to reset service '{}' due to start-limit-hit".format(service_name) ) From 054dd9f22ee7c01439e2b44af8420440f529fa41 Mon Sep 17 00:00:00 2001 From: Jingwen Xie Date: Thu, 18 Nov 2021 08:11:02 +0000 Subject: [PATCH 2/7] GU syslog test --- tests/generic_config_updater/test_syslog.py | 262 ++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 tests/generic_config_updater/test_syslog.py diff --git a/tests/generic_config_updater/test_syslog.py b/tests/generic_config_updater/test_syslog.py new file mode 100644 index 00000000000..4d1cb6ca806 --- /dev/null +++ b/tests/generic_config_updater/test_syslog.py @@ -0,0 +1,262 @@ +import logging +import pytest + +from tests.common.helpers.assertions import pytest_assert +from tests.common.config_reload import config_reload +from tests.generic_config_updater.gu_utils import apply_patch, expect_op_success_and_reset_check, expect_res_success, expect_op_failure +from tests.generic_config_updater.gu_utils import generate_tmpfile, delete_tmpfile + +pytestmark = [ + pytest.mark.topology('t0'), +] + +logger = logging.getLogger(__name__) + +# This is restricted by sonic-syslog.yang +SYSLOG_MAX_SERVER=10 + +SYSLOG_THRESHOLD=10 +SYSLOG_INTERVAL=1 + +@pytest.fixture(scope="module") +def cfg_facts(duthosts, rand_one_dut_hostname): + duthost = duthosts[rand_one_dut_hostname] + return duthost.config_facts(host=duthost.hostname, source="persistent")['ansible_facts'] + +@pytest.fixture(scope="module") +def setup_env(duthosts, rand_one_dut_hostname, cfg_facts): + """ + Setup/teardown fixture for syslog config + Args: + duthosts: list of DUTs. + rand_selected_dut: The fixture returns a randomly selected DuT. + cfg_facts: config facts for selected DUT + """ + duthost = duthosts[rand_one_dut_hostname] + + config_tmpfile = generate_tmpfile(duthost) + logger.info("config_tmpfile {}".format(config_tmpfile)) + logger.info("Backing up config_db.json") + duthost.shell("sudo cp /etc/sonic/config_db.json {}".format(config_tmpfile)) + + # Cleanup syslog server config + syslog_servers = cfg_facts.get('SYSLOG_SERVER', {}) + for syslog_server in syslog_servers: + duthost.shell("sudo config syslog del {}".format(syslog_server), + module_ignore_errors=True) + + yield + + logger.info("Restoring config_db.json") + duthost.shell("sudo cp {} /etc/sonic/config_db.json".format(config_tmpfile)) + delete_tmpfile(duthost, config_tmpfile) + config_reload(duthost) + +def expect_res_success_syslog(duthost, expected_content_list, unexpected_content_list): + """Check if syslog server show as expected + """ + cmds = "show runningconfiguration syslog" + output = duthost.shell(cmds) + pytest_assert(not output['rc'], "'{}' is not running successfully".format(cmds)) + + expect_res_success(duthost, output, expected_content_list, unexpected_content_list) + +@pytest.mark.parametrize("op, dummy_syslog_server_v4, dummy_syslog_server_v6", [ + ("add", "10.0.0.5", "cc98:2008::1") +]) +def test_syslog_server_tc1_add_init(duthost, setup_env, op, + dummy_syslog_server_v4, dummy_syslog_server_v6): + """ Add v4 and v6 syslog server to config + + Sample output + admin@vlab-01:~$ show runningconfiguration syslog + Syslog Servers + ---------------- + [10.0.0.5] + [cc98:2008::1] + """ + json_patch = [ + { + "op": "{}".format(op), + "path": "/SYSLOG_SERVER", + "value": { + "{}".format(dummy_syslog_server_v4): {}, + "{}".format(dummy_syslog_server_v6): {} + } + } + ] + + tmpfile = generate_tmpfile(duthost) + logger.info("tmpfile {}".format(tmpfile)) + + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_THRESHOLD, SYSLOG_INTERVAL, 0) + + expected_content_list = ["[{}]".format(dummy_syslog_server_v4), "[{}]".format(dummy_syslog_server_v6)] + expect_res_success_syslog(duthost, expected_content_list, []) + + delete_tmpfile(duthost, tmpfile) + +@pytest.mark.parametrize("op, dummy_syslog_server_v4, dummy_syslog_server_v6", [ + ("add", "10.0.0.5", "cc98:2008::1") +]) +def test_syslog_server_tc2_add_duplicate(duthost, setup_env, op, + dummy_syslog_server_v4, dummy_syslog_server_v6): + """ Add v4 and v6 duplicate syslog server to config + + Sample output + admin@vlab-01:~$ show runningconfiguration syslog + Syslog Servers + ---------------- + [10.0.0.5] + [cc98:2008::1] + """ + json_patch = [ + { + "op": "{}".format(op), + "path": "/SYSLOG_SERVER/{}".format(dummy_syslog_server_v4), + "value": {} + }, + { + "op": "{}".format(op), + "path": "/SYSLOG_SERVER/{}".format(dummy_syslog_server_v6), + "value": {} + } + ] + + tmpfile = generate_tmpfile(duthost) + logger.info("tmpfile {}".format(tmpfile)) + + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_THRESHOLD, SYSLOG_INTERVAL, 0) + + expected_content_list = ["[{}]".format(dummy_syslog_server_v4), "[{}]".format(dummy_syslog_server_v6)] + expect_res_success_syslog(duthost, expected_content_list, []) + + delete_tmpfile(duthost, tmpfile) + +@pytest.mark.parametrize("op, dummy_syslog_server_v4, dummy_syslog_server_v6", [ + ("add", "10.0.0.587", "cc98:2008::1"), + ("add", "10.0.0.5", "cc98:2008::xyz"), + ("remove", "10.0.0.6", "cc98:2008:1"), + ("remove", "10.0.0.5", "cc98:2008::2") +]) +def test_syslog_server_tc3_xfail(duthost, setup_env, op, + dummy_syslog_server_v4, dummy_syslog_server_v6): + """ Test expect fail testcase + + ("add", "10.0.0.587", "cc98:2008::1"), ADD Invalid IPv4 address + ("add", "10.0.0.5", "cc98:2008::xyz"), ADD Invalid IPv6 address + ("remove", "10.0.0.6", "cc98:2008:1"), REMOVE Unexist IPv4 address + ("remove", "10.0.0.5", "cc98:2008::2") REMOVE Unexist IPv6 address + """ + json_patch = [ + { + "op": "{}".format(op), + "path": "/SYSLOG_SERVER/{}".format(dummy_syslog_server_v4), + "value": {} + }, + { + "op": "{}".format(op), + "path": "/SYSLOG_SERVER/{}".format(dummy_syslog_server_v6), + "value": {} + } + ] + tmpfile = generate_tmpfile(duthost) + logger.info("tmpfile {}".format(tmpfile)) + + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_failure(output) + + delete_tmpfile(duthost, tmpfile) + +@pytest.mark.parametrize("op, dummy_syslog_server_v4, dummy_syslog_server_v6", [ + ("remove", "10.0.0.5", "cc98:2008::1") +]) +def test_syslog_server_tc4_remove(duthost, setup_env, op, + dummy_syslog_server_v4, dummy_syslog_server_v6): + """ Remove v4 and v6 syslog server + + admin@vlab-01:~$ show runningconfiguration syslog + Sample output: + Syslog Servers + ---------------- + """ + json_patch = [ + { + "op": "{}".format(op), + "path": "/SYSLOG_SERVER" + } + ] + + tmpfile = generate_tmpfile(duthost) + logger.info("tmpfile {}".format(tmpfile)) + + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_THRESHOLD, SYSLOG_INTERVAL, 0) + + unexpected_content_list = ["[{}]".format(dummy_syslog_server_v4), "[{}]".format(dummy_syslog_server_v6)] + expect_res_success_syslog(duthost, [], unexpected_content_list) + + delete_tmpfile(duthost, tmpfile) + +def test_syslog_server_tc5_add_to_max(duthost, setup_env): + """ Test syslog server max + + admin@vlab-01:~$ show runningconfiguration syslog + Sample output: + Syslog Servers + ---------------- + [10.0.0.1] + ... + [10.0.0.10] + """ + syslog_servers = ["10.0.0.{}".format(i) for i in range(1, SYSLOG_MAX_SERVER+1)] + + json_patch = [ + { + "op": "add", + "path": "/SYSLOG_SERVER", + "value": { + "{}".format(syslog_server) : {} for syslog_server in syslog_servers + } + } + ] + + tmpfile = generate_tmpfile(duthost) + logger.info("tmpfile {}".format(tmpfile)) + + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_THRESHOLD, SYSLOG_INTERVAL, 0) + logger.info("ActiveState{}".format(duthost.get_service_props('rsyslog-config'))) + status = duthost.get_service_props('rsyslog-config')["ActiveState"] + logger.info("status {}".format(status)) + pytest_assert( + duthost.get_service_props('rsyslog-config')["ActiveState"] == "active", + "rsyslog-config service is not active" + ) + + expected_content_list = ["[{}]".format(syslog_server) for syslog_server in syslog_servers] + expect_res_success_syslog(duthost, expected_content_list, []) + + delete_tmpfile(duthost, tmpfile) + +def test_syslog_server_tc6_exceed_max(duthost, setup_env): + """ Exceed syslog server maximum test + """ + + json_patch = [ + { + "op": "add", + "path": "/SYSLOG_SERVER/10.0.0.20", + "value": {} + } + ] + + tmpfile = generate_tmpfile(duthost) + logger.info("tmpfile {}".format(tmpfile)) + + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_failure(output) + + delete_tmpfile(duthost, tmpfile) From 207489415f8220936257fb4cce2112e57f05f053 Mon Sep 17 00:00:00 2001 From: Jingwen Xie Date: Thu, 18 Nov 2021 09:13:40 +0000 Subject: [PATCH 3/7] fix lgtm --- tests/generic_config_updater/gu_utils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/generic_config_updater/gu_utils.py b/tests/generic_config_updater/gu_utils.py index 9f20c2f44c9..4cb99df6725 100644 --- a/tests/generic_config_updater/gu_utils.py +++ b/tests/generic_config_updater/gu_utils.py @@ -90,12 +90,13 @@ def reset_start_limit_hit(duthost, service_name, threshold, interval, delay): "{} systemctl start service fails" ) - is_container = service_name in CONTAINER_SERVICES_LIST + if not service_name in CONTAINER_SERVICES_LIST: + return reset_service = wait_until(threshold, interval, delay, - duthost.is_service_fully_started if is_container else True, + duthost.is_service_fully_started, service_name) pytest_assert( reset_service, From 8bc45bc494dd1e68c324490916370d3de19e5843 Mon Sep 17 00:00:00 2001 From: Jingwen Xie Date: Fri, 19 Nov 2021 03:05:25 +0000 Subject: [PATCH 4/7] Skip test with max syslog server as max is removed in yang --- tests/generic_config_updater/test_syslog.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/generic_config_updater/test_syslog.py b/tests/generic_config_updater/test_syslog.py index 4d1cb6ca806..1821b0c7b25 100644 --- a/tests/generic_config_updater/test_syslog.py +++ b/tests/generic_config_updater/test_syslog.py @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) # This is restricted by sonic-syslog.yang -SYSLOG_MAX_SERVER=10 +SYSLOG_MAX_SERVER=-1 SYSLOG_THRESHOLD=10 SYSLOG_INTERVAL=1 @@ -209,8 +209,11 @@ def test_syslog_server_tc5_add_to_max(duthost, setup_env): ---------------- [10.0.0.1] ... - [10.0.0.10] + [10.0.0.SYSLOG_MAX_SERVER] """ + if SYSLOG_MAX_SERVER == -1: + pytest.skip("SYSLOG_MAX_SERVER is not set") + syslog_servers = ["10.0.0.{}".format(i) for i in range(1, SYSLOG_MAX_SERVER+1)] json_patch = [ @@ -228,9 +231,9 @@ def test_syslog_server_tc5_add_to_max(duthost, setup_env): output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_THRESHOLD, SYSLOG_INTERVAL, 0) - logger.info("ActiveState{}".format(duthost.get_service_props('rsyslog-config'))) + status = duthost.get_service_props('rsyslog-config')["ActiveState"] - logger.info("status {}".format(status)) + logger.info("rsyslog-config status {}".format(status)) pytest_assert( duthost.get_service_props('rsyslog-config')["ActiveState"] == "active", "rsyslog-config service is not active" @@ -244,6 +247,8 @@ def test_syslog_server_tc5_add_to_max(duthost, setup_env): def test_syslog_server_tc6_exceed_max(duthost, setup_env): """ Exceed syslog server maximum test """ + if SYSLOG_MAX_SERVER == -1: + pytest.skip("SYSLOG_MAX_SERVER is not set") json_patch = [ { From 2bc6b73593ff6fe0f05d508a003e99d54c4dc8cf Mon Sep 17 00:00:00 2001 From: Jingwen Xie Date: Thu, 25 Nov 2021 12:19:10 +0000 Subject: [PATCH 5/7] resolve comments --- tests/generic_config_updater/conftest.py | 10 +++++++ tests/generic_config_updater/gu_utils.py | 12 ++++---- .../generic_config_updater/test_dhcp_relay.py | 29 ++++++++----------- tests/generic_config_updater/test_syslog.py | 19 +++++------- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/tests/generic_config_updater/conftest.py b/tests/generic_config_updater/conftest.py index 910658ebfac..e98f5f6a9e1 100644 --- a/tests/generic_config_updater/conftest.py +++ b/tests/generic_config_updater/conftest.py @@ -14,3 +14,13 @@ def check_image_version(duthost): """ skip_version(duthost, ["201811", "201911", "202012"]) +@pytest.fixture(scope="module") +def cfg_facts(duthosts, rand_one_dut_hostname): + """ + Config facts for selected DUT + Args: + duthosts: list of DUTs. + rand_selected_dut: The fixture returns a randomly selected DuT. + """ + duthost = duthosts[rand_one_dut_hostname] + return duthost.config_facts(host=duthost.hostname, source="persistent")['ansible_facts'] diff --git a/tests/generic_config_updater/gu_utils.py b/tests/generic_config_updater/gu_utils.py index 4cb99df6725..5f888b2b4c6 100644 --- a/tests/generic_config_updater/gu_utils.py +++ b/tests/generic_config_updater/gu_utils.py @@ -31,12 +31,12 @@ def expect_op_success(duthost, output): "Please check if json file is validate" ) -def expect_op_success_and_reset_check(duthost, output, service_name, threshold, interval, delay): - '''Add contianer reset check after op success - ''' +def expect_op_success_and_reset_check(duthost, output, service_name, timeout, interval, delay): + """Add contianer reset check after op success + """ expect_op_success(duthost, output) if start_limit_hit(duthost, service_name): - reset_start_limit_hit(duthost, service_name, threshold, interval, delay) + reset_start_limit_hit(duthost, service_name, timeout, interval, delay) def expect_res_success(duthost, output, expected_content_list, unexpected_content_list): for expected_content in expected_content_list: @@ -73,7 +73,7 @@ def start_limit_hit(duthost, service_name): return False -def reset_start_limit_hit(duthost, service_name, threshold, interval, delay): +def reset_start_limit_hit(duthost, service_name, timeout, interval, delay): """Reset service if hit start-limit-hit """ logger.info("Reset service '{}' due to start-limit-hit".format(service_name)) @@ -93,7 +93,7 @@ def reset_start_limit_hit(duthost, service_name, threshold, interval, delay): if not service_name in CONTAINER_SERVICES_LIST: return - reset_service = wait_until(threshold, + reset_service = wait_until(timeout, interval, delay, duthost.is_service_fully_started, diff --git a/tests/generic_config_updater/test_dhcp_relay.py b/tests/generic_config_updater/test_dhcp_relay.py index 35023c7ad66..af0f014aa37 100644 --- a/tests/generic_config_updater/test_dhcp_relay.py +++ b/tests/generic_config_updater/test_dhcp_relay.py @@ -17,18 +17,13 @@ DHCP_RELAY_THRESHOLD=120 DHCP_RELAY_INTERVAL=10 -@pytest.fixture(scope="module") -def cfg_facts(duthosts, rand_one_dut_hostname): - duthost = duthosts[rand_one_dut_hostname] - return duthost.config_facts(host=duthost.hostname, source="persistent")['ansible_facts'] - @pytest.fixture(scope="module") def vlan_intfs_dict(utils_vlan_intfs_dict_orig): - ''' Add two new vlan for test + """ Add two new vlan for test If added vlan_id is 108 and 109, it will add a dict as below {108: {'ip': u'192.168.8.1/24', 'orig': False}, 109: {'ip': u'192.168.9.1/24', 'orig': False}} - ''' + """ logger.info("vlan_intrfs_dict ORIG {}".format(utils_vlan_intfs_dict_orig)) vlan_intfs_dict = utils_vlan_intfs_dict_add(utils_vlan_intfs_dict_orig, 2) logger.info("vlan_intrfs_dict FINAL {}".format(vlan_intfs_dict)) @@ -56,7 +51,7 @@ def ensure_dhcp_relay_running(duthost): ) def create_test_vlans(duthost, cfg_facts, vlan_intfs_dict, first_avai_vlan_port): - '''Generate two vlan config for testing + """Generate two vlan config for testing This function should generate two VLAN detail shown below +-----------+------------------+-----------+----------------+-------------+-----------------------+ @@ -66,7 +61,7 @@ def create_test_vlans(duthost, cfg_facts, vlan_intfs_dict, first_avai_vlan_port) +-----------+------------------+-----------+----------------+-------------+-----------------------+ | 109 | 192.168.9.1/24 | Ethernet4 | tagged | disabled | | +-----------+------------------+-----------+----------------+-------------+-----------------------+ - ''' + """ logger.info("CREATE TEST VLANS START") vlan_ports_list = [{ @@ -83,7 +78,7 @@ def clean_setup(): pass def default_setup(duthost, vlan_intfs_list): - '''Generate 4 dhcp server for each vlan + """Generate 4 dhcp server for each vlan This VLAN detail shows below +-----------+------------------+-----------+----------------+-------------+-----------------------+ @@ -99,7 +94,7 @@ def default_setup(duthost, vlan_intfs_list): | | | | | | 192.0.109.3 | | | | | | | 192.0.109.4 | +-----------+------------------+-----------+----------------+-------------+-----------------------+ - ''' + """ cmds = [] expected_content_dict = {} logger.info("default_setup is initiated") @@ -151,8 +146,8 @@ def setup_vlan(duthosts, rand_one_dut_hostname, vlan_intfs_dict, first_avai_vlan tearDown(duthost, vlan_intfs_dict, first_avai_vlan_port) def tearDown(duthost, vlan_intfs_dict, first_avai_vlan_port): - '''Clean up VLAN CONFIG for this test - ''' + """Clean up VLAN CONFIG for this test + """ logger.info("VLAN test ending ...") config_reload(duthost) @@ -161,14 +156,14 @@ def vlan_intfs_list(vlan_intfs_dict): return [ key for key, value in vlan_intfs_dict.items() if not value['orig'] ] def ensure_dhcp_server_up(duthost): - '''Wait till dhcp-relay server is setup + """Wait till dhcp-relay server is setup Sample output admin@vlab-01:~$ docker exec dhcp_relay supervisorctl status | grep ^dhcp-relay dhcp-relay:isc-dhcpv4-relay-Vlan100 RUNNING pid 72, uptime 0:00:09 dhcp-relay:isc-dhcpv4-relay-Vlan1000 RUNNING pid 73, uptime 0:00:09 - ''' + """ def _dhcp_server_up(): cmds = 'docker exec dhcp_relay supervisorctl status | grep ^dhcp-relay' output = duthost.shell(cmds) @@ -185,13 +180,13 @@ def _dhcp_server_up(): ) def dhcp_severs_by_vlanid(duthost, vlanid): - '''Get pid and then only output the related dhcp server info for that pid + """Get pid and then only output the related dhcp server info for that pid Sample output admin@vlab-01:~$ docker exec dhcp_relay ps -fp 73 UID PID PPID C STIME TTY TIME CMD root 73 1 0 06:39 pts/0 00:00:00 /usr/sbin/dhcrelay -d -m discard -a %h:%p %P --name-alias-map-file /tmp/port-name-alias-map.txt -id Vlan1000 -iu Vlan100 -iu PortChannel0001 -iu PortChannel0002 -iu PortChannel0003 -iu PortChannel0004 192.0.0.1 192.0.0.2 192.0.0.3 192.0.0.4 - ''' + """ cmds = "docker exec dhcp_relay supervisorctl status | grep ^dhcp-relay \ | grep 'Vlan{} ' | awk '{{print $4}}'".format(vlanid) output = duthost.shell(cmds) diff --git a/tests/generic_config_updater/test_syslog.py b/tests/generic_config_updater/test_syslog.py index 1821b0c7b25..d5947c00b2f 100644 --- a/tests/generic_config_updater/test_syslog.py +++ b/tests/generic_config_updater/test_syslog.py @@ -7,21 +7,15 @@ from tests.generic_config_updater.gu_utils import generate_tmpfile, delete_tmpfile pytestmark = [ - pytest.mark.topology('t0'), + pytest.mark.topology('any'), ] logger = logging.getLogger(__name__) -# This is restricted by sonic-syslog.yang -SYSLOG_MAX_SERVER=-1 - SYSLOG_THRESHOLD=10 SYSLOG_INTERVAL=1 - -@pytest.fixture(scope="module") -def cfg_facts(duthosts, rand_one_dut_hostname): - duthost = duthosts[rand_one_dut_hostname] - return duthost.config_facts(host=duthost.hostname, source="persistent")['ansible_facts'] +# This is restricted by sonic-syslog.yang. Use '-1' to indicate no max is set +SYSLOG_MAX_SERVER=-1 @pytest.fixture(scope="module") def setup_env(duthosts, rand_one_dut_hostname, cfg_facts): @@ -35,15 +29,16 @@ def setup_env(duthosts, rand_one_dut_hostname, cfg_facts): duthost = duthosts[rand_one_dut_hostname] config_tmpfile = generate_tmpfile(duthost) - logger.info("config_tmpfile {}".format(config_tmpfile)) - logger.info("Backing up config_db.json") + logger.info("config_tmpfile {} Backing up config_db.json".format(config_tmpfile)) duthost.shell("sudo cp /etc/sonic/config_db.json {}".format(config_tmpfile)) # Cleanup syslog server config syslog_servers = cfg_facts.get('SYSLOG_SERVER', {}) for syslog_server in syslog_servers: - duthost.shell("sudo config syslog del {}".format(syslog_server), + del_syslog_server = duthost.shell("sudo config syslog del {}".format(syslog_server), module_ignore_errors=True) + pytest_assert(not del_syslog_server['rc'], + "syslog server '{}' is not deleted successfully".format(syslog_server)) yield From 3abd52e7e5be84e019f342584d9b70e79ec7d1bd Mon Sep 17 00:00:00 2001 From: Jingwen Xie Date: Fri, 26 Nov 2021 01:25:30 +0000 Subject: [PATCH 6/7] Limit test max to 254 --- tests/generic_config_updater/test_syslog.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/generic_config_updater/test_syslog.py b/tests/generic_config_updater/test_syslog.py index d5947c00b2f..7a8a6b20ddb 100644 --- a/tests/generic_config_updater/test_syslog.py +++ b/tests/generic_config_updater/test_syslog.py @@ -16,6 +16,9 @@ SYSLOG_INTERVAL=1 # This is restricted by sonic-syslog.yang. Use '-1' to indicate no max is set SYSLOG_MAX_SERVER=-1 +# The max server test only support SYSLOG_MAX_SERVER that is equal or lower than 254. +# Will modify if change in future +SYSLOG_TEST_MAX_UPPER_LIMIT=254 @pytest.fixture(scope="module") def setup_env(duthosts, rand_one_dut_hostname, cfg_facts): @@ -206,8 +209,8 @@ def test_syslog_server_tc5_add_to_max(duthost, setup_env): ... [10.0.0.SYSLOG_MAX_SERVER] """ - if SYSLOG_MAX_SERVER == -1: - pytest.skip("SYSLOG_MAX_SERVER is not set") + if SYSLOG_MAX_SERVER == -1 or SYSLOG_MAX_SERVER > SYSLOG_TEST_MAX_UPPER_LIMIT: + pytest.skip("SYSLOG_MAX_SERVER is not set or is over the test max upper limit") syslog_servers = ["10.0.0.{}".format(i) for i in range(1, SYSLOG_MAX_SERVER+1)] @@ -242,13 +245,13 @@ def test_syslog_server_tc5_add_to_max(duthost, setup_env): def test_syslog_server_tc6_exceed_max(duthost, setup_env): """ Exceed syslog server maximum test """ - if SYSLOG_MAX_SERVER == -1: - pytest.skip("SYSLOG_MAX_SERVER is not set") + if SYSLOG_MAX_SERVER == -1 or SYSLOG_MAX_SERVER > SYSLOG_TEST_MAX_UPPER_LIMIT: + pytest.skip("SYSLOG_MAX_SERVER is not set or is over the test max upper limit") json_patch = [ { "op": "add", - "path": "/SYSLOG_SERVER/10.0.0.20", + "path": "/SYSLOG_SERVER/10.0.0.{}".format(SYSLOG_MAX_SERVER+1), "value": {} } ] From dd9f5da1021d50d6512be671439970fd97baf0c1 Mon Sep 17 00:00:00 2001 From: Jingwen Xie Date: Wed, 1 Dec 2021 06:45:05 +0000 Subject: [PATCH 7/7] resolve comment; Add introduction for utils file --- tests/generic_config_updater/gu_utils.py | 41 +++++++++++++++++++ .../generic_config_updater/test_dhcp_relay.py | 16 ++++---- tests/generic_config_updater/test_syslog.py | 17 ++++---- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/tests/generic_config_updater/gu_utils.py b/tests/generic_config_updater/gu_utils.py index 5f888b2b4c6..7c8527b916a 100644 --- a/tests/generic_config_updater/gu_utils.py +++ b/tests/generic_config_updater/gu_utils.py @@ -9,12 +9,23 @@ CONTAINER_SERVICES_LIST = ["swss", "syncd", "radv", "lldp", "dhcp_relay", "teamd", "bgp", "pmon", "telemetry", "acms"] def generate_tmpfile(duthost): + """Generate temp file + """ return duthost.shell('mktemp')['stdout'] def delete_tmpfile(duthost, tmpfile): + """Delete temp file + """ duthost.file(path=tmpfile, state='absent') def apply_patch(duthost, json_data, dest_file): + """Run apply-patch on target duthost + + Args: + duthost: Device Under Test (DUT) + 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) cmds = 'config apply-patch {}'.format(dest_file) @@ -25,6 +36,8 @@ def apply_patch(duthost, json_data, dest_file): return output def expect_op_success(duthost, output): + """Expected success from apply-patch output + """ pytest_assert(not output['rc'], "Command is not running successfully") pytest_assert( "Patch applied successfully" in output['stdout'], @@ -33,12 +46,28 @@ def expect_op_success(duthost, output): def expect_op_success_and_reset_check(duthost, output, service_name, timeout, interval, delay): """Add contianer reset check after op success + + Args: + duthost: Device Under Test (DUT) + output: Command couput + service_name: Service to reset + timeout: Maximum time to wait + interval: Poll interval + delay: Delay time """ expect_op_success(duthost, output) if start_limit_hit(duthost, service_name): reset_start_limit_hit(duthost, service_name, timeout, interval, delay) def expect_res_success(duthost, output, expected_content_list, unexpected_content_list): + """Check output success with expected and unexpected content + + Args: + duthost: Device Under Test (DUT) + output: Command output + expected_content_list: Expected content from output + unexpected_content_list: Unexpected content from output + """ for expected_content in expected_content_list: pytest_assert( expected_content in output['stdout'], @@ -52,6 +81,8 @@ def expect_res_success(duthost, output, expected_content_list, unexpected_conten ) def expect_op_failure(output): + """Expected failure from apply-patch output + """ logger.info("return code {}".format(output['rc'])) pytest_assert( output['rc'], @@ -60,6 +91,9 @@ def expect_op_failure(output): def start_limit_hit(duthost, service_name): """If start-limit-hit is hit, the service will not start anyway. + + Args: + service_name: Service to reset """ service_status = duthost.shell("sudo systemctl status {}.service | grep 'Active'".format(service_name)) pytest_assert( @@ -75,6 +109,13 @@ def start_limit_hit(duthost, service_name): def reset_start_limit_hit(duthost, service_name, timeout, interval, delay): """Reset service if hit start-limit-hit + + Args: + duthost: Device Under Test (DUT) + service_name: Service to reset + timeout: Maximum time to wait + interval: Poll interval + delay: Delay time """ logger.info("Reset service '{}' due to start-limit-hit".format(service_name)) diff --git a/tests/generic_config_updater/test_dhcp_relay.py b/tests/generic_config_updater/test_dhcp_relay.py index af0f014aa37..b0c06629ddb 100644 --- a/tests/generic_config_updater/test_dhcp_relay.py +++ b/tests/generic_config_updater/test_dhcp_relay.py @@ -14,8 +14,8 @@ logger = logging.getLogger(__name__) -DHCP_RELAY_THRESHOLD=120 -DHCP_RELAY_INTERVAL=10 +DHCP_RELAY_TIMEOUT = 120 +DHCP_RELAY_INTERVAL = 10 @pytest.fixture(scope="module") def vlan_intfs_dict(utils_vlan_intfs_dict_orig): @@ -175,7 +175,7 @@ def _dhcp_server_up(): return 'RUNNING' in output['stdout'] pytest_assert( - wait_until(DHCP_RELAY_THRESHOLD, DHCP_RELAY_INTERVAL, 0, _dhcp_server_up), + wait_until(DHCP_RELAY_TIMEOUT, DHCP_RELAY_INTERVAL, 0, _dhcp_server_up), "The dhcp relay server is not running" ) @@ -224,7 +224,7 @@ def test_dhcp_relay_tc1_apply_empty(duthost, setup_vlan, init_dhcp_server_config logger.info("tmpfile {}".format(tmpfile)) output = apply_patch(duthost, json_data=dhcp_apply_empty_json, dest_file=tmpfile) - expect_op_success_and_reset_check(duthost, output, 'dhcp_relay', DHCP_RELAY_THRESHOLD, DHCP_RELAY_INTERVAL, 0) + expect_op_success_and_reset_check(duthost, output, 'dhcp_relay', DHCP_RELAY_TIMEOUT, DHCP_RELAY_INTERVAL, 0) pytest_assert( duthost.is_service_fully_started('dhcp_relay'), "dhcp_relay service is not running" @@ -324,7 +324,7 @@ def test_dhcp_relay_tc5_rm(duthost, setup_vlan, init_dhcp_server_config, vlan_in logger.info("tmpfile {}".format(tmpfile)) output = apply_patch(duthost, json_data=dhcp_rm_json, dest_file=tmpfile) - expect_op_success_and_reset_check(duthost, output, 'dhcp_relay', DHCP_RELAY_THRESHOLD, DHCP_RELAY_INTERVAL, 0) + expect_op_success_and_reset_check(duthost, output, 'dhcp_relay', DHCP_RELAY_TIMEOUT, DHCP_RELAY_INTERVAL, 0) pytest_assert( duthost.is_service_fully_started('dhcp_relay'), "dhcp_relay service is not running" @@ -367,7 +367,7 @@ def test_dhcp_relay_tc6_add(duthost, setup_vlan, init_dhcp_server_config, vlan_i logger.info("tmpfile {}".format(tmpfile)) output = apply_patch(duthost, json_data=dhcp_add_json, dest_file=tmpfile) - expect_op_success_and_reset_check(duthost, output, 'dhcp_relay', DHCP_RELAY_THRESHOLD, DHCP_RELAY_INTERVAL, 0) + expect_op_success_and_reset_check(duthost, output, 'dhcp_relay', DHCP_RELAY_TIMEOUT, DHCP_RELAY_INTERVAL, 0) pytest_assert( duthost.is_service_fully_started('dhcp_relay'), "dhcp_relay service is not running" @@ -414,7 +414,7 @@ def test_dhcp_relay_tc7_add_rm(duthost, setup_vlan, init_dhcp_server_config, vla logger.info("tmpfile {}".format(tmpfile)) output = apply_patch(duthost, json_data=dhcp_add_rm_json, dest_file=tmpfile) - expect_op_success_and_reset_check(duthost, output, 'dhcp_relay', DHCP_RELAY_THRESHOLD, DHCP_RELAY_INTERVAL, 0) + expect_op_success_and_reset_check(duthost, output, 'dhcp_relay', DHCP_RELAY_TIMEOUT, DHCP_RELAY_INTERVAL, 0) pytest_assert( duthost.is_service_fully_started('dhcp_relay'), "dhcp_relay service is not running" @@ -459,7 +459,7 @@ def test_dhcp_relay_tc7_replace(duthost, setup_vlan, init_dhcp_server_config, vl logger.info("tmpfile {}".format(tmpfile)) output = apply_patch(duthost, json_data=dhcp_replace_json, dest_file=tmpfile) - expect_op_success_and_reset_check(duthost, output, 'dhcp_relay', DHCP_RELAY_THRESHOLD, DHCP_RELAY_INTERVAL, 0) + expect_op_success_and_reset_check(duthost, output, 'dhcp_relay', DHCP_RELAY_TIMEOUT, DHCP_RELAY_INTERVAL, 0) pytest_assert( duthost.is_service_fully_started('dhcp_relay'), "dhcp_relay service is not running" diff --git a/tests/generic_config_updater/test_syslog.py b/tests/generic_config_updater/test_syslog.py index 7a8a6b20ddb..f9b1a817990 100644 --- a/tests/generic_config_updater/test_syslog.py +++ b/tests/generic_config_updater/test_syslog.py @@ -12,13 +12,12 @@ logger = logging.getLogger(__name__) -SYSLOG_THRESHOLD=10 -SYSLOG_INTERVAL=1 +SYSLOG_TIMEOUT = 10 +SYSLOG_INTERVAL = 1 # This is restricted by sonic-syslog.yang. Use '-1' to indicate no max is set -SYSLOG_MAX_SERVER=-1 +SYSLOG_MAX_SERVER = -1 # The max server test only support SYSLOG_MAX_SERVER that is equal or lower than 254. -# Will modify if change in future -SYSLOG_TEST_MAX_UPPER_LIMIT=254 +SYSLOG_TEST_MAX_UPPER_LIMIT = 254 @pytest.fixture(scope="module") def setup_env(duthosts, rand_one_dut_hostname, cfg_facts): @@ -88,7 +87,7 @@ def test_syslog_server_tc1_add_init(duthost, setup_env, op, logger.info("tmpfile {}".format(tmpfile)) output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) - expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_THRESHOLD, SYSLOG_INTERVAL, 0) + expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_TIMEOUT, SYSLOG_INTERVAL, 0) expected_content_list = ["[{}]".format(dummy_syslog_server_v4), "[{}]".format(dummy_syslog_server_v6)] expect_res_success_syslog(duthost, expected_content_list, []) @@ -126,7 +125,7 @@ def test_syslog_server_tc2_add_duplicate(duthost, setup_env, op, logger.info("tmpfile {}".format(tmpfile)) output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) - expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_THRESHOLD, SYSLOG_INTERVAL, 0) + expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_TIMEOUT, SYSLOG_INTERVAL, 0) expected_content_list = ["[{}]".format(dummy_syslog_server_v4), "[{}]".format(dummy_syslog_server_v6)] expect_res_success_syslog(duthost, expected_content_list, []) @@ -191,7 +190,7 @@ def test_syslog_server_tc4_remove(duthost, setup_env, op, logger.info("tmpfile {}".format(tmpfile)) output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) - expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_THRESHOLD, SYSLOG_INTERVAL, 0) + expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_TIMEOUT, SYSLOG_INTERVAL, 0) unexpected_content_list = ["[{}]".format(dummy_syslog_server_v4), "[{}]".format(dummy_syslog_server_v6)] expect_res_success_syslog(duthost, [], unexpected_content_list) @@ -228,7 +227,7 @@ def test_syslog_server_tc5_add_to_max(duthost, setup_env): logger.info("tmpfile {}".format(tmpfile)) output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) - expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_THRESHOLD, SYSLOG_INTERVAL, 0) + expect_op_success_and_reset_check(duthost, output, 'rsyslog-config', SYSLOG_TIMEOUT, SYSLOG_INTERVAL, 0) status = duthost.get_service_props('rsyslog-config')["ActiveState"] logger.info("rsyslog-config status {}".format(status))