From cd3ee788d14a5395f4797b1d8092e372dacead26 Mon Sep 17 00:00:00 2001 From: yozhao101 <56170650+yozhao101@users.noreply.github.com> Date: Sun, 22 Aug 2021 09:55:16 -0700 Subject: [PATCH] [Config] Update config command of kdump (#1700) Signed-off-by: Yong Zhao yozhao@microsoft.com What I did This PR aims to update the config command of Kdump (Linux kernel dump) mechanism. How I did it Before updating the value of a field in the table of KDUMP, we need decide whether the KDUMP table and corresponding field does exist in the table. How to verify it I verifies this on device str-msn2700-03 and unit test passed. tests/kdump_test.py::TestKdump::test_config_kdump_disable PASSED tests/kdump_test.py::TestKdump::test_config_kdump_enable PASSED tests/kdump_test.py::TestKdump::test_config_kdump_memory PASSED tests/kdump_test.py::TestKdump::test_config_kdump_num_dumps PASSED --- config/kdump.py | 120 +++++++++++++++++++++---------- tests/kdump_test.py | 74 +++++++++++++++++++ tests/mock_tables/config_db.json | 5 ++ 3 files changed, 160 insertions(+), 39 deletions(-) create mode 100644 tests/kdump_test.py diff --git a/config/kdump.py b/config/kdump.py index 61806428d1d8..1349e8f10501 100644 --- a/config/kdump.py +++ b/config/kdump.py @@ -1,44 +1,86 @@ -import os +import sys + import click -import utilities_common.cli as clicommon -from swsscommon.swsscommon import ConfigDBConnector +from utilities_common.cli import AbbreviationGroup, pass_db + -@click.group(cls=clicommon.AbbreviationGroup, name="kdump") +# +# 'kdump' group ('sudo config kdump ...') +# +@click.group(cls=AbbreviationGroup, name="kdump") def kdump(): - """ Configure kdump """ - if os.geteuid() != 0: - exit("Root privileges are required for this operation") - -@kdump.command() -def disable(): - """Disable kdump operation""" - config_db = ConfigDBConnector() - if config_db is not None: - config_db.connect() - config_db.mod_entry("KDUMP", "config", {"enabled": "false"}) - -@kdump.command() -def enable(): - """Enable kdump operation""" - config_db = ConfigDBConnector() - if config_db is not None: - config_db.connect() - config_db.mod_entry("KDUMP", "config", {"enabled": "true"}) - -@kdump.command() + """Configure the KDUMP mechanism""" + pass + + +def check_kdump_table_existence(kdump_table): + """Checks whether the 'KDUMP' table is configured in Config DB. + + Args: + kdump_table: A dictionary represents the key-value pair in sub-table + of 'KDUMP'. + + Returns: + None. + """ + if not kdump_table: + click.echo("Unable to retrieve 'KDUMP' table from Config DB.") + sys.exit(1) + + if "config" not in kdump_table: + click.echo("Unable to retrieve key 'config' from KDUMP table.") + sys.exit(2) + + +# +# 'disable' command ('sudo config kdump disable') +# +@kdump.command(name="disable", short_help="Disable the KDUMP mechanism") +@pass_db +def kdump_disable(db): + """Disable the KDUMP mechanism""" + kdump_table = db.cfgdb.get_table("KDUMP") + check_kdump_table_existence(kdump_table) + + db.cfgdb.mod_entry("KDUMP", "config", {"enabled": "false"}) + + +# +# 'enable' command ('sudo config kdump enable') +# +@kdump.command(name="enable", short_help="Enable the KDUMP mechanism") +@pass_db +def kdump_enable(db): + """Enable the KDUMP mechanism""" + kdump_table = db.cfgdb.get_table("KDUMP") + check_kdump_table_existence(kdump_table) + + db.cfgdb.mod_entry("KDUMP", "config", {"enabled": "true"}) + + +# +# 'memory' command ('sudo config kdump memory ...') +# +@kdump.command(name="memory", short_help="Configure the memory for KDUMP mechanism") @click.argument('kdump_memory', metavar='', required=True) -def memory(kdump_memory): - """Set memory allocated for kdump capture kernel""" - config_db = ConfigDBConnector() - if config_db is not None: - config_db.connect() - config_db.mod_entry("KDUMP", "config", {"memory": kdump_memory}) - -@kdump.command('num-dumps') +@pass_db +def kdump_memory(db, kdump_memory): + """Reserve memory for kdump capture kernel""" + kdump_table = db.cfgdb.get_table("KDUMP") + check_kdump_table_existence(kdump_table) + + db.cfgdb.mod_entry("KDUMP", "config", {"memory": kdump_memory}) + + +# +# 'num_dumps' command ('sudo config keump num_dumps ...') +# +@kdump.command(name="num_dumps", short_help="Configure the maximum dump files of KDUMP mechanism") @click.argument('kdump_num_dumps', metavar='', required=True, type=int) -def num_dumps(kdump_num_dumps): - """Set max number of dump files for kdump""" - config_db = ConfigDBConnector() - if config_db is not None: - config_db.connect() - config_db.mod_entry("KDUMP", "config", {"num_dumps": kdump_num_dumps}) +@pass_db +def kdump_num_dumps(db, kdump_num_dumps): + """Set maximum number of dump files for kdump""" + kdump_table = db.cfgdb.get_table("KDUMP") + check_kdump_table_existence(kdump_table) + + db.cfgdb.mod_entry("KDUMP", "config", {"num_dumps": kdump_num_dumps}) diff --git a/tests/kdump_test.py b/tests/kdump_test.py new file mode 100644 index 000000000000..18f14181b324 --- /dev/null +++ b/tests/kdump_test.py @@ -0,0 +1,74 @@ +import importlib + +from click.testing import CliRunner +from utilities_common.db import Db + + +class TestKdump(object): + @classmethod + def setup_class(cls): + print("SETUP") + + def test_config_kdump_disable(self, get_cmd_module): + (config, show) = get_cmd_module + db = Db() + runner = CliRunner() + result = runner.invoke(config.config.commands["kdump"].commands["disable"], obj=db) + print(result.exit_code) + assert result.exit_code == 0 + + # Delete the 'KDUMP' table. + db.cfgdb.delete_table("KDUMP") + + result = runner.invoke(config.config.commands["kdump"].commands["disable"], obj=db) + print(result.exit_code) + assert result.exit_code == 1 + + def test_config_kdump_enable(self, get_cmd_module): + (config, show) = get_cmd_module + db = Db() + runner = CliRunner() + result = runner.invoke(config.config.commands["kdump"].commands["enable"], obj=db) + print(result.exit_code) + assert result.exit_code == 0 + + # Delete the 'KDUMP' table. + db.cfgdb.delete_table("KDUMP") + + result = runner.invoke(config.config.commands["kdump"].commands["enable"], obj=db) + print(result.exit_code) + assert result.exit_code == 1 + + def test_config_kdump_memory(self, get_cmd_module): + (config, show) = get_cmd_module + db = Db() + runner = CliRunner() + result = runner.invoke(config.config.commands["kdump"].commands["memory"], ["256MB"], obj=db) + print(result.exit_code) + assert result.exit_code == 0 + + # Delete the 'KDUMP' table. + db.cfgdb.delete_table("KDUMP") + + result = runner.invoke(config.config.commands["kdump"].commands["memory"], ["256MB"], obj=db) + print(result.exit_code) + assert result.exit_code == 1 + + def test_config_kdump_num_dumps(self, get_cmd_module): + (config, show) = get_cmd_module + db = Db() + runner = CliRunner() + result = runner.invoke(config.config.commands["kdump"].commands["num_dumps"], ["10"], obj=db) + print(result.exit_code) + assert result.exit_code == 0 + + # Delete the 'KDUMP' table. + db.cfgdb.delete_table("KDUMP") + + result = runner.invoke(config.config.commands["kdump"].commands["num_dumps"], ["10"], obj=db) + print(result.exit_code) + assert result.exit_code == 1 + + @classmethod + def teardown_class(cls): + print("TEARDOWN") diff --git a/tests/mock_tables/config_db.json b/tests/mock_tables/config_db.json index 4fe3ecc36b05..dc279092c8da 100644 --- a/tests/mock_tables/config_db.json +++ b/tests/mock_tables/config_db.json @@ -684,6 +684,11 @@ "DEBUG_COUNTER_DROP_REASON|DEBUG_2|IP_HEADER_ERROR": {}, "DEBUG_COUNTER_DROP_REASON|DEBUG_2|NO_L3_HEADER": {}, "DEBUG_COUNTER_DROP_REASON|lowercase_counter|L2_ANY": {}, + "KDUMP|config": { + "enabled": "false", + "memory": "256MB", + "num_dumps": "3" + }, "FEATURE|bgp": { "state": "enabled", "auto_restart": "enabled",