From 65440872ba3fb875fbb58ee8f5c7bf1dbd366f7a Mon Sep 17 00:00:00 2001 From: Sumit Naiksatam Date: Wed, 24 Aug 2011 16:53:08 -0700 Subject: [PATCH] Fixed some bugs with credential and qos resources; also fixed l2network_single_blade --- .../plugins/cisco/common/cisco_constants.py | 3 +- .../plugins/cisco/common/cisco_credentials.py | 47 ++++--- quantum/plugins/cisco/l2network_plugin.py | 116 ++++-------------- .../cisco/models/l2network_single_blade.py | 103 ++++++++++------ 4 files changed, 121 insertions(+), 148 deletions(-) diff --git a/quantum/plugins/cisco/common/cisco_constants.py b/quantum/plugins/cisco/common/cisco_constants.py index edc3e2ea1..fbcc9b94c 100644 --- a/quantum/plugins/cisco/common/cisco_constants.py +++ b/quantum/plugins/cisco/common/cisco_constants.py @@ -148,5 +148,4 @@ LEAST_RSVD_BLADE_DICT = 'least_rsvd_blade_dict' UCSM_IP = 'ucsm_ip_address' -MAX_CREDENTIALS = 65568 -MAX_QOS_LEVELS = 1024 +NETWORK_ADMIN = 'network_admin' diff --git a/quantum/plugins/cisco/common/cisco_credentials.py b/quantum/plugins/cisco/common/cisco_credentials.py index f3c63065c..d19e43928 100644 --- a/quantum/plugins/cisco/common/cisco_credentials.py +++ b/quantum/plugins/cisco/common/cisco_credentials.py @@ -24,10 +24,14 @@ import os from quantum.plugins.cisco.common import cisco_constants as const from quantum.plugins.cisco.common import cisco_configparser as confp +from quantum.plugins.cisco.common import cisco_exceptions as cexc +from quantum.plugins.cisco.db import l2network_db as cdb LOG.basicConfig(level=LOG.WARN) LOG.getLogger(const.LOGGER_COMPONENT_NAME) +TENANT = const.NETWORK_ADMIN + CREDENTIALS_FILE = "../conf/credentials.ini" cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ @@ -39,32 +43,43 @@ class Store(object): """Credential Store""" @staticmethod - def putCredential(id, username, password): + def initialize(): + for id in _creds_dictionary.keys(): + try: + cdb.add_credential(TENANT, id, + _creds_dictionary[id][const.USERNAME], + _creds_dictionary[id][const.PASSWORD]) + except cexc.CredentialAlreadyExists: + # We are quietly ignoring this, since it only happens + # if this class module is loaded more than once, in which + # case, the credentials are already populated + pass + + @staticmethod + def putCredential(cred_name, username, password): """Set the username and password""" - _creds_dictionary[id] = {const.USERNAME: username, - const.PASSWORD: password} + credential = cdb.add_credential(TENANT, cred_name, username, password) @staticmethod - def getUsername(id): + def getUsername(cred_name): """Get the username""" - return _creds_dictionary[id][const.USERNAME] + credential = cdb.get_credential_name(TENANT, cred_name) + return credential[const.CREDENTIAL_USERNAME] @staticmethod - def getPassword(id): + def getPassword(cred_name): """Get the password""" - return _creds_dictionary[id][const.PASSWORD] + credential = cdb.get_credential_name(TENANT, cred_name) + return credential[const.CREDENTIAL_PASSWORD] @staticmethod - def getCredential(id): + def getCredential(cred_name): """Get the username and password""" - return _creds_dictionary[id] - - @staticmethod - def getCredentials(): - """Get all usernames and passwords""" - return _creds_dictionary + credential = cdb.get_credential_name(TENANT, cred_name) + return {const.USERNAME: const.CREDENTIAL_USERNAME, + const.PASSWORD: const.CREDENTIAL_PASSWORD} @staticmethod - def deleteCredential(id): + def deleteCredential(cred_name): """Delete a credential""" - return _creds_dictionary.pop(id) + cdb.remove_credential(TENANT, cred_name) diff --git a/quantum/plugins/cisco/l2network_plugin.py b/quantum/plugins/cisco/l2network_plugin.py index bdeedb521..2a5ada6ff 100644 --- a/quantum/plugins/cisco/l2network_plugin.py +++ b/quantum/plugins/cisco/l2network_plugin.py @@ -42,15 +42,12 @@ class L2Network(QuantumPluginBase): """ L2 Network Framework Plugin """ supported_extension_aliases = ["Cisco Credential", "Cisco Port Profile", "Cisco qos", "Cisco Nova Tenant"] - _qos_levels = {} - _credentials = {} def __init__(self): cdb.initialize() + cred.Store.initialize() self._model = utils.import_object(conf.MODEL_CLASS) self._vlan_mgr = utils.import_object(conf.MANAGER_CLASS) - self._qoslevels_counter = 0 - self._credentials_counter = 0 LOG.debug("L2Network plugin initialization done successfully\n") """ @@ -365,84 +362,60 @@ class L2Network(QuantumPluginBase): cdb.remove_pp_binding(tenant_id, port_id, portprofile_id) - def create_default_portprofile(self, tenant_id, network_id, profile_name, - qos): - "Create default port profile""" - LOG.debug("create_default_portprofile() called\n") - portprofile = cdb.add_portprofile(tenant_id, profile_name, - const.NO_VLAN_ID, qos) - new_pp = cutil.make_portprofile_dict(tenant_id, - 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 - def get_all_qoss(self, tenant_id): """Get all QoS levels""" LOG.debug("get_all_qoss() called\n") - return self._qos_levels.values() + qoslist = cdb.get_all_qoss(tenant_id) + return qoslist def get_qos_details(self, tenant_id, qos_id): """Get QoS Details""" LOG.debug("get_qos_details() called\n") try: - qos_level = self._get_qos_level(tenant_id, qos_id) + qos_level = cdb.get_qos(tenant_id, qos_id) except Exception, excp: raise cexc.QosNotFound(tenant_id=tenant_id, - qos_id=qos_id) + qos_id=qos_id) return qos_level def create_qos(self, tenant_id, qos_name, qos_desc): """Create a QoS level""" LOG.debug("create_qos() called\n") - qos_id = self._get_unique_qos_id(tenant_id) - new_qos_level_dict = {const.QOS_LEVEL_ID: qos_id, - const.QOS_LEVEL_NAME: qos_name, - const.QOS_LEVEL_ASSOCIATIONS: [], - const.QOS_LEVEL_DESCRIPTION: qos_desc} - self._qos_levels[qos_id] = new_qos_level_dict - return new_qos_level_dict + qos = cdb.add_qos(tenant_id, qos_name, qos_desc) + return qos def delete_qos(self, tenant_id, qos_id): """Delete a QoS level""" LOG.debug("delete_qos() called\n") try: - qos_level = self._get_qos_level(tenant_id, qos_id) + qos_level = cdb.get_qos(tenant_id, qos_id) except Exception, excp: raise cexc.QosNotFound(tenant_id=tenant_id, - qos_id=qos_id) - associations = qos_level[const.QOS_LEVEL_ASSOCIATIONS] - if len(associations) > 0: - raise cexc.QoSLevelInvalidDelete(tenant_id=tenant_id, - qos_id=qos_id) - else: - self._qos_levels.pop(qos_id) + qos_id=qos_id) + return cdb.remove_qos(tenant_id, qos_id) def rename_qos(self, tenant_id, qos_id, new_name): """Rename QoS level""" LOG.debug("rename_qos() called\n") - qos_level = self._get_qos_level(tenant_id, qos_id) try: - qos_level = self._get_qos_level(tenant_id, qos_id) + qos_level = cdb.get_qos(tenant_id, qos_id) except Exception, excp: raise cexc.QosNotFound(tenant_id=tenant_id, - qos_id=qos_id) - qos_level[const.QOS_LEVEL_NAME] = new_name - return qos_level + qos_id=qos_id) + qos = cdb.update_qos(tenant_id, qos_id, new_name) + return qos def get_all_credentials(self, tenant_id): """Get all credentials""" LOG.debug("get_all_credentials() called\n") - return self._credentials.values() + credential_list = cdb.get_all_credentials(tenant_id) + return credential_list def get_credential_details(self, tenant_id, credential_id): """Get a particular credential""" LOG.debug("get_credential_details() called\n") try: - credential = self._get_credential(tenant_id, credential_id) + credential = cdb.get_credential(tenant_id, credential_id) except Exception, excp: raise cexc.CredentialNotFound(tenant_id=tenant_id, credential_id=credential_id) @@ -452,37 +425,30 @@ class L2Network(QuantumPluginBase): password): """Create a new credential""" LOG.debug("create_credential() called\n") - credential_id = self._get_unique_credential_id(tenant_id) - masked_password = const.MASKED_PASSWORD - new_credential_dict = {const.CREDENTIAL_ID: credential_id, - const.CREDENTIAL_NAME: credential_name, - const.CREDENTIAL_USERNAME: user_name, - const.CREDENTIAL_PASSWORD: masked_password} - self._credentials[credential_id] = new_credential_dict - cred.Store.putCredential(credential_id, user_name, password) - return new_credential_dict + credential = cdb.add_credential(tenant_id, credential_name, + user_name, password) + return credential def delete_credential(self, tenant_id, credential_id): """Delete a credential""" LOG.debug("delete_credential() called\n") try: - credential = self._get_credential(tenant_id, credential_id) + credential = cdb.get_credential(tenant_id, credential_id) except Exception, excp: raise cexc.CredentialNotFound(tenant_id=tenant_id, credential_id=credential_id) - self._credentials.pop(credential_id) - cred.Store.deleteCredential(credential_id) + credential = cdb.remove_credential(tenant_id, credential_id) + return credential def rename_credential(self, tenant_id, credential_id, new_name): """Do nothing for this resource""" LOG.debug("rename_credential() called\n") try: - credential = self._get_credential(tenant_id, credential_id) + credential = cdb.get_credential(tenant_id, credential_id) except Exception, excp: raise cexc.CredentialNotFound(tenant_id=tenant_id, credential_id=credential_id) - - credential[const.CREDENTIAL_NAME] = new_name + credential = cdb.update_credential(tenant_id, credential_id, new_name) return credential def get_host(self, tenant_id, instance_id, instance_desc): @@ -533,35 +499,3 @@ class L2Network(QuantumPluginBase): def _func_name(self, offset=0): """Getting the name of the calling funciton""" return inspect.stack()[1 + offset][3] - - def _get_qos_level(self, tenant_id, qos_id): - """Return a QoS level based on the ID""" - qos_level = self._qos_levels.get(qos_id) - if not qos_level: - raise cexc.QosNotFound(tenant_id=tenant_id, - qos_id=qos_id) - return qos_level - - def _get_credential(self, tenant_id, credential_id): - """Return a credential based on the ID""" - credential = self._credentials.get(credential_id) - if not credential: - raise cexc.CredentialNotFound(tenant_id=tenant_id, - credetial_id=credential_id) - return credential - - def _get_unique_qos_id(self, tenant_id): - """Get a unique QoS ID""" - self._qoslevels_counter += 1 - self._qoslevels_counter %= int(const.MAX_QOS_LEVELS) - qos_id = tenant_id[16:] + "-qos-" + str(self._qoslevels_counter) - # TODO (Sumit): Need to check if the ID has already been allocated - return qos_id - - def _get_unique_credential_id(self, tenant_id): - """Get a unique credential ID""" - self._credentials_counter += 1 - self._credentials_counter %= int(const.MAX_CREDENTIALS) - cred_id = tenant_id[16:] + "-crd-" + str(self._credentials_counter) - # TODO (Sumit): Need to check if the ID has already been allocated - return cred_id diff --git a/quantum/plugins/cisco/models/l2network_single_blade.py b/quantum/plugins/cisco/models/l2network_single_blade.py index b4277af1a..9cb0a89e0 100644 --- a/quantum/plugins/cisco/models/l2network_single_blade.py +++ b/quantum/plugins/cisco/models/l2network_single_blade.py @@ -19,26 +19,29 @@ # """ +from copy import deepcopy import inspect import logging as LOG import platform +from quantum.common import exceptions as exc from quantum.common import utils from quantum.plugins.cisco.l2network_model_base import L2NetworkModelBase from quantum.plugins.cisco import l2network_plugin_configuration as conf 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) +LOG.getLogger(__name__) -class L2NetworkSinlgeBlade(L2NetworkModelBase): +class L2NetworkSingleBlade(L2NetworkModelBase): """ Implements the L2NetworkModelBase - This implementation works with UCS and Nexus plugin, - with one UCS blade, and one Nexus switch. + This implementation works with a single UCS blade """ _plugins = {} + _inventory = {} def __init__(self): for key in conf.PLUGINS[const.PLUGINS].keys(): @@ -46,27 +49,50 @@ class L2NetworkSinlgeBlade(L2NetworkModelBase): conf.PLUGINS[const.PLUGINS][key]) LOG.debug("Loaded device plugin %s\n" % \ conf.PLUGINS[const.PLUGINS][key]) + if key in conf.PLUGINS[const.INVENTORY].keys(): + self._inventory[key] = utils.import_object( + conf.PLUGINS[const.INVENTORY][key]) + LOG.debug("Loaded device inventory %s\n" % \ + conf.PLUGINS[const.INVENTORY][key]) def _func_name(self, offset=0): """Get the name of the calling function""" return inspect.stack()[1 + offset][3] - 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 _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 _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 _invoke_plugin_per_device(self, plugin_key, function_name, args): + """Invoke only device plugin for all the devices in the system""" + 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: + self._invoke_plugin(plugin_key, function_name, args, + device_params) + else: + for device_ip in device_ips: + new_device_params = deepcopy(device_params) + new_device_params[const.DEVICE_IP] = device_ip + self._invoke_plugin(plugin_key, function_name, args, + new_device_params) + + def _invoke_inventory(self, plugin_key, function_name, args): + """Invoke only the inventory implementation""" + if not plugin_key in self._inventory.keys(): + LOG.warn("No %s inventory loaded" % plugin_key) + LOG.warn("%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): + """Invoke only the device plugin""" + return getattr(self._plugins[plugin_key], function_name)(*args, + **kwargs) def get_all_networks(self, args): """Not implemented for this model""" @@ -74,13 +100,13 @@ class L2NetworkSinlgeBlade(L2NetworkModelBase): def create_network(self, args): """Support for the Quantum core API call""" - device_params = {const.DEVICE_IP: ""} - self._invoke_all_device_plugins(self._func_name(), args, device_params) + self._invoke_plugin_per_device(const.UCS_PLUGIN, self._func_name(), + args) def delete_network(self, args): """Support for the Quantum core API call""" - device_params = {const.DEVICE_IP: ""} - self._invoke_all_device_plugins(self._func_name(), args, device_params) + self._invoke_plugin_per_device(const.UCS_PLUGIN, self._func_name(), + args) def get_network_details(self, args): """Not implemented for this model""" @@ -88,8 +114,8 @@ class L2NetworkSinlgeBlade(L2NetworkModelBase): def rename_network(self, args): """Support for the Quantum core API call""" - device_params = {const.DEVICE_IP: ""} - self._invoke_all_device_plugins(self._func_name(), args, device_params) + self._invoke_plugin_per_device(const.UCS_PLUGIN, self._func_name(), + args) def get_all_ports(self, args): """Not implemented for this model""" @@ -97,13 +123,13 @@ class L2NetworkSinlgeBlade(L2NetworkModelBase): def create_port(self, args): """Support for the Quantum core API call""" - device_params = {const.DEVICE_IP: ""} - self._invoke_ucs_plugin(self._func_name(), args, device_params) + self._invoke_plugin_per_device(const.UCS_PLUGIN, self._func_name(), + args) def delete_port(self, args): """Support for the Quantum core API call""" - device_params = {const.DEVICE_IP: ""} - self._invoke_ucs_plugin(self._func_name(), args, device_params) + self._invoke_plugin_per_device(const.UCS_PLUGIN, self._func_name(), + args) def update_port(self, args): """Not implemented for this model""" @@ -115,25 +141,24 @@ class L2NetworkSinlgeBlade(L2NetworkModelBase): def plug_interface(self, args): """Support for the Quantum core API call""" - device_params = {const.DEVICE_IP: ""} - self._invoke_ucs_plugin(self._func_name(), args, device_params) + self._invoke_plugin_per_device(const.UCS_PLUGIN, self._func_name(), + args) def unplug_interface(self, args): """Support for the Quantum core API call""" - device_params = {const.DEVICE_IP: ""} - self._invoke_ucs_plugin(self._func_name(), args, device_params) + self._invoke_plugin_per_device(const.UCS_PLUGIN, self._func_name(), + args) def get_host(self, args): """Provides the hostname on which a dynamic vnic is reserved""" LOG.debug("get_host() called\n") - host_list = {const.HOST_LIST: {const.HOST_1: platform.node()}} - return host_list + return self._invoke_inventory(const.UCS_PLUGIN, self._func_name(), + args) def get_instance_port(self, args): """ Get the portprofile name and the device namei for the dynamic vnic """ LOG.debug("get_instance_port() called\n") - vif_desc = {const.VIF_DESC: - {const.DEVICENAME: "eth2", const.UCSPROFILE: "default"}} - return vif_desc + return self._invoke_inventory(const.UCS_PLUGIN, self._func_name(), + args) -- 2.45.2