]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
[apic ml2] Bind ports regardless of the owner
authorIvar Lazzaro <ivarlazzaro@gmail.com>
Mon, 15 Dec 2014 00:17:37 +0000 (16:17 -0800)
committerIvar Lazzaro <ivarlazzaro@gmail.com>
Fri, 2 Jan 2015 19:42:19 +0000 (20:42 +0100)
Today, APIC ML2 mechanism driver is only binding compute ports
on the backend. This causes services' ports to be ignored.

Change-Id: Ie653757370d9f76b70f747a799a71c1af2406cf5
Closes-Bug: 1402458

neutron/plugins/ml2/drivers/cisco/apic/mechanism_apic.py
neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_mechanism_driver.py

index c9ef932026b9d3c95fdac14aef7c0685ffdde145..0cfff80f711757a424a975c0f8d5220b8d7bad89 100644 (file)
@@ -14,7 +14,6 @@
 #    under the License.
 
 from apicapi import apic_manager
-from apicapi import exceptions as exc
 from keystoneclient.v2_0 import client as keyclient
 import netaddr
 from oslo.config import cfg
@@ -143,12 +142,10 @@ class APICMechanismDriver(api.MechanismDriver):
         # Get port
         port = context.current
         # Check if a compute port
-        if port.get('device_owner', '').startswith('compute'):
+        if context.host:
             self._perform_path_port_operations(context, port)
-        elif port.get('device_owner') == n_constants.DEVICE_OWNER_ROUTER_GW:
+        if port.get('device_owner') == n_constants.DEVICE_OWNER_ROUTER_GW:
             self._perform_gw_port_operations(context, port)
-        elif port.get('device_owner') == n_constants.DEVICE_OWNER_DHCP:
-            self._perform_path_port_operations(context, port)
 
     def _delete_contract(self, context):
         port = context.current
@@ -180,32 +177,25 @@ class APICMechanismDriver(api.MechanismDriver):
             self._delete_port_path(context, atenant_id, anetwork_id)
 
     def _get_subnet_info(self, context, subnet):
-        tenant_id = subnet['tenant_id']
-        network_id = subnet['network_id']
-        network = context._plugin.get_network(context._plugin_context,
-                                              network_id)
-        if not network.get('router:external'):
-            cidr = netaddr.IPNetwork(subnet['cidr'])
-            gateway_ip = '%s/%s' % (subnet['gateway_ip'], str(cidr.prefixlen))
-
-            # Convert to APIC IDs
-            tenant_id = self.name_mapper.tenant(context, tenant_id)
-            network_id = self.name_mapper.network(context, network_id)
-            return tenant_id, network_id, gateway_ip
+        if subnet['gateway_ip']:
+            tenant_id = subnet['tenant_id']
+            network_id = subnet['network_id']
+            network = context._plugin.get_network(context._plugin_context,
+                                                  network_id)
+            if not network.get('router:external'):
+                cidr = netaddr.IPNetwork(subnet['cidr'])
+                gateway_ip = '%s/%s' % (subnet['gateway_ip'],
+                                        str(cidr.prefixlen))
+
+                # Convert to APIC IDs
+                tenant_id = self.name_mapper.tenant(context, tenant_id)
+                network_id = self.name_mapper.network(context, network_id)
+                return tenant_id, network_id, gateway_ip
 
     @sync_init
     def create_port_postcommit(self, context):
         self._perform_port_operations(context)
 
-    def update_port_precommit(self, context):
-        orig = context.original
-        curr = context.current
-        if (orig['device_owner'] != curr['device_owner']
-                or orig['device_id'] != curr['device_id']):
-            raise exc.ApicOperationNotSupported(
-                resource='Port', msg='Port device owner and id cannot be '
-                                     'changed.')
-
     @sync_init
     def update_port_postcommit(self, context):
         self._perform_port_operations(context)
@@ -213,12 +203,10 @@ class APICMechanismDriver(api.MechanismDriver):
     def delete_port_postcommit(self, context):
         port = context.current
         # Check if a compute port
-        if port.get('device_owner', '').startswith('compute'):
+        if context.host:
             self._delete_path_if_last(context)
-        elif port.get('device_owner') == n_constants.DEVICE_OWNER_ROUTER_GW:
+        if port.get('device_owner') == n_constants.DEVICE_OWNER_ROUTER_GW:
             self._delete_contract(context)
-        elif port.get('device_owner') == n_constants.DEVICE_OWNER_DHCP:
-            self._delete_path_if_last(context)
 
     @sync_init
     def create_network_postcommit(self, context):
index e2f50716ce8d64c7f584eb98455f3f741ceb2a80..58b5638c18617bd73f2873523e90215a7d065431 100644 (file)
@@ -80,13 +80,52 @@ class TestCiscoApicMechDriver(base.BaseTestCase,
                                             TEST_SEGMENT1)
         port_ctx = self._get_port_context(mocked.APIC_TENANT,
                                           mocked.APIC_NETWORK,
-                                          'vm1', net_ctx, HOST_ID1)
+                                          'vm1', net_ctx, HOST_ID1,
+                                          device_owner='any')
         mgr = self.driver.apic_manager
         self.driver.update_port_postcommit(port_ctx)
         mgr.ensure_path_created_for_port.assert_called_once_with(
             mocked.APIC_TENANT, mocked.APIC_NETWORK, HOST_ID1,
             ENCAP, transaction='transaction')
 
+    def test_create_port_postcommit(self):
+        net_ctx = self._get_network_context(mocked.APIC_TENANT,
+                                            mocked.APIC_NETWORK,
+                                            TEST_SEGMENT1)
+        port_ctx = self._get_port_context(mocked.APIC_TENANT,
+                                          mocked.APIC_NETWORK,
+                                          'vm1', net_ctx, HOST_ID1,
+                                          device_owner='any')
+        mgr = self.driver.apic_manager
+        self.driver.create_port_postcommit(port_ctx)
+        mgr.ensure_path_created_for_port.assert_called_once_with(
+            mocked.APIC_TENANT, mocked.APIC_NETWORK, HOST_ID1,
+            ENCAP, transaction='transaction')
+
+    def test_update_port_nobound_postcommit(self):
+        net_ctx = self._get_network_context(mocked.APIC_TENANT,
+                                            mocked.APIC_NETWORK,
+                                            TEST_SEGMENT1)
+        port_ctx = self._get_port_context(mocked.APIC_TENANT,
+                                          mocked.APIC_NETWORK,
+                                          'vm1', net_ctx, None,
+                                          device_owner='any')
+        self.driver.update_port_postcommit(port_ctx)
+        mgr = self.driver.apic_manager
+        self.assertFalse(mgr.ensure_path_created_for_port.called)
+
+    def test_create_port_nobound_postcommit(self):
+        net_ctx = self._get_network_context(mocked.APIC_TENANT,
+                                            mocked.APIC_NETWORK,
+                                            TEST_SEGMENT1)
+        port_ctx = self._get_port_context(mocked.APIC_TENANT,
+                                          mocked.APIC_NETWORK,
+                                          'vm1', net_ctx, None,
+                                          device_owner='any')
+        self.driver.create_port_postcommit(port_ctx)
+        mgr = self.driver.apic_manager
+        self.assertFalse(mgr.ensure_path_created_for_port.called)
+
     def test_update_gw_port_postcommit(self):
         net_ctx = self._get_network_context(mocked.APIC_TENANT,
                                             mocked.APIC_NETWORK,
@@ -173,6 +212,17 @@ class TestCiscoApicMechDriver(base.BaseTestCase,
             mocked.APIC_TENANT, mocked.APIC_NETWORK,
             '%s/%s' % (SUBNET_GATEWAY, SUBNET_NETMASK))
 
+    def test_create_subnet_nogw_postcommit(self):
+        net_ctx = self._get_network_context(mocked.APIC_TENANT,
+                                            mocked.APIC_NETWORK,
+                                            TEST_SEGMENT1)
+        subnet_ctx = self._get_subnet_context(None,
+                                              SUBNET_CIDR,
+                                              net_ctx)
+        mgr = self.driver.apic_manager
+        self.driver.create_subnet_postcommit(subnet_ctx)
+        self.assertFalse(mgr.ensure_subnet_created_on_apic.called)
+
     def _get_network_context(self, tenant_id, net_id, seg_id=None,
                              seg_type='vlan', external=False):
         network = {'id': net_id,
@@ -199,9 +249,9 @@ class TestCiscoApicMechDriver(base.BaseTestCase,
         return FakeSubnetContext(subnet, network)
 
     def _get_port_context(self, tenant_id, net_id, vm_id, network, host,
-                          gw=False):
+                          gw=False, device_owner='compute'):
         port = {'device_id': vm_id,
-                'device_owner': 'compute',
+                'device_owner': device_owner,
                 'binding:host_id': host,
                 'tenant_id': tenant_id,
                 'id': mocked.APIC_PORT,