]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Several fixes to initial version.
authorSumit Naiksatam <snaiksat@cisco.com>
Sat, 20 Aug 2011 09:51:59 +0000 (02:51 -0700)
committerSumit Naiksatam <snaiksat@cisco.com>
Sat, 20 Aug 2011 09:51:59 +0000 (02:51 -0700)
quantum/plugins/cisco/common/cisco_constants.py
quantum/plugins/cisco/l2network_plugin.py
quantum/plugins/cisco/models/l2network_multi_blade.py
quantum/plugins/cisco/segmentation/l2network_vlan_mgr.py
quantum/plugins/cisco/ucs/cisco_ucs_inventory.py
quantum/plugins/cisco/ucs/cisco_ucs_inventory_configuration.py [new file with mode: 0644]
quantum/plugins/cisco/ucs/cisco_ucs_plugin.py

index 02eb2d43110f0020fbc4e28746cd5f70cb029cd0..197d3f00803121af9c018fc6d4877a9612a52fc4 100644 (file)
@@ -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'
index a4b30953e792af4c231b85b74aca10b03b6cabc8..4a231ab848e453f11125f24ca2155e646bc7f80b 100644 (file)
@@ -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
index fb68c5ec5666c719bcb0beb660e51bfe117f9bbd..a6c98cfac260c7e199492db2c9cac9c4f60dadd4 100644 (file)
@@ -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):
index 533b488d54460f1855f17478b2b9ce042d5bbb9b..f361980a4de3588d46d7a5265c91395934b39d4f 100644 (file)
@@ -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"""
index ddc5eff3cf279af05b2866b887c5ae48ae80425e..ae9aa49708ebcfe15708fbdf248209919c5e2760 100644 (file)
@@ -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 (file)
index 0000000..3183658
--- /dev/null
@@ -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)
index 3268fbcb3d20a0a5a3b947a24badf7b231881c3f..87efa684cf75e8324ab0ace6bbcc518948fd2057 100644 (file)
@@ -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])