diff --git a/scripts/db_migrator.py b/scripts/db_migrator.py index 4475457dcc20..41ef8ee516df 100755 --- a/scripts/db_migrator.py +++ b/scripts/db_migrator.py @@ -174,6 +174,21 @@ def migrate_copp_table(self): for copp_key in keys: self.appDB.delete(self.appDB.APPL_DB, copp_key) + def migrate_feature_table(self): + ''' + Combine CONTAINER_FEATURE and FEATURE tables into FEATURE table. + ''' + feature_table = self.configDB.get_table('FEATURE') + for feature, config in feature_table.items(): + state = config.pop('status', 'disabled') + config['state'] = state + self.configDB.set_entry('FEATURE', feature, config) + + container_feature_table = self.configDB.get_table('CONTAINER_FEATURE') + for feature, config in container_feature_table.items(): + self.configDB.mod_entry('FEATURE', feature, config) + self.configDB.set_entry('CONTAINER_FEATURE', feature, None) + def migrate_config_db_buffer_tables_for_dynamic_calculation(self, speed_list, cable_len_list, default_dynamic_th, abandon_method, append_item_method): ''' Migrate buffer tables to dynamic calculation mode @@ -419,6 +434,8 @@ def version_1_0_3(self): """ log.log_info('Handling version_1_0_3') + self.migrate_feature_table() + # Check ASIC type, if Mellanox platform then need DB migration if self.asic_type == "mellanox": if self.mellanox_buffer_migrator.mlnx_migrate_buffer_pool_size('version_1_0_3', 'version_1_0_4') \ @@ -520,7 +537,6 @@ def get_version(self): return 'version_unknown' - def set_version(self, version=None): if not version: version = self.CURRENT_VERSION @@ -528,7 +544,6 @@ def set_version(self, version=None): entry = { self.TABLE_FIELD : version } self.configDB.set_entry(self.TABLE_NAME, self.TABLE_KEY, entry) - def common_migration_ops(self): try: with open(INIT_CFG_FILE) as f: @@ -537,14 +552,16 @@ def common_migration_ops(self): raise Exception(str(e)) for init_cfg_table, table_val in init_db.items(): - data = self.configDB.get_table(init_cfg_table) - if data: - # Ignore overriding the values that pre-exist in configDB - continue log.log_info("Migrating table {} from INIT_CFG to config_db".format(init_cfg_table)) - # Update all tables that do not exist in configDB but are present in INIT_CFG - for init_table_key, init_table_val in table_val.items(): - self.configDB.set_entry(init_cfg_table, init_table_key, init_table_val) + for key in table_val: + curr_cfg = self.configDB.get_entry(init_cfg_table, key) + init_cfg = table_val[key] + + # Override init config with current config. + # This will leave new fields from init_config + # in new_config, but not override existing configuration. + new_cfg = {**init_cfg, **curr_cfg} + self.configDB.set_entry(init_cfg_table, key, new_cfg) self.migrate_copp_table() diff --git a/tests/db_migrator_input/config_db/feature-expected.json b/tests/db_migrator_input/config_db/feature-expected.json new file mode 100644 index 000000000000..301cb915c2ad --- /dev/null +++ b/tests/db_migrator_input/config_db/feature-expected.json @@ -0,0 +1,18 @@ +{ + "FEATURE|swss": { + "auto_restart": "disabled", + "has_global_scope": "False", + "has_per_asic_scope": "True", + "has_timer": "False", + "high_mem_alert": "disabled", + "state": "enabled" + }, + "FEATURE|telemetry": { + "auto_restart": "enabled", + "has_global_scope": "False", + "has_per_asic_scope": "True", + "has_timer": "False", + "high_mem_alert": "disabled", + "state": "enabled" + } +} diff --git a/tests/db_migrator_input/config_db/feature-input.json b/tests/db_migrator_input/config_db/feature-input.json new file mode 100644 index 000000000000..31bb7895e828 --- /dev/null +++ b/tests/db_migrator_input/config_db/feature-input.json @@ -0,0 +1,13 @@ +{ + "CONTAINER_FEATURE|swss": { + "auto_restart": "disabled", + "high_mem_alert": "disabled" + }, + "CONTAINER_FEATURE|telemetry": { + "auto_restart": "enabled", + "high_mem_alert": "disabled" + }, + "FEATURE|telemetry": { + "status": "enabled" + } +} diff --git a/tests/db_migrator_input/init_cfg.json b/tests/db_migrator_input/init_cfg.json index 2c63c0851048..0b8f5a213ce1 100644 --- a/tests/db_migrator_input/init_cfg.json +++ b/tests/db_migrator_input/init_cfg.json @@ -1,2 +1,20 @@ { + "FEATURE": { + "swss": { + "auto_restart": "enabled", + "has_global_scope": "False", + "has_per_asic_scope": "True", + "has_timer": "False", + "high_mem_alert": "disabled", + "state": "enabled" + }, + "telemetry": { + "auto_restart": "disabled", + "has_global_scope": "False", + "has_per_asic_scope": "True", + "has_timer": "False", + "high_mem_alert": "disabled", + "state": "disabled" + } + } } diff --git a/tests/db_migrator_test.py b/tests/db_migrator_test.py index 61ffa674a4ea..b5f12e4f5e0a 100644 --- a/tests/db_migrator_test.py +++ b/tests/db_migrator_test.py @@ -2,6 +2,8 @@ import pytest import sys +from deepdiff import DeepDiff + from swsssdk import SonicV2Connector from sonic_py_common import device_info @@ -218,3 +220,30 @@ def test_port_autoneg_migrator(self): assert dbmgtr.configDB.get_table('PORT') == expected_db.cfgdb.get_table('PORT') assert dbmgtr.configDB.get_table('VERSIONS') == expected_db.cfgdb.get_table('VERSIONS') + + +class TestInitConfigMigrator(object): + @classmethod + def setup_class(cls): + os.environ['UTILITIES_UNIT_TESTING'] = "2" + + @classmethod + def teardown_class(cls): + os.environ['UTILITIES_UNIT_TESTING'] = "0" + dbconnector.dedicated_dbs['CONFIG_DB'] = None + + def test_init_config_feature_migration(self): + dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'config_db', 'feature-input') + import db_migrator + dbmgtr = db_migrator.DBMigrator(None) + dbmgtr.migrate() + dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'config_db', 'feature-expected') + expected_db = Db() + + resulting_table = dbmgtr.configDB.get_table('FEATURE') + expected_table = expected_db.cfgdb.get_table('FEATURE') + + diff = DeepDiff(resulting_table, expected_table, ignore_order=True) + assert not diff + + assert not expected_db.cfgdb.get_table('CONTAINER_FEATURE')