diff --git a/proliantutils/ilo/client.py b/proliantutils/ilo/client.py index 672eeade..e4cb4061 100644 --- a/proliantutils/ilo/client.py +++ b/proliantutils/ilo/client.py @@ -13,6 +13,7 @@ # under the License. """IloClient module""" +from proliantutils.ilo import ipmi from proliantutils.ilo import operations from proliantutils.ilo import ribcl from proliantutils.ilo import ris @@ -42,6 +43,7 @@ class IloClient(operations.IloOperations): self.ribcl = ribcl.RIBCLOperations(host, login, password, timeout, port) self.ris = ris.RISOperations(host, login, password, bios_password) + self.info = {'address': host, 'username': login, 'password': password} self.model = self.ribcl.get_product_name() def _call_method(self, method_name, *args, **kwargs): @@ -309,10 +311,16 @@ class IloClient(operations.IloOperations): :raises: IloCommandNotSupportedError, if the command is not supported on the server. """ + capabilities = {} if 'Gen9' in self.model: capabilities = self.ris.get_server_capabilities() - gpu = self.ribcl._get_number_of_gpu_devices_connected() + data = self.ribcl.get_host_health_data() + gpu = self.ribcl._get_number_of_gpu_devices_connected(data) capabilities.update(gpu) - return capabilities else: - return self.ribcl.get_server_capabilities() + capabilities = self.ribcl.get_server_capabilities() + nic_capacity = ipmi.get_nic_capacity(self.info) + if nic_capacity: + capabilities.update({'nic_capacity': nic_capacity}) + if capabilities: + return capabilities diff --git a/proliantutils/ilo/ipmi.py b/proliantutils/ilo/ipmi.py new file mode 100644 index 00000000..33ef8f4e --- /dev/null +++ b/proliantutils/ilo/ipmi.py @@ -0,0 +1,114 @@ +# coding=utf-8 + +# Copyright 2012 Hewlett-Packard Development Company, L.P. +# Copyright (c) 2012 NTT DOCOMO, INC. +# Copyright 2014 International Business Machines Corporation +# 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. + +""" +NOTE THAT CERTAIN DISTROS MAY INSTALL openipmi BY DEFAULT, INSTEAD OF ipmitool, +WHICH PROVIDES DIFFERENT COMMAND-LINE OPTIONS AND *IS NOT SUPPORTED* BY THIS +DRIVER. +""" + +import subprocess + + +def _exec_ipmitool(driver_info, command): + """Execute the ipmitool command. + + This uses the lanplus interface to communicate with the BMC device driver. + + :param driver_info: the ipmitool parameters for accessing a node. + :param command: the ipmitool command to be executed. + + """ + ipmi_cmd = ("ipmitool -H %(address)s" + " -I lanplus -U %(user)s -P %(passwd)s %(cmd)s" + % {'address': driver_info['address'], + 'user': driver_info['username'], + 'passwd': driver_info['password'], + 'cmd': command}) + + out = None + try: + out = subprocess.check_output(ipmi_cmd, shell=True) + except Exception: + pass + return out + + +def get_nic_capacity(driver_info): + """Gets the FRU data to see if it is NIC data + + Gets the FRU data in loop from 0-255 FRU Ids + and check if the returned data is NIC data. Couldn't + find any easy way to detect if it is NIC data. We should't be + hardcoding the FRU Id. + + :param driver_info: Contains the access credentials to access + the BMC. + :returns: the max capacity supported by the NIC adapter. + """ + i = 0 + value = None + while i < 255: + cmd = "fru print %s" % hex(i) + out = _exec_ipmitool(driver_info, cmd) + if out and 'port' in out and 'Adapter' in out: + value = _parse_ipmi_nic_capacity(out) + if value is not None: + break + i = i + 1 + return value + + +def _parse_ipmi_nic_capacity(nic_out): + """Parse the FRU output for NIC capacity + + Parses the FRU output. Seraches for the key "Product Name" + in FRU output and greps for maximum speed supported by the + NIC adapter. + + :param nic_out: the FRU output for NIC adapter. + :returns: the max capacity supported by the NIC adapter. + + """ + if (("Device not present" in nic_out) + or ("Unknown FRU header" in nic_out) or not nic_out): + return None + + capacity = None + product_name = None + data = nic_out.split('\n') + for item in data: + fields = item.split(':') + if len(fields) > 1: + first_field = fields[0].strip() + if first_field == "Product Name": + # Join the string back if the Product Name had some + # ':' by any chance + product_name = ':'.join(fields[1:]) + break + + if product_name: + product_name_array = product_name.split(' ') + for item in product_name_array: + if 'Gb' in item: + capacity_int = item.strip('Gb') + if capacity_int.isdigit(): + capacity = item + + return capacity