From a6c5cc7bfd00835ee066e9736f3c8056210a6071 Mon Sep 17 00:00:00 2001 From: Ivar Lazzaro Date: Sun, 14 Dec 2014 16:17:37 -0800 Subject: [PATCH] [apic ml2] Bind ports regardless of the owner 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 --- .../ml2/drivers/cisco/apic/mechanism_apic.py | 48 ++++++---------- .../apic/test_cisco_apic_mechanism_driver.py | 56 ++++++++++++++++++- 2 files changed, 71 insertions(+), 33 deletions(-) diff --git a/neutron/plugins/ml2/drivers/cisco/apic/mechanism_apic.py b/neutron/plugins/ml2/drivers/cisco/apic/mechanism_apic.py index c9ef93202..0cfff80f7 100644 --- a/neutron/plugins/ml2/drivers/cisco/apic/mechanism_apic.py +++ b/neutron/plugins/ml2/drivers/cisco/apic/mechanism_apic.py @@ -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): diff --git a/neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_mechanism_driver.py b/neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_mechanism_driver.py index e2f50716c..58b5638c1 100644 --- a/neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_mechanism_driver.py +++ b/neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_mechanism_driver.py @@ -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, -- 2.45.2