From 4a065b485fa57f591bdab07760656db28cee2bc0 Mon Sep 17 00:00:00 2001 From: Vaibhav Hemant Dixit Date: Thu, 23 Feb 2023 01:14:29 +0000 Subject: [PATCH 1/5] [db_migrator] Add missing attribute 'weight' to route entries in APPL DB --- scripts/db_migrator.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/db_migrator.py b/scripts/db_migrator.py index c52e38bd63..1b9d6deabe 100755 --- a/scripts/db_migrator.py +++ b/scripts/db_migrator.py @@ -899,6 +899,17 @@ def common_migration_ops(self): else: log.log_notice("Asic Type: {}, Hwsku: {}".format(self.asic_type, self.hwsku)) + route_table = self.appDB.get_table("ROUTE_TABLE") + for route_prefix, route_attr in route_table.items(): + if 'weight' not in route_attr: + if type(route_prefix) == tuple: + # IPv6 route_prefix is returned from db as tuple + route_key = "ROUTE_TABLE:" + ":".join(route_prefix) + else: + # IPv4 route_prefix is returned from db as str + route_key = "ROUTE_TABLE:{}".format(route_prefix) + self.appDB.set(self.appDB.APPL_DB, route_key, 'weight','') + def migrate(self): version = self.get_version() log.log_info('Upgrading from version ' + version) From e82509738bb100b7860317881376a18e3ac5cff5 Mon Sep 17 00:00:00 2001 From: Vaibhav Hemant Dixit Date: Mon, 27 Feb 2023 21:28:44 +0000 Subject: [PATCH 2/5] Add unit test to cover migration of routes w/o weight attribute --- .../appl_db/routes_migrate_expected.json | 12 +++++++ .../appl_db/routes_migrate_input.json | 10 ++++++ .../config_db/routes_migrate_input.json | 7 ++++ tests/db_migrator_test.py | 35 +++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 tests/db_migrator_input/appl_db/routes_migrate_expected.json create mode 100644 tests/db_migrator_input/appl_db/routes_migrate_input.json create mode 100644 tests/db_migrator_input/config_db/routes_migrate_input.json diff --git a/tests/db_migrator_input/appl_db/routes_migrate_expected.json b/tests/db_migrator_input/appl_db/routes_migrate_expected.json new file mode 100644 index 0000000000..5cad371c31 --- /dev/null +++ b/tests/db_migrator_input/appl_db/routes_migrate_expected.json @@ -0,0 +1,12 @@ +{ + "ROUTE_TABLE:192.168.104.0/25": { + "nexthop": "10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63", + "ifname" : "PortChannel101,PortChannel102,PortChannel103,PortChannel104", + "weight": "" + }, + "ROUTE_TABLE:20c0:fe28:0:80::/64": { + "nexthop": "fc00::72,fc00::76,fc00::7a,fc00::7e", + "ifname" : "PortChannel101,PortChannel102,PortChannel103,PortChannel104", + "weight": "" + } +} diff --git a/tests/db_migrator_input/appl_db/routes_migrate_input.json b/tests/db_migrator_input/appl_db/routes_migrate_input.json new file mode 100644 index 0000000000..7249488cd6 --- /dev/null +++ b/tests/db_migrator_input/appl_db/routes_migrate_input.json @@ -0,0 +1,10 @@ +{ + "ROUTE_TABLE:192.168.104.0/25": { + "nexthop": "10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63", + "ifname" : "PortChannel101,PortChannel102,PortChannel103,PortChannel104" + }, + "ROUTE_TABLE:20c0:fe28:0:80::/64": { + "nexthop": "fc00::72,fc00::76,fc00::7a,fc00::7e", + "ifname" : "PortChannel101,PortChannel102,PortChannel103,PortChannel104" + } +} diff --git a/tests/db_migrator_input/config_db/routes_migrate_input.json b/tests/db_migrator_input/config_db/routes_migrate_input.json new file mode 100644 index 0000000000..58832dc511 --- /dev/null +++ b/tests/db_migrator_input/config_db/routes_migrate_input.json @@ -0,0 +1,7 @@ +{ + "LOOPBACK_INTERFACE|Loopback0|10.1.0.32/32" : {"NULL": "NULL"}, + "LOOPBACK_INTERFACE|Loopback0|FC00:1::32/128" : {"NULL": "NULL"}, + "LOOPBACK_INTERFACE|Loopback1|10.20.8.199/32" : {"NULL": "NULL"}, + "LOOPBACK_INTERFACE|Loopback1|2001:506:28:500::1/128" : {"NULL": "NULL"}, + "VERSIONS|DATABASE": {"VERSION": "version_1_0_1"} +} diff --git a/tests/db_migrator_test.py b/tests/db_migrator_test.py index 223f5d582e..b5c70fce8e 100644 --- a/tests/db_migrator_test.py +++ b/tests/db_migrator_test.py @@ -518,3 +518,38 @@ def test_migrate_loopback_int(self): expected_keys = expected_appl_db.get_all(expected_appl_db.APPL_DB, key) diff = DeepDiff(resulting_keys, expected_keys, ignore_order=True) assert not diff + +class TestWarmUpgrade_without_route_weights(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 + dbconnector.dedicated_dbs['APPL_DB'] = None + + def test_migrate_weights_for_nexthops(self): + dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'config_db', 'routes_migrate_input') + dbconnector.dedicated_dbs['APPL_DB'] = os.path.join(mock_db_path, 'appl_db', 'routes_migrate_input') + + import db_migrator + dbmgtr = db_migrator.DBMigrator(None) + dbmgtr.migrate() + dbconnector.dedicated_dbs['APPL_DB'] = os.path.join(mock_db_path, 'appl_db', 'routes_migrate_expected') + expected_db = Db() + + # verify migrated appDB + expected_appl_db = SonicV2Connector(host='127.0.0.1') + expected_appl_db.connect(expected_appl_db.APPL_DB) + expected_keys = expected_appl_db.keys(expected_appl_db.APPL_DB, "ROUTE_TABLE:*") + expected_keys.sort() + resulting_keys = dbmgtr.appDB.keys(dbmgtr.appDB.APPL_DB, "ROUTE_TABLE:*") + resulting_keys.sort() + assert expected_keys == resulting_keys + for key in expected_keys: + resulting_keys = dbmgtr.appDB.get_all(dbmgtr.appDB.APPL_DB, key) + expected_keys = expected_appl_db.get_all(expected_appl_db.APPL_DB, key) + diff = DeepDiff(resulting_keys, expected_keys, ignore_order=True) + assert not diff From 138975d237af570176fa64f25fb9583db35c7b3e Mon Sep 17 00:00:00 2001 From: Vaibhav Hemant Dixit Date: Mon, 27 Feb 2023 21:31:02 +0000 Subject: [PATCH 3/5] [UT] Remove unnecessary fields from DB input --- tests/db_migrator_input/config_db/routes_migrate_input.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/db_migrator_input/config_db/routes_migrate_input.json b/tests/db_migrator_input/config_db/routes_migrate_input.json index 58832dc511..672268b286 100644 --- a/tests/db_migrator_input/config_db/routes_migrate_input.json +++ b/tests/db_migrator_input/config_db/routes_migrate_input.json @@ -1,7 +1,3 @@ { - "LOOPBACK_INTERFACE|Loopback0|10.1.0.32/32" : {"NULL": "NULL"}, - "LOOPBACK_INTERFACE|Loopback0|FC00:1::32/128" : {"NULL": "NULL"}, - "LOOPBACK_INTERFACE|Loopback1|10.20.8.199/32" : {"NULL": "NULL"}, - "LOOPBACK_INTERFACE|Loopback1|2001:506:28:500::1/128" : {"NULL": "NULL"}, "VERSIONS|DATABASE": {"VERSION": "version_1_0_1"} } From 0089c2a2a11e3b0340bbf19bd3064016a335f7f5 Mon Sep 17 00:00:00 2001 From: Vaibhav Hemant Dixit Date: Thu, 2 Mar 2023 21:11:29 +0000 Subject: [PATCH 4/5] Move migration logic to dedicated method --- scripts/db_migrator.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/scripts/db_migrator.py b/scripts/db_migrator.py index 1b9d6deabe..a10a6517ad 100755 --- a/scripts/db_migrator.py +++ b/scripts/db_migrator.py @@ -579,6 +579,18 @@ def migrate_port_qos_map_global(self): self.configDB.set_entry('PORT_QOS_MAP', 'global', {"dscp_to_tc_map": dscp_to_tc_map_table_names[0]}) log.log_info("Created entry for global DSCP_TO_TC_MAP {}".format(dscp_to_tc_map_table_names[0])) + def migrate_route_table_weights(self): + route_table = self.appDB.get_table("ROUTE_TABLE") + for route_prefix, route_attr in route_table.items(): + if 'weight' not in route_attr: + if type(route_prefix) == tuple: + # IPv6 route_prefix is returned from db as tuple + route_key = "ROUTE_TABLE:" + ":".join(route_prefix) + else: + # IPv4 route_prefix is returned from db as str + route_key = "ROUTE_TABLE:{}".format(route_prefix) + self.appDB.set(self.appDB.APPL_DB, route_key, 'weight','') + def version_unknown(self): """ version_unknown tracks all SONiC versions that doesn't have a version @@ -899,16 +911,7 @@ def common_migration_ops(self): else: log.log_notice("Asic Type: {}, Hwsku: {}".format(self.asic_type, self.hwsku)) - route_table = self.appDB.get_table("ROUTE_TABLE") - for route_prefix, route_attr in route_table.items(): - if 'weight' not in route_attr: - if type(route_prefix) == tuple: - # IPv6 route_prefix is returned from db as tuple - route_key = "ROUTE_TABLE:" + ":".join(route_prefix) - else: - # IPv4 route_prefix is returned from db as str - route_key = "ROUTE_TABLE:{}".format(route_prefix) - self.appDB.set(self.appDB.APPL_DB, route_key, 'weight','') + self.migrate_route_table_weights() def migrate(self): version = self.get_version() From f0c542251a785189d7eb49ca13f99e5741a4c462 Mon Sep 17 00:00:00 2001 From: Vaibhav Hemant Dixit Date: Thu, 2 Mar 2023 23:35:19 +0000 Subject: [PATCH 5/5] Name change for generic handling of route table migration --- scripts/db_migrator.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/db_migrator.py b/scripts/db_migrator.py index a10a6517ad..5c946bbb9f 100755 --- a/scripts/db_migrator.py +++ b/scripts/db_migrator.py @@ -579,7 +579,12 @@ def migrate_port_qos_map_global(self): self.configDB.set_entry('PORT_QOS_MAP', 'global', {"dscp_to_tc_map": dscp_to_tc_map_table_names[0]}) log.log_info("Created entry for global DSCP_TO_TC_MAP {}".format(dscp_to_tc_map_table_names[0])) - def migrate_route_table_weights(self): + def migrate_route_table(self): + """ + Handle route table migration. Migrations handled: + 1. 'weight' attr in ROUTE object was introduced 202205 onwards. + Upgrade from older branch to 202205 will require this 'weight' attr to be added explicitly + """ route_table = self.appDB.get_table("ROUTE_TABLE") for route_prefix, route_attr in route_table.items(): if 'weight' not in route_attr: @@ -911,7 +916,7 @@ def common_migration_ops(self): else: log.log_notice("Asic Type: {}, Hwsku: {}".format(self.asic_type, self.hwsku)) - self.migrate_route_table_weights() + self.migrate_route_table() def migrate(self): version = self.get_version()