NSXv3: Native DHCP is not supported for non-overlay networks

Since NSX backend does not support native DHCP on non-overlay networks,
the plugin will throw exception if users add a DHCP-enabled subnet in
such network.

Change-Id: Id234aedd1296c63be9999bf27cf3f0f577c9cb93
This commit is contained in:
Shih-Hao Li 2016-11-03 05:46:24 -07:00
parent a4c8dd570b
commit 30caa7c895
2 changed files with 59 additions and 17 deletions

View File

@ -641,6 +641,12 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
vlan_id, vlan_id,
nsx_result['id']) nsx_result['id'])
def _is_overlay_network(self, context, network_id):
bindings = nsx_db.get_network_bindings(context.session, network_id)
# With NSX plugin, "normal" overlay networks will have no binding
return (not bindings or
bindings[0].binding_type == utils.NsxV3NetworkTypes.VXLAN)
def _extend_network_dict_provider(self, context, network, bindings=None): def _extend_network_dict_provider(self, context, network, bindings=None):
if not bindings: if not bindings:
bindings = nsx_db.get_network_bindings(context.session, bindings = nsx_db.get_network_bindings(context.session,
@ -1143,16 +1149,26 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
subnet['subnet'].get('enable_dhcp', False)): subnet['subnet'].get('enable_dhcp', False)):
lock = 'nsxv3_network_' + subnet['subnet']['network_id'] lock = 'nsxv3_network_' + subnet['subnet']['network_id']
with locking.LockManager.get_lock(lock): with locking.LockManager.get_lock(lock):
# Check if it is the first DHCP-enabled subnet to create. # Check if it is on an overlay network and is the first
network = self._get_network(context, # DHCP-enabled subnet to create.
subnet['subnet']['network_id']) if self._is_overlay_network(
if self._has_no_dhcp_enabled_subnet(context, network): context, subnet['subnet']['network_id']):
created_subnet = super(NsxV3Plugin, self).create_subnet( network = self._get_network(
context, subnet) context, subnet['subnet']['network_id'])
self._enable_native_dhcp(context, network, created_subnet) if self._has_no_dhcp_enabled_subnet(context, network):
created_subnet = super(
NsxV3Plugin, self).create_subnet(context, subnet)
self._enable_native_dhcp(context, network,
created_subnet)
msg = None
else:
msg = (_("Can not create more than one DHCP-enabled "
"subnet in network %s") %
subnet['subnet']['network_id'])
else: else:
msg = _("Can not create more than one DHCP-enabled subnet " msg = _("Native DHCP is not supported for non-overlay "
"in network %s") % subnet['subnet']['network_id'] "network %s") % subnet['subnet']['network_id']
if msg:
LOG.error(msg) LOG.error(msg)
raise n_exc.InvalidInput(error_message=msg) raise n_exc.InvalidInput(error_message=msg)
else: else:
@ -1188,16 +1204,25 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
network = self._get_network( network = self._get_network(
context, orig_subnet['network_id']) context, orig_subnet['network_id'])
if enable_dhcp: if enable_dhcp:
if self._has_no_dhcp_enabled_subnet(context, network): if self._is_overlay_network(
updated_subnet = super( context, orig_subnet['network_id']):
NsxV3Plugin, self).update_subnet( if self._has_no_dhcp_enabled_subnet(
context, subnet_id, subnet) context, network):
self._enable_native_dhcp(context, network, updated_subnet = super(
updated_subnet) NsxV3Plugin, self).update_subnet(
context, subnet_id, subnet)
self._enable_native_dhcp(context, network,
updated_subnet)
msg = None
else:
msg = (_("Multiple DHCP-enabled subnets is "
"not allowed in network %s") %
orig_subnet['network_id'])
else: else:
msg = (_("Multiple DHCP-enabled subnets is not " msg = (_("Native DHCP is not supported for "
"allowed in network %s") % "non-overlay network %s") %
orig_subnet['network_id']) orig_subnet['network_id'])
if msg:
LOG.error(msg) LOG.error(msg)
raise n_exc.InvalidInput(error_message=msg) raise n_exc.InvalidInput(error_message=msg)
elif self._has_single_dhcp_enabled_subnet(context, elif self._has_single_dhcp_enabled_subnet(context,

View File

@ -17,6 +17,7 @@ import mock
import netaddr import netaddr
from neutron import context from neutron import context
from neutron.extensions import providernet as pnet
from neutron.extensions import securitygroup as secgrp from neutron.extensions import securitygroup as secgrp
from neutron_lib import constants from neutron_lib import constants
@ -258,6 +259,22 @@ class NsxNativeDhcpTestCase(test_plugin.NsxV3PluginTestCaseMixin):
network2['network']['id'], nsx_constants.SERVICE_DHCP) network2['network']['id'], nsx_constants.SERVICE_DHCP)
self.assertFalse(dhcp_service) self.assertFalse(dhcp_service)
def test_dhcp_service_with_create_dhcp_subnet_in_vlan_network(self):
# Test if a DHCP-enabled subnet cannot be created in a vlan network.
povidernet_args = {pnet.NETWORK_TYPE: 'vlan',
pnet.PHYSICAL_NETWORK: 'tzuuid',
pnet.SEGMENTATION_ID: 100}
with self.network(providernet_args=povidernet_args,
arg_list=(pnet.NETWORK_TYPE,
pnet.PHYSICAL_NETWORK,
pnet.SEGMENTATION_ID)) as network:
subnet = {'subnet': {'network_id': network['network']['id'],
'cidr': '10.0.0.0/24',
'enable_dhcp': True}}
self.assertRaises(
n_exc.InvalidInput, self.plugin.create_subnet,
context.get_admin_context(), subnet)
def test_dhcp_service_with_create_multiple_dhcp_subnets(self): def test_dhcp_service_with_create_multiple_dhcp_subnets(self):
# Test if multiple DHCP-enabled subnets cannot be created in a network. # Test if multiple DHCP-enabled subnets cannot be created in a network.
with self.network() as network: with self.network() as network: