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.")
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):
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)
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:
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.
'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:
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)
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)