]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Implement migration of legacy routers to distributed
authorSwaminathan Vasudevan <swaminathan.vasudevan@hp.com>
Tue, 5 Aug 2014 23:16:23 +0000 (16:16 -0700)
committerMichael Smith <michael.smith6@hp.com>
Fri, 21 Nov 2014 02:50:53 +0000 (18:50 -0800)
This patch addresses the necessary changes required
for the router migration or conversion from legacy
to distributed.

The _update_router_db() method was modified to add
logic to support the SNAT functionality of DVR by
calling create_snat_intf_ports_if_not_exists().  A
call to _unbind_router() was also called to force
the scheduling of the router with 'distributed'
enabled.

Right now we will be supporting migration from legacy
to distributed only.

Closes-bug: #1348309
Partially-implements: blueprint neutron-ovs-dvr
Co-Authored-By: Michael Smith <michael.smith6@hp.com>
Change-Id: I6f252271bb5b52ce57184ad7b0bf1ce280b965fb

neutron/db/l3_dvr_db.py
neutron/tests/unit/db/test_l3_dvr_db.py

index a68d8ca468f29a6d3e1e62f914fa2560d86628f3..c4c023729aa75567e162affd9ea00275902889ea 100644 (file)
@@ -77,11 +77,12 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
             LOG.info(_LI("Centralizing distributed router %s "
                          "is not supported"), router_db['id'])
             raise NotImplementedError()
+        # TODO(Swami): Add a check for Services FWaaS and VPNaaS
 
     def _update_distributed_attr(
         self, context, router_id, router_db, data, gw_info):
         """Update the model to support the dvr case of a router."""
-        if not attributes.is_attr_set(gw_info) and data.get('distributed'):
+        if data.get('distributed'):
             old_owner = l3_const.DEVICE_OWNER_ROUTER_INTF
             new_owner = DEVICE_OWNER_DVR_INTERFACE
             for rp in router_db.attached_ports.filter_by(port_type=old_owner):
@@ -93,15 +94,28 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
             router_db = super(
                 L3_NAT_with_dvr_db_mixin, self)._update_router_db(
                     context, router_id, data, gw_info)
+            migrating_to_distributed = (
+                not router_db.extra_attributes.distributed and
+                data.get('distributed') is True)
             self._validate_router_migration(router_db, data)
-            # FIXME(swami): need to add migration status so that the scheduler
-            # can pick the migration request and move stuff over. For now
-            # only the distributed flag and router interface's owner change.
-            # Instead of complaining on _validate_router_migration, let's
-            # succeed here and complete the task in a follow-up patch
             router_db.extra_attributes.update(data)
             self._update_distributed_attr(
                 context, router_id, router_db, data, gw_info)
+            if migrating_to_distributed:
+                if router_db['gw_port_id']:
+                    # If the Legacy router is getting migrated to a DVR
+                    # router, make sure to create corresponding
+                    # snat interface ports that are to be consumed by
+                    # the Service Node.
+                    if not self.create_snat_intf_ports_if_not_exists(
+                        context.elevated(), router_db):
+                        LOG.debug("SNAT interface ports not created: %s",
+                                  router_db['id'])
+                cur_agents = self.list_l3_agents_hosting_router(
+                    context, router_db['id'])['agents']
+                for agent in cur_agents:
+                    self._unbind_router(context, router_db['id'],
+                                        agent['id'])
             return router_db
 
     def _delete_current_gw_port(self, context, router_id, router, new_network):
@@ -116,6 +130,8 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
         super(L3_NAT_with_dvr_db_mixin,
               self)._create_gw_port(context, router_id,
                                     router, new_network)
+        # Make sure that the gateway port exists before creating the
+        # snat interface ports for distributed router.
         if router.extra_attributes.distributed and router.gw_port:
             snat_p_list = self.create_snat_intf_ports_if_not_exists(
                 context.elevated(), router)
index b9b8b3bba4e534e7dd1d42f186954b4ec837cf31..2fd04ac28d2ef71f650a4bc1c0fabac91c49cca8 100644 (file)
@@ -76,18 +76,23 @@ class L3DvrTestCase(testlib_api.SqlTestCase):
 
     def test_update_router_db_centralized_to_distributed(self):
         router = {'name': 'foo_router', 'admin_state_up': True}
+        agent = {'id': _uuid()}
         distributed = {'distributed': True}
         router_db = self._create_router(router)
         router_id = router_db['id']
         self.assertFalse(router_db.extra_attributes.distributed)
-        with mock.patch.object(self.mixin, '_update_distributed_attr') as f:
-            with mock.patch.object(self.mixin, '_get_router') as g:
-                g.return_value = router_db
-                router_db = self.mixin._update_router_db(
-                    self.ctx, router_id, distributed, mock.ANY)
-                # Assert that the DB value has changed
-                self.assertTrue(router_db.extra_attributes.distributed)
-                self.assertEqual(1, f.call_count)
+        self.mixin._get_router = mock.Mock(return_value=router_db)
+        self.mixin._validate_router_migration = mock.Mock()
+        self.mixin._update_distributed_attr = mock.Mock()
+        self.mixin.list_l3_agents_hosting_router = mock.Mock(
+            return_value={'agents': [agent]})
+        self.mixin._unbind_router = mock.Mock()
+        router_db = self.mixin._update_router_db(
+            self.ctx, router_id, distributed, mock.ANY)
+        # Assert that the DB value has changed
+        self.assertTrue(router_db.extra_attributes.distributed)
+        self.assertEqual(1,
+                         self.mixin._update_distributed_attr.call_count)
 
     def _test_get_device_owner(self, is_distributed=False,
                                expected=l3_const.DEVICE_OWNER_ROUTER_INTF,