Fix L2GW service framework for out-of-tree drivers.

Enhance the L2GW Service Driver framework to embrace
out-of-L2GW-source-tree service drivers.

Co-Authored-By: Vivekanandan Narasimhan <n.vivekanandan@ericsson.com>
Closes-Bug:1532436

Change-Id: Ib56ee8bfd182c031e468c503acb0cd75daea8c40
stable/ocata
vikas 7 years ago committed by Vivekanandan Narasimhan
parent 28ed7f33d9
commit 42aee1db03
  1. 10
      devstack/README.rst
  2. 7
      devstack/plugin.sh
  3. 1
      devstack/settings
  4. 129
      networking_l2gw/db/l2gateway/l2gateway_db.py
  5. 6
      networking_l2gw/services/l2gateway/exceptions.py
  6. 158
      networking_l2gw/services/l2gateway/plugin.py
  7. 126
      networking_l2gw/services/l2gateway/service_drivers/__init__.py
  8. 38
      networking_l2gw/services/l2gateway/service_drivers/rpc_l2gw.py
  9. 25
      networking_l2gw/tests/unit/db/test_l2gw_db.py
  10. 2
      networking_l2gw/tests/unit/services/l2gateway/ovsdb/test_data.py
  11. 185
      networking_l2gw/tests/unit/services/l2gateway/test_plugin.py

@ -11,6 +11,16 @@
enable_service l2gw-plugin l2gw-agent
OVSDB_HOSTS=<ovsdb_name>:<ip address>:<port>
3. If you want to override the default service driver for L2Gateway (which uses
L2Gateway Agent with RPC) with an alternative service driver, please give that
alternative service driver inside the parameter NETWORKING_L2GW_SERVICE_DRIVER
of your ``local.conf``.
For example, to configure ODL service driver to be used for L2Gateway,
you need to include ODL Service Driver in ``local.conf`` as below:
NETWORKING_L2GW_SERVICE_DRIVER=L2GW:OpenDaylight:networking_odl.l2gateway.driver.OpenDaylightL2gwDriver:default
3. Read the settings file for more details.
4. run ``stack.sh``

@ -45,6 +45,13 @@ if is_service_enabled l2gw-plugin; then
elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
configure_l2gw_plugin
run_l2gw_alembic_migration
if is_service_enabled q-svc; then
echo_summary "Configuring networking-l2gw"
if [ "$NETWORKING_L2GW_SERVICE_DRIVER" ]; then
inicomment $L2GW_PLUGIN_CONF_FILE service_providers service_provider
iniadd $L2GW_PLUGIN_CONF_FILE service_providers service_provider $NETWORKING_L2GW_SERVICE_DRIVER
fi
fi
elif [[ "$1" == "stack" && "$2" == "post-extra" ]]; then
# no-op
:

@ -6,6 +6,7 @@ L2GW_CONF_FILE=/etc/neutron/l2gateway_agent.ini
L2GW_PLUGIN_CONF_FILE=/etc/neutron/l2gw_plugin.ini
Q_PLUGIN_EXTRA_CONF_PATH=/etc/neutron
Q_PLUGIN_EXTRA_CONF_FILES=(l2gw_plugin.ini)
#NETWORKING_L2GW_SERVICE_DRIVER=L2GW:OpenDaylight:networking_odl.l2gateway.driver.OpenDaylightL2gwDriver:default
#
# Each service you enable has the following meaning:

@ -145,7 +145,6 @@ class L2GatewayMixin(l2gateway.L2GatewayPluginBase,
gw = l2_gateway[self.gateway_resource]
tenant_id = self._get_tenant_id_for_create(context, gw)
devices = gw['devices']
self._validate_any_seg_id_empty_in_interface_dict(devices)
with context.session.begin(subtransactions=True):
gw_db = models.L2Gateway(
id=gw.get('id', uuidutils.generate_uuid()),
@ -185,38 +184,31 @@ class L2GatewayMixin(l2gateway.L2GatewayPluginBase,
return self._make_l2_gateway_dict(gw_db)
def update_l2_gateway(self, context, id, l2_gateway):
"""Update l2 gateway."""
self._admin_check(context, 'UPDATE')
"""Update L2Gateway."""
gw = l2_gateway[self.gateway_resource]
if 'devices' in gw:
devices = gw['devices']
devices = gw.get('devices')
dev_db = None
l2gw_db = None
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)
dev_db = self._get_l2_gateway_devices(context, id)
if not gw.get('devices'):
l2gw_db.name = gw.get('name')
return self._make_l2_gateway_dict(l2gw_db)
l2gw_db = self._get_l2_gateway(context, id)
if not devices and l2gw_db:
l2gw_db.name = gw.get('name')
return self._make_l2_gateway_dict(l2gw_db)
if devices:
for device in devices:
dev_name = device['device_name']
dev_db = self._get_l2gw_devices_by_name_andl2gwid(context,
dev_name,
id)
if not dev_db:
raise l2gw_exc.L2GatewayDeviceNotFound(device_id="")
dev_db = (self._get_l2gw_devices_by_name_andl2gwid(
context, dev_name, id))
interface_dict_list = [i for i in device['interfaces']]
interface_db = self._get_l2_gw_interfaces(context,
dev_db[0].id)
self._delete_l2_gateway_interfaces(context, interface_db)
interface_dict_list = []
self.validate_device_name(context, dev_name, id)
for interfaces in device['interfaces']:
interface_dict_list.append(interfaces)
self._update_interfaces_db(context, interface_dict_list,
dev_db)
if gw.get('name'):
l2gw_db.name = gw.get('name')
return self._make_l2_gateway_dict(l2gw_db)
if l2gw_db:
if gw.get('name'):
l2gw_db.name = gw.get('name')
return self._make_l2_gateway_dict(l2gw_db)
def _update_interfaces_db(self, context, interface_dict_list, device_db):
for interfaces in interface_dict_list:
@ -249,15 +241,11 @@ class L2GatewayMixin(l2gateway.L2GatewayPluginBase,
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)
gw_db = self._get_l2_gateway(context, id)
if gw_db:
with context.session.begin(subtransactions=True):
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,
@ -293,7 +281,6 @@ class L2GatewayMixin(l2gateway.L2GatewayPluginBase,
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')
@ -304,10 +291,6 @@ class L2GatewayMixin(l2gateway.L2GatewayPluginBase,
if constants.SEG_ID in gw_connection:
segmentation_id = gw_connection.get(constants.SEG_ID)
nw_map[constants.SEG_ID] = segmentation_id
is_vlan = self._is_vlan_configured_on_any_interface_for_l2gw(context,
l2_gw_id)
network_id = l2gw_validators.validate_network_mapping_list(nw_map,
is_vlan)
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)
@ -354,7 +337,6 @@ class L2GatewayMixin(l2gateway.L2GatewayPluginBase,
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)
@ -499,6 +481,75 @@ class L2GatewayMixin(l2gateway.L2GatewayPluginBase,
device_id=device_name)
return gw
def validate_l2_gateway_for_create(self, context, l2_gateway):
self._admin_check(context, 'CREATE')
gw = l2_gateway[self.gateway_resource]
devices = gw['devices']
self._validate_any_seg_id_empty_in_interface_dict(devices)
def validate_l2_gateway_for_delete(self, context, l2gw_id):
self._admin_check(context, 'DELETE')
gw_db = self._get_l2_gateway(context, l2gw_id)
if gw_db is None:
raise l2gw_exc.L2GatewayNotFound(gateway_id=l2gw_id)
if gw_db.network_connections:
raise l2gw_exc.L2GatewayInUse(gateway_id=l2gw_id)
return
def validate_l2_gateway_for_update(self, context, id, l2_gateway):
self._admin_check(context, 'UPDATE')
gw = l2_gateway[self.gateway_resource]
devices = None
dev_db = None
l2gw_db = None
if 'devices' in gw:
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)
if devices:
for device in devices:
dev_name = device['device_name']
dev_db = (self._get_l2gw_devices_by_name_andl2gwid(
context, dev_name, id))
if not dev_db:
raise l2gw_exc.L2GatewayDeviceNotFound(device_id="")
self.validate_device_name(context, dev_name, id)
def validate_l2_gateway_connection_for_create(self, context,
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')
nw_map = {}
nw_map['network_id'] = network_id
nw_map['l2_gateway_id'] = l2_gw_id
segmentation_id = ""
if constants.SEG_ID in gw_connection:
segmentation_id = gw_connection.get(constants.SEG_ID)
nw_map[constants.SEG_ID] = segmentation_id
is_vlan = self._is_vlan_configured_on_any_interface_for_l2gw(context,
l2_gw_id)
network_id = l2gw_validators.validate_network_mapping_list(nw_map,
is_vlan)
with context.session.begin(subtransactions=True):
if self._retrieve_gateway_connections(context,
l2_gw_id,
nw_map):
raise l2gw_exc.L2GatewayConnectionExists(mapping=nw_map,
gateway_id=l2_gw_id)
def validate_l2_gateway_connection_for_delete(self, context,
l2_gateway_conn_id):
self._admin_check(context, 'DELETE')
gw_db = self._get_l2_gateway_connection(context,
l2_gateway_conn_id)
if gw_db is None:
raise l2gw_exc.L2GatewayConnectionNotFound(
gateway_id=l2_gateway_conn_id)
def l2gw_callback(resource, event, trigger, **kwargs):
l2gwservice = manager.NeutronManager.get_service_plugins().get(

@ -114,6 +114,12 @@ class L2GatewayDuplicateSegmentationID(exceptions.Conflict):
class OVSDBError(exceptions.NeutronException):
message = _("%(message)s")
class L2GatewayServiceDriverError(exceptions.NeutronException):
"""Service driver call failed."""
message = _("%(method)s failed.")
base.FAULT_MAP.update({L2GatewayInUse: web_exc.HTTPConflict,
L2GatewayPortInUse: web_exc.HTTPConflict,
L2GatewayConnectionExists: web_exc.HTTPConflict,

@ -13,15 +13,19 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_utils import excutils
from neutron.db import servicetype_db as st_db
from neutron import manager
from neutron.services import provider_configuration as pconf
from neutron.services import service_base
from networking_l2gw._i18n import _LE
from networking_l2gw._i18n import _LI
from networking_l2gw.db.l2gateway import l2gateway_db
from networking_l2gw.services.l2gateway.common import config
from networking_l2gw.services.l2gateway.common import constants
from networking_l2gw.services.l2gateway import exceptions as exc
from neutron_lib import exceptions as n_exc
from oslo_log import log as logging
@ -29,12 +33,6 @@ from oslo_log import log as logging
LOG = logging.getLogger(__name__)
def add_provider_configuration(type_manager, service_type):
type_manager.add_provider_configuration(
service_type,
pconf.ProviderConfiguration('networking_l2gw'))
class L2GatewayPlugin(l2gateway_db.L2GatewayMixin):
"""Implementation of the Neutron l2 gateway Service Plugin.
@ -49,8 +47,16 @@ class L2GatewayPlugin(l2gateway_db.L2GatewayMixin):
"""Do the initialization for the l2 gateway service plugin here."""
config.register_l2gw_opts_helper()
self.service_type_manager = st_db.ServiceTypeManager.get_instance()
add_provider_configuration(self.service_type_manager, constants.L2GW)
self.service_type_manager.add_provider_configuration(
constants.L2GW, pconf.ProviderConfiguration('networking_l2gw'))
self._load_drivers()
LOG.info(_LI("L2Gateway Service Plugin using Service Driver: %s"),
self.default_provider)
self.driver = self.drivers[self.default_provider]
if len(self.drivers) > 1:
LOG.warning(_LI("Multiple drivers configured for L2Gateway, "
"although running multiple drivers in parallel"
" is not yet supported"))
super(L2GatewayPlugin, self).__init__()
l2gateway_db.subscribe()
@ -79,43 +85,117 @@ class L2GatewayPlugin(l2gateway_db.L2GatewayMixin):
return constants.L2_GATEWAY_SERVICE_PLUGIN
def add_port_mac(self, context, port_dict):
"""Process the created port and trigger the RPC
to add to the gateway.
"""
self._get_driver_for_provider(constants.l2gw
).add_port_mac(context, port_dict)
"""Process a created Neutron port."""
self.driver.add_port_mac(context, port_dict)
def delete_port_mac(self, context, port):
"""Process the deleted port and trigger the RPC
to delete from the gateway.
When the ML2 plugin invokes this call, the argument port is
a single port dict, whereas the L2gateway service plugin
sends it as a list of port dicts.
"""
self._get_driver_for_provider(constants.l2gw
).delete_port_mac(context, port)
"""Process a deleted Neutron port."""
self.driver.delete_port_mac(context, port)
def create_l2_gateway(self, context, l2_gateway):
"""Create the L2Gateway."""
self.validate_l2_gateway_for_create(context, l2_gateway)
self.driver.create_l2_gateway(context, l2_gateway)
with context.session.begin(subtransactions=True):
l2_gateway_instance = super(L2GatewayPlugin,
self).create_l2_gateway(context,
l2_gateway)
self.driver.create_l2_gateway_precommit(context,
l2_gateway_instance)
try:
self.driver.create_l2_gateway_postcommit(
context, l2_gateway_instance)
except exc.L2GatewayServiceDriverError:
with excutils.save_and_reraise_exception():
LOG.error(_LE("L2GatewayPlugin.create_l2_gateway_postcommit "
"failed, deleting l2gateway '%s'"),
l2_gateway_instance['id'])
self.delete_l2_gateway(context, l2_gateway_instance['id'])
return l2_gateway_instance
def update_l2_gateway(self, context, l2_gateway_id, l2_gateway):
"""Update the L2Gateway."""
self.validate_l2_gateway_for_update(context, l2_gateway_id, l2_gateway)
self.driver.update_l2_gateway(context, l2_gateway_id, l2_gateway)
with context.session.begin(subtransactions=True):
l2_gateway_instance = super(L2GatewayPlugin,
self).update_l2_gateway(context,
l2_gateway_id,
l2_gateway)
self.driver.update_l2_gateway_precommit(context,
l2_gateway_instance)
try:
self.driver.update_l2_gateway_postcommit(
context, l2_gateway_instance)
except exc.L2GatewayServiceDriverError:
with excutils.save_and_reraise_exception():
LOG.error(_LE("L2GatewayPlugin.update_l2_gateway_postcommit"
" failed for l2gateway %s"), l2_gateway_id)
return l2_gateway_instance
def delete_l2_gateway(self, context, l2_gateway_id):
"""Delete the L2Gateway."""
self.validate_l2_gateway_for_delete(context, l2_gateway_id)
self.driver.delete_l2_gateway(context, l2_gateway_id)
with context.session.begin(subtransactions=True):
super(L2GatewayPlugin, self).delete_l2_gateway(context,
l2_gateway_id)
self.driver.delete_l2_gateway_precommit(context, l2_gateway_id)
try:
self.driver.delete_l2_gateway_postcommit(context, l2_gateway_id)
except exc.L2GatewayServiceDriverError:
with excutils.save_and_reraise_exception():
LOG.error(_LE("L2GatewayPlugin.delete_l2_gateway_postcommit"
" failed for l2gateway %s"), l2_gateway_id)
def create_l2_gateway_connection(self, context, l2_gateway_connection):
"""Process the call from the CLI and trigger the RPC,
"""Create an L2Gateway Connection
to update the connection to the gateway.
Bind a Neutron VXLAN Network to Physical Network Segment.
"""
self._get_driver_for_provider(constants.l2gw
).create_l2_gateway_connection(
context, l2_gateway_connection)
return super(L2GatewayPlugin, self).create_l2_gateway_connection(
self.validate_l2_gateway_connection_for_create(
context, l2_gateway_connection)
def delete_l2_gateway_connection(self, context, l2_gateway_connection):
"""Process the call from the CLI and trigger the RPC,
to update the connection from the gateway.
self.driver.create_l2_gateway_connection(context,
l2_gateway_connection)
with context.session.begin(subtransactions=True):
l2_gateway_conn_instance = super(
L2GatewayPlugin, self).create_l2_gateway_connection(
context, l2_gateway_connection)
self.driver.create_l2_gateway_connection_precommit(
context, l2_gateway_conn_instance)
try:
self.driver.create_l2_gateway_connection_postcommit(
context, l2_gateway_conn_instance)
except exc.L2GatewayServiceDriverError:
with excutils.save_and_reraise_exception():
LOG.error(_LE("L2GatewayPlugin."
"create_l2_gateway_connection_postcommit "
"failed, deleting connection '%s'"),
l2_gateway_conn_instance['id'])
self.delete_l2_gateway_connection(
context, l2_gateway_conn_instance['id'])
return l2_gateway_conn_instance
def delete_l2_gateway_connection(self, context, l2_gateway_connection_id):
"""Delete an L2Gateway Connection
Unbind a Neutron VXLAN Network from Physical Network Segment.
"""
self._get_driver_for_provider(constants.l2gw
).delete_l2_gateway_connection(
context, l2_gateway_connection)
return super(L2GatewayPlugin, self).delete_l2_gateway_connection(
context, l2_gateway_connection)
self.validate_l2_gateway_connection_for_delete(
context, l2_gateway_connection_id)
self.driver.delete_l2_gateway_connection(
context, l2_gateway_connection_id)
with context.session.begin(subtransactions=True):
super(L2GatewayPlugin, self).delete_l2_gateway_connection(
context, l2_gateway_connection_id)
self.driver.delete_l2_gateway_connection_precommit(
context, l2_gateway_connection_id)
try:
self.driver.delete_l2_gateway_connection_postcommit(
context, l2_gateway_connection_id)
except exc.L2GatewayServiceDriverError:
with excutils.save_and_reraise_exception():
LOG.error(_LE(
"L2GatewayPlugin.delete_l2_gateway_connection_postcommit"
" failed for connection %s"), l2_gateway_connection_id)

@ -23,7 +23,7 @@ LOG = logging.getLogger(__name__)
@six.add_metaclass(abc.ABCMeta)
class L2gwDriver(object):
class L2gwDriverBase(object):
def __init__(self, service_plugin, validator=None):
self.service_plugin = service_plugin
@ -40,10 +40,132 @@ class L2gwDriver(object):
def delete_port_mac(self, context, port):
pass
@abc.abstractmethod
def create_l2_gateway(self, context, l2_gateway):
pass
@abc.abstractmethod
def update_l2_gateway(self, context, l2_gateway_id, l2_gateway):
pass
@abc.abstractmethod
def delete_l2_gateway(self, context, l2_gateway_id):
pass
@abc.abstractmethod
def create_l2_gateway_connection(self, context, l2_gateway_connection):
pass
@abc.abstractmethod
def delete_l2_gateway_connection(self, context, l2_gateway_connection):
def delete_l2_gateway_connection(self, context, l2_gateway_connection_id):
pass
@abc.abstractmethod
def create_l2_gateway_precommit(self, context, l2_gateway):
pass
@abc.abstractmethod
def update_l2_gateway_precommit(self, context, l2_gateway):
pass
@abc.abstractmethod
def delete_l2_gateway_precommit(self, context, l2_gateway_id):
pass
@abc.abstractmethod
def create_l2_gateway_connection_precommit(self, context,
l2_gateway_connection):
pass
@abc.abstractmethod
def delete_l2_gateway_connection_precommit(self, context,
l2_gateway_connection_id):
pass
@abc.abstractmethod
def create_l2_gateway_postcommit(self, context, l2_gateway):
pass
@abc.abstractmethod
def delete_l2_gateway_postcommit(self, context, l2_gateway_id):
pass
@abc.abstractmethod
def update_l2_gateway_postcommit(self, context, l2_gateway):
pass
@abc.abstractmethod
def create_l2_gateway_connection_postcommit(self, context,
l2_gateway_connection):
pass
@abc.abstractmethod
def delete_l2_gateway_connection_postcommit(self, context,
l2_gateway_connection_id):
pass
@six.add_metaclass(abc.ABCMeta)
class L2gwDriver(L2gwDriverBase):
def __init__(self, service_plugin, validator=None):
super(L2gwDriver, self).__init__(service_plugin)
@property
def service_type(self):
pass
def add_port_mac(self, context, port_dict):
pass
def delete_port_mac(self, context, port):
pass
def create_l2_gateway(self, context, l2_gateway):
pass
def update_l2_gateway(self, context, l2_gateway_id, l2_gateway):
pass
def delete_l2_gateway(self, context, l2_gateway_id):
pass
def create_l2_gateway_connection(self, context, l2_gateway_connection):
pass
def delete_l2_gateway_connection(self, context, l2_gateway_connection_id):
pass
def create_l2_gateway_precommit(self, context, l2_gateway):
pass
def update_l2_gateway_precommit(self, context, l2_gateway):
pass
def delete_l2_gateway_precommit(self, context, l2_gateway_id):
pass
def create_l2_gateway_connection_precommit(self, context,
l2_gateway_connection):
pass
def delete_l2_gateway_connection_precommit(self, context,
l2_gateway_connection_id):
pass
def create_l2_gateway_postcommit(self, context, l2_gateway):
pass
def delete_l2_gateway_postcommit(self, context, l2_gateway_id):
pass
def update_l2_gateway_postcommit(self, context, l2_gateway):
pass
def create_l2_gateway_connection_postcommit(self, context,
l2_gateway_connection):
pass
def delete_l2_gateway_connection_postcommit(self, context,
l2_gateway_connection_id):
pass

@ -19,6 +19,7 @@ from neutron.db import agents_db
from neutron.extensions import portbindings
from networking_l2gw._i18n import _LE
from networking_l2gw.db.l2gateway import l2gateway_db as l2_gw_db
from networking_l2gw.db.l2gateway.ovsdb import lib as db
from networking_l2gw.services.l2gateway import agent_scheduler
from networking_l2gw.services.l2gateway.common import constants
@ -62,6 +63,8 @@ class L2gwRpcDriver(service_drivers.L2gwDriver):
self.create_rpc_conn()
LOG.debug("starting l2gateway agent scheduler")
self.start_l2gateway_agent_scheduler()
self.gateway_resource = constants.GATEWAY_RESOURCE_NAME
self.l2gateway_db = l2_gw_db.L2GatewayMixin()
@property
def service_type(self):
@ -556,6 +559,33 @@ class L2gwRpcDriver(service_drivers.L2gwDriver):
locator_list.append(pl_dict)
return locator_list
def create_l2_gateway(self, context, l2_gateway):
pass
def create_l2_gateway_postcommit(self, context, l2_gateway):
pass
def update_l2_gateway(self, context, l2_gateway_id, l2_gateway):
"""Update l2 gateway."""
pass
def update_l2_gateway_postcommit(self, context, l2_gateway):
pass
def delete_l2_gateway(self, context, id):
"""delete the l2 gateway by id."""
self.l2gateway_db._admin_check(context, 'DELETE')
with context.session.begin(subtransactions=True):
gw_db = self.l2gateway_db._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)
return gw_db
def delete_l2_gateway_postcommit(self, context, l2_gateway_id):
pass
def create_l2_gateway_connection(self, context, l2_gateway_connection):
"""Process the call from the CLI and trigger the RPC,
@ -656,6 +686,10 @@ class L2gwRpcDriver(service_drivers.L2gwDriver):
port['ovsdb_identifier'] = ovsdb_id
self.delete_port_mac(context, ports)
def create_l2_gateway_connection_postcommit(self, context,
l2_gateway_connection):
pass
def delete_l2_gateway_connection(self, context, l2_gateway_connection):
"""Process the call from the CLI and trigger the RPC,
@ -691,3 +725,7 @@ class L2gwRpcDriver(service_drivers.L2gwDriver):
port_dict)
# call delete vif_from_gateway for ovsdb_id_set
self._remove_vm_macs(context, network_id, ovsdb_id_set)
def delete_l2_gateway_connection_postcommit(self, context,
l2_gateway_connection):
pass

@ -222,6 +222,22 @@ class L2GWTestCase(testlib_api.SqlTestCase):
result = self._delete_l2gw_connection_by_l2gw_id(l2gw_id)
self.assertIsNone(result)
def _validate_l2_gateway_for_delete(self, l2gw_id):
"""Delete l2 gateway helper method."""
with self.ctx.session.begin(subtransactions=True):
return self.mixin.validate_l2_gateway_for_delete(self.ctx, l2gw_id)
def _validate_l2_gateway_for_create(self, l2gw):
"""Create l2 gateway helper method."""
with self.ctx.session.begin(subtransactions=True):
return self.mixin.validate_l2_gateway_for_create(self.ctx, l2gw)
def _validate_l2_gateway_for_update(self, l2gw_id, l2gw):
"""Update l2 gateway helper method."""
with self.ctx.session.begin(subtransactions=True):
return self.mixin.validate_l2_gateway_for_update(self.ctx,
l2gw_id, l2gw)
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"
@ -236,7 +252,7 @@ class L2GWTestCase(testlib_api.SqlTestCase):
'network_id': net['id']}}
self._create_l2gateway_connection(data_con)
self.assertRaises(exceptions.L2GatewayInUse,
self._delete_l2gateway, l2gw_id)
self._validate_l2_gateway_for_delete, l2gw_id)
def _delete_l2gateway(self, l2gw_id):
"""Delete l2 gateway helper method."""
@ -266,14 +282,14 @@ class L2GWTestCase(testlib_api.SqlTestCase):
result = self._create_l2gateway(data)
self.assertEqual(result['name'], name)
def test_l2_gateway_create_with_mul_interfaces_inconsitent_seg_id(self):
def test_l2_gateway_create_with_mul_interfaces_inconsistent_seg_id(self):
"""Test l2 gateway create with multiple interfaces."""
name = "l2gw_1"
dev_name = "device1"
data = self._get_l2_gw_multiple_interface_partial_seg_id_data(name,
dev_name)
self.assertRaises(exceptions.L2GatewaySegmentationRequired,
self._create_l2gateway, data)
self._validate_l2_gateway_for_create, data)
def test_l2_gateway_create_with_invalid_seg_id(self):
"""Test l2 gateway create with invalid seg-id."""
@ -303,7 +319,8 @@ class L2GWTestCase(testlib_api.SqlTestCase):
gw_org = self._create_l2gateway(data_l2gw_create)
l2gw_id = gw_org['id']
self.assertRaises(exceptions.L2GatewayDeviceNotFound,
self._update_l2_gateway, l2gw_id, data_l2gw_update)
self._validate_l2_gateway_for_update, l2gw_id,
data_l2gw_update)
def test_l2gw_callback_update_port(self):
service_plugins = {constants.L2GW: mock.Mock()}

@ -28,7 +28,7 @@ from networking_l2gw.services.l2gateway.ovsdb import data
from networking_l2gw.services.l2gateway.service_drivers import agent_api
class TestL2GatewayOVSDBCallbacks():
class TestL2GatewayOVSDBCallbacks(object):
def setUp(self):
super(TestL2GatewayOVSDBCallbacks, self).setUp()

@ -1,4 +1,4 @@
# Copyright (c) 2015 OpenStack Foundation
# Copyright (c) 2016 Openstack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -27,30 +27,167 @@ class TestL2GatewayPlugin(base.BaseTestCase):
def setUp(self):
super(TestL2GatewayPlugin, self).setUp()
load_driver = mock.MagicMock()
self.plugin = mock.MagicMock()
self.plugin._load_drivers.return_value = load_driver
self.plugin._get_driver_for_provider.return_value = load_driver
mock.patch.object(config, 'register_l2gw_opts_helper')
self.driver = mock.MagicMock()
mock.patch('neutron.services.service_base.load_drivers',
return_value=({'dummyprovider': self.driver},
'dummyprovider')).start()
mock.patch.object(l2gateway_db.L2GatewayMixin, '__init__'),
mock.patch.object(l2gateway_db, 'subscribe')
mock.patch('neutron.db.servicetype_db.ServiceTypeManager.get_instance',
return_value=mock.MagicMock()).start()
self.context = mock.MagicMock()
self.plugin = l2gw_plugin.L2GatewayPlugin()
self.ovsdb_identifier = 'fake_ovsdb_id'
self.ovsdb_data = data.OVSDBData(self.ovsdb_identifier)
self.context = mock.ANY
def test_l2gatewayplugin_init(self):
def _get_fake_l2_gateway(self):
fake_l2_gateway_id = "5227c228-6bba-4bbe-bdb8-6942768ff0f1"
fake_l2_gateway = {
"tenant_id": "de0a7495-05c4-4be0-b796-1412835c6820",
"id": "5227c228-6bba-4bbe-bdb8-6942768ff0f1",
"name": "test-gateway",
"devices": [
{
"device_name": "switch1",
"interfaces": [
{
"name": "port1",
"segmentation_id": [100]
},
{
"name": "port2",
"segmentation_id": [151, 152]
}
]
}
]
}
return fake_l2_gateway_id, fake_l2_gateway
def _get_fake_l2_gateway_connection(self):
fake_l2_gateway_conn_id = "5227c228-6bba-4bbe-bdb8-6942768ff02f"
fake_l2_gateway_conn = {
"tenant_id": "de0a7495-05c4-4be0-b796-1412835c6820",
"id": "5227c228-6bba-4bbe-bdb8-6942768ff02f",
"default_segmentation_id": 77,
"network_id": "5227c228-6bba-4bbe-bdb8-6942768ff077",
"l2_gateway_id": "4227c228-6bba-4bbe-bdb8-6942768ff088"
}
return fake_l2_gateway_conn_id, fake_l2_gateway_conn
def test_add_port_mac(self):
self.plugin.add_port_mac(self.context, {})
self.driver.add_port_mac.assert_called_once_with(self.context, {})
def test_delete_port_mac(self):
self.plugin.delete_port_mac(self.context, {})
self.driver.delete_port_mac.assert_called_once_with(self.context, {})
def test_create_l2_gateway(self):
fake_l2gw_id, fake_l2gw = self._get_fake_l2_gateway()
with contextlib.nested(
mock.patch.object(l2gateway_db.L2GatewayMixin,
'validate_l2_gateway_for_create'),
mock.patch.object(l2gateway_db.L2GatewayMixin,
'create_l2_gateway',
return_value=fake_l2gw)
) as (mock_validate_for_create, mock_create_l2gw_db):
self.plugin.create_l2_gateway(self.context, fake_l2gw)
mock_validate_for_create.assert_called_with(self.context,
fake_l2gw)
mock_create_l2gw_db.assert_called_with(self.context, fake_l2gw)
self.driver.create_l2_gateway.assert_called_once_with(self.context,
fake_l2gw)
self.driver.create_l2_gateway_precommit.assert_called_once_with(
self.context, fake_l2gw)
self.driver.create_l2_gateway_postcommit.assert_called_once_with(
self.context, fake_l2gw)
def test_delete_l2_gateway(self):
fake_l2gw_id, fake_l2gw = self._get_fake_l2_gateway()
with contextlib.nested(
mock.patch.object(l2gateway_db.L2GatewayMixin,
'validate_l2_gateway_for_delete'),
mock.patch.object(l2gateway_db.L2GatewayMixin,
'delete_l2_gateway')
) as (mock_validate_for_delete, mock_delete_l2gw_db):
self.plugin.delete_l2_gateway(self.context, fake_l2gw_id)
mock_validate_for_delete.assert_called_with(self.context,
fake_l2gw_id)
mock_delete_l2gw_db.assert_called_with(self.context, fake_l2gw_id)
self.driver.delete_l2_gateway.assert_called_once_with(self.context,
fake_l2gw_id)
self.driver.delete_l2_gateway_precommit.assert_called_once_with(
self.context, fake_l2gw_id)
self.driver.delete_l2_gateway_postcommit.assert_called_once_with(
self.context, fake_l2gw_id)
def test_update_l2_gateway(self):
fake_l2gw_id, fake_l2gw = self._get_fake_l2_gateway()
with contextlib.nested(
mock.patch.object(l2gateway_db.L2GatewayMixin,
'validate_l2_gateway_for_update'),
mock.patch.object(l2gateway_db.L2GatewayMixin,
'update_l2_gateway', return_value=fake_l2gw)
) as (mock_validate_for_update, mock_update_l2gw_db):
self.plugin.update_l2_gateway(self.context,
fake_l2gw_id,
fake_l2gw)
mock_validate_for_update.assert_called_with(self.context,
fake_l2gw_id,
fake_l2gw)
mock_update_l2gw_db.assert_called_with(self.context, fake_l2gw_id,
fake_l2gw)
self.driver.update_l2_gateway.assert_called_once_with(self.context,
fake_l2gw_id,
fake_l2gw)
self.driver.update_l2_gateway_precommit.assert_called_once_with(
self.context, fake_l2gw)
self.driver.update_l2_gateway_postcommit.assert_called_once_with(
self.context, fake_l2gw)
def test_create_l2_gateway_connection(self):
fake_l2gw_conn_id, fake_l2gw_conn = (
self._get_fake_l2_gateway_connection())
with contextlib.nested(
mock.patch.object(config,
'register_l2gw_opts_helper'),
mock.patch.object(l2gw_plugin.L2GatewayPlugin,
'_load_drivers'),
mock.patch.object(l2gateway_db.L2GatewayMixin,
'__init__'),
mock.patch.object(l2gateway_db,
'subscribe')
) as (reg_l2gw_opts,
load_drivers,
super_init,
subscribe):
l2gw_plugin.L2GatewayPlugin()
self.assertTrue(reg_l2gw_opts.called)
self.assertTrue(load_drivers.called)
self.assertTrue(super_init.called)
self.assertTrue(subscribe.called)
mock.patch.object(l2gateway_db.L2GatewayMixin,
'validate_l2_gateway_connection_for_create'),
mock.patch.object(l2gateway_db.L2GatewayMixin,
'create_l2_gateway_connection',
return_value=fake_l2gw_conn)
) as (mock_validate_for_conn_create, mock_conn_create_l2gw_db):
self.plugin.create_l2_gateway_connection(self.context,
fake_l2gw_conn)
mock_validate_for_conn_create.assert_called_with(self.context,
fake_l2gw_conn)
mock_conn_create_l2gw_db.assert_called_with(self.context,
fake_l2gw_conn)
self.driver.create_l2_gateway_connection.assert_called_once_with(
self.context, fake_l2gw_conn)
(self.driver.create_l2_gateway_connection_precommit.
assert_called_once_with(self.context, fake_l2gw_conn))
(self.driver.create_l2_gateway_connection_postcommit.
assert_called_once_with(self.context, fake_l2gw_conn))
def test_delete_l2_gateway_connection(self):
fake_l2gw_conn_id, fake_l2gw_conn = (
self._get_fake_l2_gateway_connection())
with contextlib.nested(
mock.patch.object(l2gateway_db.L2GatewayMixin,
'validate_l2_gateway_connection_for_delete'),
mock.patch.object(l2gateway_db.L2GatewayMixin,
'delete_l2_gateway_connection')
) as (mock_validate_for_conn_delete, mock_conn_delete_l2gw_db):
self.plugin.delete_l2_gateway_connection(self.context,
fake_l2gw_conn_id)
mock_validate_for_conn_delete.assert_called_with(self.context,
fake_l2gw_conn_id)
mock_conn_delete_l2gw_db.assert_called_with(self.context,
fake_l2gw_conn_id)
self.driver.delete_l2_gateway_connection.assert_called_once_with(
self.context, fake_l2gw_conn_id)
(self.driver.delete_l2_gateway_connection_precommit.
assert_called_once_with(self.context, fake_l2gw_conn_id))
(self.driver.delete_l2_gateway_connection_postcommit.
assert_called_once_with(self.context, fake_l2gw_conn_id))

Loading…
Cancel
Save