d3401f14ce
Fixes bug #911663 The None, True, and False values are singletons. All variable *comparisons* to singletons should use 'is' or 'is not'. All variable *evaluations* to boolean should use 'if' or 'if not'. All Object type comparisons should use isinstance() instead of comparing types directly. Change-Id: Id5c797d3339d0d7015bac386088133540f0c0c9e
715 lines
32 KiB
Python
715 lines
32 KiB
Python
"""
|
|
# 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.
|
|
#
|
|
"""
|
|
from copy import deepcopy
|
|
import logging
|
|
|
|
from quantum.common import exceptions as exc
|
|
from quantum.plugins.cisco.l2device_inventory_base \
|
|
import L2NetworkDeviceInventoryBase
|
|
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.db import api as db
|
|
from quantum.plugins.cisco.db import ucs_db as udb
|
|
from quantum.plugins.cisco.ucs \
|
|
import cisco_ucs_inventory_configuration as conf
|
|
from quantum.plugins.cisco.ucs import cisco_ucs_network_driver
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
"""
|
|
The _inventory data strcuture contains a nested disctioary:
|
|
{"UCSM_IP: {"Chassis-ID": [Balde-ID, Blade-ID],
|
|
"Chassis-ID": [Blade-ID, Blade-ID, Blade-ID]]},
|
|
"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(L2NetworkDeviceInventoryBase):
|
|
"""
|
|
Manages the state of all the UCS chasses, and blades in
|
|
the system
|
|
"""
|
|
|
|
_inventory = {}
|
|
_host_names = {}
|
|
_inventory_state = {}
|
|
|
|
def __init__(self):
|
|
self._client = cisco_ucs_network_driver.CiscoUCSMDriver()
|
|
self._load_inventory()
|
|
|
|
def _load_inventory(self):
|
|
"""Load the inventory from a config file"""
|
|
inventory = deepcopy(conf.INVENTORY)
|
|
LOG.info("Loaded UCS inventory: %s\n" % inventory)
|
|
LOG.info("Building UCS inventory state (this may take a while)...")
|
|
|
|
for ucsm in inventory.keys():
|
|
ucsm_ip = inventory[ucsm][const.IP_ADDRESS]
|
|
inventory[ucsm].pop(const.IP_ADDRESS)
|
|
chassis_dict = {}
|
|
for chassis in inventory[ucsm].keys():
|
|
chassis_id = inventory[ucsm][chassis][const.CHASSIS_ID]
|
|
inventory[ucsm][chassis].pop(const.CHASSIS_ID)
|
|
blade_list = []
|
|
for blade in inventory[ucsm][chassis].keys():
|
|
blade_id = \
|
|
inventory[ucsm][chassis][blade][const.BLADE_ID]
|
|
host_name = \
|
|
inventory[ucsm][chassis][blade][const.HOST_NAME]
|
|
host_key = ucsm_ip + "-" + chassis_id + "-" + blade_id
|
|
self._host_names[host_key] = host_name
|
|
blade_list.append(blade_id)
|
|
chassis_dict[chassis_id] = blade_list
|
|
self._inventory[ucsm_ip] = chassis_dict
|
|
|
|
self._build_inventory_state()
|
|
|
|
def _build_inventory_state(self):
|
|
"""Populate the state of all the blades"""
|
|
for ucsm_ip in self._inventory.keys():
|
|
self._inventory_state[ucsm_ip] = {ucsm_ip: {}}
|
|
ucsm_username = cred.Store.getUsername(ucsm_ip)
|
|
ucsm_password = cred.Store.getPassword(ucsm_ip)
|
|
chasses_state = {}
|
|
self._inventory_state[ucsm_ip] = chasses_state
|
|
ucsm = self._inventory[ucsm_ip]
|
|
for chassis_id in ucsm.keys():
|
|
blades_dict = {}
|
|
chasses_state[chassis_id] = blades_dict
|
|
for blade_id in ucsm[chassis_id]:
|
|
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_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_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():
|
|
dist_name = blade_intf_data[blade_intf][const.BLADE_INTF_DN]
|
|
# We first make a pass through the state in UCSM
|
|
# If a particular interface is showing as being allocated in
|
|
# UCSM then it is definitely being used and so should be
|
|
# marked as reserved, else we temporarily mark it as unreserved
|
|
# based on the UCSM state, but may later change it if a port
|
|
# association is found in the DB
|
|
if not const.TENANTID in blade_intf_data[blade_intf].keys():
|
|
blade_intf_data[blade_intf][const.TENANTID] = None
|
|
if not const.PORTID in blade_intf_data[blade_intf].keys():
|
|
blade_intf_data[blade_intf][const.PORTID] = None
|
|
if not const.PROFILE_ID in blade_intf_data[blade_intf].keys():
|
|
blade_intf_data[blade_intf][const.PROFILE_ID] = None
|
|
if not const.INSTANCE_ID in blade_intf_data[blade_intf].keys():
|
|
blade_intf_data[blade_intf][const.INSTANCE_ID] = None
|
|
if not const.VIF_ID in blade_intf_data[blade_intf].keys():
|
|
blade_intf_data[blade_intf][const.VIF_ID] = None
|
|
|
|
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
|
|
|
|
port_binding = udb.get_portbinding_dn(dist_name)
|
|
if port_binding:
|
|
# We have found a port binding for this interface in the DB,
|
|
# so we have earlier marked this interface as unreserved, we
|
|
# need to change it, and also load the state from the DB for
|
|
# other associations
|
|
intf_data = blade_intf_data[blade_intf]
|
|
if intf_data[const.BLADE_INTF_RESERVATION] == \
|
|
const.BLADE_INTF_UNRESERVED:
|
|
unreserved_counter -= 1
|
|
intf_data[const.BLADE_INTF_RESERVATION] = \
|
|
const.BLADE_INTF_RESERVED
|
|
intf_data[const.TENANTID] = \
|
|
port_binding[const.TENANTID]
|
|
intf_data[const.PORTID] = \
|
|
port_binding[const.PORTID]
|
|
intf_data[const.PROFILE_ID] = \
|
|
port_binding[const.PORTPROFILENAME]
|
|
intf_data[const.INSTANCE_ID] = \
|
|
port_binding[const.INSTANCE_ID]
|
|
intf_data[const.VIF_ID] = \
|
|
port_binding[const.VIF_ID]
|
|
host_name = self._get_host_name(ucsm_ip, chassis_id, blade_id)
|
|
blade_data = {const.BLADE_INTF_DATA: blade_intf_data,
|
|
const.BLADE_UNRESERVED_INTF_COUNT: unreserved_counter,
|
|
const.HOST_NAME: host_name}
|
|
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,
|
|
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_data = {const.BLADE_INTF_DATA: blade_intf_data,
|
|
const.BLADE_UNRESERVED_INTF_COUNT: unreserved_counter}
|
|
return blade_data
|
|
|
|
def _get_all_ucsms(self):
|
|
"""Return a list of the IPs of all the UCSMs in the system"""
|
|
return {const.DEVICE_IP: self._inventory.keys()}
|
|
|
|
def _get_blade_for_port(self, args):
|
|
"""
|
|
Return the a dict with IP address of the blade
|
|
on which a dynamic vnic was reserved for this port
|
|
"""
|
|
tenant_id = args[0]
|
|
net_id = args[1]
|
|
port_id = args[2]
|
|
rsvd_info = self._get_rsvd_blade_intf_by_port(tenant_id, port_id)
|
|
if not rsvd_info:
|
|
raise exc.PortNotFound(net_id=net_id, port_id=port_id)
|
|
device_params = {const.DEVICE_IP: [rsvd_info[const.UCSM_IP]]}
|
|
return device_params
|
|
|
|
def _get_host_name_for_rsvd_intf(self, tenant_id, instance_id):
|
|
"""
|
|
Return the hostname of the blade with a reserved instance
|
|
for this tenant
|
|
"""
|
|
for ucsm_ip in self._inventory_state.keys():
|
|
ucsm = self._inventory_state[ucsm_ip]
|
|
for chassis_id in ucsm.keys():
|
|
for blade_id in ucsm[chassis_id]:
|
|
blade_data = ucsm[chassis_id][blade_id]
|
|
blade_intf_data = blade_data[const.BLADE_INTF_DATA]
|
|
for blade_intf in blade_intf_data.keys():
|
|
tmp = deepcopy(blade_intf_data[blade_intf])
|
|
intf_data = blade_intf_data[blade_intf]
|
|
if (intf_data[const.BLADE_INTF_RESERVATION] ==
|
|
const.BLADE_INTF_RESERVED and
|
|
intf_data[const.TENANTID] == tenant_id and
|
|
intf_data[const.INSTANCE_ID] is None):
|
|
intf_data[const.INSTANCE_ID] = instance_id
|
|
host_name = self._get_host_name(ucsm_ip,
|
|
chassis_id,
|
|
blade_id)
|
|
port_binding = udb.get_portbinding_dn(blade_intf)
|
|
port_id = port_binding[const.PORTID]
|
|
udb.update_portbinding(port_id,
|
|
instance_id=instance_id)
|
|
return host_name
|
|
LOG.warn("Could not find a reserved dynamic nic for tenant: %s" %
|
|
tenant_id)
|
|
return None
|
|
|
|
def _get_instance_port(self, tenant_id, instance_id, vif_id):
|
|
"""
|
|
Return the device name for a reserved interface
|
|
"""
|
|
found_blade_intf_data = None
|
|
for ucsm_ip in self._inventory_state.keys():
|
|
ucsm = self._inventory_state[ucsm_ip]
|
|
for chassis_id in ucsm.keys():
|
|
for blade_id in ucsm[chassis_id]:
|
|
blade_data = ucsm[chassis_id][blade_id]
|
|
blade_intf_data = blade_data[const.BLADE_INTF_DATA]
|
|
for blade_intf in blade_intf_data.keys():
|
|
intf_data = blade_intf_data[blade_intf]
|
|
if intf_data[const.BLADE_INTF_RESERVATION] == \
|
|
const.BLADE_INTF_RESERVED and \
|
|
intf_data[const.TENANTID] == tenant_id and \
|
|
intf_data[const.INSTANCE_ID] == instance_id:
|
|
found_blade_intf_data = blade_intf_data
|
|
LOG.debug("Found blade %s associated with this" \
|
|
" instance: %s" % \
|
|
(blade_id,
|
|
instance_id))
|
|
break
|
|
|
|
if found_blade_intf_data:
|
|
blade_intf_data = found_blade_intf_data
|
|
for blade_intf in blade_intf_data.keys():
|
|
intf_data = blade_intf_data[blade_intf]
|
|
if intf_data[const.BLADE_INTF_RESERVATION] == \
|
|
const.BLADE_INTF_RESERVED and \
|
|
intf_data[const.TENANTID] == tenant_id and \
|
|
(not intf_data[const.VIF_ID]):
|
|
intf_data[const.VIF_ID] = vif_id
|
|
intf_data[const.INSTANCE_ID] = instance_id
|
|
port_binding = udb.get_portbinding_dn(blade_intf)
|
|
port_id = port_binding[const.PORTID]
|
|
udb.update_portbinding(port_id, instance_id=instance_id,
|
|
vif_id=vif_id)
|
|
db.port_set_attachment_by_id(port_id, vif_id +
|
|
const.UNPLUGGED)
|
|
device_name = intf_data[const.BLADE_INTF_RHEL_DEVICE_NAME]
|
|
profile_name = port_binding[const.PORTPROFILENAME]
|
|
dynamicnic_details = \
|
|
{const.DEVICENAME: device_name,
|
|
const.UCSPROFILE: profile_name}
|
|
LOG.debug("Found reserved dynamic nic: %s" \
|
|
"associated with port %s" %
|
|
(intf_data, port_id))
|
|
LOG.debug("Returning dynamic nic details: %s" %
|
|
dynamicnic_details)
|
|
return dynamicnic_details
|
|
|
|
LOG.warn("Could not find a reserved dynamic nic for tenant: %s" %
|
|
tenant_id)
|
|
return None
|
|
|
|
def _disassociate_vifid_from_port(self, tenant_id, instance_id, vif_id):
|
|
"""
|
|
Disassociate a VIF-ID from a port, this happens when a
|
|
VM is destroyed
|
|
"""
|
|
for ucsm_ip in self._inventory_state.keys():
|
|
ucsm = self._inventory_state[ucsm_ip]
|
|
for chassis_id in ucsm.keys():
|
|
for blade_id in ucsm[chassis_id]:
|
|
blade_data = ucsm[chassis_id][blade_id]
|
|
blade_intf_data = blade_data[const.BLADE_INTF_DATA]
|
|
for blade_intf in blade_intf_data.keys():
|
|
intf_data = blade_intf_data[blade_intf]
|
|
if intf_data[const.BLADE_INTF_RESERVATION] == \
|
|
const.BLADE_INTF_RESERVED and \
|
|
intf_data[const.TENANTID] == tenant_id and \
|
|
blade_intf_data[blade_intf][const.INSTANCE_ID] == \
|
|
instance_id and \
|
|
intf_data[const.VIF_ID][:const.UUID_LENGTH] == \
|
|
vif_id:
|
|
intf_data[const.VIF_ID] = None
|
|
intf_data[const.INSTANCE_ID] = None
|
|
port_binding = udb.get_portbinding_dn(blade_intf)
|
|
port_id = port_binding[const.PORTID]
|
|
udb.update_portbinding(port_id, instance_id=None,
|
|
vif_id=None)
|
|
db.port_unset_attachment_by_id(port_id)
|
|
LOG.debug("Disassociated VIF-ID: %s " \
|
|
"from port: %s" \
|
|
"in UCS inventory state for blade: %s" %
|
|
(vif_id, port_id, intf_data))
|
|
device_params = {const.DEVICE_IP: [ucsm_ip],
|
|
const.PORTID: port_id}
|
|
return device_params
|
|
LOG.warn("Disassociating VIF-ID in UCS inventory failed. " \
|
|
"Could not find a reserved dynamic nic for tenant: %s" %
|
|
tenant_id)
|
|
return None
|
|
|
|
def _get_rsvd_blade_intf_by_port(self, tenant_id, port_id):
|
|
"""
|
|
Lookup a reserved blade interface based on tenant_id and port_id
|
|
and return the blade interface info
|
|
"""
|
|
for ucsm_ip in self._inventory_state.keys():
|
|
ucsm = self._inventory_state[ucsm_ip]
|
|
for chassis_id in ucsm.keys():
|
|
for blade_id in ucsm[chassis_id]:
|
|
blade_data = ucsm[chassis_id][blade_id]
|
|
blade_intf_data = blade_data[const.BLADE_INTF_DATA]
|
|
for blade_intf in blade_intf_data.keys():
|
|
if not blade_intf_data[blade_intf][const.PORTID] or \
|
|
not blade_intf_data[blade_intf][const.TENANTID]:
|
|
continue
|
|
intf_data = blade_intf_data[blade_intf]
|
|
if intf_data[const.BLADE_INTF_RESERVATION] == \
|
|
const.BLADE_INTF_RESERVED and \
|
|
intf_data[const.TENANTID] == tenant_id and \
|
|
intf_data[const.PORTID] == port_id:
|
|
interface_dn = intf_data[const.BLADE_INTF_DN]
|
|
blade_intf_info = {const.UCSM_IP: ucsm_ip,
|
|
const.CHASSIS_ID: chassis_id,
|
|
const.BLADE_ID: blade_id,
|
|
const.BLADE_INTF_DN:
|
|
interface_dn}
|
|
return blade_intf_info
|
|
LOG.warn("Could not find a reserved nic for tenant: %s port: %s" %
|
|
(tenant_id, port_id))
|
|
return None
|
|
|
|
def _get_least_reserved_blade(self, intf_count=1):
|
|
"""Return the blade with least number of dynamic nics reserved"""
|
|
unreserved_interface_count = 0
|
|
least_reserved_blade_ucsm = None
|
|
least_reserved_blade_chassis = None
|
|
least_reserved_blade_id = None
|
|
least_reserved_blade_data = None
|
|
|
|
for ucsm_ip in self._inventory_state.keys():
|
|
ucsm = self._inventory_state[ucsm_ip]
|
|
for chassis_id in ucsm.keys():
|
|
for blade_id in ucsm[chassis_id]:
|
|
blade_data = ucsm[chassis_id][blade_id]
|
|
if blade_data[const.BLADE_UNRESERVED_INTF_COUNT] > \
|
|
unreserved_interface_count:
|
|
unreserved_interface_count = \
|
|
blade_data[const.BLADE_UNRESERVED_INTF_COUNT]
|
|
least_reserved_blade_ucsm = ucsm_ip
|
|
least_reserved_blade_chassis = chassis_id
|
|
least_reserved_blade_id = blade_id
|
|
least_reserved_blade_data = blade_data
|
|
|
|
if unreserved_interface_count < intf_count:
|
|
LOG.warn("Not enough dynamic nics available on a single host." \
|
|
" Requested: %s, Maximum available: %s" %
|
|
(intf_count, unreserved_interface_count))
|
|
return False
|
|
|
|
least_reserved_blade_dict = \
|
|
{const.LEAST_RSVD_BLADE_UCSM: least_reserved_blade_ucsm,
|
|
const.LEAST_RSVD_BLADE_CHASSIS: least_reserved_blade_chassis,
|
|
const.LEAST_RSVD_BLADE_ID: least_reserved_blade_id,
|
|
const.LEAST_RSVD_BLADE_DATA: least_reserved_blade_data}
|
|
LOG.debug("Found dynamic nic %s available for reservation",
|
|
least_reserved_blade_dict)
|
|
return least_reserved_blade_dict
|
|
|
|
def reload_inventory(self):
|
|
"""Reload the inventory from a conf file"""
|
|
self._load_inventory()
|
|
|
|
def reserve_blade_interface(self, ucsm_ip, chassis_id, blade_id,
|
|
blade_data_dict, tenant_id, port_id,
|
|
portprofile_name):
|
|
"""Reserve an interface on a blade"""
|
|
ucsm_username = cred.Store.getUsername(ucsm_ip)
|
|
ucsm_password = cred.Store.getPassword(ucsm_ip)
|
|
"""
|
|
We are first getting the updated UCSM-specific blade
|
|
interface state
|
|
"""
|
|
blade_data = self._get_blade_state(chassis_id, blade_id, ucsm_ip,
|
|
ucsm_username, ucsm_password)
|
|
blade_intf_data = blade_data[const.BLADE_INTF_DATA]
|
|
#import sys
|
|
#sys.exit(ucsm_ip)
|
|
chassis_data = self._inventory_state[ucsm_ip][chassis_id]
|
|
old_blade_intf_data = chassis_data[blade_id][const.BLADE_INTF_DATA]
|
|
|
|
"""
|
|
We will now copy the older non-UCSM-specific blade
|
|
interface state
|
|
"""
|
|
for blade_intf in blade_intf_data.keys():
|
|
old_intf_data = old_blade_intf_data[blade_intf]
|
|
blade_intf_data[blade_intf][const.BLADE_INTF_RESERVATION] = \
|
|
old_intf_data[const.BLADE_INTF_RESERVATION]
|
|
blade_intf_data[blade_intf][const.TENANTID] = \
|
|
old_intf_data[const.TENANTID]
|
|
blade_intf_data[blade_intf][const.PORTID] = \
|
|
old_intf_data[const.PORTID]
|
|
blade_intf_data[blade_intf][const.PROFILE_ID] = \
|
|
old_intf_data[const.PROFILE_ID]
|
|
blade_intf_data[blade_intf][const.INSTANCE_ID] = \
|
|
old_intf_data[const.INSTANCE_ID]
|
|
blade_intf_data[blade_intf][const.VIF_ID] = \
|
|
old_intf_data[const.VIF_ID]
|
|
|
|
blade_data[const.BLADE_UNRESERVED_INTF_COUNT] = \
|
|
chassis_data[blade_id][const.BLADE_UNRESERVED_INTF_COUNT]
|
|
"""
|
|
Now we will reserve an interface if its available
|
|
"""
|
|
for blade_intf in blade_intf_data.keys():
|
|
intf_data = blade_intf_data[blade_intf]
|
|
if intf_data[const.BLADE_INTF_RESERVATION] == \
|
|
const.BLADE_INTF_UNRESERVED:
|
|
intf_data[const.BLADE_INTF_RESERVATION] = \
|
|
const.BLADE_INTF_RESERVED
|
|
intf_data[const.TENANTID] = tenant_id
|
|
intf_data[const.PORTID] = port_id
|
|
#intf_data[const.PROFILE_ID] = \
|
|
# portprofile_name
|
|
intf_data[const.INSTANCE_ID] = None
|
|
dev_eth_name = intf_data[const.BLADE_INTF_RHEL_DEVICE_NAME]
|
|
"""
|
|
We are replacing the older blade interface state with new
|
|
"""
|
|
chassis_data[blade_id][const.BLADE_INTF_DATA] = blade_intf_data
|
|
chassis_data[blade_id][const.BLADE_UNRESERVED_INTF_COUNT] -= 1
|
|
host_name = self._get_host_name(ucsm_ip, chassis_id,
|
|
blade_id)
|
|
reserved_nic_dict = {const.RESERVED_NIC_HOSTNAME: host_name,
|
|
const.RESERVED_NIC_NAME: dev_eth_name,
|
|
const.BLADE_INTF_DN: blade_intf}
|
|
port_binding = udb.add_portbinding(port_id, blade_intf, None,
|
|
None, None, None)
|
|
udb.update_portbinding(port_id,
|
|
tenant_id=intf_data[const.TENANTID])
|
|
LOG.debug("Reserved blade interface: %s\n" % reserved_nic_dict)
|
|
return reserved_nic_dict
|
|
|
|
LOG.warn("Dynamic nic %s could not be reserved for port-id: %s" %
|
|
(blade_data, port_id))
|
|
return False
|
|
|
|
def unreserve_blade_interface(self, ucsm_ip, chassis_id, blade_id,
|
|
interface_dn):
|
|
"""Unreserve a previously reserved interface on a blade"""
|
|
ucsm_username = cred.Store.getUsername(ucsm_ip)
|
|
ucsm_password = cred.Store.getPassword(ucsm_ip)
|
|
blade_data = self._inventory_state[ucsm_ip][chassis_id][blade_id]
|
|
|
|
blade_data[const.BLADE_UNRESERVED_INTF_COUNT] += 1
|
|
blade_intf = blade_data[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 add_blade(self, ucsm_ip, chassis_id, blade_id):
|
|
"""Add a blade to the inventory"""
|
|
# TODO (Sumit)
|
|
pass
|
|
|
|
def get_all_networks(self, args):
|
|
"""Return all UCSM IPs"""
|
|
LOG.debug("get_all_networks() called\n")
|
|
return self._get_all_ucsms()
|
|
|
|
def create_network(self, args):
|
|
"""Return all UCSM IPs"""
|
|
LOG.debug("create_network() called\n")
|
|
return self._get_all_ucsms()
|
|
|
|
def delete_network(self, args):
|
|
"""Return all UCSM IPs"""
|
|
LOG.debug("delete_network() called\n")
|
|
return self._get_all_ucsms()
|
|
|
|
def get_network_details(self, args):
|
|
"""Return all UCSM IPs"""
|
|
LOG.debug("get_network_details() called\n")
|
|
return self._get_all_ucsms()
|
|
|
|
def update_network(self, args):
|
|
"""Return all UCSM IPs"""
|
|
LOG.debug("update_network() called\n")
|
|
return self._get_all_ucsms()
|
|
|
|
def get_all_ports(self, args):
|
|
"""Return all UCSM IPs"""
|
|
LOG.debug("get_all_ports() called\n")
|
|
return self._get_all_ucsms()
|
|
|
|
def create_port(self, args):
|
|
"""
|
|
Return the a dict with information of the blade
|
|
on which a dynamic vnic is available
|
|
"""
|
|
LOG.debug("create_port() called\n")
|
|
least_reserved_blade_dict = self._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,
|
|
const.LEAST_RSVD_BLADE_DICT:\
|
|
least_reserved_blade_dict}
|
|
return device_params
|
|
|
|
def delete_port(self, args):
|
|
"""
|
|
Return the a dict with information of the blade
|
|
on which a dynamic vnic was reserved for this port
|
|
"""
|
|
LOG.debug("delete_port() called\n")
|
|
tenant_id = args[0]
|
|
net_id = args[1]
|
|
port_id = args[2]
|
|
rsvd_info = self._get_rsvd_blade_intf_by_port(tenant_id, port_id)
|
|
if not rsvd_info:
|
|
LOG.warn("UCSInventory: Port not found: net_id: %s, port_id: %s" %
|
|
(net_id, port_id))
|
|
return {const.DEVICE_IP: []}
|
|
device_params = \
|
|
{const.DEVICE_IP: [rsvd_info[const.UCSM_IP]],
|
|
const.UCS_INVENTORY: self,
|
|
const.CHASSIS_ID: rsvd_info[const.CHASSIS_ID],
|
|
const.BLADE_ID: rsvd_info[const.BLADE_ID],
|
|
const.BLADE_INTF_DN: rsvd_info[const.BLADE_INTF_DN]}
|
|
return device_params
|
|
|
|
def update_port(self, args):
|
|
"""
|
|
Return the a dict with IP address of the blade
|
|
on which a dynamic vnic was reserved for this port
|
|
"""
|
|
LOG.debug("update_port() called\n")
|
|
return self._get_blade_for_port(args)
|
|
|
|
def get_port_details(self, args):
|
|
"""
|
|
Return the a dict with IP address of the blade
|
|
on which a dynamic vnic was reserved for this port
|
|
"""
|
|
LOG.debug("get_port_details() called\n")
|
|
return self._get_blade_for_port(args)
|
|
|
|
def plug_interface(self, args):
|
|
"""
|
|
Return the a dict with IP address of the blade
|
|
on which a dynamic vnic was reserved for this port
|
|
"""
|
|
LOG.debug("plug_interface() called\n")
|
|
return self._get_blade_for_port(args)
|
|
|
|
def unplug_interface(self, args):
|
|
"""
|
|
Return the a dict with IP address of the blade
|
|
on which a dynamic vnic was reserved for this port
|
|
"""
|
|
LOG.debug("unplug_interface() called\n")
|
|
return self._get_blade_for_port(args)
|
|
|
|
def schedule_host(self, args):
|
|
"""Provides the hostname on which a dynamic vnic is reserved"""
|
|
LOG.debug("schedule_host() called\n")
|
|
instance_id = args[1]
|
|
tenant_id = args[2][const.PROJECT_ID]
|
|
host_name = self._get_host_name_for_rsvd_intf(tenant_id, instance_id)
|
|
host_list = {const.HOST_LIST: {const.HOST_1: host_name}}
|
|
LOG.debug("host_list is: %s" % host_list)
|
|
return host_list
|
|
|
|
def associate_port(self, args):
|
|
"""
|
|
Get the portprofile name and the device name for the dynamic vnic
|
|
"""
|
|
LOG.debug("associate_port() called\n")
|
|
instance_id = args[1]
|
|
tenant_id = args[2][const.PROJECT_ID]
|
|
vif_id = args[2][const.VIF_ID]
|
|
vif_info = self._get_instance_port(tenant_id, instance_id, vif_id)
|
|
vif_desc = {const.VIF_DESC: vif_info}
|
|
|
|
LOG.debug("vif_desc is: %s" % vif_desc)
|
|
return vif_desc
|
|
|
|
def detach_port(self, args):
|
|
"""
|
|
Remove the VIF-ID and instance name association
|
|
with the port
|
|
"""
|
|
LOG.debug("detach_port() called\n")
|
|
instance_id = args[1]
|
|
tenant_id = args[2][const.PROJECT_ID]
|
|
vif_id = args[2][const.VIF_ID]
|
|
device_params = self._disassociate_vifid_from_port(tenant_id,
|
|
instance_id,
|
|
vif_id)
|
|
return device_params
|
|
|
|
def create_multiport(self, args):
|
|
"""
|
|
Create multiple ports for a VM
|
|
"""
|
|
LOG.debug("create_ports() called\n")
|
|
tenant_id = args[0]
|
|
ports_num = args[2]
|
|
least_reserved_blade_dict = self._get_least_reserved_blade(ports_num)
|
|
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,
|
|
const.LEAST_RSVD_BLADE_DICT:\
|
|
least_reserved_blade_dict}
|
|
return device_params
|