]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
BigSwitch: Create router ports synchronously
authorKevin Benton <blak111@gmail.com>
Tue, 8 Apr 2014 16:04:08 +0000 (09:04 -0700)
committerKevin Benton <blak111@gmail.com>
Tue, 8 Apr 2014 16:36:20 +0000 (09:36 -0700)
Since router ports are created as part of a
long transaction with multiple REST calls, they
need to be created sychronously. This is to prevent
the async thread from deleting them from the backend
if it can't find them in cases where they haven't been
committed to the DB yet.

Closes-Bug: #1305331
Change-Id: I2ab3c862dc6b1760199654bbd0969ac5efdbe704

neutron/plugins/bigswitch/plugin.py
neutron/tests/unit/bigswitch/test_restproxy_plugin.py

index cf9dbe62d14d97b6d46feb583730382f3cca8c83..92db9a95e88bbbaa001de9ceab9373571609e9e9 100644 (file)
@@ -664,8 +664,12 @@ class NeutronRestProxyV2(NeutronRestProxyV2Base,
         with context.session.begin(subtransactions=True):
             self._ensure_default_security_group_on_port(context, port)
             sgids = self._get_security_groups_on_port(context, port)
-            # set port status to pending. updated after rest call completes
-            port['port']['status'] = const.PORT_STATUS_BUILD
+            # non-router port status is set to pending. it is then updated
+            # after the async rest call completes. router ports are synchronous
+            if port['port']['device_owner'] == l3_db.DEVICE_OWNER_ROUTER_INTF:
+                port['port']['status'] = const.PORT_STATUS_ACTIVE
+            else:
+                port['port']['status'] = const.PORT_STATUS_BUILD
             dhcp_opts = port['port'].get(edo_ext.EXTRADHCPOPTS, [])
             new_port = super(NeutronRestProxyV2, self).create_port(context,
                                                                    port)
@@ -691,8 +695,15 @@ class NeutronRestProxyV2(NeutronRestProxyV2Base,
 
         # create on network ctrl
         mapped_port = self._map_state_and_status(new_port)
-        self.evpool.spawn_n(self.async_port_create, net["tenant_id"],
-                            new_port["network_id"], mapped_port)
+        # ports have to be created synchronously when creating a router
+        # port since adding router interfaces is a multi-call process
+        if mapped_port['device_owner'] == l3_db.DEVICE_OWNER_ROUTER_INTF:
+            self.servers.rest_create_port(net["tenant_id"],
+                                          new_port["network_id"],
+                                          mapped_port)
+        else:
+            self.evpool.spawn_n(self.async_port_create, net["tenant_id"],
+                                new_port["network_id"], mapped_port)
         self.notify_security_groups_member_updated(context, new_port)
         return new_port
 
index 9e0f0bee3f060f3a09e8d88be699e0856dc54d78..012dae9a20cb1250e92c4441c6b1842d2fd7d30a 100644 (file)
@@ -20,6 +20,7 @@ import mock
 from oslo.config import cfg
 import webob.exc
 
+from neutron.common import constants
 from neutron import context
 from neutron.extensions import portbindings
 from neutron.manager import NeutronManager
@@ -81,7 +82,21 @@ class TestBigSwitchProxyPortsV2(test_plugin.TestPortsV2,
         super(TestBigSwitchProxyPortsV2,
               self).setUp(self._plugin_name)
 
+    def test_router_port_status_active(self):
+        # router ports screw up port auto-deletion so it has to be
+        # disabled for this test
+        with self.network(do_delete=False) as net:
+            with self.subnet(network=net, do_delete=False) as sub:
+                with self.port(
+                    subnet=sub,
+                    no_delete=True,
+                    device_owner=constants.DEVICE_OWNER_ROUTER_INTF
+                ) as port:
+                    # router ports should be immediately active
+                    self.assertEqual(port['port']['status'], 'ACTIVE')
+
     def test_update_port_status_build(self):
+        # normal ports go into the pending build state for async creation
         with self.port() as port:
             self.assertEqual(port['port']['status'], 'BUILD')
             self.assertEqual(self.port_create_status, 'BUILD')