diff --git a/vmware_nsx/plugins/common_v3/plugin.py b/vmware_nsx/plugins/common_v3/plugin.py index 4562a58024..a097003efc 100644 --- a/vmware_nsx/plugins/common_v3/plugin.py +++ b/vmware_nsx/plugins/common_v3/plugin.py @@ -552,7 +552,7 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, for fixed_ip in port_data['fixed_ips']) # check only dhcp enabled subnets - return (self.get_subnet(context.elevated(), subnet_id) + return (self._get_subnet(context.elevated(), subnet_id) for subnet_id in subnet_ids) def _validate_create_port(self, context, port_data): diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index b6421e2a3e..a7e7f5186d 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -1493,11 +1493,10 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base, 'network_id': [original_port['network_id']]} interfaces = self.get_ports(context.elevated(), filters=port_filters) for interface in interfaces: - for subnet in subnets: - for fixed_ip in interface['fixed_ips']: - if fixed_ip['subnet_id'] in subnet_ids: - # Router exists - validation passed - return + for fixed_ip in interface['fixed_ips']: + if fixed_ip['subnet_id'] in subnet_ids: + # Router exists - validation passed + return err_msg = _("Neutron is configured with DHCP_Relay but no router " "connected to the subnet") diff --git a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py index bf5eb88503..aafffe3205 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py @@ -15,6 +15,7 @@ import mock import netaddr +from neutron.db import l3_db from neutron.db import models_v2 from neutron.db import securitygroups_db as sg_db from neutron.extensions import address_scope @@ -1736,6 +1737,40 @@ class TestPortsV2(common_v3.NsxV3SubnetMixin, self.plugin.create_port, self.ctx, data) + def test_create_compute_port_with_relay_and_router(self): + self._enable_dhcp_relay() + with self.network() as network, \ + self.subnet(network=network, enable_dhcp=True) as s1,\ + mock.patch.object(self.plugin, '_get_router', + return_value={'name': 'dummy'}): + # first create a router interface to simulate a router + data = {'port': { + 'network_id': network['network']['id'], + 'tenant_id': self._tenant_id, + 'name': 'port', + 'admin_state_up': True, + 'device_id': 'dummy', + 'device_owner': l3_db.DEVICE_OWNER_ROUTER_INTF, + 'fixed_ips': [{'subnet_id': s1['subnet']['id']}], + 'mac_address': '00:00:00:00:00:02'} + } + port1 = self.plugin.create_port(self.ctx, data) + self.assertIn('id', port1) + # Now create a compute port + device_owner = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'X' + data = {'port': { + 'network_id': network['network']['id'], + 'tenant_id': self._tenant_id, + 'name': 'port', + 'admin_state_up': True, + 'device_id': 'fake_device', + 'device_owner': device_owner, + 'fixed_ips': [{'subnet_id': s1['subnet']['id']}], + 'mac_address': '00:00:00:00:00:01'} + } + port2 = self.plugin.create_port(self.ctx, data) + self.assertIn('id', port2) + def _test_create_direct_network(self, vlan_id=0): net_type = vlan_id and 'vlan' or 'flat' name = 'direct_net'