diff --git a/neutron/services/l3_router/service_providers/base.py b/neutron/services/l3_router/service_providers/base.py index 47bccd9beb1..8d04cfc7c86 100644 --- a/neutron/services/l3_router/service_providers/base.py +++ b/neutron/services/l3_router/service_providers/base.py @@ -58,3 +58,10 @@ class L3ServiceProvider(object): def __init__(self, l3plugin): self.l3plugin = l3plugin + + def owns_router(self, context, router_id): + """Returns True if router is associated with driver, else False.""" + if not router_id: + return False + return self.l3plugin.l3_driver_controller.get_provider_for_router( + context, router_id) == self diff --git a/neutron/services/l3_router/service_providers/driver_controller.py b/neutron/services/l3_router/service_providers/driver_controller.py index df35231d4b7..98f509a5b69 100644 --- a/neutron/services/l3_router/service_providers/driver_controller.py +++ b/neutron/services/l3_router/service_providers/driver_controller.py @@ -103,7 +103,7 @@ class DriverController(object): 'ha' and/or 'distributed' attributes. If we allow updates of flavor_id directly in the future those requests will also land here. """ - drv = self._get_provider_for_router(context, router_id) + drv = self.get_provider_for_router(context, router_id) new_drv = None if _flavor_specified(router): if router['flavor_id'] != old_router['flavor_id']: @@ -145,7 +145,7 @@ class DriverController(object): self._stm.add_resource_association( context, lib_const.L3, new_drv.name, router_id) - def _get_provider_for_router(self, context, router_id): + def get_provider_for_router(self, context, router_id): """Return the provider driver handle for a router id.""" driver_name = self._stm.get_provider_names_by_resource_ids( context, [router_id]).get(router_id) @@ -194,7 +194,7 @@ class DriverController(object): def uses_scheduler(self, context, router_id): """Returns True if the integrated L3 scheduler should be used.""" - return (self._get_provider_for_router(context, router_id). + return (self.get_provider_for_router(context, router_id). use_integrated_agent_scheduler) diff --git a/neutron/tests/unit/services/l3_router/service_providers/test_driver_controller.py b/neutron/tests/unit/services/l3_router/service_providers/test_driver_controller.py index 74a25944edb..99a88784315 100644 --- a/neutron/tests/unit/services/l3_router/service_providers/test_driver_controller.py +++ b/neutron/tests/unit/services/l3_router/service_providers/test_driver_controller.py @@ -37,6 +37,7 @@ class TestDriverController(testlib_api.SqlTestCase): self.setup_coreplugin(DB_PLUGIN_KLASS) self.fake_l3 = mock.Mock() self.dc = driver_controller.DriverController(self.fake_l3) + self.fake_l3.l3_driver_controller = self.dc self.ctx = context.get_admin_context() def _return_provider_for_flavor(self, provider): @@ -58,6 +59,20 @@ class TestDriverController(testlib_api.SqlTestCase): self.dc.drivers['dvrha'].use_integrated_agent_scheduler = False self.assertFalse(self.dc.uses_scheduler(self.ctx, router_id)) + def test_driver_owns_router(self): + self._return_provider_for_flavor('dvrha') + router_db = mock.Mock() + flavor_id = uuidutils.generate_uuid() + r1 = uuidutils.generate_uuid() + r2 = uuidutils.generate_uuid() + router = dict(id=r1, flavor_id=flavor_id) + self.dc._set_router_provider('router', 'PRECOMMIT_CREATE', self, + self.ctx, router, router_db) + self.assertTrue(self.dc.drivers['dvrha'].owns_router(self.ctx, r1)) + self.assertFalse(self.dc.drivers['dvr'].owns_router(self.ctx, r1)) + self.assertFalse(self.dc.drivers['dvr'].owns_router(self.ctx, r2)) + self.assertFalse(self.dc.drivers['dvr'].owns_router(self.ctx, None)) + def test__set_router_provider_flavor_specified(self): self._return_provider_for_flavor('dvrha') router_db = mock.Mock() @@ -68,12 +83,12 @@ class TestDriverController(testlib_api.SqlTestCase): self.ctx, router, router_db) self.assertEqual(flavor_id, router_db.flavor_id) self.assertEqual(self.dc.drivers['dvrha'], - self.dc._get_provider_for_router(self.ctx, - router_id)) + self.dc.get_provider_for_router(self.ctx, + router_id)) def test__update_router_provider_invalid(self): test_dc = driver_controller.DriverController(self.fake_l3) - with mock.patch.object(test_dc, "_get_provider_for_router"): + with mock.patch.object(test_dc, "get_provider_for_router"): with mock.patch.object( driver_controller, "_ensure_driver_supports_request") as _ensure: @@ -119,8 +134,8 @@ class TestDriverController(testlib_api.SqlTestCase): self.dc._set_router_provider('router', 'PRECOMMIT_CREATE', self, self.ctx, body, mock.Mock()) self.assertEqual(self.dc.drivers[driver], - self.dc._get_provider_for_router(self.ctx, - body['id']), + self.dc.get_provider_for_router(self.ctx, + body['id']), 'Expecting %s for body %s' % (driver, body)) def test__clear_router_provider(self): @@ -130,14 +145,14 @@ class TestDriverController(testlib_api.SqlTestCase): self.dc._set_router_provider('router', 'PRECOMMIT_CREATE', self, self.ctx, body, mock.Mock()) self.assertEqual(self.dc.drivers['dvrha'], - self.dc._get_provider_for_router(self.ctx, - body['id'])) + self.dc.get_provider_for_router(self.ctx, + body['id'])) self.dc._clear_router_provider('router', 'PRECOMMIT_DELETE', self, self.ctx, body['id']) with testtools.ExpectedException(ValueError): # if association was cleared, get_router will be called self.fake_l3.get_router.side_effect = ValueError - self.dc._get_provider_for_router(self.ctx, body['id']) + self.dc.get_provider_for_router(self.ctx, body['id']) def test__flavor_plugin(self): directory.add_plugin(p_cons.FLAVORS, mock.Mock())