L2gateway db implementation for RESTful API
This is initial db related files required for implementing l2gateway RESTful API Implements: blueprint l2-gateway-api Change-Id: Ie6bd6b506bd704e0a86273ec7240b7eebb3b18b1stable/ocata
parent
522c44a3e1
commit
47de11fc2e
@ -0,0 +1,91 @@
|
||||
# Copyright 2015 OpenStack Foundation
|
||||
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.common import exceptions
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
class L2GatewayCommonDbMixin(object):
|
||||
|
||||
def _apply_filters_to_query(self, query, model, filters):
|
||||
"""Apply filters to query for the models."""
|
||||
if filters:
|
||||
for key, value in filters.iteritems():
|
||||
column = getattr(model, key, None)
|
||||
if column:
|
||||
query = query.filter(column.in_(value))
|
||||
return query
|
||||
|
||||
def _model_query(self, context, model):
|
||||
"""Query model based on filter."""
|
||||
query = context.session.query(model)
|
||||
query_filter = None
|
||||
if not context.is_admin and hasattr(model, 'tenant_id'):
|
||||
if hasattr(model, 'shared'):
|
||||
query_filter = ((model.tenant_id == context.tenant_id) |
|
||||
(model.shared == sa.true()))
|
||||
else:
|
||||
query_filter = (model.tenant_id == context.tenant_id)
|
||||
if query_filter is not None:
|
||||
query = query.filter(query_filter)
|
||||
return query
|
||||
|
||||
def _get_collection_query(self, context, model, filters=None,
|
||||
sorts=None, limit=None, marker_obj=None,
|
||||
page_reverse=False):
|
||||
"""Get collection query for the models."""
|
||||
collection = self._model_query(context, model)
|
||||
collection = self._apply_filters_to_query(collection, model, filters)
|
||||
return collection
|
||||
|
||||
def _get_marker_obj(self, context, resource, limit, marker):
|
||||
"""Get marker object for the resource."""
|
||||
if limit and marker:
|
||||
return getattr(self, '_get_%s' % resource)(context, marker)
|
||||
return None
|
||||
|
||||
def _fields(self, resource, fields):
|
||||
"""Get fields for the resource for get query."""
|
||||
if fields:
|
||||
return dict(((key, item) for key, item in resource.items()
|
||||
if key in fields))
|
||||
return resource
|
||||
|
||||
def _get_tenant_id_for_create(self, context, resource):
|
||||
"""Get tenant id for creation of resources."""
|
||||
if context.is_admin and 'tenant_id' in resource:
|
||||
tenant_id = resource['tenant_id']
|
||||
elif ('tenant_id' in resource and
|
||||
resource['tenant_id'] != context.tenant_id):
|
||||
reason = _('Cannot create resource for another tenant')
|
||||
raise exceptions.AdminRequired(reason=reason)
|
||||
else:
|
||||
tenant_id = context.tenant_id
|
||||
return tenant_id
|
||||
|
||||
def _get_collection(self, context, model, dict_func, filters=None,
|
||||
fields=None, sorts=None, limit=None, marker_obj=None,
|
||||
page_reverse=False):
|
||||
"""Get collection object based on query for resources."""
|
||||
query = self._get_collection_query(context, model, filters=filters,
|
||||
sorts=sorts,
|
||||
limit=limit,
|
||||
marker_obj=marker_obj,
|
||||
page_reverse=page_reverse)
|
||||
items = [dict_func(c, fields) for c in query]
|
||||
if limit and page_reverse:
|
||||
items.reverse()
|
||||
return items
|
@ -0,0 +1,358 @@
|
||||
# Copyright 2015 OpenStack Foundation
|
||||
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.common import exceptions
|
||||
from neutron.openstack.common import log as logging
|
||||
from neutron.openstack.common import uuidutils
|
||||
|
||||
from networking_l2gw.db.l2gateway import db_query
|
||||
from networking_l2gw.db.l2gateway import l2gateway_models as models
|
||||
from networking_l2gw.extensions import l2gateway
|
||||
from networking_l2gw.extensions import l2gatewayconnection
|
||||
from networking_l2gw.services.l2gateway.common import config
|
||||
from networking_l2gw.services.l2gateway.common import constants
|
||||
from networking_l2gw.services.l2gateway.common import l2gw_validators
|
||||
from networking_l2gw.services.l2gateway import exceptions as l2gw_exc
|
||||
|
||||
from sqlalchemy.orm import exc as sa_orm_exc
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class L2GatewayMixin(l2gateway.L2GatewayPluginBase,
|
||||
db_query.L2GatewayCommonDbMixin,
|
||||
l2gatewayconnection.L2GatewayConnectionPluginBase):
|
||||
"""Class L2GatewayMixin for handling l2_gateway resource."""
|
||||
gateway_resource = constants.GATEWAY_RESOURCE_NAME
|
||||
connection_resource = constants.CONNECTION_RESOURCE_NAME
|
||||
config.register_l2gw_opts_helper()
|
||||
|
||||
def _get_l2_gateway(self, context, gw_id):
|
||||
try:
|
||||
gw = context.session.query(models.L2Gateway).get(gw_id)
|
||||
except sa_orm_exc.NoResultFound:
|
||||
raise l2gw_exc.L2GatewayNotFound(gateway_id=gw_id)
|
||||
return gw
|
||||
|
||||
def _get_l2_gateways(self, context):
|
||||
try:
|
||||
gw = context.session.query(models.L2Gateway).all()
|
||||
except sa_orm_exc.NoResultFound:
|
||||
raise l2gw_exc.L2GatewayNotFound(gateway_id="")
|
||||
return gw
|
||||
|
||||
def _get_l2_gateway_interface(self, context, id):
|
||||
try:
|
||||
gw = context.session.query(models.L2GatewayInterface).filter_by(
|
||||
device_id=id).all()
|
||||
except sa_orm_exc.NoResultFound:
|
||||
raise l2gw_exc.L2GatewayInterfaceNotFound(interface_id=id)
|
||||
return gw
|
||||
|
||||
def _check_vlan_on_interface(self, context, l2gw_id):
|
||||
device_db = self._get_l2_gateway_device(context, l2gw_id)
|
||||
for device_model in device_db:
|
||||
interface_db = self._get_l2_gateway_interface(context,
|
||||
device_model.id)
|
||||
for int_model in interface_db:
|
||||
query = context.session.query(models.L2GatewayInterface)
|
||||
int_db = query.filter_by(id=int_model.id).first()
|
||||
seg_id = int_db[constants.SEG_ID]
|
||||
if seg_id > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _get_l2_gateway_device(self, context, l2gw_id):
|
||||
try:
|
||||
gw = context.session.query(models.L2GatewayDevice).filter_by(
|
||||
l2_gateway_id=l2gw_id).all()
|
||||
except sa_orm_exc.NoResultFound:
|
||||
raise l2gw_exc.L2GatewayDeviceNotFound(device_id=l2gw_id)
|
||||
return gw
|
||||
|
||||
def _get_l2_gateway_connection(self, context, cn_id):
|
||||
try:
|
||||
con = context.session.query(models.L2GatewayConnection).get(cn_id)
|
||||
except sa_orm_exc.NoResultFound:
|
||||
raise l2gw_exc.L2GatewayConnectionNotFound(id=cn_id)
|
||||
return con
|
||||
|
||||
def _make_l2gw_connections_dict(self, gw_conn, fields=None):
|
||||
if gw_conn is None:
|
||||
raise l2gw_exc.L2GatewayConnectionNotFound(id="")
|
||||
res = {'id': gw_conn['id'],
|
||||
'network_id': gw_conn['network_id'],
|
||||
'l2_gateway_id': gw_conn['l2_gateway_id']
|
||||
}
|
||||
return self._fields(res, fields)
|
||||
|
||||
def _make_l2_gateway_dict(self, l2_gateway, interface_db, fields=None):
|
||||
device_list = []
|
||||
interface_list = []
|
||||
for d in l2_gateway['devices']:
|
||||
if not interface_list:
|
||||
for interfaces_db in d['interfaces']:
|
||||
interface_list.append({'name':
|
||||
interfaces_db['interface_name'],
|
||||
constants.SEG_ID:
|
||||
interfaces_db[constants.SEG_ID]})
|
||||
device_list.append({'device_name': d['device_name'],
|
||||
'id': d['id'],
|
||||
'interfaces': interface_list})
|
||||
res = {'id': l2_gateway['id'],
|
||||
'name': l2_gateway['name'],
|
||||
'devices': device_list,
|
||||
'tenant_id': l2_gateway['tenant_id']}
|
||||
return self._fields(res, fields)
|
||||
|
||||
def _set_mapping_info_defaults(self, mapping_info):
|
||||
if not mapping_info.get(constants.SEG_ID):
|
||||
mapping_info[constants.SEG_ID] = 0
|
||||
|
||||
def _retrieve_gateway_connections(self, context, gateway_id,
|
||||
mapping_info={}, only_one=False):
|
||||
filters = {'l2_gateway_id': [gateway_id]}
|
||||
for k, v in mapping_info.iteritems():
|
||||
if v:
|
||||
filters[k] = [v]
|
||||
query = self._get_collection_query(context,
|
||||
models.L2GatewayConnection,
|
||||
filters)
|
||||
return query.one() if only_one else query.all()
|
||||
|
||||
def create_l2_gateway(self, context, l2_gateway):
|
||||
"""Create a logical gateway."""
|
||||
self._admin_check(context, 'CREATE')
|
||||
gw = l2_gateway[self.gateway_resource]
|
||||
tenant_id = self._get_tenant_id_for_create(context, gw)
|
||||
devices = gw['devices']
|
||||
with context.session.begin(subtransactions=True):
|
||||
gw_db = models.L2Gateway(
|
||||
id=gw.get('id', uuidutils.generate_uuid()),
|
||||
tenant_id=tenant_id,
|
||||
name=gw.get('name'))
|
||||
context.session.add(gw_db)
|
||||
l2gw_device_dict = {}
|
||||
interface_db_list = []
|
||||
for device in devices:
|
||||
l2gw_device_dict['l2_gateway_id'] = id
|
||||
device_name = device['device_name']
|
||||
l2gw_device_dict['device_name'] = device_name
|
||||
l2gw_device_dict['id'] = uuidutils.generate_uuid()
|
||||
uuid = self._generate_uuid()
|
||||
d_db = models.L2GatewayDevice(id=uuid,
|
||||
l2_gateway_id=gw_db.id,
|
||||
device_name=device_name)
|
||||
context.session.add(d_db)
|
||||
for interface_list in device['interfaces']:
|
||||
name = interface_list.get('name')
|
||||
seg_list = interface_list.get(constants.SEG_ID, None)
|
||||
if seg_list:
|
||||
for segs in seg_list:
|
||||
uuid = self._generate_uuid()
|
||||
interface_db = self._get_int_model(uuid,
|
||||
name,
|
||||
d_db.id,
|
||||
segs)
|
||||
context.session.add(interface_db)
|
||||
interface_db_list.append(interface_db)
|
||||
else:
|
||||
uuid = self._generate_uuid()
|
||||
default_seg_id = constants.SEG_ID
|
||||
interface_db = self._get_int_model(uuid,
|
||||
name,
|
||||
d_db.id,
|
||||
default_seg_id)
|
||||
context.session.add(interface_db)
|
||||
interface_db_list.append(interface_db)
|
||||
context.session.query(models.L2GatewayDevice).all()
|
||||
return self._make_l2_gateway_dict(gw_db, interface_db_list)
|
||||
|
||||
def update_l2_gateway(self, context, id, l2_gateway):
|
||||
"""Update l2 gateway."""
|
||||
self._admin_check(context, 'UPDATE')
|
||||
gw = l2_gateway[self.gateway_resource]
|
||||
devices = gw['devices']
|
||||
with context.session.begin(subtransactions=True):
|
||||
l2gw_db = self._get_l2_gateway(context, id)
|
||||
if l2gw_db.network_connections:
|
||||
raise l2gw_exc.L2GatewayInUse(gateway_id=id)
|
||||
l2gw_db.name = gw.get('name')
|
||||
interface_db_list = []
|
||||
device_db = self._get_l2_gateway_device(context, id)
|
||||
interface_dict_list = []
|
||||
for device in devices:
|
||||
for interfaces in device['interfaces']:
|
||||
interface_dict_list.append(interfaces)
|
||||
for d_val in device_db:
|
||||
interface_db = self._get_l2_gateway_interface(context,
|
||||
d_val.id)
|
||||
self._delete_l2_gateway_interfaces(context, interface_db)
|
||||
for interfaces in interface_dict_list:
|
||||
int_name = interfaces.get('name')
|
||||
seg_id_list = interfaces.get(constants.SEG_ID, None)
|
||||
uuid = self._generate_uuid()
|
||||
for seg_ids in seg_id_list:
|
||||
interface_db = self._get_int_model(uuid,
|
||||
int_name,
|
||||
d_val.id,
|
||||
seg_ids)
|
||||
context.session.add(interface_db)
|
||||
interface_db_list.append(interface_db)
|
||||
return self._make_l2_gateway_dict(l2gw_db, interface_db_list)
|
||||
|
||||
def get_l2_gateway(self, context, id, fields=None):
|
||||
"""get the l2 gateway by id."""
|
||||
self._admin_check(context, 'GET')
|
||||
gw_db = self._get_l2_gateway(context, id)
|
||||
if gw_db:
|
||||
device_db = self._get_l2_gateway_device(context, gw_db.id)
|
||||
for devices in device_db:
|
||||
interface_db = self._get_l2_gateway_interface(context,
|
||||
devices.id)
|
||||
return self._make_l2_gateway_dict(gw_db, interface_db, fields)
|
||||
else:
|
||||
return []
|
||||
|
||||
def delete_l2_gateway(self, context, id):
|
||||
"""delete the l2 gateway by id."""
|
||||
self._admin_check(context, 'DELETE')
|
||||
with context.session.begin(subtransactions=True):
|
||||
gw_db = self._get_l2_gateway(context, id)
|
||||
if gw_db is None:
|
||||
raise l2gw_exc.L2GatewayNotFound(gateway_id=id)
|
||||
if gw_db.network_connections:
|
||||
raise l2gw_exc.L2GatewayInUse(gateway_id=id)
|
||||
context.session.delete(gw_db)
|
||||
LOG.debug("l2 gateway '%s' was deleted.", id)
|
||||
|
||||
def get_l2_gateways(self, context, filters=None, fields=None,
|
||||
sorts=None,
|
||||
limit=None,
|
||||
marker=None,
|
||||
page_reverse=False):
|
||||
"""list the l2 gateways available in the neutron DB."""
|
||||
self._admin_check(context, 'GET')
|
||||
marker_obj = self._get_marker_obj(
|
||||
context, 'l2_gateway', limit, marker)
|
||||
return self._get_collection(context, models.L2Gateway,
|
||||
self._make_l2_gateway_dict,
|
||||
filters=filters, fields=fields,
|
||||
sorts=sorts, limit=limit,
|
||||
marker_obj=marker_obj,
|
||||
page_reverse=page_reverse)
|
||||
|
||||
def _update_segmentation_id(self, context, l2gw_id, segmentation_id):
|
||||
"""Update segmentation id for interfaces."""
|
||||
device_db = self._get_l2_gateway_device(context, l2gw_id)
|
||||
for device_model in device_db:
|
||||
interface_db = self._get_l2_gateway_interface(context,
|
||||
device_model.id)
|
||||
for interface_model in interface_db:
|
||||
interface_model.segmentation_id = segmentation_id
|
||||
|
||||
def _delete_l2_gateway_interfaces(self, context, int_db_list):
|
||||
"""delete the l2 interfaces by id."""
|
||||
with context.session.begin(subtransactions=True):
|
||||
for interfaces in int_db_list:
|
||||
context.session.delete(interfaces)
|
||||
LOG.debug("l2 gateway interfaces was deleted.")
|
||||
|
||||
def create_l2_gateway_connection(self, context, l2_gateway_connection):
|
||||
"""Create l2 gateway connection."""
|
||||
self._admin_check(context, 'CREATE')
|
||||
gw_connection = l2_gateway_connection[self.connection_resource]
|
||||
l2_gw_id = gw_connection.get('l2_gateway_id')
|
||||
network_id = gw_connection.get('network_id')
|
||||
segmentation_id = gw_connection.get(constants.SEG_ID)
|
||||
nw_map = {}
|
||||
nw_map['network_id'] = network_id
|
||||
nw_map['l2_gateway_id'] = l2_gw_id
|
||||
if segmentation_id in gw_connection:
|
||||
nw_map[constants.SEG_ID] = segmentation_id
|
||||
check_vlan = self._check_vlan_on_interface(context, l2_gw_id)
|
||||
network_id = l2gw_validators.validate_network_mapping_list(nw_map,
|
||||
check_vlan)
|
||||
if segmentation_id:
|
||||
self._update_segmentation_id(context, l2_gw_id, segmentation_id)
|
||||
with context.session.begin(subtransactions=True):
|
||||
gw_db = self._get_l2_gateway(context, l2_gw_id)
|
||||
tenant_id = self._get_tenant_id_for_create(context, gw_db)
|
||||
if self._retrieve_gateway_connections(context,
|
||||
l2_gw_id,
|
||||
nw_map):
|
||||
raise l2gw_exc.L2GatewayConnectionExists(mapping=nw_map,
|
||||
gateway_id=l2_gw_id)
|
||||
nw_map['tenant_id'] = tenant_id
|
||||
connection_id = uuidutils.generate_uuid()
|
||||
nw_map['id'] = connection_id
|
||||
nw_map.pop(constants.SEG_ID, None)
|
||||
gw_db.network_connections.append(
|
||||
models.L2GatewayConnection(**nw_map))
|
||||
gw_db = models.L2GatewayConnection(id=connection_id,
|
||||
tenant_id=tenant_id,
|
||||
network_id=network_id,
|
||||
l2_gateway_id=l2_gw_id)
|
||||
return self._make_l2gw_connections_dict(gw_db)
|
||||
|
||||
def get_l2_gateway_connections(self, context, filters=None,
|
||||
fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
"""List l2 gateway connections."""
|
||||
self._admin_check(context, 'GET')
|
||||
marker_obj = self._get_marker_obj(
|
||||
context, 'l2_gateway_connection', limit, marker)
|
||||
return self._get_collection(context, models.L2GatewayConnection,
|
||||
self._make_l2gw_connections_dict,
|
||||
filters=filters, fields=fields,
|
||||
sorts=sorts, limit=limit,
|
||||
marker_obj=marker_obj,
|
||||
page_reverse=page_reverse)
|
||||
|
||||
def get_l2_gateway_connection(self, context, id, fields=None):
|
||||
"""Get l2 gateway connection."""
|
||||
self._admin_check(context, 'GET')
|
||||
"""Get the l2 gateway connection by id."""
|
||||
gw_db = self._get_l2_gateway_connection(context, id)
|
||||
return self._make_l2gw_connections_dict(gw_db, fields)
|
||||
|
||||
def delete_l2_gateway_connection(self, context, id):
|
||||
"""Delete the l2 gateway connection by id."""
|
||||
self._admin_check(context, 'DELETE')
|
||||
with context.session.begin(subtransactions=True):
|
||||
gw_db = self._get_l2_gateway_connection(context, id)
|
||||
context.session.delete(gw_db)
|
||||
LOG.debug("l2 gateway '%s' was destroyed.", id)
|
||||
|
||||
def _admin_check(self, context, action):
|
||||
"""Admin role check helper."""
|
||||
# TODO(selva): his check should be required if the tenant_id is
|
||||
# specified inthe request, otherwise the policy.json do a trick
|
||||
# this need further revision.
|
||||
if not context.is_admin:
|
||||
reason = _('Cannot %(action)s resource for non admin tenant')
|
||||
raise exceptions.AdminRequired(reason=reason)
|
||||
|
||||
def _generate_uuid(self):
|
||||
"""Generate uuid helper."""
|
||||
uuid = uuidutils.generate_uuid()
|
||||
return uuid
|
||||
|
||||
def _get_int_model(self, uuid, interface_name, dev_id, seg_id):
|
||||
return models.L2GatewayInterface(id=uuid,
|
||||
interface_name=interface_name,
|
||||
device_id=dev_id,
|
||||
segmentation_id=seg_id)
|
@ -0,0 +1,63 @@
|
||||
# Copyright 2015 OpenStack Foundation
|
||||
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.db import model_base
|
||||
from neutron.db import models_v2
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import orm
|
||||
|
||||
|
||||
class L2GatewayConnection(model_base.BASEV2, models_v2.HasTenant,
|
||||
models_v2.HasId):
|
||||
"""Define an l2 gateway connection between a l2 gateway and a network."""
|
||||
l2_gateway_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('l2gateways.id',
|
||||
ondelete='CASCADE'))
|
||||
network_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('networks.id', ondelete='CASCADE'))
|
||||
__table_args__ = (sa.UniqueConstraint(l2_gateway_id,
|
||||
network_id),)
|
||||
|
||||
|
||||
class L2GatewayInterface(model_base.BASEV2, models_v2.HasId):
|
||||
"""Define an l2 gateway interface."""
|
||||
interface_name = sa.Column(sa.String(255))
|
||||
device_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('l2gatewaydevices.id',
|
||||
ondelete='CASCADE'))
|
||||
segmentation_id = sa.Column(sa.Integer)
|
||||
|
||||
|
||||
class L2GatewayDevice(model_base.BASEV2, models_v2.HasId):
|
||||
"""Define an l2 gateway device."""
|
||||
device_name = sa.Column(sa.String(255))
|
||||
interfaces = orm.relationship(L2GatewayInterface,
|
||||
backref='l2gatewaydevices',
|
||||
cascade='all,delete')
|
||||
l2_gateway_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('l2gateways.id',
|
||||
ondelete='CASCADE'))
|
||||
|
||||
|
||||
class L2Gateway(model_base.BASEV2, models_v2.HasId,
|
||||
models_v2.HasTenant):
|
||||
"""Define an l2 gateway."""
|
||||
name = sa.Column(sa.String(255))
|
||||
devices = orm.relationship(L2GatewayDevice,
|
||||
backref='l2gateways',
|
||||
cascade='all,delete')
|
||||
network_connections = orm.relationship(L2GatewayConnection,
|
||||
lazy='joined')
|
@ -0,0 +1,88 @@
|
||||
# Copyright 2015 OpenStack Foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
"""l2gateway_models
|
||||
|
||||
Revision ID: 42438454c556
|
||||
Revises: 54c9c8fe22bf
|
||||
Create Date: 2014-11-27 01:57:56.997665
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '42438454c556'
|
||||
down_revision = '54c9c8fe22bf'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table('l2gateways',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=True),
|
||||
sa.Column('tenant_id', sa.String(length=255),
|
||||
nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'))
|
||||
|
||||
op.create_table('l2gatewaydevices',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('device_name', sa.String(length=255),
|
||||
nullable=False),
|
||||
sa.Column('l2_gateway_id', sa.String(length=36),
|
||||
nullable=False),
|
||||
sa.ForeignKeyConstraint(['l2_gateway_id'],
|
||||
['l2gateways.id'],
|
||||
ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id'))
|
||||
|
||||
op.create_table('l2gatewayinterfaces',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('interface_name', sa.String(length=255),
|
||||
nullable=True),
|
||||
sa.Column('segmentation_id', sa.Integer(),
|
||||
nullable=True),
|
||||
sa.Column('device_id', sa.String(length=36),
|
||||
nullable=False),
|
||||
sa.ForeignKeyConstraint(['device_id'],
|
||||
['l2gatewaydevices.id'],
|
||||
ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id'))
|
||||
|
||||
op.create_table('l2gatewayconnections',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('tenant_id', sa.String(length=255),
|
||||
nullable=True),
|
||||
sa.Column('l2_gateway_id', sa.String(length=36),
|
||||
nullable=True),
|
||||
sa.Column('network_id', sa.String(length=36),
|
||||
nullable=True),
|
||||
sa.Column('segmentation_id', sa.Integer(),
|
||||
nullable=True),
|
||||
sa.ForeignKeyConstraint(['l2_gateway_id'],
|
||||
['l2gateways.id'],
|
||||
ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['network_id'], ['networks.id'],
|
||||
ondelete='CASCADE'),
|
||||
sa.UniqueConstraint('l2_gateway_id',
|
||||
'network_id'),
|
||||
sa.PrimaryKeyConstraint('id'))
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_table('l2gatewayconnections')
|
||||
op.drop_table('l2gatewayinterfaces')
|
||||
op.drop_table('l2gatewaydevices')
|
||||
op.drop_table('l2gateways')
|
@ -1 +1 @@
|
||||
54c9c8fe22bf
|
||||
42438454c556
|
||||
|
@ -0,0 +1,115 @@
|
||||
# Copyright 2015 OpenStack Foundation
|
||||
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import abc
|
||||
from neutron.api import extensions
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.api.v2 import resource_helper
|
||||
|
||||
from networking_l2gw.services.l2gateway.common import constants
|
||||
from networking_l2gw.services.l2gateway.common import l2gw_validators
|
||||
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
constants.L2_GATEWAYS: {
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
'is_visible': True},
|
||||
'name': {'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True, 'default': ''},
|
||||
'devices': {'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:l2gwdevice_list': None},
|
||||
'is_visible': True},
|
||||
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:string': None},
|
||||
'required_by_policy': True,
|
||||
'is_visible': True}
|
||||
},
|
||||
}
|
||||
|
||||
validator_func = l2gw_validators.validate_gwdevice_list
|
||||
attributes.validators['type:l2gwdevice_list'] = validator_func
|
||||
|
||||
|
||||
class L2gateway(extensions.ExtensionDescriptor):
|
||||
|
||||
"""API extension for Layer-2 Gateway support."""
|
||||
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return "L2 Gateway"
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return "l2-gateway"
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return "Connects Neutron networks with external networks at layer 2."
|
||||
|
||||
@classmethod
|
||||
def get_namespace(cls):
|
||||
return "https://review.openstack.org/#/c/144173/3/specs/kilo/"
|
||||
"l2-gateway-api.rst"
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
return "2015-01-01T00:00:00-00:00"
|
||||
|
||||
@classmethod
|
||||
def get_resources(cls):
|
||||
"""Returns Ext Resources."""
|
||||
mem_actions = {}
|
||||
plural_mappings = resource_helper.build_plural_mappings(
|
||||
{}, RESOURCE_ATTRIBUTE_MAP)
|
||||
attributes.PLURALS.update(plural_mappings)
|
||||
resources = resource_helper.build_resource_info(plural_mappings,
|
||||
RESOURCE_ATTRIBUTE_MAP,
|
||||
constants.L2GW,
|
||||
action_map=mem_actions,
|
||||
register_quota=True,
|
||||
translate_name=True)
|
||||
|
||||
return resources
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version == "2.0":
|
||||
return RESOURCE_ATTRIBUTE_MAP
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
||||
class L2GatewayPluginBase(object):
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_l2_gateway(self, context, l2_gateway):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_l2_gateway(self, context, id, fields=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete_l2_gateway(self, context, id):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_l2_gateways(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def update_l2_gateway(self, context, id, l2_gateway):
|
||||
pass
|
@ -0,0 +1,115 @@
|
||||
# Copyright 2015 OpenStack Foundation
|
||||
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import abc
|
||||
from neutron.api import extensions
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.api.v2 import resource_helper
|
||||
|
||||
from networking_l2gw.services.l2gateway.common import constants
|
||||
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
constants.L2_GATEWAYS_CONNECTION: {
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
'is_visible': True},
|
||||
'l2_gateway_id': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True, 'default': ''},
|
||||
'network_id': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True},
|
||||
'segmentation_id': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True, 'default': ''},
|
||||
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:string': None},
|
||||
'required_by_policy': True,
|
||||
'is_visible': True}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class L2gatewayconnection(extensions.ExtensionDescriptor):
|
||||
|
||||
"""API extension for Layer-2 Gateway connection support."""
|
||||
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return "L2 Gateway connection"
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return "l2-gateway-connection"
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return "Connects Neutron networks with external networks at layer 2."
|
||||
|
||||
@classmethod
|
||||
def get_namespace(cls):
|
||||
return "https://review.openstack.org/#/c/144173/3/specs/kilo/"
|
||||
"l2-gateway-api.rst"
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
return "2014-01-01T00:00:00-00:00"
|
||||
|
||||
@classmethod
|
||||
def get_resources(cls):
|
||||
"""Returns Ext Resources."""
|
||||
|
||||
mem_actions = {}
|
||||
plural_mappings = resource_helper.build_plural_mappings(
|
||||
{}, RESOURCE_ATTRIBUTE_MAP)
|
||||
attributes.PLURALS.update(plural_mappings)
|
||||
resources = resource_helper.build_resource_info(plural_mappings,
|
||||
RESOURCE_ATTRIBUTE_MAP,
|
||||
constants.L2GW,
|
||||
action_map=mem_actions,
|
||||
register_quota=True,
|
||||
translate_name=True)
|
||||
|
||||
return resources
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version == "2.0":
|
||||
return RESOURCE_ATTRIBUTE_MAP
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
||||
class L2GatewayConnectionPluginBase(object):
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete_l2_gateway_connection(self, context, l2_gateway_id,
|
||||
network_mapping_list):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_l2_gateway_connection(self, context, l2_gateway_id,
|
||||
network_mapping_list):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_l2_gateway_connections(self, context, filters=None,
|
||||
fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_l2_gateway_connection(self, context, id, fields=None):
|
||||
pass
|
@ -0,0 +1,87 @@
|
||||
# Copyright 2015 OpenStack Foundation
|
||||
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.common import exceptions
|
||||
|
||||
from networking_l2gw.services.l2gateway.common import constants
|
||||
|
||||
ALLOWED_CONNECTION_ATTRIBUTES = set((constants.NETWORK_ID,
|
||||
constants.SEG_ID,
|
||||
constants.L2GATEWAY_ID
|
||||
))
|
||||
|
||||
|
||||
def validate_gwdevice_list(data, valid_values=None):
|
||||
"""Validate the list of devices."""
|
||||
if not data:
|
||||
# Devices must be provided
|
||||
msg = _("Cannot create a gateway with an empty device list")
|
||||
return msg
|
||||
try:
|
||||
for device in data:
|
||||
interface_data = device.get(constants.IFACE_NAME_ATTR)
|
||||
device_name = device.get(constants.DEVICE_ID_ATTR)
|
||||
if not interface_data:
|
||||
msg = _("Cannot create a gateway with an empty interfaces")
|
||||
return msg
|
||||
if not device_name:
|
||||
msg = _("Cannot create a gateway with an empty device_name")
|
||||
return msg
|
||||
for int_dict in interface_data:
|
||||
err_msg = attributes._validate_dict(int_dict, None)
|
||||
if not int_dict.get('name'):
|
||||
msg = _("Cannot create a gateway with an empty"
|
||||
"interface name")
|
||||
return msg
|
||||
segmentation_id_list = int_dict.get(constants.SEG_ID)
|
||||
if type(segmentation_id_list) is not list:
|
||||
msg = _("segmentation_id type should be of list type ")
|
||||
return msg
|
||||
if not segmentation_id_list:
|
||||
msg = _("segmentation_id_list should not be empty")
|
||||
return msg
|
||||
if err_msg:
|
||||
return err_msg
|
||||
except TypeError:
|
||||
return (_("%s: provided data are not iterable") %
|
||||
validate_gwdevice_list.__name__)
|
||||
|
||||
|
||||
def validate_network_mapping_list(network_mapping, check_vlan):
|
||||
"""Validate network mapping list in connection."""
|
||||
if not network_mapping.get('segmentation_id'):
|
||||
if check_vlan is False:
|
||||
raise exceptions.InvalidInput(
|
||||
error_message=_("Segmentation id must be specified in create"
|
||||
"l2gateway connections"))
|
||||
network_id = network_mapping.get(constants.NETWORK_ID)
|
||||
if not network_id:
|
||||
raise exceptions.InvalidInput(
|
||||
error_message=_("A valid network identifier must be specified "
|
||||
"when connecting a network to a network "
|
||||
"gateway. Unable to complete operation"))
|
||||
connection_attrs = set(network_mapping.keys())
|
||||
if not connection_attrs.issubset(ALLOWED_CONNECTION_ATTRIBUTES):
|
||||
raise exceptions.InvalidInput(
|
||||
error_message=(_("Invalid keys found among the ones provided "
|
||||
"in request : %(connection_attrs)s."),
|
||||
connection_attrs))
|
||||
seg_id = network_mapping.get(constants.SEG_ID)
|
||||
if seg_id:
|
||||
if int(seg_id) < 0 or int(seg_id) > 4095:
|
||||
msg = _("Segmentation id is invalid")
|
||||
raise exceptions.InvalidInput(error_message=msg)
|
||||
return network_id
|
@ -0,0 +1,178 @@
|
||||
# Copyright 2015 OpenStack Foundation
|
||||
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron import context
|
||||
from neutron.openstack.common import log as logging
|
||||
from neutron.tests.unit import testlib_api
|
||||
|
||||
from networking_l2gw.db.l2gateway import l2gateway_db
|
||||
from networking_l2gw.services.l2gateway.common import constants
|
||||
from networking_l2gw.services.l2gateway import exceptions
|
||||
|
||||
from oslo.utils import importutils
|
||||
|
||||
DB_PLUGIN_KLASS = 'neutron.db.db_base_plugin_v2.NeutronDbPluginV2'
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class L2GWTestCase(testlib_api.SqlTestCase):
|
||||
|
||||
"""Unit test for l2 Gateway DB support."""
|
||||
|
||||
def setUp(self):
|
||||
super(L2GWTestCase, self).setUp()
|
||||
self.ctx = context.get_admin_context()
|
||||
self.mixin = l2gateway_db.L2GatewayMixin()
|
||||
self.gw_resource = constants.L2_GATEWAYS
|
||||
self.con_resource = constants.CONNECTION_RESOURCE_NAME
|
||||
self.plugin = importutils.import_object(DB_PLUGIN_KLASS)
|
||||
|
||||
def _create_l2gateway(self, l2gateway):
|
||||
"""Create l2gateway helper method."""
|
||||
with self.ctx.session.begin(subtransactions=True):
|
||||
return self.mixin.create_l2_gateway(self.ctx, l2gateway)
|
||||
|
||||
def _get_l2_gateway_data(self, name, device_name):
|
||||
"""Get l2 gateway data helper method."""
|
||||
data = {"l2_gateway": {"name": name,
|
||||
"devices":
|
||||
[{"interfaces": [{"name": "port1",
|
||||
"segmentation_id": ["111"]}],
|
||||
"device_name": device_name}]}}
|
||||
return data
|
||||
|
||||
def _get_nw_data(self):
|
||||
return {'network': {'id': 'fake-id',
|
||||
'name': 'net1',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'test-tenant',
|
||||
'shared': False}}
|
||||
|
||||
def _get_l2_gateway_data_without_seg_id(self, name, device_name):
|
||||
"""Get l2 gateway data helper method."""
|
||||
data = {"l2_gateway": {"name": name,
|
||||
"devices":
|
||||
[{"interfaces": [{"name": "port1"}],
|
||||
"device_name": device_name}]}}
|
||||
return data
|
||||
|
||||
def test_l2_gateway_create(self):
|
||||
"""Test l2 gateway create."""
|
||||
name = "l2gw_1"
|
||||
device_name = "device1"
|
||||
data = self._get_l2_gateway_data(name, device_name)
|
||||
result = self._create_l2gateway(data)
|
||||
self.assertEqual(result['name'], name)
|
||||
|
||||
def _get_l2_gateways(self):
|
||||
"""Update l2gateway helper."""
|
||||
with self.ctx.session.begin(subtransactions=True):
|
||||
return self.mixin.get_l2_gateways(self.ctx)
|
||||
|
||||
def test_l2gateway_list(self):
|
||||
"""Test l2 gateway list."""
|
||||
name = "l2gw_1"
|
||||
device_name = "device1"
|
||||
data = self._get_l2_gateway_data(name, device_name)
|
||||
self._create_l2gateway(data)
|
||||
result2 = self._get_l2_gateways()
|
||||
self.assertIn('id', result2[0])
|
||||
|
||||
def _update_l2_gateway(self, id, l2gateway):
|
||||
"""Update l2gateway helper."""
|
||||
with self.ctx.session.begin(subtransactions=True):
|
||||
return self.mixin.update_l2_gateway(self.ctx, id, l2gateway)
|
||||
|
||||
def test_l2_gateway_update(self):
|
||||
"""Test l2 gateway update."""
|
||||
name_create = "l2gw_1"
|
||||
name_update = "l2gw_2"
|
||||
device_name = "device1"
|
||||
data_l2gw_create = self._get_l2_gateway_data(name_create,
|
||||
device_name)
|
||||
gw_org = self._create_l2gateway(data_l2gw_create)
|
||||
l2gw_id = gw_org['id']
|
||||
l2_gw_update_dict = self._get_l2_gateway_data(name_update,
|
||||
device_name)
|
||||
result = self._update_l2_gateway(l2gw_id, l2_gw_update_dict)
|
||||
self.assertNotEqual(result['name'], name_create)
|
||||
|
||||
def _create_l2gateway_connection(self, l2gateway_con):
|
||||
"""Create L2 gateway connection resource helper method."""
|
||||
with self.ctx.session.begin(subtransactions=True):
|
||||
return self.mixin.create_l2_gateway_connection(self.ctx,
|
||||
l2gateway_con)
|
||||
|
||||
def _list_l2gateway_connection(self):
|
||||
"""Create L2 gateway connection resource helper method."""
|
||||
with self.ctx.session.begin(subtransactions=True):
|
||||
return self.mixin.get_l2_gateway_connections(self.ctx)
|
||||
|
||||
def test_l2gateway_connection_create_delete_list(self):
|
||||
"""Test l2 gateway connection create and delete."""
|
||||
name = "l2gw_con1"
|
||||
device_name = "device_name1"
|
||||
data_l2gw = self._get_l2_gateway_data(name, device_name)
|
||||
gw = self._create_l2gateway(data_l2gw)
|
||||
net_data = self._get_nw_data()
|
||||
net = self.plugin.create_network(self.ctx, net_data)
|
||||
l2gw_id = gw['id']
|
||||
data_con = {self.con_resource: {'l2_gateway_id': l2gw_id,
|
||||
'network_id': net['id'],
|
||||
'segmentation_id': "199"}}
|
||||
gw_con = self._create_l2gateway_connection(data_con)
|
||||
exp_net_id = gw_con['network_id']
|
||||
self.assertEqual(net['id'], exp_net_id)
|
||||
cn_id = gw_con['id']
|
||||
list_con = self._list_l2gateway_connection()
|
||||
self.assertIn('id', list_con[0])
|
||||
result = self._delete_l2gw_connection(cn_id)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_l2gateway_con_create_and_delete_in_use_without_seg_id(self):
|
||||
"""Test l2 gateway connection create without seg id when use."""
|
||||
name = "l2gw_con2"
|
||||
device_name = "device_name2"
|
||||
data_l2gw = self._get_l2_gateway_data(name,
|
||||
device_name)
|
||||
gw = self._create_l2gateway(data_l2gw)
|
||||
net_data = self._get_nw_data()
|
||||
net = self.plugin.create_network(self.ctx, net_data)
|
||||
l2gw_id = gw['id']
|
||||
data_con = {self.con_resource: {'l2_gateway_id': l2gw_id,
|
||||
'network_id': net['id']}}
|
||||
self._create_l2gateway_connection(data_con)
|
||||
self.assertRaises(exceptions.L2GatewayInUse,
|
||||
self._delete_l2gateway, l2gw_id)
|
||||
|
||||
def _delete_l2gateway(self, l2gw_id):
|
||||
"""Delete l2 gateway helper method."""
|
||||
with self.ctx.session.begin(subtransactions=True):
|
||||
return self.mixin.delete_l2_gateway(self.ctx,
|
||||
l2gw_id)
|
||||
|
||||
def test_l2gateway_delete(self):
|
||||
"""Test l2 gateway delete."""
|
||||
data_l2gw = self._get_l2_gateway_data("gateway_delete",
|
||||
"device_name")
|
||||
gw_actual = self._create_l2gateway(data_l2gw)
|
||||
l2gw_id = gw_actual['id']
|
||||
result = self._delete_l2gateway(l2gw_id)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def _delete_l2gw_connection(self, con_id):
|
||||
"""Delete l2 gateway connection."""
|
||||
with self.ctx.session.begin(subtransactions=True):
|
||||
return self.mixin.delete_l2_gateway_connection(self.ctx, con_id)
|
Loading…
Reference in New Issue