Final decomposition of Brocade vendor code

This removes what's left of the brocade code and artifacts from the
neutron tree. All the vendor code is now in the
openstack/networking-brocade repo.

Closes-Bug: #1518637

Change-Id: Ia366ec28d0ae9fd7f9fe41c9a82d5d44971d27d8
This commit is contained in:
Henry Gessau 2015-11-21 18:50:31 -05:00 committed by Henry Gessau
parent c96a892453
commit a050433d0d
41 changed files with 9 additions and 2330 deletions

View File

@ -1,29 +0,0 @@
[switch]
# username = The SSH username to use
# password = The SSH password to use
# address = The address of the host to SSH to
# ostype = Should be NOS, but is unused otherwise
#
# Example:
# username = admin
# password = password
# address = 10.24.84.38
# ostype = NOS
[physical_interface]
# physical_interface = The network interface to use when creating a port
#
# Example:
# physical_interface = physnet1
[vlans]
# network_vlan_ranges = <physical network name>:nnnn:mmmm
#
# Example:
# network_vlan_ranges = physnet1:1000:2999
[linux_bridge]
# physical_interface_mappings = <physical network name>:<local interface>
#
# Example:
# physical_interface_mappings = physnet1:em1

View File

@ -1,19 +0,0 @@
[l3_brocade_mlx]
# switch_names = Comma separated list of names of MLX switches to be configured
# Example:
# switch_names = mlx
[L3_BROCADE_MLX_EXAMPLE]
# address = The IP address of the MLX switch
# username = The SSH username to use to connect to device
# password = The SSH password to use to connect to device
# physical_networks = Allowed physical networks for VLAN configuration
# ports = Comma separated list of ports on the switch which needs to be tagged to VLAN
#
# Example:
# [mlx]
# address = 10.24.20.21
# username = admin
# password = password
# physical_networks = physnet1
# ports = 3/3, 3/9

View File

@ -1,22 +0,0 @@
# Brocade Vyatta vRouter L3 Plugin Configuration File
[vrouter]
# Tenant admin name
# tenant_admin_name = admin
# Tenant admin password
# tenant_admin_password = devstack
# Service VM Admin Tenant id
# tenant_id =
# Example: tenant_id = 2bde406aa6ba424d80a9eb658a02178c
# Vyatta vRouter Image id. Image should be imported using Glance.
# image_id =
# Example: image_id = 527b9c5a-b297-4a09-8785-c492465c8461
# VM Flavor for vRouter
# flavor = 2
# vRouter Management network id
# management_network_id =
# Example: management_network_id = 7190bb5f-e32a-48fb-9c67-12c1365d0083

View File

@ -1,15 +0,0 @@
[ml2_brocade]
# username = <mgmt admin username>
# password = <mgmt admin password>
# address = <switch mgmt ip address>
# ostype = NOS
# osversion = autodetect | n.n.n
# physical_networks = physnet1,physnet2
#
# Example:
# username = admin
# password = password
# address = 10.24.84.38
# ostype = NOS
# osversion = 4.1.1
# physical_networks = physnet1,physnet2

View File

@ -1,33 +0,0 @@
[ml2_brocade_fi_ni]
# switch_names = Comma separated names of switch to be configured
# Example:
# switch_names = icx-1, icx-2
[ML2_BROCADE_MLX_EXAMPLE]
# address = The address of the host to SSH to
# username = The username to use to connect to device
# password = The password to use to connect to device
# physical_networks = Allowed physical networks
# ports = Ports on the switch which needs to tagged to VLAN. Multiple ports can be separated by a comma.
# transport = Protocol to use for device connection(SSH or Telnet). Default is SSH. This is an optional parameter
# ostype = Optional parameter, which will identify the firmware version(FI/NI)
#
# Example:
# [icx-1]
# address = 10.24.20.22
# username = admin
# password = password
# physical_networks = physnet1
# ports = 1/1/1, 1/1/2
# transport = SSH
# ostype = FI
# Example:
# [mlx]
# address = 10.24.20.21
# username = admin
# password = password
# physical_networks = physnet1
# ports = 3/3, 3/9
# transport = SSH
# ostype = NI

View File

@ -100,6 +100,14 @@ REPO_NEC_TABLES = [
'packetfilters',
]
# Brocade models are in openstack/networking-brocade
REPO_BROCADE_TABLES = [
'brocadenetworks',
'brocadeports',
'ml2_brocadenetworks',
'ml2_brocadeports',
]
# BigSwitch models are in openstack/networking-bigswitch
REPO_BIGSWITCH_TABLES = [
'consistencyhashes',
@ -112,4 +120,5 @@ TABLES = (FWAAS_TABLES + LBAAS_TABLES + VPNAAS_TABLES +
REPO_CISCO_TABLES +
REPO_VMWARE_TABLES +
REPO_NEC_TABLES +
REPO_BROCADE_TABLES +
REPO_BIGSWITCH_TABLES)

View File

@ -47,9 +47,6 @@ from neutron.db import rbac_db_models # noqa
from neutron.db import securitygroups_db # noqa
from neutron.db import servicetype_db # noqa
from neutron.ipam.drivers.neutrondb_ipam import db_models # noqa
from neutron.plugins.brocade.db import models as brocade_models # noqa
from neutron.plugins.ml2.drivers.brocade.db import ( # noqa
models as ml2_brocade_models)
from neutron.plugins.ml2.drivers import type_flat # noqa
from neutron.plugins.ml2.drivers import type_geneve # noqa
from neutron.plugins.ml2.drivers import type_gre # noqa

View File

@ -1,498 +0,0 @@
# Copyright 2013 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.
#
# (Some parts adapted from LinuxBridge Plugin)
# TODO(shiv) need support for security groups
"""Implementation of Brocade Neutron Plugin."""
from oslo_config import cfg
from oslo_log import log as logging
import oslo_messaging
from oslo_utils import importutils
from neutron._i18n import _LE, _LI
from neutron.agent import securitygroups_rpc as sg_rpc
from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api
from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api
from neutron.api.rpc.handlers import dhcp_rpc
from neutron.api.rpc.handlers import l3_rpc
from neutron.api.rpc.handlers import metadata_rpc
from neutron.api.rpc.handlers import securitygroups_rpc
from neutron.common import constants as n_const
from neutron.common import rpc as n_rpc
from neutron.common import topics
from neutron.common import utils
from neutron import context as n_context
from neutron.db import agents_db
from neutron.db import agentschedulers_db
from neutron.db import api as db
from neutron.db import db_base_plugin_v2
from neutron.db import external_net_db
from neutron.db import extraroute_db
from neutron.db import l3_agentschedulers_db
from neutron.db import portbindings_base
from neutron.db import securitygroups_rpc_base as sg_db_rpc
from neutron.extensions import portbindings
from neutron.extensions import securitygroup as ext_sg
from neutron.plugins.brocade.db import models as brocade_db
from neutron.plugins.brocade import vlanbm as vbm
from neutron.plugins.common import constants as svc_constants
LOG = logging.getLogger(__name__)
AGENT_OWNER_PREFIX = "network:"
NOS_DRIVER = 'neutron.plugins.brocade.nos.nosdriver.NOSdriver'
SWITCH_OPTS = [cfg.StrOpt('address', default='',
help=_('The address of the host to SSH to')),
cfg.StrOpt('username', default='',
help=_('The SSH username to use')),
cfg.StrOpt('password', default='', secret=True,
help=_('The SSH password to use')),
cfg.StrOpt('ostype', default='NOS',
help=_('Currently unused'))
]
PHYSICAL_INTERFACE_OPTS = [cfg.StrOpt('physical_interface', default='eth0',
help=_('The network interface to use when creating '
'a port'))
]
cfg.CONF.register_opts(SWITCH_OPTS, "SWITCH")
cfg.CONF.register_opts(PHYSICAL_INTERFACE_OPTS, "PHYSICAL_INTERFACE")
class BridgeRpcCallbacks(object):
"""Agent callback."""
target = oslo_messaging.Target(version='1.2')
# Device names start with "tap"
# history
# 1.1 Support Security Group RPC
# 1.2 Support get_devices_details_list
def get_device_details(self, rpc_context, **kwargs):
"""Agent requests device details."""
agent_id = kwargs.get('agent_id')
device = kwargs.get('device')
LOG.debug("Device %(device)s details requested from %(agent_id)s",
{'device': device, 'agent_id': agent_id})
port = brocade_db.get_port(rpc_context,
device[len(n_const.TAP_DEVICE_PREFIX):])
if port:
entry = {'device': device,
'vlan_id': port.vlan_id,
'network_id': port.network_id,
'port_id': port.port_id,
'physical_network': port.physical_interface,
'admin_state_up': port.admin_state_up
}
else:
entry = {'device': device}
LOG.debug("%s can not be found in database", device)
return entry
def get_devices_details_list(self, rpc_context, **kwargs):
return [
self.get_device_details(
rpc_context,
device=device,
**kwargs
)
for device in kwargs.pop('devices', [])
]
def update_device_down(self, rpc_context, **kwargs):
"""Device no longer exists on agent."""
device = kwargs.get('device')
port = self.get_port_from_device(device)
if port:
entry = {'device': device,
'exists': True}
# Set port status to DOWN
port_id = port['port_id']
brocade_db.update_port_state(rpc_context, port_id, False)
else:
entry = {'device': device,
'exists': False}
LOG.debug("%s can not be found in database", device)
return entry
class SecurityGroupServerRpcMixin(sg_db_rpc.SecurityGroupServerRpcMixin):
@classmethod
def get_port_from_device(cls, device):
"""Get port from the brocade specific db."""
# TODO(shh) context is not being passed as
# an argument to this function;
#
# need to be fixed in:
# file: neutron/db/securtygroups_rpc_base.py
# function: securitygroup_rules_for_devices()
# which needs to pass context to us
# Doing what other plugins are doing
session = db.get_session()
port = brocade_db.get_port_from_device(
session, device[len(n_const.TAP_DEVICE_PREFIX):])
# TODO(shiv): need to extend the db model to include device owners
# make it appears that the device owner is of type network
if port:
port['device'] = device
port['device_owner'] = AGENT_OWNER_PREFIX
port['binding:vif_type'] = 'bridge'
return port
class AgentNotifierApi(sg_rpc.SecurityGroupAgentRpcApiMixin):
"""Agent side of the linux bridge rpc API.
API version history:
1.0 - Initial version.
1.1 - Added get_active_networks_info, create_dhcp_port,
and update_dhcp_port methods.
"""
def __init__(self, topic):
self.topic = topic
target = oslo_messaging.Target(topic=topic, version='1.0')
self.client = n_rpc.get_client(target)
self.topic_network_delete = topics.get_topic_name(topic,
topics.NETWORK,
topics.DELETE)
self.topic_port_update = topics.get_topic_name(topic,
topics.PORT,
topics.UPDATE)
def network_delete(self, context, network_id):
cctxt = self.client.prepare(topic=self.topic_network_delete,
fanout=True)
cctxt.cast(context, 'network_delete', network_id=network_id)
def port_update(self, context, port, physical_network, vlan_id):
cctxt = self.client.prepare(topic=self.topic_port_update, fanout=True)
cctxt.cast(context, 'port_update', port=port,
physical_network=physical_network, vlan_id=vlan_id)
class BrocadePluginV2(db_base_plugin_v2.NeutronDbPluginV2,
external_net_db.External_net_db_mixin,
extraroute_db.ExtraRoute_db_mixin,
SecurityGroupServerRpcMixin,
l3_agentschedulers_db.L3AgentSchedulerDbMixin,
agentschedulers_db.DhcpAgentSchedulerDbMixin,
portbindings_base.PortBindingBaseMixin):
"""BrocadePluginV2 is a Neutron plugin.
Provides L2 Virtual Network functionality using VDX. Upper
layer driver class that interfaces to NETCONF layer below.
"""
def __init__(self):
"""Initialize Brocade Plugin.
Specify switch address and db configuration.
"""
super(BrocadePluginV2, self).__init__()
self.supported_extension_aliases = ["binding", "security-group",
"external-net", "router",
"extraroute", "agent",
"l3_agent_scheduler",
"dhcp_agent_scheduler"]
self.physical_interface = (cfg.CONF.PHYSICAL_INTERFACE.
physical_interface)
self.base_binding_dict = self._get_base_binding_dict()
portbindings_base.register_port_dict_function()
self.ctxt = n_context.get_admin_context()
self._vlan_bitmap = vbm.VlanBitmap(self.ctxt)
self._setup_rpc()
self.network_scheduler = importutils.import_object(
cfg.CONF.network_scheduler_driver
)
self.router_scheduler = importutils.import_object(
cfg.CONF.router_scheduler_driver
)
self.brocade_init()
self.start_periodic_dhcp_agent_status_check()
def brocade_init(self):
"""Brocade specific initialization."""
self._switch = {'address': cfg.CONF.SWITCH.address,
'username': cfg.CONF.SWITCH.username,
'password': cfg.CONF.SWITCH.password
}
self._driver = importutils.import_object(NOS_DRIVER)
def _setup_rpc(self):
# RPC support
self.service_topics = {svc_constants.CORE: topics.PLUGIN,
svc_constants.L3_ROUTER_NAT: topics.L3PLUGIN}
self.rpc_context = n_context.ContextBase('neutron', 'neutron',
is_admin=False)
self.conn = n_rpc.create_connection()
self.endpoints = [BridgeRpcCallbacks(),
securitygroups_rpc.SecurityGroupServerRpcCallback(),
dhcp_rpc.DhcpRpcCallback(),
l3_rpc.L3RpcCallback(),
agents_db.AgentExtRpcCallback(),
metadata_rpc.MetadataRpcCallback()]
for svc_topic in self.service_topics.values():
self.conn.create_consumer(svc_topic, self.endpoints, fanout=False)
# Consume from all consumers in threads
self.conn.consume_in_threads()
self.notifier = AgentNotifierApi(topics.AGENT)
self.agent_notifiers[n_const.AGENT_TYPE_DHCP] = (
dhcp_rpc_agent_api.DhcpAgentNotifyAPI()
)
self.agent_notifiers[n_const.AGENT_TYPE_L3] = (
l3_rpc_agent_api.L3AgentNotifyAPI()
)
def create_network(self, context, network):
"""Create network.
This call to create network translates to creation of port-profile on
the physical switch.
"""
with context.session.begin(subtransactions=True):
net = super(BrocadePluginV2, self).create_network(context, network)
net_uuid = net['id']
vlan_id = self._vlan_bitmap.get_next_vlan(None)
switch = self._switch
try:
self._driver.create_network(switch['address'],
switch['username'],
switch['password'],
vlan_id)
except Exception:
# Proper formatting
LOG.exception(_LE("Brocade NOS driver error"))
LOG.debug("Returning the allocated vlan (%d) to the pool",
vlan_id)
self._vlan_bitmap.release_vlan(int(vlan_id))
raise Exception(_("Brocade plugin raised exception, "
"check logs"))
brocade_db.create_network(context, net_uuid, vlan_id)
self._process_l3_create(context, net, network['network'])
LOG.info(_LI("Allocated vlan (%d) from the pool"), vlan_id)
return net
def delete_network(self, context, net_id):
"""Delete network.
This call to delete the network translates to removing the
port-profile on the physical switch.
"""
with context.session.begin(subtransactions=True):
self._process_l3_delete(context, net_id)
result = super(BrocadePluginV2, self).delete_network(context,
net_id)
# we must delete all ports in db first (foreign key constraint)
# there is no need to delete port in the driver (its a no-op)
# (actually: note there is no such call to the driver)
bports = brocade_db.get_ports(context, net_id)
for bport in bports:
brocade_db.delete_port(context, bport['port_id'])
# find the vlan for this network
net = brocade_db.get_network(context, net_id)
vlan_id = net['vlan']
# Tell hw to do remove PP
switch = self._switch
try:
self._driver.delete_network(switch['address'],
switch['username'],
switch['password'],
vlan_id)
except Exception:
# Proper formatting
LOG.exception(_LE("Brocade NOS driver error"))
raise Exception(_("Brocade plugin raised exception, "
"check logs"))
# now ok to delete the network
brocade_db.delete_network(context, net_id)
# relinquish vlan in bitmap
self._vlan_bitmap.release_vlan(int(vlan_id))
return result
def update_network(self, context, id, network):
session = context.session
with session.begin(subtransactions=True):
net = super(BrocadePluginV2, self).update_network(context, id,
network)
self._process_l3_update(context, net, network['network'])
return net
def create_port(self, context, port):
"""Create logical port on the switch."""
tenant_id = port['port']['tenant_id']
network_id = port['port']['network_id']
admin_state_up = port['port']['admin_state_up']
physical_interface = self.physical_interface
with context.session.begin(subtransactions=True):
bnet = brocade_db.get_network(context, network_id)
vlan_id = bnet['vlan']
neutron_port = super(BrocadePluginV2, self).create_port(context,
port)
self._process_portbindings_create_and_update(context,
port['port'],
neutron_port)
interface_mac = neutron_port['mac_address']
port_id = neutron_port['id']
switch = self._switch
# convert mac format: xx:xx:xx:xx:xx:xx -> xxxx.xxxx.xxxx
mac = self.mac_reformat_62to34(interface_mac)
try:
self._driver.associate_mac_to_network(switch['address'],
switch['username'],
switch['password'],
vlan_id,
mac)
except Exception:
# Proper formatting
LOG.exception(_LE("Brocade NOS driver error"))
raise Exception(_("Brocade plugin raised exception, "
"check logs"))
# save to brocade persistent db
brocade_db.create_port(context, port_id, network_id,
physical_interface,
vlan_id, tenant_id, admin_state_up)
# apply any extensions
return neutron_port
def delete_port(self, context, port_id):
with context.session.begin(subtransactions=True):
neutron_port = self.get_port(context, port_id)
interface_mac = neutron_port['mac_address']
# convert mac format: xx:xx:xx:xx:xx:xx -> xxxx.xxxx.xxxx
mac = self.mac_reformat_62to34(interface_mac)
brocade_port = brocade_db.get_port(context, port_id)
vlan_id = brocade_port['vlan_id']
switch = self._switch
try:
self._driver.dissociate_mac_from_network(switch['address'],
switch['username'],
switch['password'],
vlan_id,
mac)
except Exception:
LOG.exception(_LE("Brocade NOS driver error"))
raise Exception(
_("Brocade plugin raised exception, check logs"))
super(BrocadePluginV2, self).delete_port(context, port_id)
brocade_db.delete_port(context, port_id)
def update_port(self, context, port_id, port):
original_port = self.get_port(context, port_id)
session = context.session
port_updated = False
with session.begin(subtransactions=True):
# delete the port binding and read it with the new rules
if ext_sg.SECURITYGROUPS in port['port']:
port['port'][ext_sg.SECURITYGROUPS] = (
self._get_security_groups_on_port(context, port))
self._delete_port_security_group_bindings(context, port_id)
# process_port_create_security_group also needs port id
port['port']['id'] = port_id
self._process_port_create_security_group(
context,
port['port'],
port['port'][ext_sg.SECURITYGROUPS])
port_updated = True
port_data = port['port']
port = super(BrocadePluginV2, self).update_port(
context, port_id, port)
self._process_portbindings_create_and_update(context,
port_data,
port)
if original_port['admin_state_up'] != port['admin_state_up']:
port_updated = True
if (original_port['fixed_ips'] != port['fixed_ips'] or
not utils.compare_elements(
original_port.get(ext_sg.SECURITYGROUPS),
port.get(ext_sg.SECURITYGROUPS))):
self.notifier.security_groups_member_updated(
context, port.get(ext_sg.SECURITYGROUPS))
if port_updated:
self._notify_port_updated(context, port)
return port
def _notify_port_updated(self, context, port):
port_id = port['id']
bport = brocade_db.get_port(context, port_id)
self.notifier.port_update(context, port,
bport.physical_interface,
bport.vlan_id)
def _get_base_binding_dict(self):
binding = {
portbindings.VIF_TYPE: portbindings.VIF_TYPE_BRIDGE,
portbindings.VIF_DETAILS: {
# TODO(rkukura): Replace with new VIF security details
portbindings.CAP_PORT_FILTER:
'security-group' in self.supported_extension_aliases}}
return binding
@staticmethod
def mac_reformat_62to34(interface_mac):
"""Transform MAC address format.
Transforms from 6 groups of 2 hexadecimal numbers delimited by ":"
to 3 groups of 4 hexadecimals numbers delimited by ".".
:param interface_mac: MAC address in the format xx:xx:xx:xx:xx:xx
:type interface_mac: string
:returns: MAC address in the format xxxx.xxxx.xxxx
:rtype: string
"""
mac = interface_mac.replace(":", "")
mac = mac[0:4] + "." + mac[4:8] + "." + mac[8:12]
return mac

View File

@ -1,112 +0,0 @@
Brocade OpenStack Neutron Plugin
================================
* up-to-date version of these instructions are located at:
http://wiki.openstack.org/brocade-neutron-plugin
* N.B.: Please see Prerequisites section regarding ncclient (netconf client library)
* Supports VCS (Virtual Cluster of Switches)
OpenStack Brocade Neutron Plugin implements the Neutron v2.0 API.
This plugin is meant to orchestrate Brocade VCS switches running NOS, examples of these are:
1. VDX 67xx series of switches
2. VDX 87xx series of switches
Brocade Neutron plugin implements the Neutron v2.0 API. It uses NETCONF at the backend
to configure the Brocade switch.
+------------+ +------------+ +-------------+
| | | | | |
| | | | | Brocade |
| OpenStack | v2.0 | Brocade | NETCONF | VCS Switch |
| Neutron +--------+ Neutron +----------+ |
| | | Plugin | | VDX 67xx |
| | | | | VDX 87xx |
| | | | | |
| | | | | |
+------------+ +------------+ +-------------+
Directory Structure
===================
Normally you will have your OpenStack directory structure as follows:
/opt/stack/nova/
/opt/stack/horizon/
...
/opt/stack/neutron/neutron/plugins/
Within this structure, Brocade plugin resides at:
/opt/stack/neutron/neutron/plugins/brocade
Prerequsites
============
This plugin requires installation of the python netconf client (ncclient) library:
ncclient v0.3.1 - Python library for NETCONF clients available at http://github.com/brocade/ncclient
% git clone https://www.github.com/brocade/ncclient
% cd ncclient; sudo python ./setup.py install
Configuration
=============
1. Specify to Neutron that you will be using the Brocade Plugin - this is done
by setting the parameter core_plugin in Neutron:
core_plugin = neutron.plugins.brocade.NeutronPlugin.BrocadePluginV2
2. Physical switch configuration parameters and Brocade specific database configuration is specified in
the configuration file specified in the brocade.ini files:
% cat /etc/neutron/plugins/brocade/brocade.ini
[SWITCH]
username = admin
password = password
address = <switch mgmt ip address>
ostype = NOS
[database]
connection = mysql+pymysql://root:pass@localhost/brocade_neutron?charset=utf8
(please see list of more configuration parameters in the brocade.ini file)
Running Setup.py
================
Running setup.py with appropriate permissions will copy the default configuration
file to /etc/neutron/plugins/brocade/brocade.ini. This file MUST be edited to
suit your setup/environment.
% cd /opt/stack/neutron/neutron/plugins/brocade
% python setup.py
Devstack
========
Please see special notes for devstack at:
http://wiki.openstack.org/brocade-neutron-plugin
In order to use Brocade Neutron Plugin, add the following lines in localrc, if localrc file doe
not exist create one:
ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-obj,n-cpu,n-net,n-cond,cinder,c-sch,c-api,c-vol,n-sch,n-novnc,n-xvnc,n-cauth,horizon,rabbit,neutron,q-svc,q-agt
Q_PLUGIN=brocade
As part of running devstack/stack.sh, the configuration files is copied as:
% cp /opt/stack/neutron/etc/neutron/plugins/brocade/brocade.ini /etc/neutron/plugins/brocade/brocade.ini
(hence it is important to make any changes to the configuration in:
/opt/stack/neutron/etc/neutron/plugins/brocade/brocade.ini)

View File

@ -1,146 +0,0 @@
# Copyright 2013 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.
"""Brocade specific database schema/model."""
import sqlalchemy as sa
from neutron.db import model_base
from neutron.db import models_v2
class BrocadeNetwork(model_base.BASEV2, models_v2.HasId):
"""Schema for brocade network."""
vlan = sa.Column(sa.String(10))
class BrocadePort(model_base.BASEV2):
"""Schema for brocade port."""
port_id = sa.Column(sa.String(36), primary_key=True, default="",
server_default='')
network_id = sa.Column(sa.String(36),
sa.ForeignKey("brocadenetworks.id"),
nullable=False)
admin_state_up = sa.Column(sa.Boolean, nullable=False)
physical_interface = sa.Column(sa.String(36))
vlan_id = sa.Column(sa.String(36))
tenant_id = sa.Column(sa.String(36))
def create_network(context, net_id, vlan):
"""Create a brocade specific network/port-profiles."""
session = context.session
with session.begin(subtransactions=True):
net = BrocadeNetwork(id=net_id, vlan=vlan)
session.add(net)
return net
def delete_network(context, net_id):
"""Delete a brocade specific network/port-profiles."""
session = context.session
with session.begin(subtransactions=True):
net = (session.query(BrocadeNetwork).filter_by(id=net_id).first())
if net is not None:
session.delete(net)
def get_network(context, net_id, fields=None):
"""Get brocade specific network, with vlan extension."""
session = context.session
return (session.query(BrocadeNetwork).filter_by(id=net_id).first())
def get_networks(context, filters=None, fields=None):
"""Get all brocade specific networks."""
session = context.session
try:
nets = session.query(BrocadeNetwork).all()
return nets
except sa.exc.SQLAlchemyError:
return None
def create_port(context, port_id, network_id, physical_interface,
vlan_id, tenant_id, admin_state_up):
"""Create a brocade specific port, has policy like vlan."""
# port_id is truncated: since the linux-bridge tap device names are
# based on truncated port id, this enables port lookups using
# tap devices
port_id = port_id[0:11]
session = context.session
with session.begin(subtransactions=True):
port = BrocadePort(port_id=port_id,
network_id=network_id,
physical_interface=physical_interface,
vlan_id=vlan_id,
admin_state_up=admin_state_up,
tenant_id=tenant_id)
session.add(port)
return port
def get_port(context, port_id):
"""get a brocade specific port."""
port_id = port_id[0:11]
session = context.session
port = (session.query(BrocadePort).filter_by(port_id=port_id).first())
return port
def get_ports(context, network_id=None):
"""get a brocade specific port."""
session = context.session
ports = (session.query(BrocadePort).filter_by(network_id=network_id).all())
return ports
def delete_port(context, port_id):
"""delete brocade specific port."""
port_id = port_id[0:11]
session = context.session
with session.begin(subtransactions=True):
port = (session.query(BrocadePort).filter_by(port_id=port_id).first())
if port is not None:
session.delete(port)
def get_port_from_device(session, port_id):
"""get port from the tap device."""
# device is same as truncated port_id
port = (session.query(BrocadePort).filter_by(port_id=port_id).first())
return port
def update_port_state(context, port_id, admin_state_up):
"""Update port attributes."""
port_id = port_id[0:11]
session = context.session
session.query(BrocadePort).filter_by(
port_id=port_id).update({'admin_state_up': admin_state_up})

View File

@ -1,111 +0,0 @@
# Copyright 2013 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.
"""FAKE DRIVER, for unit tests purposes.
Brocade NOS Driver implements NETCONF over SSHv2 for
Neutron network life-cycle management.
"""
class NOSdriver(object):
"""NOS NETCONF interface driver for Neutron network.
Fake: Handles life-cycle management of Neutron network,
leverages AMPP on NOS
(for use by unit tests, avoids touching any hardware)
"""
def __init__(self):
pass
def connect(self, host, username, password):
"""Connect via SSH and initialize the NETCONF session."""
pass
def create_network(self, host, username, password, net_id):
"""Creates a new virtual network."""
pass
def delete_network(self, host, username, password, net_id):
"""Deletes a virtual network."""
pass
def associate_mac_to_network(self, host, username, password,
net_id, mac):
"""Associates a MAC address to virtual network."""
pass
def dissociate_mac_from_network(self, host, username, password,
net_id, mac):
"""Dissociates a MAC address from virtual network."""
pass
def create_vlan_interface(self, mgr, vlan_id):
"""Configures a VLAN interface."""
pass
def delete_vlan_interface(self, mgr, vlan_id):
"""Deletes a VLAN interface."""
pass
def get_port_profiles(self, mgr):
"""Retrieves all port profiles."""
pass
def get_port_profile(self, mgr, name):
"""Retrieves a port profile."""
pass
def create_port_profile(self, mgr, name):
"""Creates a port profile."""
pass
def delete_port_profile(self, mgr, name):
"""Deletes a port profile."""
pass
def activate_port_profile(self, mgr, name):
"""Activates a port profile."""
pass
def deactivate_port_profile(self, mgr, name):
"""Deactivates a port profile."""
pass
def associate_mac_to_port_profile(self, mgr, name, mac_address):
"""Associates a MAC address to a port profile."""
pass
def dissociate_mac_from_port_profile(self, mgr, name, mac_address):
"""Dissociates a MAC address from a port profile."""
pass
def create_vlan_profile_for_port_profile(self, mgr, name):
"""Creates VLAN sub-profile for port profile."""
pass
def configure_l2_mode_for_vlan_profile(self, mgr, name):
"""Configures L2 mode for VLAN sub-profile."""
pass
def configure_trunk_mode_for_vlan_profile(self, mgr, name):
"""Configures trunk mode for VLAN sub-profile."""
pass
def configure_allowed_vlans_for_vlan_profile(self, mgr, name, vlan_id):
"""Configures allowed VLANs for VLAN sub-profile."""
pass

View File

@ -1,197 +0,0 @@
# Copyright (c) 2013 Brocade Communications Systems, 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.
"""NOS NETCONF XML Configuration Command Templates.
Interface Configuration Commands
"""
# Create VLAN (vlan_id)
CREATE_VLAN_INTERFACE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<interface-vlan xmlns="urn:brocade.com:mgmt:brocade-interface">
<interface>
<vlan>
<name>{vlan_id}</name>
</vlan>
</interface>
</interface-vlan>
</config>
"""
# Delete VLAN (vlan_id)
DELETE_VLAN_INTERFACE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<interface-vlan xmlns="urn:brocade.com:mgmt:brocade-interface">
<interface>
<vlan operation="delete">
<name>{vlan_id}</name>
</vlan>
</interface>
</interface-vlan>
</config>
"""
#
# AMPP Life-cycle Management Configuration Commands
#
# Create AMPP port-profile (port_profile_name)
CREATE_PORT_PROFILE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile xmlns="urn:brocade.com:mgmt:brocade-port-profile">
<name>{name}</name>
</port-profile>
</config>
"""
# Create VLAN sub-profile for port-profile (port_profile_name)
CREATE_VLAN_PROFILE_FOR_PORT_PROFILE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile xmlns="urn:brocade.com:mgmt:brocade-port-profile">
<name>{name}</name>
<vlan-profile/>
</port-profile>
</config>
"""
# Configure L2 mode for VLAN sub-profile (port_profile_name)
CONFIGURE_L2_MODE_FOR_VLAN_PROFILE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile xmlns="urn:brocade.com:mgmt:brocade-port-profile">
<name>{name}</name>
<vlan-profile>
<switchport/>
</vlan-profile>
</port-profile>
</config>
"""
# Configure trunk mode for VLAN sub-profile (port_profile_name)
CONFIGURE_TRUNK_MODE_FOR_VLAN_PROFILE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile xmlns="urn:brocade.com:mgmt:brocade-port-profile">
<name>{name}</name>
<vlan-profile>
<switchport>
<mode>
<vlan-mode>trunk</vlan-mode>
</mode>
</switchport>
</vlan-profile>
</port-profile>
</config>
"""
# Configure allowed VLANs for VLAN sub-profile
# (port_profile_name, allowed_vlan, native_vlan)
CONFIGURE_ALLOWED_VLANS_FOR_VLAN_PROFILE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile xmlns="urn:brocade.com:mgmt:brocade-port-profile">
<name>{name}</name>
<vlan-profile>
<switchport>
<trunk>
<allowed>
<vlan>
<add>{vlan_id}</add>
</vlan>
</allowed>
</trunk>
</switchport>
</vlan-profile>
</port-profile>
</config>
"""
# Delete port-profile (port_profile_name)
DELETE_PORT_PROFILE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile
xmlns="urn:brocade.com:mgmt:brocade-port-profile" operation="delete">
<name>{name}</name>
</port-profile>
</config>
"""
# Activate port-profile (port_profile_name)
ACTIVATE_PORT_PROFILE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile-global xmlns="urn:brocade.com:mgmt:brocade-port-profile">
<port-profile>
<name>{name}</name>
<activate/>
</port-profile>
</port-profile-global>
</config>
"""
# Deactivate port-profile (port_profile_name)
DEACTIVATE_PORT_PROFILE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile-global xmlns="urn:brocade.com:mgmt:brocade-port-profile">
<port-profile>
<name>{name}</name>
<activate
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete" />
</port-profile>
</port-profile-global>
</config>
"""
# Associate MAC address to port-profile (port_profile_name, mac_address)
ASSOCIATE_MAC_TO_PORT_PROFILE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile-global xmlns="urn:brocade.com:mgmt:brocade-port-profile">
<port-profile>
<name>{name}</name>
<static>
<mac-address>{mac_address}</mac-address>
</static>
</port-profile>
</port-profile-global>
</config>
"""
# Dissociate MAC address from port-profile (port_profile_name, mac_address)
DISSOCIATE_MAC_FROM_PORT_PROFILE = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<port-profile-global xmlns="urn:brocade.com:mgmt:brocade-port-profile">
<port-profile>
<name>{name}</name>
<static
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete">
<mac-address>{mac_address}</mac-address>
</static>
</port-profile>
</port-profile-global>
</config>
"""
#
# Custom RPC Commands
#
#
# Constants
#
# Port profile naming convention for Neutron networks
OS_PORT_PROFILE_NAME = "openstack-profile-{id}"
# Port profile filter expressions
PORT_PROFILE_XPATH_FILTER = "/port-profile"
PORT_PROFILE_NAME_XPATH_FILTER = "/port-profile[name='{name}']"

View File

@ -1,228 +0,0 @@
# Copyright 2013 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.
"""Brocade NOS Driver implements NETCONF over SSHv2 for
Neutron network life-cycle management.
"""
from ncclient import manager
from oslo_log import log as logging
from oslo_utils import excutils
from neutron._i18n import _LE
from neutron.plugins.brocade.nos import nctemplates as template
LOG = logging.getLogger(__name__)
SSH_PORT = 22
def nos_unknown_host_cb(host, fingerprint):
"""An unknown host callback.
Returns `True` if it finds the key acceptable,
and `False` if not. This default callback for NOS always returns 'True'
(i.e. trusts all hosts for now).
"""
return True
class NOSdriver(object):
"""NOS NETCONF interface driver for Neutron network.
Handles life-cycle management of Neutron network (leverages AMPP on NOS)
"""
def __init__(self):
self.mgr = None
def connect(self, host, username, password):
"""Connect via SSH and initialize the NETCONF session."""
# Use the persisted NETCONF connection
if self.mgr and self.mgr.connected:
return self.mgr
# Open new NETCONF connection
try:
self.mgr = manager.connect(host=host, port=SSH_PORT,
username=username, password=password,
unknown_host_cb=nos_unknown_host_cb)
except Exception as e:
with excutils.save_and_reraise_exception():
LOG.error(_LE("Connect failed to switch: %s"), e)
LOG.debug("Connect success to host %(host)s:%(ssh_port)d",
dict(host=host, ssh_port=SSH_PORT))
return self.mgr
def close_session(self):
"""Close NETCONF session."""
if self.mgr:
self.mgr.close_session()
self.mgr = None
def create_network(self, host, username, password, net_id):
"""Creates a new virtual network."""
name = template.OS_PORT_PROFILE_NAME.format(id=net_id)
try:
mgr = self.connect(host, username, password)
self.create_vlan_interface(mgr, net_id)
self.create_port_profile(mgr, name)
self.create_vlan_profile_for_port_profile(mgr, name)
self.configure_l2_mode_for_vlan_profile(mgr, name)
self.configure_trunk_mode_for_vlan_profile(mgr, name)
self.configure_allowed_vlans_for_vlan_profile(mgr, name, net_id)
self.activate_port_profile(mgr, name)
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("NETCONF error"))
self.close_session()
def delete_network(self, host, username, password, net_id):
"""Deletes a virtual network."""
name = template.OS_PORT_PROFILE_NAME.format(id=net_id)
try:
mgr = self.connect(host, username, password)
self.deactivate_port_profile(mgr, name)
self.delete_port_profile(mgr, name)
self.delete_vlan_interface(mgr, net_id)
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("NETCONF error"))
self.close_session()
def associate_mac_to_network(self, host, username, password,
net_id, mac):
"""Associates a MAC address to virtual network."""
name = template.OS_PORT_PROFILE_NAME.format(id=net_id)
try:
mgr = self.connect(host, username, password)
self.associate_mac_to_port_profile(mgr, name, mac)
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("NETCONF error"))
self.close_session()
def dissociate_mac_from_network(self, host, username, password,
net_id, mac):
"""Dissociates a MAC address from virtual network."""
name = template.OS_PORT_PROFILE_NAME.format(id=net_id)
try:
mgr = self.connect(host, username, password)
self.dissociate_mac_from_port_profile(mgr, name, mac)
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("NETCONF error"))
self.close_session()
def create_vlan_interface(self, mgr, vlan_id):
"""Configures a VLAN interface."""
confstr = template.CREATE_VLAN_INTERFACE.format(vlan_id=vlan_id)
mgr.edit_config(target='running', config=confstr)
def delete_vlan_interface(self, mgr, vlan_id):
"""Deletes a VLAN interface."""
confstr = template.DELETE_VLAN_INTERFACE.format(vlan_id=vlan_id)
mgr.edit_config(target='running', config=confstr)
def get_port_profiles(self, mgr):
"""Retrieves all port profiles."""
filterstr = template.PORT_PROFILE_XPATH_FILTER
response = mgr.get_config(source='running',
filter=('xpath', filterstr)).data_xml
return response
def get_port_profile(self, mgr, name):
"""Retrieves a port profile."""
filterstr = template.PORT_PROFILE_NAME_XPATH_FILTER.format(name=name)
response = mgr.get_config(source='running',
filter=('xpath', filterstr)).data_xml
return response
def create_port_profile(self, mgr, name):
"""Creates a port profile."""
confstr = template.CREATE_PORT_PROFILE.format(name=name)
mgr.edit_config(target='running', config=confstr)
def delete_port_profile(self, mgr, name):
"""Deletes a port profile."""
confstr = template.DELETE_PORT_PROFILE.format(name=name)
mgr.edit_config(target='running', config=confstr)
def activate_port_profile(self, mgr, name):
"""Activates a port profile."""
confstr = template.ACTIVATE_PORT_PROFILE.format(name=name)
mgr.edit_config(target='running', config=confstr)
def deactivate_port_profile(self, mgr, name):
"""Deactivates a port profile."""
confstr = template.DEACTIVATE_PORT_PROFILE.format(name=name)
mgr.edit_config(target='running', config=confstr)
def associate_mac_to_port_profile(self, mgr, name, mac_address):
"""Associates a MAC address to a port profile."""
confstr = template.ASSOCIATE_MAC_TO_PORT_PROFILE.format(
name=name, mac_address=mac_address)
mgr.edit_config(target='running', config=confstr)
def dissociate_mac_from_port_profile(self, mgr, name, mac_address):
"""Dissociates a MAC address from a port profile."""
confstr = template.DISSOCIATE_MAC_FROM_PORT_PROFILE.format(
name=name, mac_address=mac_address)
mgr.edit_config(target='running', config=confstr)
def create_vlan_profile_for_port_profile(self, mgr, name):
"""Creates VLAN sub-profile for port profile."""
confstr = template.CREATE_VLAN_PROFILE_FOR_PORT_PROFILE.format(
name=name)
mgr.edit_config(target='running', config=confstr)
def configure_l2_mode_for_vlan_profile(self, mgr, name):
"""Configures L2 mode for VLAN sub-profile."""
confstr = template.CONFIGURE_L2_MODE_FOR_VLAN_PROFILE.format(
name=name)
mgr.edit_config(target='running', config=confstr)
def configure_trunk_mode_for_vlan_profile(self, mgr, name):
"""Configures trunk mode for VLAN sub-profile."""
confstr = template.CONFIGURE_TRUNK_MODE_FOR_VLAN_PROFILE.format(
name=name)
mgr.edit_config(target='running', config=confstr)
def configure_allowed_vlans_for_vlan_profile(self, mgr, name, vlan_id):
"""Configures allowed VLANs for VLAN sub-profile."""
confstr = template.CONFIGURE_ALLOWED_VLANS_FOR_VLAN_PROFILE.format(
name=name, vlan_id=vlan_id)
mgr.edit_config(target='running', config=confstr)

View File

@ -1,24 +0,0 @@
Start the neutron-server with IP address of switch configured in brocade.ini:
(for configuration instruction please see README.md in the above directory)
nostest.py:
This tests two things:
1. Creates port-profile on the physical switch when a neutron 'network' is created
2. Associates the MAC address with the created port-profile
noscli.py:
CLI interface to create/delete/associate MAC/dissociate MAC
Commands:
% noscli.py create <network>
(after running check that PP is created on the switch)
% noscli.py delete <network>
(after running check that PP is deleted from the switch)
% noscli.py associate <network> <mac>
(after running check that MAC is associated with PP)
% noscli.py dissociate <network> <mac>
(after running check that MAC is dissociated from the PP)

View File

@ -1,90 +0,0 @@
#!/usr/bin/env python
#
# Copyright (c) 2013 Brocade Communications Systems, 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.
"""Brocade NOS Driver CLI."""
from __future__ import print_function
import argparse
from oslo_log import log as logging
from neutron.plugins.brocade.nos import nosdriver as nos
LOG = logging.getLogger(__name__)
class NOSCli(object):
def __init__(self, host, username, password):
self.host = host
self.username = username
self.password = password
self.driver = nos.NOSdriver()
def execute(self, cmd):
numargs = len(args.otherargs)
if args.cmd == 'create' and numargs == 1:
self._create(args.otherargs[0])
elif args.cmd == 'delete' and numargs == 1:
self._delete(args.otherargs[0])
elif args.cmd == 'associate' and numargs == 2:
self._associate(args.otherargs[0], args.otherargs[1])
elif args.cmd == 'dissociate' and numargs == 2:
self._dissociate(args.otherargs[0], args.otherargs[1])
else:
print(usage_desc)
exit(0)
def _create(self, net_id):
self.driver.create_network(self.host, self.username, self.password,
net_id)
def _delete(self, net_id):
self.driver.delete_network(self.host, self.username, self.password,
net_id)
def _associate(self, net_id, mac):
self.driver.associate_mac_to_network(
self.host, self.username, self.password, net_id, mac)
def _dissociate(self, net_id, mac):
self.driver.dissociate_mac_from_network(
self.host, self.username, self.password, net_id, mac)
usage_desc = """
Command descriptions:
create <id>
delete <id>
associate <id> <mac>
dissociate <id> <mac>
"""
parser = argparse.ArgumentParser(description='process args',
usage=usage_desc, epilog='foo bar help')
parser.add_argument('--ip', default='localhost')
parser.add_argument('--username', default='admin')
parser.add_argument('--password', default='password')
parser.add_argument('cmd')
parser.add_argument('otherargs', nargs='*')
args = parser.parse_args()
noscli = NOSCli(args.ip, args.username, args.password)
noscli.execute(args.cmd)

View File

@ -1,44 +0,0 @@
# Copyright (c) 2013 Brocade Communications Systems, 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.
"""Brocade NOS Driver Test."""
from __future__ import print_function
import sys
from neutron.plugins.brocade.nos import nosdriver as nos
def nostest(host, username, password):
# Driver
driver = nos.NOSdriver()
# Neutron operations
vlan = 1001
mac = '0050.56bf.0001'
driver.create_network(host, username, password, vlan)
driver.associate_mac_to_network(host, username, password, vlan, mac)
driver.dissociate_mac_from_network(host, username, password, vlan, mac)
driver.delete_network(host, username, password, vlan)
# AMPP enumeration
with driver.connect(host, username, password) as mgr:
print(driver.get_port_profiles(mgr))
print(driver.get_port_profile(mgr, 'default'))
if __name__ == '__main__':
nostest(sys.argv[1], sys.argv[2], sys.argv[3])

View File

@ -1,53 +0,0 @@
# Copyright 2013 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.
"""A Vlan Bitmap class to handle allocation/de-allocation of vlan ids."""
from six import moves
from neutron.plugins.brocade.db import models as brocade_db
from neutron.plugins.common import constants as p_const
MIN_VLAN = p_const.MIN_VLAN_TAG + 1
MAX_VLAN = p_const.MAX_VLAN_TAG
class VlanBitmap(object):
"""Setup a vlan bitmap for allocation/de-allocation."""
# Keep track of the vlans that have been allocated/de-allocated
# uses a bitmap to do this
def __init__(self, ctxt):
"""Initialize the vlan as a set."""
self.vlans = set(int(net['vlan'])
for net in brocade_db.get_networks(ctxt)
if net['vlan']
)
def get_next_vlan(self, vlan_id=None):
"""Try to get a specific vlan if requested or get the next vlan."""
min_vlan_search = vlan_id or MIN_VLAN
max_vlan_search = (vlan_id + 1) if vlan_id else MAX_VLAN
for vlan in moves.range(min_vlan_search, max_vlan_search):
if vlan not in self.vlans:
self.vlans.add(vlan)
return vlan
def release_vlan(self, vlan_id):
"""Return the vlan to the pool."""
if vlan_id in self.vlans:
self.vlans.remove(vlan_id)

View File

@ -1,76 +0,0 @@
Brocade ML2 Mechanism driver from ML2 plugin
============================================
* The real code now resides outside the Neutron Stadium in an OpenStack git repository:
http://github.com/openstack/networking-brocade
* up-to-date version of these instructions are located at:
http://50.56.236.34/docs/brocade-ml2-mechanism.txt
* N.B.: Please see Prerequisites section regarding ncclient (netconf client library)
* Supports VCS (Virtual Cluster of Switches)
* Issues/Questions/Bugs: sharis@brocade.com
1. VDX 67xx series of switches
2. VDX 87xx series of switches
ML2 plugin requires mechanism driver to support configuring of hardware switches.
Brocade Mechanism for ML2 uses NETCONF at the backend to configure the Brocade switch.
Currently the mechanism drivers support VLANs only.
+------------+ +------------+ +-------------+
| | | | | |
Neutron | | | | | Brocade |
v2.0 | OpenStack | | Brocade | NETCONF | VCS Switch |
----+ Neutron +--------+ Mechanism +----------+ |
| ML2 | | Driver | | VDX 67xx |
| Plugin | | | | VDX 87xx |
| | | | | |
| | | | | |
+------------+ +------------+ +-------------+
Configuration
In order to use this mechnism the brocade configuration file needs to be edited with the appropriate
configuration information:
% cat /etc/neutron/plugins/ml2/ml2_conf_brocade.ini
[switch]
username = admin
password = password
address = <switch mgmt ip address>
ostype = NOS
physical_networks = phys1
Additionally the brocade mechanism driver needs to be enabled from the ml2 config file:
% cat /etc/neutron/plugins/ml2/ml2_conf.ini
[ml2]
tenant_network_types = vlan
type_drivers = local,flat,vlan,gre,vxlan
mechanism_drivers = openvswitch,brocade
# OR mechanism_drivers = openvswitch,linuxbridge,hyperv,brocade
...
...
...
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

@ -1,135 +0,0 @@
# 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.
"""Brocade specific database schema/model."""
import sqlalchemy as sa
from neutron.db import model_base
from neutron.db import models_v2
class ML2_BrocadeNetwork(model_base.BASEV2, models_v2.HasId,
models_v2.HasTenant):
"""Schema for brocade network."""
vlan = sa.Column(sa.String(10))
segment_id = sa.Column(sa.String(36))
network_type = sa.Column(sa.String(10))
class ML2_BrocadePort(model_base.BASEV2, models_v2.HasId,
models_v2.HasTenant):
"""Schema for brocade port."""
network_id = sa.Column(sa.String(36),
sa.ForeignKey("ml2_brocadenetworks.id"),
nullable=False)
admin_state_up = sa.Column(sa.Boolean, nullable=False)
physical_interface = sa.Column(sa.String(36))
vlan_id = sa.Column(sa.String(36))
def create_network(context, net_id, vlan, segment_id, network_type, tenant_id):
"""Create a brocade specific network/port-profiles."""
# only network_type of vlan is supported
session = context.session
with session.begin(subtransactions=True):
net = get_network(context, net_id, None)
if not net:
net = ML2_BrocadeNetwork(id=net_id, vlan=vlan,
segment_id=segment_id,
network_type='vlan',
tenant_id=tenant_id)
session.add(net)
return net
def delete_network(context, net_id):
"""Delete a brocade specific network/port-profiles."""
session = context.session
with session.begin(subtransactions=True):
net = get_network(context, net_id, None)
if net:
session.delete(net)
def get_network(context, net_id, fields=None):
"""Get brocade specific network, with vlan extension."""
session = context.session
return session.query(ML2_BrocadeNetwork).filter_by(id=net_id).first()
def get_networks(context, filters=None, fields=None):
"""Get all brocade specific networks."""
session = context.session
return session.query(ML2_BrocadeNetwork).all()
def create_port(context, port_id, network_id, physical_interface,
vlan_id, tenant_id, admin_state_up):
"""Create a brocade specific port, has policy like vlan."""
session = context.session
with session.begin(subtransactions=True):
port = get_port(context, port_id)
if not port:
port = ML2_BrocadePort(id=port_id,
network_id=network_id,
physical_interface=physical_interface,
vlan_id=vlan_id,
admin_state_up=admin_state_up,
tenant_id=tenant_id)
session.add(port)
return port
def get_port(context, port_id):
"""get a brocade specific port."""
session = context.session
return session.query(ML2_BrocadePort).filter_by(id=port_id).first()
def get_ports(context, network_id=None):
"""get a brocade specific port."""
session = context.session
return session.query(ML2_BrocadePort).filter_by(
network_id=network_id).all()
def delete_port(context, port_id):
"""delete brocade specific port."""
session = context.session
with session.begin(subtransactions=True):
port = get_port(context, port_id)
if port:
session.delete(port)
def update_port_state(context, port_id, admin_state_up):
"""Update port attributes."""
session = context.session
with session.begin(subtransactions=True):
session.query(ML2_BrocadePort).filter_by(
id=port_id).update({'admin_state_up': admin_state_up})

View File

@ -1,53 +0,0 @@
# Copyright 2015 Brocade Communications Systems, 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.
"""Implementation of Brocade ML2 Mechanism driver for ICX and MLX."""
from networking_brocade.mlx.ml2.fi_ni import mechanism_brocade_fi_ni
from oslo_config import cfg
SWITCHES = [
cfg.StrOpt(
'switch_names',
default='',
help=('Switches connected to the compute nodes'))]
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('physical_networks', default='',
help=('Allowed physical networks')),
cfg.StrOpt('ports', default='',
help=('Ports')),
cfg.StrOpt('transport', default='SSH',
choices=('SSH', 'TELNET'),
help=('Protocol used to communicate with Switch')),
cfg.StrOpt('ostype', default='NI', choices=('NI', 'FI'),
help=('OS type of the device.')),
]
cfg.CONF.register_opts(SWITCHES, 'ml2_brocade_fi_ni')
cfg.CONF.register_opts(ML2_BROCADE, 'ML2_BROCADE_MLX_EXAMPLE')
class BrocadeFiNiMechanism(mechanism_brocade_fi_ni.BrocadeFiNiMechanism):
def __init__(self):
self._switch_names = cfg.CONF.ml2_brocade_fi_ni.switch_names
switches = [x.strip() for x in self._switch_names.split(',')]
for switch in switches:
cfg.CONF.register_opts(ML2_BROCADE, switch)
super(BrocadeFiNiMechanism, self).__init__()

View File

@ -1,35 +0,0 @@
# 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.
"""Implementation of Brocade ML2 Mechanism driver for ML2 Plugin."""
from oslo_config import cfg
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('physical_networks', default='',
help=_('Allowed physical networks')),
cfg.StrOpt('ostype', default='NOS',
help=_('OS Type of the switch')),
cfg.StrOpt('osversion', default='4.0.0',
help=_('OS Version number'))
]
cfg.CONF.register_opts(ML2_BROCADE, "ml2_brocade")

View File

@ -1 +0,0 @@
networking-brocade

View File

@ -1,32 +0,0 @@
# 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.
#
"""Implementation of Brocade SVI service Plugin."""
from oslo_config import cfg
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")

View File

@ -1,51 +0,0 @@
# Copyright 2015 Brocade Communications Systems, 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.
#
"""Implementation of Brocade L3RouterPlugin for MLX switches."""
from networking_brocade.mlx.services.l3_router.brocade import (
l3_router_plugin as plugin)
from oslo_config import cfg
SWITCHES = [
cfg.StrOpt(
'switch_names',
default='',
help=('Switches connected to the compute nodes'))]
L3_BROCADE = [cfg.StrOpt('address', default='',
help=('The IP address of the MLX switch')),
cfg.StrOpt('username', default='admin',
help=('The SSH username of the switch')),
cfg.StrOpt('password', default='password', secret=True,
help=('The SSH password of the switch')),
cfg.StrOpt('physical_networks', default='',
help=('Allowed physical networks where VLAN can '
'be configured on this switch')),
cfg.StrOpt('ports', default='',
help=('Ports to be tagged in the VLAN being '
'configured on the switch')),
]
cfg.CONF.register_opts(SWITCHES, 'l3_brocade_mlx')
cfg.CONF.register_opts(L3_BROCADE, 'L3_BROCADE_MLX_EXAMPLE')
class BrocadeRouterPlugin(plugin.BrocadeRouterPlugin):
def __init__(self):
self._switch_names = cfg.CONF.l3_brocade_mlx.switch_names
switches = [x.strip() for x in self._switch_names.split(',')]
for switch in switches:
cfg.CONF.register_opts(L3_BROCADE, switch)
super(BrocadeRouterPlugin, self).__init__()

View File

@ -1 +0,0 @@
networking-brocade

View File

@ -1,71 +0,0 @@
# Copyright 2015 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.
from networking_brocade.vyatta.vrouter import neutron_plugin as vrouter_plugin
from oslo_config import cfg
from neutron.common import constants as l3_constants
vrouter_opts = [
cfg.StrOpt('tenant_admin_name', help=_('Name of tenant admin user.')),
cfg.StrOpt('tenant_admin_password', secret=True,
help=_('Tenant admin password.')),
cfg.StrOpt('tenant_id',
help=_('UUID of tenant that holds Vyatta vRouter instances.')),
cfg.StrOpt('image_id',
help=_('Nova image id for instances of Vyatta vRouter.')),
cfg.StrOpt('flavor', default=2,
help=_('Nova VM flavor for instances of Vyatta vRouter.')),
cfg.StrOpt('management_network_id',
help=_('Vyatta vRouter management network id.')),
cfg.StrOpt('vrouter_credentials', default="vyatta:vyatta",
help=_('Vyatta vRouter login credentials')),
cfg.IntOpt('nova_poll_interval', default=5,
help=_('Number of seconds between consecutive Nova queries '
'when waiting for router instance status change.')),
cfg.IntOpt('nova_spawn_timeout', default=300,
help=_('Number of seconds to wait for Nova to activate '
'instance before setting resource to error state.')),
cfg.IntOpt('vrouter_poll_interval', default=5,
help=_('Number of seconds between consecutive Vyatta vRouter '
'queries when waiting for router instance boot.')),
cfg.IntOpt('vrouter_boot_timeout', default=300,
help=_('Number of seconds to wait for Vyatta vRouter to boot '
'before setting resource to error state.')),
cfg.StrOpt('keystone_url', help=_('Keystone URL.'))
]
cfg.CONF.register_opts(vrouter_opts, "VROUTER")
class VyattaVRouterPlugin(vrouter_plugin.VyattaVRouterMixin):
"""Brocade Neutron L3 Plugin for Vyatta vRouter.
Supports CRUD operations on vRouter, add/remove interfaces from vRouter
and floating IPs for VMs.It performs vRouter VM lifecyle management by
calling Nova APIs during the Create and Delete Router calls.
Once the vRouter VM is up, L3 plugin uses REST API to perform the
configurations. L3 plugin supports add/remove router interfaces by
attaching the neutron ports to vRouter VM using Nova API.
RPC notifications will be used by the firewall agent that is coupled
with l3-agent. This is needed for our firewall plugin.
"""
supported_extension_aliases = [
"router", "ext-gw-mode", "extraroute",
l3_constants.L3_AGENT_SCHEDULER_EXT_ALIAS]
def __init__(self):
super(VyattaVRouterPlugin, self).__init__()

View File

@ -1,98 +0,0 @@
# Copyright (c) 2013 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.
"""
Unit test brocade db.
"""
import uuid
from neutron import context
from neutron.plugins.brocade.db import models as brocade_db
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
TEST_VLAN = 1000
class TestBrocadeDb(test_plugin.NeutronDbPluginV2TestCase):
"""Test brocade db functionality."""
def test_create_network(self):
"""Test brocade specific network db."""
net_id = str(uuid.uuid4())
# Create a network
self.context = context.get_admin_context()
brocade_db.create_network(self.context, net_id, TEST_VLAN)
# Get the network and verify
net = brocade_db.get_network(self.context, net_id)
self.assertEqual(net['id'], net_id)
self.assertEqual(int(net['vlan']), TEST_VLAN)
# Delete the network
brocade_db.delete_network(self.context, net['id'])
self.assertFalse(brocade_db.get_networks(self.context))
def test_create_port(self):
"""Test brocade specific port db."""
net_id = str(uuid.uuid4())
port_id = str(uuid.uuid4())
# port_id is truncated: since the linux-bridge tap device names are
# based on truncated port id, this enables port lookups using
# tap devices
port_id = port_id[0:11]
tenant_id = str(uuid.uuid4())
admin_state_up = True
# Create Port
# To create a port a network must exists, Create a network
self.context = context.get_admin_context()
brocade_db.create_network(self.context, net_id, TEST_VLAN)
physical_interface = "em1"
brocade_db.create_port(self.context, port_id, net_id,
physical_interface,
TEST_VLAN, tenant_id, admin_state_up)
port = brocade_db.get_port(self.context, port_id)
self.assertEqual(port['port_id'], port_id)
self.assertEqual(port['network_id'], net_id)
self.assertEqual(port['physical_interface'], physical_interface)
self.assertEqual(int(port['vlan_id']), TEST_VLAN)
self.assertEqual(port['tenant_id'], tenant_id)
self.assertEqual(port['admin_state_up'], admin_state_up)
admin_state_up = True
brocade_db.update_port_state(self.context, port_id, admin_state_up)
port = brocade_db.get_port(self.context, port_id)
self.assertEqual(port['admin_state_up'], admin_state_up)
admin_state_up = False
brocade_db.update_port_state(self.context, port_id, admin_state_up)
port = brocade_db.get_port(self.context, port_id)
self.assertEqual(port['admin_state_up'], admin_state_up)
admin_state_up = True
brocade_db.update_port_state(self.context, port_id, admin_state_up)
port = brocade_db.get_port(self.context, port_id)
self.assertEqual(port['admin_state_up'], admin_state_up)
# Delete Port
brocade_db.delete_port(self.context, port_id)
self.assertFalse(brocade_db.get_ports(self.context))

View File

@ -1,74 +0,0 @@
# Copyright (c) 2012 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_utils import importutils
from neutron.extensions import portbindings
from neutron.plugins.brocade import NeutronPlugin as brocade_plugin
from neutron.tests.unit import _test_extension_portbindings as test_bindings
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
PLUGIN_NAME = ('neutron.plugins.brocade.'
'NeutronPlugin.BrocadePluginV2')
NOS_DRIVER = ('neutron.plugins.brocade.'
'nos.fake_nosdriver.NOSdriver')
FAKE_IPADDRESS = '2.2.2.2'
FAKE_USERNAME = 'user'
FAKE_PASSWORD = 'password'
FAKE_PHYSICAL_INTERFACE = 'em1'
class BrocadePluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase):
_plugin_name = PLUGIN_NAME
def setUp(self):
def mocked_brocade_init(self):
self._switch = {'address': FAKE_IPADDRESS,
'username': FAKE_USERNAME,
'password': FAKE_PASSWORD
}
self._driver = importutils.import_object(NOS_DRIVER)
with mock.patch.object(brocade_plugin.BrocadePluginV2,
'brocade_init', new=mocked_brocade_init):
super(BrocadePluginV2TestCase, self).setUp(self._plugin_name)
class TestBrocadeBasicGet(test_plugin.TestBasicGet,
BrocadePluginV2TestCase):
pass
class TestBrocadeV2HTTPResponse(test_plugin.TestV2HTTPResponse,
BrocadePluginV2TestCase):
pass
class TestBrocadePortsV2(test_plugin.TestPortsV2,
BrocadePluginV2TestCase,
test_bindings.PortBindingsTestCase):
VIF_TYPE = portbindings.VIF_TYPE_BRIDGE
HAS_PORT_FILTER = True
class TestBrocadeNetworksV2(test_plugin.TestNetworksV2,
BrocadePluginV2TestCase):
pass

View File

@ -1,67 +0,0 @@
# Copyright (c) 2013 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.
"""
Test vlans alloc/dealloc.
"""
from neutron import context as n_context
from neutron.plugins.brocade import vlanbm as vlan_bitmap
from neutron.tests.unit import testlib_api
class TestVlanBitmap(testlib_api.SqlTestCase):
"""exercise Vlan bitmap ."""
def setUp(self):
super(TestVlanBitmap, self).setUp()
self.context = n_context.get_admin_context()
def test_vlan(self):
"""test vlan allocation/de-alloc."""
self.vbm_ = vlan_bitmap.VlanBitmap(self.context)
vlan_id = self.vbm_.get_next_vlan(None)
# First vlan is always 2
self.assertEqual(vlan_id, 2)
# next vlan is always 3
vlan_id = self.vbm_.get_next_vlan(None)
self.assertEqual(vlan_id, 3)
# get a specific vlan i.e. 4
vlan_id = self.vbm_.get_next_vlan(4)
self.assertEqual(vlan_id, 4)
# get a specific vlan i.e. 5
vlan_id = self.vbm_.get_next_vlan(5)
self.assertEqual(vlan_id, 5)
# Skip 6
# get a specific vlan i.e. 7
vlan_id = self.vbm_.get_next_vlan(7)
self.assertEqual(vlan_id, 7)
# get a specific vlan i.e. 1900
vlan_id = self.vbm_.get_next_vlan(1900)
self.assertEqual(vlan_id, 1900)
# Release 4 and get next again
self.vbm_.release_vlan(4)
vlan_id = self.vbm_.get_next_vlan(None)
self.assertEqual(vlan_id, 4)

View File

@ -35,15 +35,9 @@ data_files =
etc/neutron/rootwrap.d/l3.filters
etc/neutron/rootwrap.d/linuxbridge-plugin.filters
etc/neutron/rootwrap.d/openvswitch-plugin.filters
etc/neutron/plugins/brocade =
etc/neutron/plugins/brocade/brocade.ini
etc/neutron/plugins/brocade/brocade_mlx.ini
etc/neutron/plugins/brocade/vyatta = etc/neutron/plugins/brocade/vyatta/vrouter.ini
etc/neutron/plugins/cisco =
etc/neutron/plugins/cisco/cisco_vpn_agent.ini
etc/neutron/plugins/ml2 =
etc/neutron/plugins/ml2/ml2_conf_brocade.ini
etc/neutron/plugins/ml2/ml2_conf_brocade_fi_ni.ini
etc/neutron/plugins/ml2/ml2_conf_ofa.ini
etc/neutron/plugins/nuage = etc/neutron/plugins/nuage/nuage_plugin.ini
scripts =
@ -76,14 +70,11 @@ console_scripts =
neutron-sriov-nic-agent = neutron.plugins.ml2.drivers.mech_sriov.agent.sriov_nic_agent:main
neutron-sanity-check = neutron.cmd.sanity_check:main
neutron.core_plugins =
brocade = neutron.plugins.brocade.NeutronPlugin:BrocadePluginV2
ml2 = neutron.plugins.ml2.plugin:Ml2Plugin
nuage = neutron.plugins.nuage.plugin:NuagePlugin
neutron.service_plugins =
dummy = neutron.tests.unit.dummy_plugin:DummyServicePlugin
router = neutron.services.l3_router.l3_router_plugin:L3RouterPlugin
brocade_vyatta_l3 = neutron.services.l3_router.brocade.vyatta.vrouter_neutron_plugin:VyattaVRouterPlugin
brocade_mlx_l3 = neutron.services.l3_router.brocade.mlx.l3_router_plugin:BrocadeRouterPlugin
firewall = neutron_fwaas.services.firewall.fwaas_plugin:FirewallPlugin
lbaas = neutron_lbaas.services.loadbalancer.plugin:LoadBalancerPlugin
vpnaas = neutron_vpnaas.services.vpn.plugin:VPNDriverPlugin
@ -110,8 +101,6 @@ neutron.ml2.mechanism_drivers =
hyperv = neutron.plugins.ml2.drivers.hyperv.mech_hyperv:HypervMechanismDriver
l2population = neutron.plugins.ml2.drivers.l2pop.mech_driver:L2populationMechanismDriver
ofagent = neutron.plugins.ml2.drivers.ofagent.driver:OfagentMechanismDriver
brocade = networking_brocade.vdx.ml2driver.mechanism_brocade:BrocadeMechanism
brocade_fi_ni = neutron.plugins.ml2.drivers.brocade.fi_ni.mechanism_brocade_fi_ni:BrocadeFiNiMechanism
sriovnicswitch = neutron.plugins.ml2.drivers.mech_sriov.mech_driver.mech_driver:SriovNicSwitchMechanismDriver
fake_agent = neutron.tests.unit.plugins.ml2.drivers.mech_fake_agent:FakeAgentMechanismDriver
neutron.ml2.extension_drivers =

View File

@ -13,7 +13,6 @@ test_files=$(find ${test_path} -iname 'test_*.py')
ignore_regexes=(
# The following vendor plugins are not required to confrm to the
# structural requirements.
"^plugins/brocade.*$"
"^plugins/ibm.*$"
# The following open source plugin tests are not actually unit
# tests and are ignored pending their relocation to the functional