diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index f1b1e9a6bf..2dd9a9ff94 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -1432,7 +1432,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, if dhcp_service['port_id']: try: - self.delete_port(context, dhcp_service['port_id']) + self.delete_port(context, dhcp_service['port_id'], + force_delete_dhcp=True) except Exception: # This could happen when the port has been manually deleted. LOG.error("Failed to delete DHCP port %(port)s for " @@ -2606,7 +2607,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, self._add_dhcp_binding(context, port_data) except nsx_lib_exc.ManagerError: # Rollback create port - self.delete_port(context, port_data['id']) + self.delete_port(context, port_data['id'], + force_delete_dhcp=True) msg = _('Unable to create port. Please contact admin') LOG.exception(msg) raise nsx_exc.NsxPluginException(err_msg=msg) @@ -2632,7 +2634,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, raise n_exc.ServicePortInUse(port_id=port_id, reason=e) def delete_port(self, context, port_id, - l3_port_check=True, l2gw_port_check=True): + l3_port_check=True, l2gw_port_check=True, + force_delete_dhcp=False): # if needed, check to see if this is a port owned by # a l2 gateway. If so, we should prevent deletion here self._pre_delete_port_check(context, port_id, l2gw_port_check) @@ -2641,6 +2644,12 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, if l3_port_check: self.prevent_l3_port_deletion(context, port_id) port = self.get_port(context, port_id) + # Prevent DHCP port deletion if native support is enabled + if (cfg.CONF.nsx_v3.native_dhcp_metadata and + not force_delete_dhcp and + port['device_owner'] in [const.DEVICE_OWNER_DHCP]): + msg = (_('Can not delete DHCP port %s') % port['id']) + raise n_exc.BadRequest(resource='port', msg=msg) if not self._network_is_external(context, port['network_id']): _net_id, nsx_port_id = nsx_db.get_nsx_switch_and_port_id( context.session, port_id) diff --git a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py index 637536aaaf..eb5c037b85 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py @@ -620,6 +620,18 @@ class TestPortsV2(test_plugin.TestPortsV2, NsxV3PluginTestCaseMixin, self.assertEqual(res['port']['fixed_ips'], data['port']['fixed_ips']) + def test_delete_dhcp_port(self): + cfg.CONF.set_override('native_dhcp_metadata', True, 'nsx_v3') + with self.subnet(): + pl = directory.get_plugin() + ctx = context.Context(user_id=None, tenant_id=self._tenant_id, + is_admin=False) + ports = pl.get_ports( + ctx, filters={'device_owner': [constants.DEVICE_OWNER_DHCP]}) + req = self.new_delete_request('ports', ports[0]['id']) + res = req.get_response(self.api) + self.assertEqual(exc.HTTPBadRequest.code, res.status_int) + def test_fail_create_port_with_ext_net(self): expected_error = 'InvalidInput' with self._create_l3_ext_network() as network: