From 90736b35179ceee6ef5457af6021f385f02b4300 Mon Sep 17 00:00:00 2001 From: Pavlo Shchelokovskyy Date: Tue, 18 Mar 2025 09:03:50 +0000 Subject: [PATCH] Update provider name when migrating to OVN otherwise, any router created before migration becomes unmanageable, as the only service provider ML2/OVN supports is 'ovn'. Closes-Bug: #2103697 Change-Id: I104c188c2f86f4a2929ea00a8f28cf616c1bb64b --- neutron/plugins/ml2/drivers/ovn/db_migration.py | 15 +++++++++++++++ .../plugins/ml2/drivers/ovn/test_db_migration.py | 16 ++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/neutron/plugins/ml2/drivers/ovn/db_migration.py b/neutron/plugins/ml2/drivers/ovn/db_migration.py index b0977acd55f..c6af3fc3554 100644 --- a/neutron/plugins/ml2/drivers/ovn/db_migration.py +++ b/neutron/plugins/ml2/drivers/ovn/db_migration.py @@ -25,6 +25,7 @@ from sqlalchemy.orm import exc as sqla_exc from neutron.common import _constants as n_const from neutron.db.models.plugins.ml2 import geneveallocation from neutron.db.models.plugins.ml2 import vxlanallocation +from neutron.db.models import servicetype from neutron.objects import network as network_obj from neutron.objects import ports as port_obj from neutron.objects import trunk as trunk_obj @@ -40,6 +41,7 @@ def migrate_neutron_database_to_ovn(): - Removes bridge name from port binding vif details to support operations on instances with a trunk bridge. - Updates the port profile for trunk ports. + - Updates provider name in ProviderResourceAssociation """ ctx = n_context.get_admin_context() with db_api.CONTEXT_WRITER.using(ctx) as session: @@ -133,3 +135,16 @@ def migrate_neutron_database_to_ovn(): pb.update() trunk_updated.update(diff) + + # update ``ProviderResourceAssociation`` objects + # NOTE(pas-ha): OVS has four L3 service providers, while OVN has only one + # (compare neutron/services/ovn_l3/service_providers/driver_controller.py + # and neutron/services/l3_router/service_providers/driver_controller.py), + # so we can blindly replace all OVS provider associations with "ovn" ones + pra_model = servicetype.ProviderResourceAssociation + ovs_providers = ("single_node", "ha", "dvr", "dvrha") + ovn_provider = "ovn" + with db_api.CONTEXT_WRITER.using(ctx) as session: + session.query(pra_model).filter( + pra_model.provider_name.in_(ovs_providers) + ).update({"provider_name": ovn_provider}) diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/test_db_migration.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/test_db_migration.py index 423e9337b6a..966b771eda3 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/ovn/test_db_migration.py +++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/test_db_migration.py @@ -13,6 +13,7 @@ # under the License. import copy from unittest import mock +import uuid from neutron_lib.api.definitions import portbindings as pb from neutron_lib.api.definitions import provider_net as pnet @@ -25,6 +26,7 @@ from neutron.common import _constants as n_const from neutron.db.models.plugins.ml2 import geneveallocation from neutron.db.models.plugins.ml2 import vxlanallocation from neutron.objects import ports as port_obj +from neutron.objects import servicetype as servicetype_obj from neutron.objects import trunk as trunk_obj from neutron.plugins.ml2.drivers.ovn import db_migration from neutron.tests.unit.plugins.ml2.drivers.ovn.mech_driver import ( @@ -97,6 +99,15 @@ class TestMigrateNeutronDatabaseToOvn( self.subport_profiles[subport2['id']]["foo"] = "bar" + providers = ("fake", "ovn", "single_node", "ha", "dvr", "dvrha") + with db_api.CONTEXT_WRITER.using(ctx): + for name in providers: + servicetype_obj.ProviderResourceAssociation( + context=ctx, + provider_name=name, + resource_id=uuid.uuid4(), + ).create() + def _validate_resources_after_migration(self, expected_vif_details): ctx = n_context.get_admin_context() @@ -133,6 +144,11 @@ class TestMigrateNeutronDatabaseToOvn( self.subport_profiles[subport.port_id], port["binding:profile"]) + pra = servicetype_obj.ProviderResourceAssociation.get_objects(ctx) + self.assertEqual(6, len(pra)) + self.assertEqual(5, len([p for p in pra if p.provider_name == "ovn"])) + self.assertEqual(1, len([p for p in pra if p.provider_name == "fake"])) + def test_db_migration(self): """Test the DB migration