diff --git a/tests/generic_config_updater/test_syslog.py b/tests/generic_config_updater/test_syslog.py index f9b1a817990..816b6c5317a 100644 --- a/tests/generic_config_updater/test_syslog.py +++ b/tests/generic_config_updater/test_syslog.py @@ -2,9 +2,9 @@ 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 apply_patch, expect_res_success, expect_op_failure, expect_op_success from tests.generic_config_updater.gu_utils import generate_tmpfile, delete_tmpfile +from tests.generic_config_updater.gu_utils import create_checkpoint, delete_checkpoint, rollback_or_reload, rollback pytestmark = [ pytest.mark.topology('any'), @@ -12,56 +12,151 @@ 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 +SYSLOG_DUMMY_IPV4_SERVER = "10.0.0.5" +SYSLOG_DUMMY_IPV6_SERVER = "cc98:2008::1" +SETUP_ENV_CP = "test_setup_checkpoint" +CONFIG_CLEANUP = "config_cleanup" +CONFIG_ADD_DEFAULT = "config_add_default" + +@pytest.fixture(scope="module", params=[CONFIG_CLEANUP, CONFIG_ADD_DEFAULT]) +def init_syslog_config(request): + return request.param + +def syslog_config_cleanup(duthost, cfg_facts): + """ Cleanup syslog server + + Sample output + admin@vlab-01:~$ show runningconfiguration syslog + Syslog Servers + ---------------- + """ + syslog_servers = cfg_facts.get('SYSLOG_SERVER', {}) + for syslog_server in syslog_servers: + del_syslog_server = duthost.shell("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)) + + +def syslog_config_add_default(duthost): + """ Add default v4 and v6 syslog server to config + + Sample output + admin@vlab-01:~$ show runningconfiguration syslog + Syslog Servers + ---------------- + [10.0.0.5] + [cc98:2008::1] + """ + for syslog_server in [SYSLOG_DUMMY_IPV4_SERVER, SYSLOG_DUMMY_IPV6_SERVER]: + add_syslog_server = duthost.shell("config syslog add {}".format(syslog_server), + module_ignore_errors=True) + pytest_assert(not add_syslog_server['rc'], + "syslog server '{}' is not deleted successfully".format(syslog_server)) @pytest.fixture(scope="module") -def setup_env(duthosts, rand_one_dut_hostname, cfg_facts): +def original_syslog_servers(duthost, tbinfo): + """A module level fixture to store original syslog servers info + """ + mg_facts = duthost.get_extended_minigraph_facts(tbinfo) + + original_syslog_servers = [] + for syslog_server in mg_facts['syslog_servers']: + original_syslog_servers.append(syslog_server) + + return original_syslog_servers + +def get_current_syslog_servers(duthost): + """Get current syslog servers from running host + """ + cmds = "show runningconfiguration syslog" + output = duthost.shell(cmds) + + pytest_assert(not output['rc'], + "'{}' is not running successfully".format(cmds) + ) + + # If len less than 3 means not syslog output + lines = output['stdout'].splitlines() + if len(lines) < 3: + return [] + # Jump over introductory printout + current_syslog_servers = [] + for line in lines[2:]: + # remove enclosed sqaure bracket + current_syslog_servers.append(line[1:-1]) + return current_syslog_servers + +def check_rollback_res(duthost, output, init_syslog_config): + pytest_assert( + not output['rc'] and "Config rolled back successfull" in output['stdout'], + "Rollback to previous setup env failed." + ) + if init_syslog_config == CONFIG_CLEANUP: + pytest_assert(not get_current_syslog_servers(duthost), + "Failed to rollback to {}".format(init_syslog_config) + ) + elif init_syslog_config == CONFIG_ADD_DEFAULT: + pytest_assert( + set(get_current_syslog_servers(duthost)) == set([SYSLOG_DUMMY_IPV4_SERVER, SYSLOG_DUMMY_IPV6_SERVER]), + "Failed to rollback to {}".format(init_syslog_config) + ) + +@pytest.fixture(autouse=True) +def setup_env(duthosts, rand_one_dut_hostname, cfg_facts, init_syslog_config, original_syslog_servers): """ 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 + init_syslog_config: set up the initial syslog config for test + original_syslog_servers: original syslog servers stored in config """ duthost = duthosts[rand_one_dut_hostname] + create_checkpoint(duthost) - 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)) + syslog_config_cleanup(duthost, cfg_facts) - # 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)) + if init_syslog_config == CONFIG_ADD_DEFAULT: + syslog_config_add_default(duthost) + + create_checkpoint(duthost, SETUP_ENV_CP) 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) + # Rollback twice. First rollback to checkpoint just before 'yield' + # Second rollback is to back to original setup + try: + output = rollback(duthost, SETUP_ENV_CP) + check_rollback_res(duthost, output, init_syslog_config) + + logger.info("Rolled back to original checkpoint") + rollback_or_reload(duthost) + + current_syslog_servers = get_current_syslog_servers(duthost) + pytest_assert(set(current_syslog_servers) == set(original_syslog_servers), + "Syslog servers are not rollback_or_reload to initial config setup" + ) + finally: + delete_checkpoint(duthost, SETUP_ENV_CP) + delete_checkpoint(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)) + 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") + ("add", SYSLOG_DUMMY_IPV4_SERVER, SYSLOG_DUMMY_IPV6_SERVER) ]) -def test_syslog_server_tc1_add_init(duthost, setup_env, op, +def test_syslog_server_tc1_add_init(duthost, init_syslog_config, op, dummy_syslog_server_v4, dummy_syslog_server_v6): """ Add v4 and v6 syslog server to config @@ -72,6 +167,9 @@ def test_syslog_server_tc1_add_init(duthost, setup_env, op, [10.0.0.5] [cc98:2008::1] """ + if init_syslog_config != CONFIG_CLEANUP: + pytest.skip("Unsupported initial config") + json_patch = [ { "op": "{}".format(op), @@ -86,18 +184,19 @@ def test_syslog_server_tc1_add_init(duthost, setup_env, op, 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) + try: + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_success(duthost,output) - 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) + expected_content_list = ["[{}]".format(dummy_syslog_server_v4), "[{}]".format(dummy_syslog_server_v6)] + expect_res_success_syslog(duthost, expected_content_list, []) + finally: + delete_tmpfile(duthost, tmpfile) @pytest.mark.parametrize("op, dummy_syslog_server_v4, dummy_syslog_server_v6", [ - ("add", "10.0.0.5", "cc98:2008::1") + ("add", SYSLOG_DUMMY_IPV4_SERVER, SYSLOG_DUMMY_IPV6_SERVER) ]) -def test_syslog_server_tc2_add_duplicate(duthost, setup_env, op, +def test_syslog_server_tc2_add_duplicate(duthost, init_syslog_config, op, dummy_syslog_server_v4, dummy_syslog_server_v6): """ Add v4 and v6 duplicate syslog server to config @@ -108,6 +207,9 @@ def test_syslog_server_tc2_add_duplicate(duthost, setup_env, op, [10.0.0.5] [cc98:2008::1] """ + if init_syslog_config != CONFIG_ADD_DEFAULT: + pytest.skip("Unsupported initial config") + json_patch = [ { "op": "{}".format(op), @@ -124,13 +226,14 @@ def test_syslog_server_tc2_add_duplicate(duthost, setup_env, op, 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, []) + try: + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_success(duthost,output) - delete_tmpfile(duthost, tmpfile) + expected_content_list = ["[{}]".format(dummy_syslog_server_v4), "[{}]".format(dummy_syslog_server_v6)] + expect_res_success_syslog(duthost, expected_content_list, []) + finally: + delete_tmpfile(duthost, tmpfile) @pytest.mark.parametrize("op, dummy_syslog_server_v4, dummy_syslog_server_v6", [ ("add", "10.0.0.587", "cc98:2008::1"), @@ -138,7 +241,7 @@ def test_syslog_server_tc2_add_duplicate(duthost, setup_env, op, ("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, +def test_syslog_server_tc3_xfail(duthost, init_syslog_config, op, dummy_syslog_server_v4, dummy_syslog_server_v6): """ Test expect fail testcase @@ -147,6 +250,9 @@ def test_syslog_server_tc3_xfail(duthost, setup_env, op, ("remove", "10.0.0.6", "cc98:2008:1"), REMOVE Unexist IPv4 address ("remove", "10.0.0.5", "cc98:2008::2") REMOVE Unexist IPv6 address """ + if init_syslog_config != CONFIG_ADD_DEFAULT: + pytest.skip("Unsupported initial config") + json_patch = [ { "op": "{}".format(op), @@ -162,15 +268,16 @@ def test_syslog_server_tc3_xfail(duthost, setup_env, op, 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) + try: + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_failure(output) + finally: + delete_tmpfile(duthost, tmpfile) @pytest.mark.parametrize("op, dummy_syslog_server_v4, dummy_syslog_server_v6", [ - ("remove", "10.0.0.5", "cc98:2008::1") + ("remove", SYSLOG_DUMMY_IPV4_SERVER, SYSLOG_DUMMY_IPV6_SERVER) ]) -def test_syslog_server_tc4_remove(duthost, setup_env, op, +def test_syslog_server_tc4_remove(duthost, init_syslog_config, op, dummy_syslog_server_v4, dummy_syslog_server_v6): """ Remove v4 and v6 syslog server @@ -179,6 +286,9 @@ def test_syslog_server_tc4_remove(duthost, setup_env, op, Syslog Servers ---------------- """ + if init_syslog_config != CONFIG_ADD_DEFAULT: + pytest.skip("Unsupported initial config") + json_patch = [ { "op": "{}".format(op), @@ -189,68 +299,49 @@ def test_syslog_server_tc4_remove(duthost, setup_env, op, 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) + try: + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_success(duthost,output) - unexpected_content_list = ["[{}]".format(dummy_syslog_server_v4), "[{}]".format(dummy_syslog_server_v6)] - expect_res_success_syslog(duthost, [], unexpected_content_list) + unexpected_content_list = ["[{}]".format(dummy_syslog_server_v4), "[{}]".format(dummy_syslog_server_v6)] + expect_res_success_syslog(duthost, [], unexpected_content_list) + finally: + delete_tmpfile(duthost, tmpfile) - delete_tmpfile(duthost, tmpfile) - -def test_syslog_server_tc5_add_to_max(duthost, setup_env): - """ Test syslog server max +@pytest.mark.parametrize("op, replace_syslog_server_v4, replace_syslog_server_v6", [ + ("add", "10.0.0.6", "cc98:2008::2") +]) +def test_syslog_server_tc5_replace(duthost, init_syslog_config, op, + replace_syslog_server_v4, replace_syslog_server_v6): + """ Add v4 and v6 duplicate syslog server to config + Sample output admin@vlab-01:~$ show runningconfiguration syslog - Sample output: Syslog Servers ---------------- - [10.0.0.1] - ... - [10.0.0.SYSLOG_MAX_SERVER] + [10.0.0.5] + [cc98:2008::1] """ - 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)] + if init_syslog_config != CONFIG_ADD_DEFAULT: + pytest.skip("Unsupported initial config") 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": "remove", + "path": "/SYSLOG_SERVER/{}".format(SYSLOG_DUMMY_IPV6_SERVER) + }, + { + "op": "remove", + "path": "/SYSLOG_SERVER/{}".format(SYSLOG_DUMMY_IPV4_SERVER) + }, { - "op": "add", - "path": "/SYSLOG_SERVER/10.0.0.{}".format(SYSLOG_MAX_SERVER+1), + "op": "{}".format(op), + "path": "/SYSLOG_SERVER/{}".format(replace_syslog_server_v4), + "value": {} + }, + { + "op": "{}".format(op), + "path": "/SYSLOG_SERVER/{}".format(replace_syslog_server_v6), "value": {} } ] @@ -258,7 +349,12 @@ def test_syslog_server_tc6_exceed_max(duthost, setup_env): tmpfile = generate_tmpfile(duthost) logger.info("tmpfile {}".format(tmpfile)) - output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) - expect_op_failure(output) + try: + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_success(duthost,output) - delete_tmpfile(duthost, tmpfile) + expected_content_list = ["[{}]".format(replace_syslog_server_v4), "[{}]".format(replace_syslog_server_v6)] + unexpected_content_list = ["[{}]".format(SYSLOG_DUMMY_IPV4_SERVER), "[{}]".format(SYSLOG_DUMMY_IPV6_SERVER)] + expect_res_success_syslog(duthost, expected_content_list, unexpected_content_list) + finally: + delete_tmpfile(duthost, tmpfile)