NSX: Validate gateway device list against DB
This patch adds a check for validating the devices for a network gateway are defined in the neutron DB before the request for creating the network gateway is sent to the NSX backend. Change-Id: Ic2245f965da332dbaee4ab5a869ce47f06a9e6ce Partial-Bug: #1319581
This commit is contained in:
parent
f9d3e91789
commit
9d80a8accd
|
@ -60,6 +60,11 @@ class GatewayDeviceNotFound(exceptions.NotFound):
|
|||
message = _("Network Gateway Device %(device_id)s could not be found.")
|
||||
|
||||
|
||||
class GatewayDevicesNotFound(exceptions.NotFound):
|
||||
message = _("One or more Network Gateway Devices could not be found: "
|
||||
"%(device_ids)s.")
|
||||
|
||||
|
||||
class NetworkGatewayPortInUse(exceptions.InUse):
|
||||
message = _("Port '%(port_id)s' is owned by '%(device_owner)s' and "
|
||||
"therefore cannot be deleted directly via the port API.")
|
||||
|
@ -244,7 +249,24 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase):
|
|||
raise NetworkGatewayPortInUse(port_id=port['id'],
|
||||
device_owner=port['device_owner'])
|
||||
|
||||
def create_network_gateway(self, context, network_gateway):
|
||||
def _validate_device_list(self, context, tenant_id, gateway_data):
|
||||
device_query = self._query_gateway_devices(
|
||||
context, filters={'id': [device['id']
|
||||
for device in gateway_data['devices']]})
|
||||
retrieved_device_ids = set()
|
||||
for device in device_query:
|
||||
retrieved_device_ids.add(device['id'])
|
||||
if device['tenant_id'] != tenant_id:
|
||||
raise GatewayDeviceNotFound(device_id=device['id'])
|
||||
missing_device_ids = (
|
||||
set(device['id'] for device in gateway_data['devices']) -
|
||||
retrieved_device_ids)
|
||||
if missing_device_ids:
|
||||
raise GatewayDevicesNotFound(
|
||||
device_ids=",".join(missing_device_ids))
|
||||
|
||||
def create_network_gateway(self, context, network_gateway,
|
||||
validate_device_list=True):
|
||||
gw_data = network_gateway[self.gateway_resource]
|
||||
tenant_id = self._get_tenant_id_for_create(context, gw_data)
|
||||
with context.session.begin(subtransactions=True):
|
||||
|
@ -252,13 +274,10 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase):
|
|||
id=gw_data.get('id', uuidutils.generate_uuid()),
|
||||
tenant_id=tenant_id,
|
||||
name=gw_data.get('name'))
|
||||
# Device list is guaranteed to be a valid list
|
||||
device_query = self._query_gateway_devices(
|
||||
context, filters={'id': [device['id']
|
||||
for device in gw_data['devices']]})
|
||||
for device in device_query:
|
||||
if device['tenant_id'] != tenant_id:
|
||||
raise GatewayDeviceNotFound(device_id=device['id'])
|
||||
# Device list is guaranteed to be a valid list, but some devices
|
||||
# might still either not exist or belong to a different tenant
|
||||
if validate_device_list:
|
||||
self._validate_device_list(context, tenant_id, gw_data)
|
||||
gw_db.devices.extend([NetworkGatewayDeviceReference(**device)
|
||||
for device in gw_data['devices']])
|
||||
context.session.add(gw_db)
|
||||
|
|
|
@ -1998,11 +1998,12 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||
Create the gateway service on NSX platform and corresponding data
|
||||
structures in Neutron datase.
|
||||
"""
|
||||
# Ensure the default gateway in the config file is in sync with the db
|
||||
self._ensure_default_network_gateway()
|
||||
# Need to re-do authZ checks here in order to avoid creation on NSX
|
||||
gw_data = network_gateway[networkgw.GATEWAY_RESOURCE_NAME]
|
||||
tenant_id = self._get_tenant_id_for_create(context, gw_data)
|
||||
# Ensure the default gateway in the config file is in sync with the db
|
||||
self._ensure_default_network_gateway()
|
||||
# Validate provided gateway device list
|
||||
self._validate_device_list(context, tenant_id, gw_data)
|
||||
devices = gw_data['devices']
|
||||
# Populate default physical network where not specified
|
||||
for device in devices:
|
||||
|
@ -2029,7 +2030,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||
raise nsx_exc.NsxPluginException(err_msg=err_msg)
|
||||
gw_data['id'] = nsx_uuid
|
||||
return super(NsxPluginV2, self).create_network_gateway(
|
||||
context, network_gateway)
|
||||
context, network_gateway, validate_device_list=False)
|
||||
|
||||
def delete_network_gateway(self, context, gateway_id):
|
||||
"""Remove a layer-2 network gateway.
|
||||
|
|
|
@ -557,6 +557,13 @@ class NetworkGatewayDbTestCase(test_db_plugin.NeutronDbPluginV2TestCase):
|
|||
'json', _uuid(), name=name, devices=devices)
|
||||
self.assertEqual(404, res.status_int)
|
||||
|
||||
def test_create_network_gateway_non_existent_device_raises_404(self):
|
||||
name = 'test-gw'
|
||||
devices = [{'id': _uuid(), 'interface_name': 'xxx'}]
|
||||
res = self._create_network_gateway(
|
||||
'json', _uuid(), name=name, devices=devices)
|
||||
self.assertEqual(404, res.status_int)
|
||||
|
||||
def test_delete_network_gateway(self):
|
||||
tenant_id = _uuid()
|
||||
with self._gateway_device(tenant_id=tenant_id) as dev:
|
||||
|
@ -979,9 +986,12 @@ class TestNetworkGateway(test_nsx_plugin.NsxPluginV2TestCase,
|
|||
with mock.patch.object(nsxlib.l2gateway,
|
||||
'create_l2_gw_service',
|
||||
new=raise_nsx_api_exc):
|
||||
with self._gateway_device() as dev:
|
||||
tenant_id = _uuid()
|
||||
with self._gateway_device(tenant_id=tenant_id) as dev:
|
||||
res = self._create_network_gateway(
|
||||
self.fmt, 'xxx', name='yyy',
|
||||
self.fmt,
|
||||
tenant_id,
|
||||
name='yyy',
|
||||
devices=[{'id': dev[self.dev_resource]['id']}])
|
||||
self.assertEqual(500, res.status_int)
|
||||
|
||||
|
@ -989,9 +999,12 @@ class TestNetworkGateway(test_nsx_plugin.NsxPluginV2TestCase,
|
|||
with mock.patch.object(nsxlib.l2gateway,
|
||||
'create_l2_gw_service',
|
||||
side_effect=api_exc.Conflict):
|
||||
with self._gateway_device() as dev:
|
||||
tenant_id = _uuid()
|
||||
with self._gateway_device(tenant_id=tenant_id) as dev:
|
||||
res = self._create_network_gateway(
|
||||
self.fmt, 'xxx', name='yyy',
|
||||
self.fmt,
|
||||
tenant_id,
|
||||
name='yyy',
|
||||
devices=[{'id': dev[self.dev_resource]['id']}])
|
||||
self.assertEqual(409, res.status_int)
|
||||
|
||||
|
|
Loading…
Reference in New Issue