From: Sumit Naiksatam Date: Sat, 20 Aug 2011 09:51:59 +0000 (-0700) Subject: Several fixes to initial version. X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=9092441db4a33d5ccde7f32658b3251212eb9ccf;p=openstack-build%2Fneutron-build.git Several fixes to initial version. --- diff --git a/quantum/plugins/cisco/common/cisco_constants.py b/quantum/plugins/cisco/common/cisco_constants.py index 02eb2d431..197d3f008 100644 --- a/quantum/plugins/cisco/common/cisco_constants.py +++ b/quantum/plugins/cisco/common/cisco_constants.py @@ -134,6 +134,7 @@ BLADE_ID = 'blade_id' HOST_NAME = 'host_name' INSTANCE_ID = 'instance_id' +VIF_ID = 'vif_id' UCS_INVENTORY = 'ucs_inventory' LEAST_RSVD_BLADE_DICT = 'least_rsvd_blade_dict' diff --git a/quantum/plugins/cisco/l2network_plugin.py b/quantum/plugins/cisco/l2network_plugin.py index a4b30953e..4a231ab84 100644 --- a/quantum/plugins/cisco/l2network_plugin.py +++ b/quantum/plugins/cisco/l2network_plugin.py @@ -45,14 +45,14 @@ class L2Network(QuantumPluginBase): _credentials = {} def __init__(self): - self._vlan_counter = int(conf.VLAN_START) - 1 + cdb.initialize() self._model = utils.import_object(conf.MODEL_CLASS) self._vlan_mgr = utils.import_object(conf.MANAGER_CLASS) - cdb.initialize() # TODO (Sumit): The following should move to the segmentation module - cdb.create_vlanids() + #cdb.create_vlanids() self._qoslevels_counter = 0 self._credentials_counter = 0 + LOG.debug("L2Network plugin initialization done successfully\n") """ Core API implementation diff --git a/quantum/plugins/cisco/models/l2network_multi_blade.py b/quantum/plugins/cisco/models/l2network_multi_blade.py index fb68c5ec5..a6c98cfac 100644 --- a/quantum/plugins/cisco/models/l2network_multi_blade.py +++ b/quantum/plugins/cisco/models/l2network_multi_blade.py @@ -23,10 +23,12 @@ 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 from quantum.plugins.cisco.ucs import cisco_ucs_inventory as ucsinv LOG.basicConfig(level=LOG.WARN) @@ -116,6 +118,8 @@ class L2NetworkMultiBlade(L2NetworkModelBase): """Support for the Quantum core API call""" least_reserved_blade_dict = \ self._ucs_inventory.get_least_reserved_blade() + if not least_reserved_blade_dict: + raise cexc.NoMoreNics() ucsm_ip = least_reserved_blade_dict[const.LEAST_RSVD_BLADE_UCSM] device_params = {const.DEVICE_IP: ucsm_ip, const.UCS_INVENTORY: self._ucs_inventory, @@ -128,6 +132,8 @@ class L2NetworkMultiBlade(L2NetworkModelBase): rsvd_info = \ self._ucs_inventory.get_rsvd_blade_intf_by_port(args[0], args[2]) + if not rsvd_info: + raise exc.PortNotFound(net_id=args[1], port_id=args[2]) device_params = \ {const.DEVICE_IP: rsvd_info[const.UCSM_IP], const.UCS_INVENTORY: self._ucs_inventory, @@ -146,12 +152,22 @@ class L2NetworkMultiBlade(L2NetworkModelBase): def plug_interface(self, args): """Support for the Quantum core API call""" - device_params = {const.DEVICE_IP: ""} + rsvd_info = \ + self._ucs_inventory.get_rsvd_blade_intf_by_port(args[0], + args[2]) + if not rsvd_info: + raise exc.PortNotFound(net_id=args[1], port_id=args[2]) + device_params = {const.DEVICE_IP: rsvd_info[const.UCSM_IP]} self._invoke_ucs_plugin(self._func_name(), args, device_params) def unplug_interface(self, args): """Support for the Quantum core API call""" - device_params = {const.DEVICE_IP: ""} + rsvd_info = \ + self._ucs_inventory.get_rsvd_blade_intf_by_port(args[0], + args[2]) + if not rsvd_info: + raise exc.PortNotFound(net_id=args[1], port_id=args[2]) + device_params = {const.DEVICE_IP: rsvd_info[const.UCSM_IP]} self._invoke_ucs_plugin(self._func_name(), args, device_params) def get_host(self, args): diff --git a/quantum/plugins/cisco/segmentation/l2network_vlan_mgr.py b/quantum/plugins/cisco/segmentation/l2network_vlan_mgr.py index 533b488d5..f361980a4 100644 --- a/quantum/plugins/cisco/segmentation/l2network_vlan_mgr.py +++ b/quantum/plugins/cisco/segmentation/l2network_vlan_mgr.py @@ -34,6 +34,8 @@ class L2NetworkVLANMgr(L2NetworkSegmentationMgrBase): """ VLAN Manager which gets VLAN ID from DB """ + def __init__(self): + cdb.create_vlanids() def reserve_segmentation_id(self, tenant_id, net_name, **kwargs): """Get an available VLAN ID""" diff --git a/quantum/plugins/cisco/ucs/cisco_ucs_inventory.py b/quantum/plugins/cisco/ucs/cisco_ucs_inventory.py index ddc5eff3c..ae9aa4970 100644 --- a/quantum/plugins/cisco/ucs/cisco_ucs_inventory.py +++ b/quantum/plugins/cisco/ucs/cisco_ucs_inventory.py @@ -18,6 +18,7 @@ # @author: Sumit Naiksatam, Cisco Systems, Inc. # """ +from copy import deepcopy import logging as LOG from quantum.common import exceptions as exc @@ -25,7 +26,8 @@ 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_exceptions as cexc from quantum.plugins.cisco.common import cisco_utils as cutil -from quantum.plugins.cisco.ucs import cisco_ucs_configuration as conf +from quantum.plugins.cisco.ucs \ + import cisco_ucs_inventory_configuration as conf from quantum.plugins.cisco.ucs import cisco_ucs_network_driver LOG.basicConfig(level=LOG.WARN) @@ -38,6 +40,42 @@ The _inventory data strcuture contains a nested disctioary: "UCSM_IP: {"Chassis-ID": [Balde-ID]} } """ +""" +_inventory_state data structure is organized as below: +{ucsm_ip: + {chassis_id: + {blade_id: + {'blade-data': + {blade-dn-1: {blade-intf-data}, + blade-dn-2: {blade-intf-data} + } + } + } + } +} +'blade-data': Blade Data dictionary has the following keys: +=========================================================== +const.BLADE_INTF_DATA: This is a dictionary, with the key as the + dn of the interface, and the value as the + Blade Interface Dictionary described next +const.BLADE_UNRESERVED_INTF_COUNT: Number of unreserved interfaces + on this blade + +'blade-intf-data': Blade Interface dictionary has the following keys: +===================================================================== +const.BLADE_INTF_DN +const.BLADE_INTF_ORDER +const.BLADE_INTF_LINK_STATE +const.BLADE_INTF_OPER_STATE +const.BLADE_INTF_INST_TYPE +const.BLADE_INTF_RHEL_DEVICE_NAME +const.BLADE_INTF_RESERVATION +const.TENANTID +const.PORTID +const.PROFILE_ID +const.INSTANCE_ID +const.VIF_ID +""" class UCSInventory(object): @@ -56,7 +94,9 @@ class UCSInventory(object): def _load_inventory(self): """Load the inventory from a config file""" - inventory = conf.INVENTORY + inventory = deepcopy(conf.INVENTORY) + LOG.debug("Loaded UCS inventory: %s\n" % inventory) + for ucsm in inventory.keys(): ucsm_ip = inventory[ucsm][const.IP_ADDRESS] inventory[ucsm].pop(const.IP_ADDRESS) @@ -75,14 +115,47 @@ class UCSInventory(object): blade_list.append(blade_id) chassis_dict[chassis_id] = blade_list self._inventory[ucsm_ip] = chassis_dict + + self.build_inventory_state() def _get_host_name(self, ucsm_ip, chassis_id, blade_id): """Get the hostname based on the blade info""" host_key = ucsm_ip + "-" + chassis_id + "-" + blade_id return self._host_names[host_key] - def _get_blade_state(self, chassis_id, blade_id, ucsm_ip, ucsm_username, - ucsm_password): + def _get_initial_blade_state(self, chassis_id, blade_id, ucsm_ip, + ucsm_username, ucsm_password): + """Get the initial blade state""" + blade_intf_data = self._client.get_blade_data(chassis_id, blade_id, + ucsm_ip, ucsm_username, + ucsm_password) + unreserved_counter = 0 + + for blade_intf in blade_intf_data.keys(): + if (blade_intf_data[blade_intf][const.BLADE_INTF_LINK_STATE] == \ + const.BLADE_INTF_STATE_UNALLOCATED or \ + blade_intf_data[blade_intf][const.BLADE_INTF_LINK_STATE] == \ + const.BLADE_INTF_STATE_UNKNOWN) and \ + blade_intf_data[blade_intf][const.BLADE_INTF_OPER_STATE] == \ + const.BLADE_INTF_STATE_UNKNOWN: + blade_intf_data[blade_intf][const.BLADE_INTF_RESERVATION] = \ + const.BLADE_INTF_UNRESERVED + unreserved_counter += 1 + else: + blade_intf_data[blade_intf][const.BLADE_INTF_RESERVATION] = \ + const.BLADE_INTF_RESERVED + blade_intf_data[blade_intf][const.TENANTID] = None + blade_intf_data[blade_intf][const.PORTID] = None + blade_intf_data[blade_intf][const.PROFILE_ID] = None + blade_intf_data[blade_intf][const.INSTANCE_ID] = None + blade_intf_data[blade_intf][const.VIF_ID] = None + + blade_data = {const.BLADE_INTF_DATA: blade_intf_data, + const.BLADE_UNRESERVED_INTF_COUNT: unreserved_counter} + return blade_data + + def _get_blade_state(self, chassis_id, blade_id, ucsm_ip, + ucsm_username, ucsm_password): """Get the blade state""" blade_intf_data = self._client.get_blade_data(chassis_id, blade_id, ucsm_ip, ucsm_username, @@ -128,11 +201,14 @@ class UCSInventory(object): blades_dict = {} chasses_state[chassis_id] = blades_dict for blade_id in ucsm[chassis_id]: - blade_data = self._get_blade_state(chassis_id, blade_id, - ucsm_ip, ucsm_username, - ucsm_password) + blade_data = self._get_initial_blade_state(chassis_id, + blade_id, + ucsm_ip, + ucsm_username, + ucsm_password) blades_dict[blade_id] = blade_data + LOG.debug("UCS Inventory state is: %s\n" % self._inventory_state) return True def get_least_reserved_blade(self): @@ -182,12 +258,22 @@ class UCSInventory(object): old_blade_intf_data = blade_data_dict[const.BLADE_INTF_DATA] """ - We will now copy the older blade interface reservation state + We will now copy the older blade interface state """ for blade_intf in blade_intf_data.keys(): blade_intf_data[blade_intf][const.BLADE_INTF_RESERVATION] = \ old_blade_intf_data[blade_intf]\ [const.BLADE_INTF_RESERVATION] + blade_intf_data[blade_intf][const.TENANTID] = \ + old_blade_intf_data[blade_intf][const.TENANTID] + blade_intf_data[blade_intf][const.PORTID] = \ + old_blade_intf_data[blade_intf][const.PORTID] + blade_intf_data[blade_intf][const.PROFILE_ID] = \ + old_blade_intf_data[blade_intf][const.PROFILE_ID] + blade_intf_data[blade_intf][const.INSTANCE_ID] = \ + old_blade_intf_data[blade_intf][const.INSTANCE_ID] + blade_intf_data[blade_intf][const.VIF_ID] = \ + old_blade_intf_data[blade_intf][const.VIF_ID] blade_data[const.BLADE_UNRESERVED_INTF_COUNT] = \ blade_data_dict[const.BLADE_UNRESERVED_INTF_COUNT] @@ -228,12 +314,16 @@ class UCSInventory(object): """Unreserve a previously reserved interface on a blade""" ucsm_username = cred.Store.getUsername(ucsm_ip) ucsm_password = cred.Store.getPassword(ucsm_ip) - self._inventory_state[ucsm_ip][chassis_id][blade_id]\ - [const.BLADE_INTF_DATA] \ - [interface_dn][const.BLADE_INTF_RESERVATION] = \ - const.BLADE_INTF_UNRESERVED self._inventory_state[ucsm_ip][chassis_id][blade_id] \ [const.BLADE_UNRESERVED_INTF_COUNT] += 1 + blade_intf = self._inventory_state[ucsm_ip][chassis_id]\ + [blade_id][const.BLADE_INTF_DATA][interface_dn] + blade_intf[const.BLADE_INTF_RESERVATION] = const.BLADE_INTF_UNRESERVED + blade_intf[const.TENANTID] = None + blade_intf[const.PORTID] = None + blade_intf[const.PROFILE_ID] = None + blade_intf[const.INSTANCE_ID] = None + blade_intf[const.VIF_ID] = None LOG.debug("Unreserved blade interface %s\n" % interface_dn) def get_rsvd_blade_intf_by_port(self, tenant_id, port_id): @@ -292,7 +382,7 @@ class UCSInventory(object): return host_name return None - def get_instance_port(self, tenant_id, instance_id): + def get_instance_port(self, tenant_id, instance_id, vif_id): """ Return the device name for a reserved interface """ @@ -310,6 +400,9 @@ class UCSInventory(object): [const.TENANTID] == tenant_id and \ blade_intf_data[blade_intf]\ [const.INSTANCE_ID] == instance_id: + blade_intf_data[blade_intf][const.VIF_ID] = \ + vif_id + return blade_intf_data[blade_intf]\ [const.BLADE_INTF_RHEL_DEVICE_NAME] return None diff --git a/quantum/plugins/cisco/ucs/cisco_ucs_inventory_configuration.py b/quantum/plugins/cisco/ucs/cisco_ucs_inventory_configuration.py new file mode 100644 index 000000000..3183658c3 --- /dev/null +++ b/quantum/plugins/cisco/ucs/cisco_ucs_inventory_configuration.py @@ -0,0 +1,31 @@ +""" +# 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: Sumit Naiksatam, Cisco Systems, Inc. +# +""" + +import os + +from quantum.plugins.cisco.common import cisco_configparser as confp + +CONF_FILE = "../conf/ucs_inventory.ini" + +CP = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ + + "/" + CONF_FILE) + +INVENTORY = CP.walk(CP.dummy) diff --git a/quantum/plugins/cisco/ucs/cisco_ucs_plugin.py b/quantum/plugins/cisco/ucs/cisco_ucs_plugin.py index 3268fbcb3..87efa684c 100644 --- a/quantum/plugins/cisco/ucs/cisco_ucs_plugin.py +++ b/quantum/plugins/cisco/ucs/cisco_ucs_plugin.py @@ -41,7 +41,6 @@ class UCSVICPlugin(L2DevicePluginBase): def __init__(self): self._client = utils.import_object(conf.UCSM_DRIVER) LOG.debug("Loaded driver %s\n" % conf.UCSM_DRIVER) - self._utils = cutil.DBUtils() # TODO (Sumit) Make the counter per UCSM self._port_profile_counter = 0 @@ -173,7 +172,6 @@ class UCSVICPlugin(L2DevicePluginBase): try: #TODO (Sumit): Before deleting port profile make sure that there # is no VM using this port profile - self._client.release_dynamic_nic("dummy") port_profile = port[const.PORT_PROFILE] self._delete_port_profile(port_id, port_profile[const.PROFILE_NAME])