Layer 3 service plugin to support hardware based routing

Change-Id: Ie8e97a6d4fde0bda7cf049696e1384586492f676
Implements: blueprint brocade-l3-svi-service-plugin
This commit is contained in:
Shiv Haris 2014-08-16 19:09:52 -07:00
parent 6454ce084e
commit dee32d91e0
6 changed files with 661 additions and 2 deletions

View File

@ -58,3 +58,13 @@ Additionally the brocade mechanism driver needs to be enabled from the ml2 confi
Required L2 Agent
This mechanism driver works in conjunction with an L2 Agent. The agent should be loaded as well in order for it to configure the virtual network int the host machine. Please see the configuration above. Atleast one of linuxbridge or openvswitch must be specified.
Hardware L3 Router (SVI)
Brocade Hardaware supports SVI (Switch Virtual Interface) which provides ASIC level routing/gateway functionality in the switch for configured VLANs. This Service plugin provides support for this feature which enables line rate routing/gateway functionality.
l3_router_plugin.py provides a hardware based l3 router.
Please refer to: https://blueprints.launchpad.net/neutron/+spec/brocade-l3-svi-service-plugin for more details

View File

@ -217,7 +217,7 @@ xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete">
</config>
"""
#port-profile domain management commands
# port-profile domain management commands
REMOVE_PORTPROFILE_FROM_DOMAIN = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile-domain xmlns="urn:brocade.com:mgmt:brocade-port-profile">
@ -228,7 +228,7 @@ REMOVE_PORTPROFILE_FROM_DOMAIN = """
</port-profile-domain>
</config>
"""
#put port profile in default domain
# put port profile in default domain
CONFIGURE_PORTPROFILE_IN_DOMAIN = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile-domain xmlns="urn:brocade.com:mgmt:brocade-port-profile">
@ -240,12 +240,197 @@ CONFIGURE_PORTPROFILE_IN_DOMAIN = """
</config>
"""
#
# L3 Life-cycle Management Configuration Commands
#
# Create SVI and assign ippaddres (rbridge_id,vlan_id,ip_address)
CONFIGURE_SVI_WITH_IP_ADDRESS = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<rbridge-id xmlns="urn:brocade.com:mgmt:brocade-rbridge">
<rbridge-id>{rbridge_id}</rbridge-id>
<interface xmlns="urn:brocade.com:mgmt:brocade-interface">
<ve>
<name>{vlan_id}</name>
<ip xmlns="urn:brocade.com:mgmt:brocade-ip-config">
<ip-config>
<address>
<address>{ip_address}</address>
</address>
</ip-config>
</ip>
</ve>
</interface>
</rbridge-id>
</config>
"""
# delete SVI (rbridge_id,vlan_id)
DELETE_SVI = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<rbridge-id xmlns="urn:brocade.com:mgmt:brocade-rbridge">
<rbridge-id>{rbridge_id}</rbridge-id>
<interface xmlns="urn:brocade.com:mgmt:brocade-interface">
<ve operation="delete">
<name>{vlan_id}</name>
</ve>
</interface>
</rbridge-id>
</config>
"""
# Activate SVI (rbridge_id,vlan_id)
ACTIVATE_SVI = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<rbridge-id xmlns="urn:brocade.com:mgmt:brocade-rbridge">
<rbridge-id>{rbridge_id}</rbridge-id>
<interface xmlns="urn:brocade.com:mgmt:brocade-interface">
<ve>
<name>{vlan_id}</name>
<shutdown xmlns="urn:brocade.com:mgmt:brocade-ip-config"
xc:operation="delete"></shutdown>
</ve>
</interface>
</rbridge-id>
</config>
"""
# Remove ipaddress from SVI (rbridge_id,vlan_id)
DECONFIGURE_IP_FROM_SVI = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<rbridge-id xmlns="urn:brocade.com:mgmt:brocade-rbridge">
<rbridge-id>{rbridge_id}</rbridge-id>
<interface xmlns="urn:brocade.com:mgmt:brocade-interface">
<ve>
<name>{vlan_id}</name>
<ip xmlns="urn:brocade.com:mgmt:brocade-ip-config">
<ip-config>
<address xc:operation="delete">
<address>{gw_ip}</address>
</address>
</ip-config>
</ip>
</ve>
</interface>
</rbridge-id>
</config>
"""
# create vrf (rbridge_id,vrf_name)
CREATE_VRF = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<rbridge-id xmlns="urn:brocade.com:mgmt:brocade-rbridge">
<rbridge-id>{rbridge_id}</rbridge-id>
<vrf xmlns="urn:brocade.com:mgmt:brocade-vrf">
<vrf-name>{vrf_name}</vrf-name>
</vrf>
</rbridge-id>
</config>
"""
# delete vrf (rbridge_id,vrf_name)
DELETE_VRF = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<rbridge-id xmlns="urn:brocade.com:mgmt:brocade-rbridge">
<rbridge-id>{rbridge_id}</rbridge-id>
<vrf xmlns="urn:brocade.com:mgmt:brocade-vrf"
xc:operation="delete">
<vrf-name>{vrf_name}</vrf-name>
</vrf>
</rbridge-id>
</config>
"""
# configure route distinguisher for vrf (rbridge_id,vrf_name, rd)
CONFIGURE_RD_FOR_VRF = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<rbridge-id xmlns="urn:brocade.com:mgmt:brocade-rbridge">
<rbridge-id>{rbridge_id}</rbridge-id>
<vrf xmlns="urn:brocade.com:mgmt:brocade-vrf">
<vrf-name>{vrf_name}</vrf-name>
<route-distiniguisher>{rd}</route-distiniguisher>
</vrf>
</rbridge-id>
</config>
"""
# configure address-family for vrf (rbridge_id,vrf_name)
ADD_ADDRESS_FAMILY_FOR_VRF_V1 = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<rbridge-id xmlns="urn:brocade.com:mgmt:brocade-rbridge">
<rbridge-id>{rbridge_id}</rbridge-id>
<vrf xmlns="urn:brocade.com:mgmt:brocade-vrf">
<vrf-name>{vrf_name}</vrf-name>
<address-family xmlns="urn:brocade.com:mgmt:brocade-vrf">
<ipv4>
<max-route>1200</max-route>
</ipv4>
</address-family>
</vrf>
</rbridge-id>
</config>
"""
# configure address-family for vrf (rbridge_id,vrf_name)
ADD_ADDRESS_FAMILY_FOR_VRF = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<rbridge-id xmlns="urn:brocade.com:mgmt:brocade-rbridge">
<rbridge-id>{rbridge_id}</rbridge-id>
<vrf xmlns="urn:brocade.com:mgmt:brocade-vrf">
<vrf-name>{vrf_name}</vrf-name>
<address-family xmlns="urn:brocade.com:mgmt:brocade-vrf">
<ip>
<unicast/>
</ip>
</address-family>
</vrf>
</rbridge-id>
</config>
"""
# Bind vrf to SVI (rbridge_id,vlan_idi, vrf)
ADD_VRF_TO_SVI = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<rbridge-id xmlns="urn:brocade.com:mgmt:brocade-rbridge">
<rbridge-id>{rbridge_id}</rbridge-id>
<interface xmlns="urn:brocade.com:mgmt:brocade-interface">
<ve>
<name>{vlan_id}</name>
<vrf xmlns="urn:brocade.com:mgmt:brocade-ip-config">
<forwarding>{vrf_name}</forwarding>
</vrf>
</ve>
</interface>
</rbridge-id>
</config>
"""
# unbind vrf from SVI (rbridge_id,vlan_idi, vrf)
DELETE_VRF_FROM_SVI = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<rbridge-id xmlns="urn:brocade.com:mgmt:brocade-rbridge">
<rbridge-id>{rbridge_id}</rbridge-id>
<interface xmlns="urn:brocade.com:mgmt:brocade-interface">
<ve>
<name>{vlan_id}</name>
<vrf xmlns="urn:brocade.com:mgmt:brocade-ip-config"
operation="delete">
<forwarding>{vrf_name}</forwarding>
</vrf>
</ve>
</interface>
</rbridge-id>
</config>
"""
#
# Constants
#
# Port profile naming convention for Neutron networks
OS_PORT_PROFILE_NAME = "openstack-profile-{id}"
OS_VRF_NAME = "osv-{id}"
# Port profile filter expressions
PORT_PROFILE_XPATH_FILTER = "/port-profile"

View File

@ -315,3 +315,174 @@ class NOSdriver():
if vfab_enable is not None:
return "enabled"
return "disabled"
def create_svi(self, host, username, password,
rbridge_id, vlan_id, ip_address, router_id):
"""create svi on configured rbridge-id."""
try:
mgr = self.connect(host, username, password)
self.bind_vrf_to_svi(host, username, password,
rbridge_id, vlan_id, router_id)
self.configure_svi_with_ip_address(mgr,
rbridge_id, vlan_id, ip_address)
self.activate_svi(mgr, rbridge_id, vlan_id)
except Exception as ex:
with excutils.save_and_reraise_exception():
LOG.exception(_("NETCONF error: %s"), ex)
self.close_session()
def delete_svi(self, host, username, password,
rbridge_id, vlan_id, gw_ip, router_id):
"""delete svi from configured rbridge-id."""
try:
mgr = self.connect(host, username, password)
self.remove_svi(mgr, rbridge_id, vlan_id)
except Exception as ex:
with excutils.save_and_reraise_exception():
LOG.exception(_("NETCONF error: %s"), ex)
self.close_session()
def create_router(self, host, username, password, rbridge_id, router_id):
"""create vrf and associate vrf."""
router_id = router_id[0:11]
vrf_name = template.OS_VRF_NAME.format(id=router_id)
rd = router_id + ":" + router_id
try:
mgr = self.connect(host, username, password)
self.create_vrf(mgr, rbridge_id, vrf_name)
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception(_("NETCONF error"))
self.close_session()
try:
# For Nos5.0.0
self.configure_rd_for_vrf(mgr, rbridge_id, vrf_name, rd)
self.configure_address_family_for_vrf(mgr, rbridge_id, vrf_name)
except Exception:
with excutils.save_and_reraise_exception() as ctxt:
try:
# This is done because on 4.0.0 rd doesnt accept alpha
# character nor hyphen
rd = "".join(i for i in router_id if i in "0123456789")
rd = rd[:4] + ":" + rd[:4]
self.configure_rd_for_vrf(mgr, rbridge_id, vrf_name, rd)
self.configure_address_family_for_vrf_v1(mgr,
rbridge_id,
vrf_name)
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception(_("NETCONF error"))
self.close_session()
ctxt.reraise = False
def delete_router(self, host, username, password, rbridge_id, router_id):
"""delete router and associated vrf."""
router_id = router_id[0:11]
vrf_name = template.OS_VRF_NAME.format(id=router_id)
try:
mgr = self.connect(host, username, password)
self.delete_vrf(mgr, rbridge_id, vrf_name)
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception(_("NETCONF error"))
self.close_session()
def bind_vrf_to_svi(self, host, username, password, rbridge_id,
vlan_id, router_id):
"""binds vrf to a svi."""
router_id = router_id[0:11]
vrf_name = template.OS_VRF_NAME.format(id=router_id)
try:
mgr = self.connect(host, username, password)
self.add_vrf_to_svi(mgr, rbridge_id, vlan_id, vrf_name)
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception(_("NETCONF error"))
self.close_session()
def unbind_vrf_to_svi(self, host, username, password, rbridge_id,
vlan_id, router_id):
"""unbind vrf from the svi."""
router_id = router_id[0:11]
vrf_name = template.OS_VRF_NAME.format(id=router_id)
try:
mgr = self.connect(host, username, password)
self.delete_vrf_from_svi(mgr, rbridge_id, vlan_id, vrf_name)
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception(_("NETCONF error"))
self.close_session()
def create_vrf(self, mgr, rbridge_id, vrf_name):
"""create vrf on rbridge."""
confstr = template.CREATE_VRF.format(rbridge_id=rbridge_id,
vrf_name=vrf_name)
mgr.edit_config(target='running', config=confstr)
def delete_vrf(self, mgr, rbridge_id, vrf_name):
"""delete vrf on rbridge."""
confstr = template.DELETE_VRF.format(rbridge_id=rbridge_id,
vrf_name=vrf_name)
mgr.edit_config(target='running', config=confstr)
def configure_rd_for_vrf(self, mgr, rbridge_id, vrf_name, rd):
"""configure rd on vrf on rbridge."""
confstr = template.CONFIGURE_RD_FOR_VRF.format(rbridge_id=rbridge_id,
vrf_name=vrf_name,
rd=rd)
mgr.edit_config(target='running', config=confstr)
def configure_address_family_for_vrf_v1(self, mgr, rbridge_id, vrf_name):
"""configure ipv4 address family to vrf on rbridge."""
confstr = template.ADD_ADDRESS_FAMILY_FOR_VRF_V1.format(
rbridge_id=rbridge_id,
vrf_name=vrf_name)
mgr.edit_config(target='running', config=confstr)
def configure_address_family_for_vrf(self, mgr, rbridge_id, vrf_name):
"""configure ipv4 address family to vrf on rbridge."""
confstr = template.ADD_ADDRESS_FAMILY_FOR_VRF.format(
rbridge_id=rbridge_id, vrf_name=vrf_name)
mgr.edit_config(target='running', config=confstr)
def configure_svi_with_ip_address(self, mgr, rbridge_id,
vlan_id, ip_address):
"""configure SVI with ip address on rbridge."""
confstr = template.CONFIGURE_SVI_WITH_IP_ADDRESS.format(
rbridge_id=rbridge_id,
vlan_id=vlan_id,
ip_address=ip_address)
mgr.edit_config(target='running', config=confstr)
def activate_svi(self, mgr, rbridge_id, vlan_id):
"""activate the svi on the rbridge."""
confstr = template.ACTIVATE_SVI.format(rbridge_id=rbridge_id,
vlan_id=vlan_id)
mgr.edit_config(target='running', config=confstr)
def add_vrf_to_svi(self, mgr, rbridge_id, vlan_id, vrf_name):
"""add vrf to svi on rbridge."""
confstr = template.ADD_VRF_TO_SVI.format(rbridge_id=rbridge_id,
vlan_id=vlan_id,
vrf_name=vrf_name)
mgr.edit_config(target='running', config=confstr)
def delete_vrf_from_svi(self, mgr, rbridge_id, vlan_id, vrf_name):
"""delete vrf from svi on rbridge."""
confstr = template.DELETE_VRF_FROM_SVI.format(rbridge_id=rbridge_id,
vlan_id=vlan_id,
vrf_name=vrf_name)
mgr.edit_config(target='running', config=confstr)
def remove_svi(self, mgr, rbridge_id, vlan_id):
"""delete vrf from svi on rbridge."""
confstr = template.DELETE_SVI.format(rbridge_id=rbridge_id,
vlan_id=vlan_id)
mgr.edit_config(target='running', config=confstr)

View File

@ -0,0 +1,236 @@
# Copyright 2014 Brocade Communications System, Inc.
# All rights reserved.
#
# 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.
#
"""Implentation of Brocade SVI service Plugin."""
from oslo.config import cfg
from neutron.common import constants as l3_constants
from neutron.openstack.common import excutils
from neutron.openstack.common import log as logging
from neutron.plugins.ml2 import db
from neutron.plugins.ml2.drivers.brocade.db import models as brocade_db
from neutron.plugins.ml2.drivers.brocade.nos import nosdriver as driver
from neutron.services.l3_router import l3_router_plugin as router
DEVICE_OWNER_ROUTER_INTF = l3_constants.DEVICE_OWNER_ROUTER_INTF
DEVICE_OWNER_ROUTER_GW = l3_constants.DEVICE_OWNER_ROUTER_GW
DEVICE_OWNER_FLOATINGIP = l3_constants.DEVICE_OWNER_FLOATINGIP
ML2_BROCADE = [cfg.StrOpt('address', default='',
help=_('The address of the host to SSH to')),
cfg.StrOpt('username', default='admin',
help=_('The SSH username to use')),
cfg.StrOpt('password', default='password', secret=True,
help=_('The SSH password to use')),
cfg.StrOpt('rbridge_id', default=1,
help=_('Rbridge id of provider edge router(s)')),
]
cfg.CONF.register_opts(ML2_BROCADE, "ml2_brocade")
LOG = logging.getLogger(__name__)
class BrocadeSVIPlugin(router.L3RouterPlugin):
"""Brocade SVI service Plugin."""
def __init__(self):
"""Initialize Brocade Plugin
Specify switch address and db configuration.
"""
super(BrocadeSVIPlugin, self).__init__()
self._switch = None
self._driver = None
self.brocade_init()
def brocade_init(self):
"""Brocade specific initialization."""
LOG.debug("brocadeSVIPlugin::brocade_init()")
self._switch = {'address': cfg.CONF.ml2_brocade.address,
'username': cfg.CONF.ml2_brocade.username,
'password': cfg.CONF.ml2_brocade.password,
'rbridge_id': cfg.CONF.ml2_brocade.rbridge_id
}
self._driver = driver.NOSdriver()
LOG.info(_("rbridge id %s"), self._switch['rbridge_id'])
def create_router(self, context, router):
""" creates a vrf on NOS device."""
LOG.debug("BrocadeSVIPlugin.create_router called: ")
with context.session.begin(subtransactions=True):
new_router = super(BrocadeSVIPlugin, self).create_router(context,
router)
# Router on VDX
try:
switch = self._switch
self._driver.create_router(switch['address'],
switch['username'],
switch['password'],
switch['rbridge_id'],
str(new_router['id']))
except Exception:
with excutils.save_and_reraise_exception():
with context.session.begin(subtransactions=True):
super(BrocadeSVIPlugin, self).delete_router(
context,
new_router['id'])
LOG.debug("BrocadeSVIPlugin.create_router: "
"router created on VDX switch")
return new_router
def delete_router(self, context, router_id):
""" delete a vrf on NOS device."""
router = super(BrocadeSVIPlugin, self).get_router(context, router_id)
super(BrocadeSVIPlugin, self).delete_router(context, router_id)
try:
switch = self._switch
self._driver.delete_router(switch['address'],
switch['username'],
switch['password'],
switch['rbridge_id'],
str(router['id']))
except Exception:
excutils.save_and_reraise_exception()
def add_router_interface(self, context, router_id, interface_info):
"""creates svi on NOS device and assigns ip addres to SVI."""
LOG.debug("BrocadeSVIPlugin.add_router_interface on VDX: "
"router_id=%(router_id)s "
"interface_info=%(interface_info)r",
{'router_id': router_id, 'interface_info': interface_info})
with context.session.begin(subtransactions=True):
info = super(BrocadeSVIPlugin, self).add_router_interface(
context, router_id, interface_info)
port = db.get_port(context.session, info["port_id"])
# shutting down neutron port to allow NOS to do Arp/Routing
port['admin_state_up'] = False
port['port'] = port
self._core_plugin.update_port(context, info["port_id"], port)
interface_info = info
subnet = self._core_plugin._get_subnet(context,
interface_info["subnet_id"])
cidr = subnet["cidr"]
net_addr, net_len = self.net_addr(cidr)
gateway_ip = subnet["gateway_ip"]
network_id = subnet['network_id']
bnet = brocade_db.get_network(context, network_id)
vlan_id = bnet['vlan']
gateway_ip_cidr = gateway_ip + '/' + str(net_len)
LOG.debug("Allocated cidr %(cidr)s from the pool, "
"network_id %(net_id)s "
"bnet %(bnet)s "
"vlan %(vlan_id)d " % ({'cidr': gateway_ip_cidr,
'net_id': network_id,
'bnet': bnet,
'vlan_id': int(vlan_id)}))
port_filters = {'network_id': [network_id],
'device_owner': [DEVICE_OWNER_ROUTER_INTF]}
port_count = self._core_plugin.get_ports_count(context,
port_filters)
LOG.info(_("BrocadeSVIPlugin.add_router_interface ports_count %d"),
port_count)
# port count is checked against 2 since the current port is already
# added to db
if port_count == 2:
# This subnet is already part of some router
# (this is not supported in this version of brocade svi plugin)
LOG.error(_("BrocadeSVIPlugin: adding redundant router "
"interface is not supported"))
raise Exception(_("BrocadeSVIPlugin:adding redundant router "
"interface is not supported"))
try:
switch = self._switch
self._driver.create_svi(switch['address'],
switch['username'],
switch['password'],
switch['rbridge_id'],
vlan_id,
gateway_ip_cidr,
str(router_id))
except Exception:
LOG.error(_("Failed to create Brocade resources to add router "
"interface. info=%(info)s, router_id=%(router_id)s"),
{"info": info, "router_id": router_id})
with excutils.save_and_reraise_exception():
with context.session.begin(subtransactions=True):
self.remove_router_interface(context, router_id,
interface_info)
return info
def remove_router_interface(self, context, router_id, interface_info):
"""Deletes svi from NOS device."""
LOG.debug("BrocadeSVIPlugin.remove_router_interface called: "
"router_id=%(router_id)s "
"interface_info=%(interface_info)r",
{'router_id': router_id, 'interface_info': interface_info})
with context.session.begin(subtransactions=True):
info = super(BrocadeSVIPlugin, self).remove_router_interface(
context, router_id, interface_info)
try:
subnet = self._core_plugin._get_subnet(context,
info['subnet_id'])
cidr = subnet['cidr']
net_addr, net_len = self.net_addr(cidr)
gateway_ip = subnet['gateway_ip']
network_id = subnet['network_id']
bnet = brocade_db.get_network(context, network_id)
vlan_id = bnet['vlan']
gateway_ip_cidr = gateway_ip + '/' + str(net_len)
LOG.debug("remove_router_interface removed cidr %(cidr)s"
" from the pool,"
" network_id %(net_id)s bnet %(bnet)s"
" vlan %(vlan_id)d" %
({'cidr': gateway_ip_cidr,
'net_id': network_id,
'bnet': bnet, 'vlan_id': int(vlan_id)}))
switch = self._switch
self._driver.delete_svi(switch['address'],
switch['username'],
switch['password'],
switch['rbridge_id'],
vlan_id,
gateway_ip_cidr,
str(router_id))
except Exception:
with excutils.save_and_reraise_exception():
LOG.error(_("Fail remove of interface from brocade router "
"interface. info=%(info)s, "
"router_id=%(router_id)s") %
({"info": info, "router_id": router_id}))
return True
@staticmethod
def net_addr(addr):
"""Get network address prefix and length from a given address."""
if addr is None:
return None, None
nw_addr, nw_len = addr.split('/')
nw_len = int(nw_len)
return nw_addr, nw_len

View File

@ -0,0 +1,57 @@
# Copyright (c) 2014 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.
#
#
import mock
from oslo.config import cfg
from neutron.db import api as db
from neutron.openstack.common import context
from neutron.openstack.common import importutils
from neutron.openstack.common import log as logging
from neutron.tests.unit import test_l3_plugin
LOG = logging.getLogger(__name__)
L3_SVC_PLUGIN = ('neutron.services.l3_router.'
'brocade.l3_router_plugin.BrocadeSVIPlugin')
class BrocadeSVIPlugin_TestCases(test_l3_plugin.TestL3NatBasePlugin):
def setUp(self):
def mocked_brocade_init(self):
LOG.debug("brocadeSVIPlugin::mocked_brocade_init()")
self._switch = {'address': cfg.CONF.ml2_brocade.address,
'username': cfg.CONF.ml2_brocade.username,
'password': cfg.CONF.ml2_brocade.password,
'rbridge_id': cfg.CONF.ml2_brocade.rbridge_id
}
LOG.info(_("rbridge id %s"), self._switch['rbridge_id'])
self._driver = mock.MagicMock()
self.context = context.get_admin_context()
self.context.session = db.get_session()
self.l3_plugin = importutils.import_object(L3_SVC_PLUGIN)
with mock.patch.object(self.l3_plugin,
'brocade_init', new=mocked_brocade_init):
super(BrocadeSVIPlugin_TestCases, self).setUp()
class TestBrocadeSVINatBase(test_l3_plugin.L3NatExtensionTestCase,
BrocadeSVIPlugin_TestCases):
pass