Merge "Enhancements to Cisco v2 meta-plugin"

This commit is contained in:
Jenkins 2012-08-15 08:16:21 +00:00 committed by Gerrit Code Review
commit 8a09da6495
11 changed files with 536 additions and 41 deletions

View File

@ -7,5 +7,5 @@ ports=<put_interfaces_names_here_separated_by_commas>
nexus_ssh_port=22
[DRIVER]
#name=quantum.plugins.cisco.nexus.cisco_nexus_network_driver.CiscoNEXUSDriver
#name=quantum.plugins.cisco.nexus.cisco_nexus_network_driver_v2.CiscoNEXUSDriver
name=quantum.plugins.cisco.tests.unit.v2.nexus.fake_nexus_driver.CiscoNEXUSFakeDriver

View File

@ -254,6 +254,38 @@ PYTHONPATH=. python quantum/plugins/cisco/client/cli.py create_multiport <tenant
(Note that you should not be using the create port core API in the above case.)
Using an independent plugin as a device sub-plugin
-------------------------------------------------
If you would like to use an independent virtual switch plugin as one of the sub-plugins
(for eg: the OpenVSwitch plugin) with the nexus device sub-plugin perform the following steps:
(The following instructions are with respect to the OpenVSwitch plugin)
1. Update etc/quantum/plugins/cisco/l2network_plugin.ini
In the [MODEL] section of the configuration file put the following configuration
(note that this should be the only configuration in this section, all other configuration
should be either removed or commented)
model_class=quantum.plugins.cisco.models.virt_phy_sw_v2.VirtualPhysicalSwitchModelV2
2. Update etc/quantum/plugins/cisco/cisco_plugins.ini
In the [PLUGINS] section of the configuration file put the following configuration:
vswitch_plugin=quantum.plugins.openvswitch.ovs_quantum_plugin.OVSQuantumPluginV2
3. Set the DB name, the same name has to be configured in three places:
In etc/quantum/plugins/cisco/conf/db_conn.ini set the "name" value
In /etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini set the "sql_connection"
In /etc/quantum/dhcp_agent.ini set the "db_connection"
4. The range of VLAN IDs has to be set in the OpenVSwitch configuration file:
In /etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini
Set:
vlan_min = <lower_id>
vlan_max = <higher_id>
enable_tunneling = False
5. For Nexus device sub-plugin configuration refer to the above sections
How to test the installation
----------------------------

View File

@ -117,6 +117,7 @@ UCS_PLUGIN = 'ucs_plugin'
NEXUS_PLUGIN = 'nexus_plugin'
UCS_INVENTORY = 'ucs_inventory'
NEXUS_INVENTORY = 'nexus_inventory'
VSWITCH_PLUGIN = 'vswitch_plugin'
PLUGIN_OBJ_REF = 'plugin-obj-ref'
PARAM_LIST = 'param-list'

View File

@ -146,7 +146,7 @@ def get_all_vlan_bindings():
LOG.debug("get_all_vlan_bindings() called")
session = db.get_session()
try:
bindings = session.query(network_models_v2.VlanBinding).all()
bindings = session.query(network_models_v2.Vlan_Binding).all()
return bindings
except exc.NoResultFound:
return []
@ -157,7 +157,7 @@ def get_vlan_binding(netid):
LOG.debug("get_vlan_binding() called")
session = db.get_session()
try:
binding = (session.query(network_models_v2.VlanBinding).
binding = (session.query(network_models_v2.Vlan_Binding).
filter_by(network_id=netid).one())
return binding
except exc.NoResultFound:
@ -169,12 +169,12 @@ def add_vlan_binding(vlanid, vlanname, netid):
LOG.debug("add_vlan_binding() called")
session = db.get_session()
try:
binding = (session.query(network_models_v2.VlanBinding).
binding = (session.query(network_models_v2.Vlan_Binding).
filter_by(vlan_id=vlanid).one())
raise c_exc.NetworkVlanBindingAlreadyExists(vlan_id=vlanid,
network_id=netid)
except exc.NoResultFound:
binding = network_models_v2.VlanBinding(vlanid, vlanname, netid)
binding = network_models_v2.Vlan_Binding(vlanid, vlanname, netid)
session.add(binding)
session.flush()
return binding
@ -185,7 +185,7 @@ def remove_vlan_binding(netid):
LOG.debug("remove_vlan_binding() called")
session = db.get_session()
try:
binding = (session.query(network_models_v2.VlanBinding).
binding = (session.query(network_models_v2.Vlan_Binding).
filter_by(network_id=netid).one())
session.delete(binding)
session.flush()
@ -199,7 +199,7 @@ def update_vlan_binding(netid, newvlanid=None, newvlanname=None):
LOG.debug("update_vlan_binding() called")
session = db.get_session()
try:
binding = (session.query(network_models_v2.VlanBinding).
binding = (session.query(network_models_v2.Vlan_Binding).
filter_by(network_id=netid).one())
if newvlanid:
binding["vlan_id"] = newvlanid

View File

@ -68,7 +68,7 @@ class L2NetworkBase(object):
class VlanID(model_base.BASEV2, L2NetworkBase):
"""Represents a vlan_id usage"""
__tablename__ = 'vlan_ids'
__tablename__ = 'cisco_vlan_ids'
vlan_id = Column(Integer, primary_key=True)
vlan_used = Column(Boolean)
@ -81,9 +81,9 @@ class VlanID(model_base.BASEV2, L2NetworkBase):
return "<VlanID(%d,%s)>" % (self.vlan_id, self.vlan_used)
class VlanBinding(model_base.BASEV2, L2NetworkBase):
class Vlan_Binding(model_base.BASEV2, L2NetworkBase):
"""Represents a binding of vlan_id to network_id"""
__tablename__ = 'vlan_bindings'
__tablename__ = 'cisco_vlan_bindings'
vlan_id = Column(Integer, primary_key=True)
vlan_name = Column(String(255))

View File

@ -0,0 +1,251 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2012 Cisco 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.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
# @author: Rohit Agarwalla, Cisco Systems, Inc.
from copy import deepcopy
import inspect
import logging
from quantum.manager import QuantumManager
from quantum.openstack.common import importutils
from quantum.plugins.cisco.common import cisco_constants as const
from quantum.plugins.cisco.common import cisco_credentials_v2 as cred
from quantum.plugins.cisco.db import network_db_v2 as cdb
from quantum.plugins.cisco import l2network_plugin_configuration as conf
from quantum.plugins.openvswitch import ovs_db_v2 as odb
from quantum import quantum_plugin_base_v2
LOG = logging.getLogger(__name__)
class VirtualPhysicalSwitchModelV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
"""
This implementation works with OVS and Nexus plugin for the
following topology:
One or more servers to a nexus switch.
"""
MANAGE_STATE = True
supported_extension_aliases = []
_plugins = {}
_inventory = {}
_methods_to_delegate = ['update_network', 'get_network', 'get_networks',
'create_port', 'delete_port', 'update_port',
'get_port', 'get_ports',
'create_subnet', 'delete_subnet', 'update_subnet',
'get_subnet', 'get_subnets']
def __init__(self):
"""
Initialize the segmentation manager, check which device plugins are
configured, and load the inventories those device plugins for which the
inventory is configured
"""
cdb.initialize()
cred.Store.initialize()
for key in conf.PLUGINS[const.PLUGINS].keys():
plugin_obj = conf.PLUGINS[const.PLUGINS][key]
self._plugins[key] = importutils.import_object(plugin_obj)
LOG.debug("Loaded device plugin %s\n" %
conf.PLUGINS[const.PLUGINS][key])
if key in conf.PLUGINS[const.INVENTORY].keys():
inventory_obj = conf.PLUGINS[const.INVENTORY][key]
self._inventory[key] = importutils.import_object(inventory_obj)
LOG.debug("Loaded device inventory %s\n" %
conf.PLUGINS[const.INVENTORY][key])
LOG.debug("%s.%s init done" % (__name__, self.__class__.__name__))
def __getattribute__(self, name):
methods = object.__getattribute__(self, "_methods_to_delegate")
if name in methods:
return getattr(object.__getattribute__(self, "_plugins")
[const.VSWITCH_PLUGIN], name)
else:
return object.__getattribute__(self, name)
def _func_name(self, offset=0):
"""Get the name of the calling function"""
frame_record = inspect.stack()[1 + offset]
func_name = frame_record[3]
return func_name
def _invoke_plugin_per_device(self, plugin_key, function_name, args):
"""
Invokes a device plugin's relevant functions (on the it's
inventory and plugin implementation) for completing this operation.
"""
if not plugin_key in self._plugins.keys():
LOG.info("No %s Plugin loaded" % plugin_key)
LOG.info("%s: %s with args %s ignored" %
(plugin_key, function_name, args))
return
device_params = self._invoke_inventory(plugin_key, function_name,
args)
device_ips = device_params[const.DEVICE_IP]
if not device_ips:
return [self._invoke_plugin(plugin_key, function_name, args,
device_params)]
else:
output = []
for device_ip in device_ips:
new_device_params = deepcopy(device_params)
new_device_params[const.DEVICE_IP] = device_ip
output.append(self._invoke_plugin(plugin_key, function_name,
args, new_device_params))
return output
def _invoke_inventory(self, plugin_key, function_name, args):
"""
Invokes the relevant function on a device plugin's
inventory for completing this operation.
"""
if not plugin_key in self._inventory.keys():
LOG.info("No %s inventory loaded" % plugin_key)
LOG.info("%s: %s with args %s ignored" %
(plugin_key, function_name, args))
return {const.DEVICE_IP: []}
else:
return getattr(self._inventory[plugin_key], function_name)(args)
def _invoke_plugin(self, plugin_key, function_name, args, kwargs):
"""
Invokes the relevant function on a device plugin's
implementation for completing this operation.
"""
func = getattr(self._plugins[plugin_key], function_name)
func_args_len = int(inspect.getargspec(func).args.__len__()) - 1
fargs, varargs, varkw, defaults = inspect.getargspec(func)
if args.__len__() > func_args_len:
func_args = args[:func_args_len]
extra_args = args[func_args_len:]
for dict_arg in extra_args:
for k, v in dict_arg.iteritems():
kwargs[k] = v
return func(*func_args, **kwargs)
else:
if (varkw == 'kwargs'):
return func(*args, **kwargs)
else:
return func(*args)
def create_network(self, context, network):
"""
Perform this operation in the context of the configured device
plugins.
"""
LOG.debug("create_network() called\n")
try:
args = [context, network]
ovs_output = self._invoke_plugin_per_device(const.VSWITCH_PLUGIN,
self._func_name(),
args)
vlan_id = odb.get_vlan(ovs_output[0]['id'])
vlan_name = conf.VLAN_NAME_PREFIX + str(vlan_id)
vlan_ids = odb.get_vlans()
vlanids = ''
for v_id in vlan_ids:
vlanids = str(v_id[0]) + ',' + vlanids
vlanids = vlanids.strip(',')
args = [ovs_output[0]['tenant_id'], ovs_output[0]['name'],
ovs_output[0]['id'], vlan_name, vlan_id,
{'vlan_ids':vlanids}]
nexus_output = self._invoke_plugin_per_device(const.NEXUS_PLUGIN,
self._func_name(),
args)
return ovs_output[0]
except:
# TODO (Sumit): Check if we need to perform any rollback here
raise
def update_network(self, context, id, network):
"""For this model this method will be delegated to vswitch plugin"""
pass
def delete_network(self, context, id):
"""
Perform this operation in the context of the configured device
plugins.
"""
try:
base_plugin_ref = QuantumManager.get_plugin()
n = base_plugin_ref.get_network(context, id)
tenant_id = n['tenant_id']
vlan_id = odb.get_vlan(id)
output = []
args = [tenant_id, id, {const.VLANID:vlan_id},
{const.CONTEXT:context},
{const.BASE_PLUGIN_REF:base_plugin_ref}]
nexus_output = self._invoke_plugin_per_device(const.NEXUS_PLUGIN,
self._func_name(),
args)
args = [context, id]
ovs_output = self._invoke_plugin_per_device(const.VSWITCH_PLUGIN,
self._func_name(),
args)
return ovs_output[0]
except:
raise
def get_network(self, context, id, fields=None, verbose=None):
"""For this model this method will be delegated to vswitch plugin"""
pass
def get_networks(self, context, filters=None, fields=None, verbose=None):
"""For this model this method will be delegated to vswitch plugin"""
pass
def create_port(self, context, port):
"""For this model this method will be delegated to vswitch plugin"""
pass
def get_port(self, context, id, fields=None, verbose=None):
"""For this model this method will be delegated to vswitch plugin"""
pass
def get_ports(self, context, filters=None, fields=None, verbose=None):
"""For this model this method will be delegated to vswitch plugin"""
pass
def update_port(self, context, id, port):
"""For this model this method will be delegated to vswitch plugin"""
pass
def delete_port(self, context, id, kwargs):
"""For this model this method will be delegated to vswitch plugin"""
pass
def create_subnet(self, context, subnet):
"""For this model this method will be delegated to vswitch plugin"""
pass
def update_subnet(self, context, id, subnet):
"""For this model this method will be delegated to vswitch plugin"""
pass
def get_subnet(self, context, id, fields=None, verbose=None):
"""For this model this method will be delegated to vswitch plugin"""
pass
def delete_subnet(self, context, id, kwargs):
"""For this model this method will be delegated to vswitch plugin"""
pass
def get_subnets(self, context, filters=None, fields=None, verbose=None):
"""For this model this method will be delegated to vswitch plugin"""
pass

View File

@ -29,45 +29,83 @@ from quantum.plugins.cisco.common import cisco_exceptions as cexc
from quantum.plugins.cisco.common import cisco_utils as cutil
from quantum.plugins.cisco.db import network_db_v2 as cdb
from quantum.plugins.cisco import l2network_plugin_configuration as conf
from quantum.quantum_plugin_base_v2 import QuantumPluginBaseV2
LOG = logging.getLogger(__name__)
class PluginV2(db_base_plugin_v2.QuantumDbPluginV2):
"""
Plugin with v2 API support for multiple sub-plugins
Meta-Plugin with v2 API support for multiple sub-plugins.
"""
supported_extension_aliases = ["Cisco Credential", "Cisco Port Profile",
"Cisco qos", "Cisco Nova Tenant",
"Cisco Multiport"]
_methods_to_delegate = ['create_network', 'delete_network',
'update_network', 'get_network', 'get_networks',
'create_port', 'delete_port', 'update_port',
'get_port', 'get_ports',
'create_subnet', 'delete_subnet', 'update_subnet',
'get_subnet', 'get_subnets']
_master = True
def __init__(self):
"""
Loads the model class, initializes the DB, and credential store.
"""
self._model = importutils.import_object(conf.MODEL_CLASS)
if hasattr(self._model, "MANAGE_STATE") and self._model.MANAGE_STATE:
self._master = False
LOG.debug("Model %s manages state" % conf.MODEL_CLASS)
else:
cdb.initialize()
cred.Store.initialize()
if hasattr(self._model, "supported_extension_aliases"):
self.supported_extension_aliases.extend(
self._model.supported_extension_aliases)
super(PluginV2, self).__init__()
LOG.debug("Plugin initialization complete")
def __getattribute__(self, name):
"""
When the configured model class offers to manage the state of the
logical resources, we delegate the core API calls directly to it.
"""
master = object.__getattribute__(self, "_master")
methods = object.__getattribute__(self, "_methods_to_delegate")
if not master and name in methods:
return getattr(object.__getattribute__(self, "_model"),
name)
else:
return object.__getattribute__(self, name)
def __getattr__(self, name):
"""
This delegates the calls to the extensions explicitly implemented by
the model.
"""
if hasattr(self._model, name):
return getattr(self._model, name)
"""
Core API implementation
"""
def __init__(self):
"""
Initializes the DB, and credential store.
"""
cdb.initialize()
cred.Store.initialize()
self._model = importutils.import_object(conf.MODEL_CLASS)
super(PluginV2, self).__init__()
LOG.debug("Plugin initialization complete")
def create_network(self, context, network):
"""
Creates a new Virtual Network, and assigns it
a symbolic name.
"""
LOG.debug("create_network() called\n")
new_network = super(PluginV2, self).create_network(context, network)
new_network = super(PluginV2, self).create_network(context,
network)
try:
self._invoke_device_plugins(self._func_name(), [context,
new_network])
return new_network
except:
super(PluginV2, self).delete_network(context, new_network['id'])
super(PluginV2, self).delete_network(context,
new_network['id'])
raise
def update_network(self, context, id, network):
@ -79,7 +117,8 @@ class PluginV2(db_base_plugin_v2.QuantumDbPluginV2):
try:
self._invoke_device_plugins(self._func_name(), [context, id,
network])
return super(PluginV2, self).update_network(context, id, network)
return super(PluginV2, self).update_network(context, id,
network)
except:
raise
@ -92,7 +131,6 @@ class PluginV2(db_base_plugin_v2.QuantumDbPluginV2):
#We first need to check if there are any ports on this network
with context.session.begin():
network = self._get_network(context, id)
filter = {'network_id': [id]}
ports = self.get_ports(context, filters=filter)
if ports:
@ -109,6 +147,22 @@ class PluginV2(db_base_plugin_v2.QuantumDbPluginV2):
except:
raise
def get_network(self, context, id, fields=None, verbose=None):
"""
Gets a particular network
"""
LOG.debug("get_network() called\n")
return super(PluginV2, self).get_network(context, id,
fields, verbose)
def get_networks(self, context, filters=None, fields=None, verbose=None):
"""
Gets all networks
"""
LOG.debug("get_networks() called\n")
return super(PluginV2, self).get_networks(context, filters,
fields, verbose)
def create_port(self, context, port):
"""
Creates a port on the specified Virtual Network.
@ -446,9 +500,11 @@ class PluginV2(db_base_plugin_v2.QuantumDbPluginV2):
"""
def _invoke_device_plugins(self, function_name, args):
"""
All device-specific calls are delegated to the model
Device-specific calls including core API and extensions are
delegated to the model.
"""
return getattr(self._model, function_name)(*args)
if hasattr(self._model, function_name):
return getattr(self._model, function_name)(*args)
def _func_name(self, offset=0):
"""Getting the name of the calling funciton"""

View File

@ -0,0 +1,150 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco 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.
#
# @author: Debojyoti Dutta, Cisco Systems, Inc.
# @author: Edgar Magana, Cisco Systems Inc.
#
"""
Implements a Nexus-OS NETCONF over SSHv2 API Client
"""
import logging
from ncclient import manager
from quantum.plugins.cisco.db import network_db_v2 as cdb
from quantum.plugins.cisco.nexus import cisco_nexus_snippets as snipp
LOG = logging.getLogger(__name__)
class CiscoNEXUSDriver():
"""
Nexus Driver Main Class
"""
def __init__(self):
pass
def nxos_connect(self, nexus_host, nexus_ssh_port, nexus_user,
nexus_password):
"""
Makes the SSH connection to the Nexus Switch
"""
man = manager.connect(host=nexus_host, port=nexus_ssh_port,
username=nexus_user, password=nexus_password)
return man
def create_xml_snippet(self, cutomized_config):
"""
Creates the Proper XML structure for the Nexus Switch Configuration
"""
conf_xml_snippet = snipp.EXEC_CONF_SNIPPET % (cutomized_config)
return conf_xml_snippet
def enable_vlan(self, mgr, vlanid, vlanname):
"""
Creates a VLAN on Nexus Switch given the VLAN ID and Name
"""
confstr = snipp.CMD_VLAN_CONF_SNIPPET % (vlanid, vlanname)
confstr = self.create_xml_snippet(confstr)
mgr.edit_config(target='running', config=confstr)
def disable_vlan(self, mgr, vlanid):
"""
Delete a VLAN on Nexus Switch given the VLAN ID
"""
confstr = snipp.CMD_NO_VLAN_CONF_SNIPPET % vlanid
confstr = self.create_xml_snippet(confstr)
mgr.edit_config(target='running', config=confstr)
def enable_port_trunk(self, mgr, interface):
"""
Enables trunk mode an interface on Nexus Switch
"""
confstr = snipp.CMD_PORT_TRUNK % (interface)
confstr = self.create_xml_snippet(confstr)
LOG.debug("NexusDriver: %s" % confstr)
mgr.edit_config(target='running', config=confstr)
def disable_switch_port(self, mgr, interface):
"""
Disables trunk mode an interface on Nexus Switch
"""
confstr = snipp.CMD_NO_SWITCHPORT % (interface)
confstr = self.create_xml_snippet(confstr)
LOG.debug("NexusDriver: %s" % confstr)
mgr.edit_config(target='running', config=confstr)
def enable_vlan_on_trunk_int(self, mgr, interface, vlanid):
"""
Enables trunk mode vlan access an interface on Nexus Switch given
VLANID
"""
confstr = snipp.CMD_VLAN_INT_SNIPPET % (interface, vlanid)
confstr = self.create_xml_snippet(confstr)
LOG.debug("NexusDriver: %s" % confstr)
mgr.edit_config(target='running', config=confstr)
def disable_vlan_on_trunk_int(self, mgr, interface, vlanid):
"""
Enables trunk mode vlan access an interface on Nexus Switch given
VLANID
"""
confstr = snipp.CMD_NO_VLAN_INT_SNIPPET % (interface, vlanid)
confstr = self.create_xml_snippet(confstr)
LOG.debug("NexusDriver: %s" % confstr)
mgr.edit_config(target='running', config=confstr)
def create_vlan(self, vlan_name, vlan_id, nexus_host, nexus_user,
nexus_password, nexus_ports,
nexus_ssh_port, vlan_ids=None):
"""
Creates a VLAN and Enable on trunk mode an interface on Nexus Switch
given the VLAN ID and Name and Interface Number
"""
with self.nxos_connect(nexus_host, int(nexus_ssh_port), nexus_user,
nexus_password) as man:
self.enable_vlan(man, vlan_id, vlan_name)
if vlan_ids is '':
vlan_ids = self.build_vlans_cmd()
LOG.debug("NexusDriver VLAN IDs: %s" % vlan_ids)
for ports in nexus_ports:
self.enable_vlan_on_trunk_int(man, ports, vlan_ids)
def delete_vlan(self, vlan_id, nexus_host, nexus_user, nexus_password,
nexus_ports, nexus_ssh_port):
"""
Delete a VLAN and Disables trunk mode an interface on Nexus Switch
given the VLAN ID and Interface Number
"""
with self.nxos_connect(nexus_host, int(nexus_ssh_port), nexus_user,
nexus_password) as man:
self.disable_vlan(man, vlan_id)
for ports in nexus_ports:
self.disable_vlan_on_trunk_int(man, ports, vlan_id)
def build_vlans_cmd(self):
"""
Builds a string with all the VLANs on the same Switch
"""
assigned_vlan = cdb.get_all_vlanids_used()
vlans = ''
for vlanid in assigned_vlan:
vlans = str(vlanid["vlan_id"]) + ',' + vlans
if vlans == '':
vlans = 'none'
return vlans.strip(',')

View File

@ -71,10 +71,14 @@ class NexusPlugin(L2DevicePluginBase):
for this VLAN
"""
LOG.debug("NexusPlugin:create_network() called\n")
vlan_ids = ''
for key in kwargs:
if key == 'vlan_ids':
vlan_ids = kwargs['vlan_ids']
self._client.create_vlan(
vlan_name, str(vlan_id), self._nexus_ip,
self._nexus_username, self._nexus_password,
self._nexus_ports, self._nexus_ssh_port)
self._nexus_ports, self._nexus_ssh_port, vlan_ids)
for ports in self._nexus_ports:
try:
nxos_db.add_nexusport_binding(ports, str(vlan_id))
@ -95,10 +99,15 @@ class NexusPlugin(L2DevicePluginBase):
from the relevant interfaces
"""
LOG.debug("NexusPlugin:delete_network() called\n")
vlan_id = None
context = kwargs[const.CONTEXT]
base_plugin_ref = kwargs[const.BASE_PLUGIN_REF]
vlan_id = self._get_vlan_id_for_network(tenant_id, net_id,
context, base_plugin_ref)
for key in kwargs:
if key == 'vlan_id':
vlan_id = kwargs['vlan_id']
if vlan_id is None:
vlan_id = self._get_vlan_id_for_network(tenant_id, net_id,
context, base_plugin_ref)
ports_id = nxos_db.get_nexusport_binding(vlan_id)
LOG.debug("NexusPlugin: Interfaces to be disassociated: %s" % ports_id)
nxos_db.remove_nexusport_binding(vlan_id)
@ -185,10 +194,8 @@ class NexusPlugin(L2DevicePluginBase):
"""
Obtain the VLAN ID given the Network ID
"""
net = self._get_network(tenant_id, network_id, context,
base_plugin_ref)
vlan_id = net[const.NET_VLAN_ID]
return vlan_id
vlan = cdb.get_vlan_binding(network_id)
return vlan.vlan_id
def _get_network(self, tenant_id, network_id, context, base_plugin_ref):
"""
@ -197,8 +204,5 @@ class NexusPlugin(L2DevicePluginBase):
network = base_plugin_ref._get_network(context, network_id)
if not network:
raise exc.NetworkNotFound(net_id=network_id)
vlan = cdb.get_vlan_binding(network_id)
return {const.NET_ID: network_id, const.NET_NAME: network.name,
const.NET_PORTS: network.ports,
const.NET_VLAN_NAME: vlan.vlan_name,
const.NET_VLAN_ID: vlan.vlan_id}
const.NET_PORTS: network.ports}

View File

@ -29,7 +29,7 @@ LOG = logging.getLogger(__name__)
# The following are standard strings, messages used to communicate with Nexus,
EXEC_CONF_SNIPPET = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<configure xmlns="http://www.cisco.com/nxos:1.0:vlan_mgr_cli">
<configure>
<__XML__MODE__exec_configure>%s
</__XML__MODE__exec_configure>
</configure>

View File

@ -21,6 +21,7 @@ import os
from quantum.api.v2.router import APIRouter
from quantum.common import config
from quantum.db import api as db
from quantum.manager import QuantumManager
from quantum.plugins.cisco.db import network_models_v2
from quantum.openstack.common import cfg
from quantum.tests.unit import test_db_plugin
@ -38,7 +39,7 @@ class NetworkPluginV2TestCase(test_db_plugin.QuantumDbPluginV2TestCase):
def setUp(self):
db._ENGINE = None
db._MAKER = None
QuantumManager._instance = None
self._tenant_id = 'test-tenant'
json_deserializer = JSONDeserializer()