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)
"""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,
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,
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):
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
"""
+from copy import deepcopy
import logging as LOG
from quantum.common import exceptions as exc
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)
"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):
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)
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,
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):
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]
"""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):
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
"""
[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