Merge "Layer 3 service plugin to support hardware based routing"
This commit is contained in:
commit
30837fdfee
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
0
neutron/services/l3_router/brocade/__init__.py
Normal file
0
neutron/services/l3_router/brocade/__init__.py
Normal file
236
neutron/services/l3_router/brocade/l3_router_plugin.py
Normal file
236
neutron/services/l3_router/brocade/l3_router_plugin.py
Normal 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
|
@ -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
|
Loading…
Reference in New Issue
Block a user