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 6cf4637c006..7c8527b916a 100644 --- a/tests/generic_config_updater/gu_utils.py +++ b/tests/generic_config_updater/gu_utils.py @@ -6,13 +6,26 @@ logger = logging.getLogger(__name__) +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) @@ -23,20 +36,38 @@ 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'], "Please check if json file is validate" ) -def expect_op_success_and_reset_check(duthost, output, container_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 + + 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, 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, 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'], @@ -50,19 +81,24 @@ 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'], "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. + + Args: + service_name: Service to reset """ - 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 +107,39 @@ 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, 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 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, + if not service_name in CONTAINER_SERVICES_LIST: + return + + reset_service = wait_until(timeout, interval, delay, duthost.is_service_fully_started, - container_name) + 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) ) diff --git a/tests/generic_config_updater/test_dhcp_relay.py b/tests/generic_config_updater/test_dhcp_relay.py index 35023c7ad66..b0c06629ddb 100644 --- a/tests/generic_config_updater/test_dhcp_relay.py +++ b/tests/generic_config_updater/test_dhcp_relay.py @@ -14,21 +14,16 @@ logger = logging.getLogger(__name__) -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'] +DHCP_RELAY_TIMEOUT = 120 +DHCP_RELAY_INTERVAL = 10 @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) @@ -180,18 +175,18 @@ 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" ) 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) @@ -229,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" @@ -329,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" @@ -372,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" @@ -419,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" @@ -464,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 new file mode 100644 index 00000000000..f9b1a817990 --- /dev/null +++ b/tests/generic_config_updater/test_syslog.py @@ -0,0 +1,264 @@ +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('any'), +] + +logger = logging.getLogger(__name__) + +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 +# The max server test only support SYSLOG_MAX_SERVER that is equal or lower than 254. +SYSLOG_TEST_MAX_UPPER_LIMIT = 254 + +@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 {} 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: + 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 + + 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_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, []) + + 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_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, []) + + 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_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) + + 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.SYSLOG_MAX_SERVER] + """ + 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)] + + 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_TIMEOUT, SYSLOG_INTERVAL, 0) + + status = duthost.get_service_props('rsyslog-config')["ActiveState"] + logger.info("rsyslog-config 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 + """ + 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.{}".format(SYSLOG_MAX_SERVER+1), + "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)