From cfac3bc3c9a96be293f5b4e166faff0f9d4328dd Mon Sep 17 00:00:00 2001 From: John Davidge Date: Tue, 1 Nov 2016 14:36:49 +0000 Subject: [PATCH] Fix DHCP Port Creation on Service Subnets This changes the IPAM logic for service subnets to allow DHCP ports to be created on subnets of any service type, provided that the subnet has DHCP enabled.. This ensures that DHCP ports can still be created automatically on 'nova:compute' service subnets, for example. DocImpact Change-Id: I736262f2a7d3f3d7dfdc5276e2364aca7187d18b Closes-Bug: #1636963 (cherry picked from commit 1800ae63c2c1b6366f555c2f943e97f361c9ecd4) --- neutron/db/ipam_backend_mixin.py | 12 +++++++--- .../extensions/test_subnet_service_types.py | 23 +++++++++++++++++-- ...-for-service-subnets-06f03d902f2fb738.yaml | 10 ++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/dhcp-for-service-subnets-06f03d902f2fb738.yaml diff --git a/neutron/db/ipam_backend_mixin.py b/neutron/db/ipam_backend_mixin.py index 39dc546e747..bf10e6eef18 100644 --- a/neutron/db/ipam_backend_mixin.py +++ b/neutron/db/ipam_backend_mixin.py @@ -595,12 +595,18 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon): return query.filter(models_v2.Subnet.network_id == network_id) def _query_filter_service_subnets(self, query, service_type): + Subnet = models_v2.Subnet ServiceType = sst_model.SubnetServiceType query = query.add_entity(ServiceType) query = query.outerjoin(ServiceType) - query = query.filter(or_(ServiceType.service_type.is_(None), - ServiceType.service_type == service_type)) - return query.from_self(models_v2.Subnet) + query = query.filter(or_( + ServiceType.service_type.is_(None), + ServiceType.service_type == service_type, + # Allow DHCP ports to be created on subnets of any + # service type when DHCP is enabled on the subnet. + and_(Subnet.enable_dhcp.is_(True), + service_type == const.DEVICE_OWNER_DHCP))) + return query.from_self(Subnet) @staticmethod def _query_filter_by_segment_host_mapping(query, host): diff --git a/neutron/tests/unit/extensions/test_subnet_service_types.py b/neutron/tests/unit/extensions/test_subnet_service_types.py index 1a1f9e130fb..030ec3c0203 100644 --- a/neutron/tests/unit/extensions/test_subnet_service_types.py +++ b/neutron/tests/unit/extensions/test_subnet_service_types.py @@ -55,7 +55,7 @@ class SubnetServiceTypesExtensionTestCase( self).setUp(plugin=plugin, ext_mgr=ext_mgr) def _create_service_subnet(self, service_types=None, cidr=None, - network=None): + network=None, enable_dhcp=False): if not network: with self.network() as network: pass @@ -65,7 +65,8 @@ class SubnetServiceTypesExtensionTestCase( args = {'net_id': network['id'], 'tenant_id': network['tenant_id'], 'cidr': cidr, - 'ip_version': self.IP_VERSION} + 'ip_version': self.IP_VERSION, + 'enable_dhcp': enable_dhcp} if service_types: args['service_types'] = service_types return self._create_subnet(self.fmt, **args) @@ -274,6 +275,24 @@ class SubnetServiceTypesExtensionTestCase( def test_create_port_exhausted_subnet_no_fallback(self): self.test_create_port_exhausted_subnet(fallback=False) + def test_create_dhcp_port_compute_subnet(self, enable_dhcp=True): + with self.network() as network: + pass + res = self._create_service_subnet(['compute:nova'], + network=network, + enable_dhcp=enable_dhcp) + subnet = self.deserialize('json', res)['subnet'] + network = network['network'] + port = self._create_port(self.fmt, + net_id=network['id'], + tenant_id=network['tenant_id'], + fixed_ips=[{'subnet_id': subnet['id']}], + device_owner='network:dhcp') + self._assert_port_res(port, 'network:dhcp', subnet, enable_dhcp) + + def test_create_dhcp_port_compute_subnet_no_dhcp(self): + self.test_create_dhcp_port_compute_subnet(enable_dhcp=False) + class SubnetServiceTypesExtensionTestCasev6( SubnetServiceTypesExtensionTestCase): diff --git a/releasenotes/notes/dhcp-for-service-subnets-06f03d902f2fb738.yaml b/releasenotes/notes/dhcp-for-service-subnets-06f03d902f2fb738.yaml new file mode 100644 index 00000000000..704d549ace0 --- /dev/null +++ b/releasenotes/notes/dhcp-for-service-subnets-06f03d902f2fb738.yaml @@ -0,0 +1,10 @@ +--- +fixes: + - A special case has been added to allow the creation of DHCP ports + on Service Subnets that do not have the service type "network:dhcp", + provided that the subnet has 'enable_dhcp' set to 'True'. + This fixes the recurring error seen when neutron attempts to + automatically create a DHCP port on a dhcp-enabled subnet after the + subnet is created. See bug report + `1636963 `_ for + more details.