+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
import logging as LOG
-import os
-
from configobj import ConfigObj
-from validate import Validator
-
from quantum.plugins.cisco.common import cisco_constants as const
-from quantum.plugins.cisco.common import cisco_exceptions as cexc
LOG.basicConfig(level=LOG.WARN)
LOG.getLogger(const.LOGGER_COMPONENT_NAME)
class CiscoConfigParser(ConfigObj):
+ """Config Parser based on the ConfigObj module"""
def __init__(self, filename):
super(CiscoConfigParser, self).__init__(filename, raise_errors=True,
file_error=True)
def dummy(self, section, key):
+ """Dummy function to return the same key, used in walk"""
return section[key]
-
-
-def main():
- cp = CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
- + "/" + "test.ini")
- print ("%s\n") % cp['PLUGIN']['provider']
-
-if __name__ == '__main__':
- main()
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
PLUGINS = 'PLUGINS'
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
import logging as LOG
import os
class Store(object):
+ """Credential Store"""
+
@staticmethod
def putCredential(id, username, password):
+ """Set the username and password"""
_creds_dictionary[id] = {const.USERNAME: username,
- const.PASSWORD: password}
+ const.PASSWORD: password}
@staticmethod
def getUsername(id):
+ """Get the username"""
return _creds_dictionary[id][const.USERNAME]
@staticmethod
def getPassword(id):
+ """Get the password"""
return _creds_dictionary[id][const.PASSWORD]
@staticmethod
def getCredential(id):
+ """Get the username and password"""
return _creds_dictionary[id]
@staticmethod
def getCredentials():
+ """Get all usernames and passwords"""
return _creds_dictionary
@staticmethod
def deleteCredential(id):
+ """Delete a credential"""
return _creds_dictionary.pop(id)
-
-
-def main():
- Store.putCredential("10.10.10.10", "foo", "bar")
- print ("%s\n") % Store.getCredentials()
-
-if __name__ == '__main__':
- main()
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
# @author: Rohit Agarwalla, Cisco Systems, Inc.
-
+"""
"""
Exceptions used by the Cisco plugin
"""
-
from quantum.common import exceptions
class NoMoreNics(exceptions.QuantumException):
- message = _("Unable to complete operation on port %(port_id)s " \
- "for network %(net_id)s. No more dynamic nics are available" \
- "in the system.")
+ """No more dynamic nics are available in the system"""
+ message = _("Unable to complete operation. No more dynamic nics are " \
+ "available in the system.")
class PortProfileLimit(exceptions.QuantumException):
+ """Port profile limit has been hit"""
message = _("Unable to complete operation on port %(port_id)s " \
"for network %(net_id)s. The system has reached the maximum" \
"limit of allowed port profiles.")
class UCSMPortProfileLimit(exceptions.QuantumException):
+ """UCSM Port profile limit has been hit"""
message = _("Unable to complete operation on port %(port_id)s " \
"for network %(net_id)s. The system has reached the maximum" \
"limit of allowed UCSM port profiles.")
class NetworksLimit(exceptions.QuantumException):
+ """Total number of network objects limit has been hit"""
message = _("Unable to create new network. Number of networks" \
"for the system has exceeded the limit")
class PortProfileNotFound(exceptions.QuantumException):
+ """Port profile cannot be found"""
message = _("Port profile %(portprofile_id)s could not be found " \
"for tenant %(tenant_id)s")
class PortProfileInvalidDelete(exceptions.QuantumException):
+ """Port profile cannot be deleted since its being used"""
message = _("Port profile %(profile_id)s could not be deleted " \
"for tenant %(tenant_id)s since port associations exist")
class NetworkVlanBindingAlreadyExists(exceptions.QuantumException):
+ """Binding cannot be created, since it already exists"""
message = _("NetworkVlanBinding for %(vlan_id)s and network " \
"%(network_id)s already exists")
class PortProfileAlreadyExists(exceptions.QuantumException):
+ """Port profile cannot be created since it already exisits"""
message = _("PortProfile %(pp_name) for %(tenant_id)s " \
"already exists")
class PortProfileBindingAlreadyExists(exceptions.QuantumException):
+ """Binding cannot be created, since it already exists"""
message = _("PortProfileBinding for port profile %(pp_id)s to " \
"port %(port_id) already exists")
class VlanIDNotFound(exceptions.QuantumException):
+ """VLAN ID cannot be found"""
message = _("Vlan ID %(vlan_id)s not found")
class VlanIDNotAvailable(exceptions.QuantumException):
+ """VLAN ID is reserved"""
message = _("No available Vlan ID found")
+
+try:
+ _("test")
+except NameError:
+
+ def _(a_string):
+ """
+ Default implementation of the gettext string
+ translation function: no translation
+ """
+ return a_string
+except TypeError:
+ # during doctesting, _ might mean something else
+ pass
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
import os
CONF_FILE = "../conf/nova.ini"
-cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
+CP = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
+ "/" + CONF_FILE)
-section = cp['NOVA']
-DB_SERVER_IP = section['db_server_ip']
-DB_NAME = section['db_name']
-DB_USERNAME = section['db_username']
-DB_PASSWORD = section['db_password']
-NOVA_HOST_NAME = section['nova_host_name']
-NOVA_PROJ_NAME = section['nova_proj_name']
-
-
-def main():
- print NOVA_PROJ_NAME
-
-if __name__ == '__main__':
- main()
+SECTION = CP['NOVA']
+DB_SERVER_IP = SECTION['db_server_ip']
+DB_NAME = SECTION['db_name']
+DB_USERNAME = SECTION['db_username']
+DB_PASSWORD = SECTION['db_password']
+NOVA_HOST_NAME = SECTION['nova_host_name']
+NOVA_PROJ_NAME = SECTION['nova_proj_name']
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
import hashlib
import logging as LOG
import MySQLdb
-import sys
import traceback
-from quantum.common import exceptions as exc
from quantum.plugins.cisco.common import cisco_constants as const
-from quantum.plugins.cisco.common import cisco_credentials as cred
from quantum.plugins.cisco.common import cisco_nova_configuration as conf
LOG.basicConfig(level=LOG.WARN)
def get16ByteUUID(uuid):
+ """
+ Return a 16 byte has of the UUID, used when smaller unique
+ ID is required.
+ """
return hashlib.md5(uuid).hexdigest()[:16]
class DBUtils(object):
+ """Utilities to use connect to MySQL DB and execute queries"""
def __init__(self):
pass
def _get_db_connection(self):
+ """Get a connection to the DB"""
db_ip = conf.DB_SERVER_IP
db_username = conf.DB_USERNAME
db_password = conf.DB_PASSWORD
return self.db
def execute_db_query(self, sql_query):
+ """Execute a DB query"""
db = self._get_db_connection()
cursor = db.cursor()
try:
results = cursor.fetchall()
db.commit()
LOG.debug("DB query execution succeeded: %s" % sql_query)
- db.close()
+ db.close()
except:
db.rollback()
LOG.debug("DB query execution failed: %s" % sql_query)
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
import inspect
from abc import ABCMeta, abstractmethod
class L2DevicePluginBase(object):
+ """
+ Base class for a device-specific plugin.
+ An example of a device-specific plugin is a Nexus switch plugin.
+ The network model relies on device-category-specific plugins to perform
+ the configuration on each device.
+ """
__metaclass__ = ABCMeta
marked with the abstractmethod decorator is
provided by the plugin class.
"""
- if cls is QuantumPluginBase:
+ if cls is L2DevicePluginBase:
for method in cls.__abstractmethods__:
method_ok = False
for base in klass.__mro__:
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
import inspect
import logging as LOG
class L2NetworkModel(L2NetworkModelBase):
+ """
+ Implements the L2NetworkModelBase
+ This implementation works with UCS and Nexus plugin,
+ with one UCS blade, and one Nexus switch.
+ """
_plugins = {}
def __init__(self):
- for key in conf.plugins[const.PLUGINS].keys():
+ for key in conf.PLUGINS[const.PLUGINS].keys():
self._plugins[key] = utils.import_object(
- conf.plugins[const.PLUGINS][key])
+ conf.PLUGINS[const.PLUGINS][key])
LOG.debug("Loaded device plugin %s\n" % \
- conf.plugins[const.PLUGINS][key])
+ conf.PLUGINS[const.PLUGINS][key])
- def _funcName(self, offset=0):
+ def _func_name(self, offset=0):
+ """Get the name of the calling function"""
return inspect.stack()[1 + offset][3]
- def _invokeAllDevicePlugins(self, function_name, args, kwargs):
- for pluginObjRef in self._plugins.values():
- getattr(pluginObjRef, function_name)(*args, **kwargs)
+ def _invoke_all_device_plugins(self, function_name, args, kwargs):
+ """Invoke all device plugins for this model implementation"""
+ for plugin_obj_ref in self._plugins.values():
+ getattr(plugin_obj_ref, function_name)(*args, **kwargs)
- def _invokeUCSPlugin(self, function_name, args, kwargs):
+ def _invoke_ucs_plugin(self, function_name, args, kwargs):
+ """Invoke only the UCS plugin"""
if const.UCS_PLUGIN in self._plugins.keys():
getattr(self._plugins[const.UCS_PLUGIN],
function_name)(*args, **kwargs)
- def _invokeNexusPlugin(self, function_name, args, kwargs):
+ def _invoke_nexus_plugin(self, function_name, args, kwargs):
+ """Invoke only the Nexus plugin"""
if const.NEXUS_PLUGIN in self._plugins.keys():
getattr(self._plugins[const.NEXUS_PLUGIN],
function_name)(*args, **kwargs)
def get_all_networks(self, args):
+ """Not implemented for this model"""
pass
def create_network(self, args):
- deviceParams = {const.DEVICE_IP: ""}
- self._invokeAllDevicePlugins(self._funcName(), args, deviceParams)
+ """Support for the Quantum core API call"""
+ device_params = {const.DEVICE_IP: ""}
+ self._invoke_all_device_plugins(self._func_name(), args, device_params)
def delete_network(self, args):
- deviceParams = {const.DEVICE_IP: ""}
- self._invokeAllDevicePlugins(self._funcName(), args, deviceParams)
+ """Support for the Quantum core API call"""
+ device_params = {const.DEVICE_IP: ""}
+ self._invoke_all_device_plugins(self._func_name(), args, device_params)
def get_network_details(self, args):
+ """Not implemented for this model"""
pass
def rename_network(self, args):
- deviceParams = {const.DEVICE_IP: ""}
- self._invokeAllDevicePlugins(self._funcName(), args, deviceParams)
+ """Support for the Quantum core API call"""
+ device_params = {const.DEVICE_IP: ""}
+ self._invoke_all_device_plugins(self._func_name(), args, device_params)
def get_all_ports(self, args):
+ """Not implemented for this model"""
pass
def create_port(self, args):
- deviceParams = {const.DEVICE_IP: ""}
- self._invokeUCSPlugin(self._funcName(), args, deviceParams)
+ """Support for the Quantum core API call"""
+ device_params = {const.DEVICE_IP: ""}
+ self._invoke_ucs_plugin(self._func_name(), args, device_params)
def delete_port(self, args):
- deviceParams = {const.DEVICE_IP: ""}
- self._invokeUCSPlugin(self._funcName(), args, deviceParams)
+ """Support for the Quantum core API call"""
+ device_params = {const.DEVICE_IP: ""}
+ self._invoke_ucs_plugin(self._func_name(), args, device_params)
def update_port(self, args):
+ """Not implemented for this model"""
pass
def get_port_details(self, args):
+ """Not implemented for this model"""
pass
def plug_interface(self, args):
- deviceParams = {const.DEVICE_IP: ""}
- self._invokeUCSPlugin(self._funcName(), args, deviceParams)
+ """Support for the Quantum core API call"""
+ device_params = {const.DEVICE_IP: ""}
+ self._invoke_ucs_plugin(self._func_name(), args, device_params)
def unplug_interface(self, args):
- deviceParams = {const.DEVICE_IP: ""}
- self._invokeUCSPlugin(self._funcName(), args, deviceParams)
-
-
-def main():
- client = L2NetworkModel()
-
-if __name__ == '__main__':
- main()
+ """Support for the Quantum core API call"""
+ device_params = {const.DEVICE_IP: ""}
+ self._invoke_ucs_plugin(self._func_name(), args, device_params)
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
import inspect
from abc import ABCMeta, abstractmethod
class L2NetworkModelBase(object):
+ """
+ Base class for L2 Network Model
+ It relies on a pluggable network configuration module to gather
+ knowledge of the system, but knows which device-specific plugins
+ to invoke for a corresponding core API call, and what parameters to pass
+ to that plugin.
+ """
__metaclass__ = ABCMeta
marked with the abstractmethod decorator is
provided by the plugin class.
"""
- if cls is QuantumPluginBase:
+ if cls is L2NetworkModelBase:
for method in cls.__abstractmethods__:
method_ok = False
for base in klass.__mro__:
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
import inspect
import logging as LOG
class L2Network(QuantumPluginBase):
+ """ L2 Network Framework Plugin """
def __init__(self):
self._vlan_counter = int(conf.VLAN_START) - 1
the specified tenant.
"""
LOG.debug("get_all_networks() called\n")
- self._invokeDevicePlugins(self._funcName(), [tenant_id])
+ self._invoke_device_plugins(self._func_name(), [tenant_id])
networks_list = db.network_list(tenant_id)
new_networks_list = []
for network in networks_list:
new_net_id = new_network[const.UUID]
vlan_id = self._get_vlan_for_tenant(tenant_id, net_name)
vlan_name = self._get_vlan_name(new_net_id, str(vlan_id))
- self._invokeDevicePlugins(self._funcName(), [tenant_id, net_name,
+ self._invoke_device_plugins(self._func_name(), [tenant_id, net_name,
new_net_id, vlan_name,
vlan_id])
cdb.add_vlan_binding(vlan_id, vlan_name, new_net_id)
for port in ports_on_net:
self.delete_port(tenant_id, net_id, port[const.PORTID])
- self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id])
+ self._invoke_device_plugins(self._func_name(), [tenant_id, net_id])
net_dict = self._make_net_dict(net[const.UUID],
net[const.NETWORKNAME],
[])
Gets the details of a particular network
"""
LOG.debug("get_network_details() called\n")
- self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id])
+ self._invoke_device_plugins(self._func_name(), [tenant_id, net_id])
network = db.network_get(net_id)
ports_list = network[const.NETWORKPORTS]
ports_on_net = []
Virtual Network.
"""
LOG.debug("rename_network() called\n")
- self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id,
+ self._invoke_device_plugins(self._func_name(), [tenant_id, net_id,
new_name])
network = db.network_rename(tenant_id, net_id, new_name)
net_dict = self._make_net_dict(network[const.UUID],
specified Virtual Network.
"""
LOG.debug("get_all_ports() called\n")
- self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id])
+ self._invoke_device_plugins(self._func_name(), [tenant_id, net_id])
network = db.network_get(net_id)
ports_list = network[const.NETWORKPORTS]
ports_on_net = []
LOG.debug("create_port() called\n")
port = db.port_create(net_id, port_state)
unique_port_id_string = port[const.UUID]
- self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id,
+ self._invoke_device_plugins(self._func_name(), [tenant_id, net_id,
port_state,
unique_port_id_string])
new_port_dict = self._make_port_dict(port[const.UUID],
then the port can be deleted.
"""
LOG.debug("delete_port() called\n")
- self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id,
+ self._invoke_device_plugins(self._func_name(), [tenant_id, net_id,
port_id])
db.port_destroy(net_id, port_id)
new_port_dict = self._make_port_dict(port_id, None, None, None)
Updates the state of a port on the specified Virtual Network.
"""
LOG.debug("update_port() called\n")
- self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id,
+ self._invoke_device_plugins(self._func_name(), [tenant_id, net_id,
port_id, port_state])
self._validate_port_state(port_state)
db.port_set_state(net_id, port_id, port_state)
that is attached to this particular port.
"""
LOG.debug("get_port_details() called\n")
- self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id,
+ self._invoke_device_plugins(self._func_name(), [tenant_id, net_id,
port_id])
port = db.port_get(net_id, port_id)
new_port_dict = self._make_port_dict(port[const.UUID],
specified Virtual Network.
"""
LOG.debug("plug_interface() called\n")
- self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id,
+ self._invoke_device_plugins(self._func_name(), [tenant_id, net_id,
port_id,
remote_interface_id])
db.port_set_attachment(net_id, port_id, remote_interface_id)
specified Virtual Network.
"""
LOG.debug("unplug_interface() called\n")
- self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id,
+ self._invoke_device_plugins(self._func_name(), [tenant_id, net_id,
port_id])
db.port_unset_attachment(net_id, port_id)
Extension API implementation
"""
def get_all_portprofiles(self, tenant_id):
- #return self._portprofiles.values()
+ """Get all port profiles"""
pplist = cdb.get_all_portprofiles()
new_pplist = []
- for pp in pplist:
+ for portprofile in pplist:
new_pp = self._make_portprofile_dict(tenant_id,
- pp[const.UUID],
- pp[const.PPNAME],
- pp[const.PPQOS])
+ portprofile[const.UUID],
+ portprofile[const.PPNAME],
+ portprofile[const.PPQOS])
new_pplist.append(new_pp)
return new_pplist
def get_portprofile_details(self, tenant_id, profile_id):
- #return self._get_portprofile(tenant_id, profile_id)
- pp = cdb.get_portprofile(tenant_id, profile_id)
+ """Get port profile details"""
+ portprofile = cdb.get_portprofile(tenant_id, profile_id)
new_pp = self._make_portprofile_dict(tenant_id,
- pp[const.UUID],
- pp[const.PPNAME],
- pp[const.PPQOS])
+ portprofile[const.UUID],
+ portprofile[const.PPNAME],
+ portprofile[const.PPQOS])
return new_pp
def create_portprofile(self, tenant_id, profile_name, qos):
- pp = cdb.add_portprofile(tenant_id, profile_name,
+ """Create port profile"""
+ portprofile = cdb.add_portprofile(tenant_id, profile_name,
const.NO_VLAN_ID, qos)
new_pp = self._make_portprofile_dict(tenant_id,
- pp[const.UUID],
- pp[const.PPNAME],
- pp[const.PPQOS])
+ portprofile[const.UUID],
+ portprofile[const.PPNAME],
+ portprofile[const.PPQOS])
return new_pp
def delete_portprofile(self, tenant_id, profile_id):
+ """Delete portprofile"""
try:
- pp = cdb.get_portprofile(tenant_id, profile_id)
- except Exception, e:
+ portprofile = cdb.get_portprofile(tenant_id, profile_id)
+ except Exception, exc:
raise cexc.PortProfileNotFound(tenant_id=tenant_id,
portprofile_id=profile_id)
cdb.remove_portprofile(tenant_id, profile_id)
def rename_portprofile(self, tenant_id, profile_id, new_name):
+ """Rename port profile"""
try:
- pp = cdb.get_portprofile(tenant_id, profile_id)
- except Exception, e:
+ portprofile = cdb.get_portprofile(tenant_id, profile_id)
+ except Exception, exc:
raise cexc.PortProfileNotFound(tenant_id=tenant_id,
portprofile_id=profile_id)
- pp = cdb.update_portprofile(tenant_id, profile_id, new_name)
+ portprofile = cdb.update_portprofile(tenant_id, profile_id, new_name)
new_pp = self._make_portprofile_dict(tenant_id,
- pp[const.UUID],
- pp[const.PPNAME],
- pp[const.PPQOS])
+ portprofile[const.UUID],
+ portprofile[const.PPNAME],
+ portprofile[const.PPQOS])
return new_pp
def associate_portprofile(self, tenant_id, net_id,
port_id, portprofile_id):
+ """Associate port profile"""
try:
- pp = cdb.get_portprofile(tenant_id, portprofile_id)
- except Exception, e:
+ portprofile = cdb.get_portprofile(tenant_id, portprofile_id)
+ except Exception, exc:
raise cexc.PortProfileNotFound(tenant_id=tenant_id,
portprofile_id=portprofile_id)
def disassociate_portprofile(self, tenant_id, net_id,
port_id, portprofile_id):
+ """Disassociate port profile"""
try:
- pp = cdb.get_portprofile(tenant_id, portprofile_id)
- except Exception, e:
+ portprofile = cdb.get_portprofile(tenant_id, portprofile_id)
+ except Exception, exc:
raise cexc.PortProfileNotFound(tenant_id=tenant_id,
portprofile_id=portprofile_id)
cdb.remove_pp_binding(tenant_id, port_id, portprofile_id)
- def create_defaultPProfile(self, tenant_id, network_id, profile_name,
- qos):
- pp = cdb.add_portprofile(tenant_id, profile_name,
+ def create_default_port_profile(self, tenant_id, network_id, profile_name,
+ qos):
+ "Create default port profile"""
+ portprofile = cdb.add_portprofile(tenant_id, profile_name,
const.NO_VLAN_ID, qos)
new_pp = self._make_portprofile_dict(tenant_id,
- pp[const.UUID],
- pp[const.PPNAME],
- pp[const.PPQOS])
- cdb.add_pp_binding(tenant_id, port_id, portprofile_id, True)
+ portprofile[const.UUID],
+ portprofile[const.PPNAME],
+ portprofile[const.PPQOS])
+ # TODO (Sumit): Need to check the following
+ port_id = None
+ cdb.add_pp_binding(tenant_id, port_id, portprofile[const.UUID], True)
return new_pp
"""
Private functions
"""
- def _invokeDevicePlugins(self, function_name, args):
+ def _invoke_device_plugins(self, function_name, args):
"""
All device-specific calls are delegate to the model
"""
getattr(self._model, function_name)(args)
def _get_vlan_for_tenant(self, tenant_id, net_name):
+ """Get vlan ID"""
# TODO (Sumit):
# The VLAN ID for a tenant might need to be obtained from
# somewhere (from Donabe/Melange?)
return cdb.reserve_vlanid()
def _release_vlan_for_tenant(self, tenant_id, net_id):
+ """Relase VLAN"""
vlan_binding = cdb.get_vlan_binding(net_id)
return cdb.release_vlanid(vlan_binding[const.VLANID])
def _get_vlan_name(self, net_id, vlan):
+ """Getting the vlan name from the tenant and vlan"""
vlan_name = conf.VLAN_NAME_PREFIX + vlan
return vlan_name
def _validate_port_state(self, port_state):
+ """Checking the port state"""
if port_state.upper() not in (const.PORT_UP, const.PORT_DOWN):
raise exc.StateInvalid(port_state=port_state)
return True
- def _funcName(self, offset=0):
+ def _func_name(self, offset=0):
+ """Getting the name of the calling funciton"""
return inspect.stack()[1 + offset][3]
def _make_net_dict(self, net_id, net_name, ports):
+ """Helper funciton"""
res = {const.NET_ID: net_id, const.NET_NAME: net_name}
res[const.NET_PORTS] = ports
return res
def _make_port_dict(self, port_id, port_state, net_id, attachment):
+ """Helper funciton"""
res = {const.PORT_ID: port_id, const.PORT_STATE: port_state}
res[const.NET_ID] = net_id
res[const.ATTACHMENT] = attachment
def _make_portprofile_dict(self, tenant_id, profile_id, profile_name,
qos):
+ """Helper funciton"""
profile_associations = self._make_portprofile_assc_list(tenant_id,
profile_id)
res = {const.PROFILE_ID: str(profile_id),
return res
def _make_portprofile_assc_list(self, tenant_id, profile_id):
+ """Helper function to create port profile association list"""
plist = cdb.get_pp_binding(tenant_id, profile_id)
assc_list = []
for port in plist:
assc_list.append(port[const.PORTID])
return assc_list
-
-
-def main():
- client = L2Network()
- """
- client.create_portprofile("12345", "tpp1", "2")
- client.create_portprofile("12345", "tpp2", "3")
- print ("%s\n") % client.get_all_portprofiles("12345")
- """
-
-if __name__ == '__main__':
- main()
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
# @author: Rohit Agarwalla, Cisco Systems, Inc.
+"""
import os
CONF_FILE = "conf/l2network_plugin.ini"
-cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
- + "/" + CONF_FILE)
+CONF_PARSER_OBJ = confp.\
+CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \
+"/" + CONF_FILE)
-section = cp['VLANS']
-VLAN_NAME_PREFIX = section['vlan_name_prefix']
-VLAN_START = section['vlan_start']
-VLAN_END = section['vlan_end']
+SECTION_CONF = CONF_PARSER_OBJ['VLANS']
+VLAN_NAME_PREFIX = SECTION_CONF['vlan_name_prefix']
+VLAN_START = SECTION_CONF['vlan_start']
+VLAN_END = SECTION_CONF['vlan_end']
-section = cp['PORTS']
-MAX_PORTS = section['max_ports']
+SECTION_CONF = CONF_PARSER_OBJ['PORTS']
+MAX_PORTS = SECTION_CONF['max_ports']
-section = cp['PORTPROFILES']
-MAX_PORT_PROFILES = section['max_port_profiles']
+SECTION_CONF = CONF_PARSER_OBJ['PORTPROFILES']
+MAX_PORT_PROFILES = SECTION_CONF['max_port_profiles']
-section = cp['NETWORKS']
-MAX_NETWORKS = section['max_networks']
+SECTION_CONF = CONF_PARSER_OBJ['NETWORKS']
+MAX_NETWORKS = SECTION_CONF['max_networks']
-section = cp['MODEL']
-MODEL_CLASS = section['model_class']
+SECTION_CONF = CONF_PARSER_OBJ['MODEL']
+MODEL_CLASS = SECTION_CONF['model_class']
CONF_FILE = "conf/plugins.ini"
-cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
- + "/" + CONF_FILE)
-plugins = cp.walk(cp.dummy)
+CONF_PARSER_OBJ = confp.\
+CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \
+"/" + CONF_FILE)
-CONF_FILE = "conf/db_conn.ini"
-
-cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
- + "/" + CONF_FILE)
+PLUGINS = CONF_PARSER_OBJ.walk(CONF_PARSER_OBJ.dummy)
-section = cp['DATABASE']
-DB_NAME = section['name']
-DB_USER = section['user']
-DB_PASS = section['pass']
-DB_HOST = section['host']
+CONF_FILE = "conf/db_conn.ini"
-def main():
- print plugins['PLUGINS']
+CONF_PARSER_OBJ = confp.\
+CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \
+"/" + CONF_FILE)
-if __name__ == '__main__':
- main()
+SECTION_CONF = CONF_PARSER_OBJ['DATABASE']
+DB_NAME = SECTION_CONF['name']
+DB_USER = SECTION_CONF['user']
+DB_PASS = SECTION_CONF['pass']
+DB_HOST = SECTION_CONF['host']
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Rohit Agarwalla, Cisco Systems Inc.
#
-import sys
+"""
+
import subprocess
def get_next_dynic(argv=[]):
+ """Get the next available dynamic nic on this host"""
cmd = ["ifconfig", "-a"]
f_cmd_output = subprocess.Popen(cmd, stdout=subprocess.PIPE).\
communicate()[0]
if not used:
break
return eth
-
-if __name__ == '__main__':
- #nic = get_next_dynic(sys.argv)
- nic = get_next_dynic()
- print nic
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
import os
CONF_FILE = "../conf/ucs.ini"
-cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
+CP = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
+ "/" + CONF_FILE)
-section = cp['UCSM']
-UCSM_IP_ADDRESS = section['ip_address']
-DEFAULT_VLAN_NAME = section['default_vlan_name']
-DEFAULT_VLAN_ID = section['default_vlan_id']
-MAX_UCSM_PORT_PROFILES = section['max_ucsm_port_profiles']
-PROFILE_NAME_PREFIX = section['profile_name_prefix']
+SECTION = CP['UCSM']
+UCSM_IP_ADDRESS = SECTION['ip_address']
+DEFAULT_VLAN_NAME = SECTION['default_vlan_name']
+DEFAULT_VLAN_ID = SECTION['default_vlan_id']
+MAX_UCSM_PORT_PROFILES = SECTION['max_ucsm_port_profiles']
+PROFILE_NAME_PREFIX = SECTION['profile_name_prefix']
-section = cp['DRIVER']
-UCSM_DRIVER = section['name']
-
-
-def main():
- print MAX_UCSM_PORT_PROFILES
-
-if __name__ == '__main__':
- main()
+SECTION = CP['DRIVER']
+UCSM_DRIVER = SECTION['name']
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems Inc.
#
+"""
+
"""
Implements a UCSM XML API Client
"""
import httplib
import logging as LOG
-import string
-import subprocess
from xml.etree import ElementTree as et
-import urllib
from quantum.plugins.cisco.common import cisco_constants as const
from quantum.plugins.cisco.common import cisco_exceptions as cexc
class CiscoUCSMDriver():
+ """UCSM Driver"""
def __init__(self):
pass
def _post_data(self, ucsm_ip, ucsm_username, ucsm_password, data):
+ """Send command to UCSM in http request"""
conn = httplib.HTTPConnection(ucsm_ip)
login_data = "<aaaLogin inName=\"" + ucsm_username + \
"\" inPassword=\"" + ucsm_password + "\" />"
LOG.debug(response.reason)
LOG.debug(response_data)
# TODO (Sumit): If login is not successful, throw exception
- xmlTree = et.XML(response_data)
- cookie = xmlTree.attrib["outCookie"]
+ xml_tree = et.XML(response_data)
+ cookie = xml_tree.attrib["outCookie"]
data = data.replace(COOKIE_VALUE, cookie)
LOG.debug("POST: %s" % data)
LOG.debug(response_data)
def _create_vlan_post_data(self, vlan_name, vlan_id):
+ """Create command"""
data = CREATE_VLAN.replace(VLAN_NAME, vlan_name)
data = data.replace(VLAN_ID, vlan_id)
return data
def _create_profile_post_data(self, profile_name, vlan_name):
+ """Create command"""
data = CREATE_PROFILE.replace(PROFILE_NAME, profile_name)
data = data.replace(VLAN_NAME, vlan_name)
return data
- def _create_profile_client_post_data(self, profile_name,
+ def _create_pclient_post_data(self, profile_name,
profile_client_name):
+ """Create command"""
data = ASSOCIATE_PROFILE.replace(PROFILE_NAME, profile_name)
data = data.replace(PROFILE_CLIENT, profile_client_name)
return data
- def _change_vlan_in_profile_post_data(self, profile_name, old_vlan_name,
+ def _change_vlaninprof_post_data(self, profile_name, old_vlan_name,
new_vlan_name):
+ """Create command"""
data = CHANGE_VLAN_IN_PROFILE.replace(PROFILE_NAME, profile_name)
data = data.replace(OLD_VLAN_NAME, old_vlan_name)
data = data.replace(VLAN_NAME, new_vlan_name)
return data
def _delete_vlan_post_data(self, vlan_name):
+ """Create command"""
data = DELETE_VLAN.replace(VLAN_NAME, vlan_name)
return data
def _delete_profile_post_data(self, profile_name):
+ """Create command"""
data = DELETE_PROFILE.replace(PROFILE_NAME, profile_name)
return data
def _get_next_dynamic_nic(self):
+ """Get an avaialble dynamic nic on the host"""
dynamic_nic_id = gvif.get_next_dynic()
if len(dynamic_nic_id) > 0:
return dynamic_nic_id
else:
- raise cisco_exceptions.NoMoreNics(net_id=net_id, port_id=port_id)
+ raise cexc.NoMoreNics()
def create_vlan(self, vlan_name, vlan_id, ucsm_ip, ucsm_username,
ucsm_password):
+ """Create request for UCSM"""
data = self._create_vlan_post_data(vlan_name, vlan_id)
self._post_data(ucsm_ip, ucsm_username, ucsm_password, data)
def create_profile(self, profile_name, vlan_name, ucsm_ip, ucsm_username,
ucsm_password):
+ """Create request for UCSM"""
data = self._create_profile_post_data(profile_name, vlan_name)
self._post_data(ucsm_ip, ucsm_username, ucsm_password, data)
- data = self._create_profile_client_post_data(profile_name,
+ data = self._create_pclient_post_data(profile_name,
profile_name[-16:])
self._post_data(ucsm_ip, ucsm_username, ucsm_password, data)
def change_vlan_in_profile(self, profile_name, old_vlan_name,
new_vlan_name, ucsm_ip, ucsm_username,
ucsm_password):
- data = self._change_vlan_in_profile_post_data(profile_name,
+ """Create request for UCSM"""
+ data = self._change_vlaninprof_post_data(profile_name,
old_vlan_name,
new_vlan_name)
self._post_data(ucsm_ip, ucsm_username, ucsm_password, data)
def get_dynamic_nic(self, host):
+ """Get an avaialble dynamic nic on the host"""
# TODO (Sumit): Check availability per host
# TODO (Sumit): If not available raise exception
# TODO (Sumit): This simple logic assumes that create-port and
return dynamic_nic_name
def delete_vlan(self, vlan_name, ucsm_ip, ucsm_username, ucsm_password):
+ """Create request for UCSM"""
data = self._delete_vlan_post_data(vlan_name)
self._post_data(ucsm_ip, ucsm_username, ucsm_password, data)
def delete_profile(self, profile_name, ucsm_ip, ucsm_username,
ucsm_password):
+ """Create request for UCSM"""
data = self._delete_profile_post_data(profile_name)
self._post_data(ucsm_ip, ucsm_username, ucsm_password, data)
def release_dynamic_nic(self, host):
+ """Release a reserved dynamic nic on the host"""
# TODO (Sumit): Release on a specific host
pass
-
-
-def main():
- client = CiscoUCSMDriver()
- #client.create_vlan("quantum-vlan-3", "3","172.20.231.27","admin",
- # "c3l12345")
- #client.create_profile("q-prof-3", "quantum-vlan-3","172.20.231.27",
- # "admin", "c3l12345")
- #client.get_dynamic_nic("dummy")
- #client.get_dynamic_nic("dummy")
- #client.release_dynamic_nic("dummy")
- print client.get_dynamic_nic("dummy")
- """
- client.change_vlan_in_profile("br100", "default", "test-2",
- "172.20.231.27","admin",
- "c3l12345")
- client.change_vlan_in_profile("br100", "test-2", "default",
- "172.20.231.27", "admin", "c3l12345")
- """
-
-if __name__ == '__main__':
- main()
+"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+"""
import logging as LOG
class UCSVICPlugin(L2DevicePluginBase):
+ """UCS Device Plugin"""
_networks = {}
def __init__(self):
port_profile[const.PROFILE_VLAN_ID] = conf.DEFAULT_VLAN_ID
def _get_profile_name(self, port_id):
- #profile_name = conf.PROFILE_NAME_PREFIX + port_id
+ """Returns the port profile name based on the port UUID"""
profile_name = conf.PROFILE_NAME_PREFIX \
+ cutil.get16ByteUUID(port_id)
return profile_name
def _validate_port_state(self, port_state):
+ """Check the port state"""
if port_state.upper() not in (const.PORT_UP, const.PORT_DOWN):
raise exc.StateInvalid(port_state=port_state)
return True
def _validate_attachment(self, tenant_id, network_id, port_id,
remote_interface_id):
+ """Check if the VIF can be attached"""
network = self._get_network(tenant_id, network_id)
for port in network[const.NET_PORTS].values():
if port[const.ATTACHMENT] == remote_interface_id:
att_id=port[const.ATTACHMENT])
def _get_network(self, tenant_id, network_id):
+ """Get the network object ref"""
network = self._networks.get(network_id)
if not network:
raise exc.NetworkNotFound(net_id=network_id)
return network
def _get_vlan_name_for_network(self, tenant_id, network_id):
+ """Return the VLAN name as set by the L2 network plugin"""
net = self._get_network(tenant_id, network_id)
vlan_name = net[const.NET_VLAN_NAME]
return vlan_name
def _get_vlan_id_for_network(self, tenant_id, network_id):
+ """Return the VLAN id as set by the L2 network plugin"""
net = self._get_network(tenant_id, network_id)
vlan_id = net[const.NET_VLAN_ID]
return vlan_id
def _get_port(self, tenant_id, network_id, port_id):
+ """Get the port object ref"""
net = self._get_network(tenant_id, network_id)
port = net[const.NET_PORTS].get(port_id)
if not port:
def _create_port_profile(self, tenant_id, net_id, port_id, vlan_name,
vlan_id):
+ """Create port profile in UCSM"""
if self._port_profile_counter >= int(conf.MAX_UCSM_PORT_PROFILES):
raise cexc.UCSMPortProfileLimit(net_id=net_id, port_id=port_id)
profile_name = self._get_profile_name(port_id)
return new_port_profile
def _delete_port_profile(self, port_id, profile_name):
+ """Delete port profile in UCSM"""
self._client.delete_profile(profile_name, self._ucsm_ip,
self._ucsm_username, self._ucsm_password)
self._port_profile_counter -= 1