2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-06-13 09:50:19 +00:00

rinv for openbmc in python (#4802)

* rinv for openbmc in python
This commit is contained in:
xuweibj
2018-02-07 17:04:04 +08:00
committed by Bin Xu
parent 56814b4908
commit cdd89cf970
5 changed files with 246 additions and 3 deletions

View File

@ -0,0 +1,122 @@
#!/usr/bin/env python
###############################################################################
# IBM(c) 2018 EPL license http://www.eclipse.org/legal/epl-v10.html
###############################################################################
# -*- coding: utf-8 -*-
#
from __future__ import print_function
import gevent
import time
from common.task import ParallelNodesCommand
from common.exceptions import SelfClientException, SelfServerException
from hwctl import openbmc_client as openbmc
from common import utils
import logging
logger = logging.getLogger('xcatagent')
class OpenBMCInventoryTask(ParallelNodesCommand):
"""Executor for inventory-related actions."""
def _get_firm_info(self, firm_info_list):
(has_functional, firm_obj_dict) = firm_info_list
firm_info = []
keys = firm_obj_dict.keys()
keys.sort()
for key in keys:
flag = ''
if firm_obj_dict[key].functional:
flag = '*'
elif firm_obj_dict[key].priority == 0:
if not has_functional:
flag = '*'
else:
flag = '+'
if flag != '*' and not self.verbose:
continue
firm_info.append('%s Firmware Product: %s (%s)%s' %
(firm_obj_dict[key].purpose,
firm_obj_dict[key].version,
firm_obj_dict[key].active,
flag))
if firm_obj_dict[key].extver:
extendeds = firm_obj_dict[key].extver.split(',')
extendeds.sort()
for extended in extendeds:
firm_info.append('%s Firmware Product: ' \
'-- additional info: %s' % \
(firm_obj_dict[key].purpose, extended))
return firm_info
def get_info(self, inventory_type, **kw):
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
inventory_info = []
try:
obmc.login()
inventory_info_dict = obmc.get_inventory_info()
if inventory_type == 'all' or not inventory_type:
keys = inventory_info_dict.keys()
keys.sort()
for key in keys:
inventory_info += utils.sort_string_with_numbers(inventory_info_dict[key])
firm_dict_list = obmc.list_firmware()
firm_info = self._get_firm_info(firm_dict_list)
inventory_info += firm_info
elif inventory_type == 'model' or inventory_type == 'serial':
key = 'Model' if inventory_type == 'model' else 'SerialNumber'
if 'SYSTEM' in inventory_info_dict:
for system_info in inventory_info_dict['SYSTEM']:
if key in system_info:
inventory_info = [system_info]
break
else:
key = inventory_type.upper()
if key in inventory_info_dict:
inventory_info = utils.sort_string_with_numbers(inventory_info_dict[key])
if not inventory_info:
inventory_info = ['No attributes returned from the BMC.']
for info in inventory_info:
self.callback.info( '%s: %s' % (node, info))
except (SelfServerException, SelfClientException) as e:
self.callback.info('%s: %s' % (node, e.message))
return inventory_info
def get_firm_info(self, **kw):
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
firm_info = []
try:
obmc.login()
firm_dict_list = obmc.list_firmware()
firm_info = self._get_firm_info(firm_dict_list)
for info in firm_info:
self.callback.info( '%s: %s' % (node, info))
except (SelfServerException, SelfClientException) as e:
self.callback.info('%s: %s' % (node, e.message))
return firm_info

View File

@ -0,0 +1,32 @@
#!/usr/bin/env python
###############################################################################
# IBM(c) 2018 EPL license http://www.eclipse.org/legal/epl-v10.html
###############################################################################
# -*- coding: utf-8 -*-
#
class InventoryInterface(object):
"""Interface for inventory-related actions."""
interface_type = 'inventory'
version = '1.0'
def get_inventory_info(self, task, inventory_type=None):
"""Return the inventory info of the task's nodes.
:param inventory_type: type of inventory info want to get.
:param task: a Task instance containing the nodes to act on.
:return inventory info list
"""
return task.run('get_info', inventory_type)
def get_firm_info(self, task):
"""Return the firm info of the task's nodes.
:param task: a Task instance containing the nodes to act on.
:return firm info list
"""
return task.run('get_firm_info')
class DefaultInventoryManager(InventoryInterface):
"""Interface for inventory-related actions."""
pass

View File

@ -29,6 +29,8 @@ RBEACON_URLS = {
},
}
INVENTORY_URL = "/inventory/enumerate"
LEDS_URL = "/led/physical/enumerate"
LEDS_KEY_LIST = ("fan0", "fan1", "fan2", "fan3",
@ -382,6 +384,43 @@ class OpenBMCRest(object):
error = 'Error: Received wrong format response: %s' % sensor_data
raise SelfServerException(error)
def get_inventory_info(self):
inventory_data = self.request('GET', INVENTORY_URL, cmd='get_inventory_info')
try:
inverntory_dict = {}
for key, value in inventory_data.items():
if 'Present' not in value:
logger.debug('Not "Present" for %s' % key)
continue
key_list = key.split('/')
try:
key_id = key_list[-1]
key_tmp = key_list[-2]
except IndexError:
logger.debug('IndexError (-2) for %s' % key)
continue
key_type = filter(lambda x:x not in '0123456789', key_id).upper()
if key_type == 'CORE':
key_type = 'CPU'
source = '%s %s' % (key_tmp, key_id)
else:
source = key_id
if key_type not in inverntory_dict:
inverntory_dict[key_type] = []
for (sub_key, v) in value.items():
inverntory_dict[key_type].append('%s %s : %s' % (source.upper(), sub_key, v))
return inverntory_dict
except KeyError:
error = 'Error: Received wrong format response: %s' % inventory_data
raise SelfServerException(error)
def list_firmware(self):
data = self.request('GET', FIRM_URLS['list']['path'], cmd='list_firmware')
@ -407,8 +446,12 @@ class OpenBMCRest(object):
class OpenBMCImage(object):
def __init__(self, rawid, data=None):
self.id = rawid.split('/')[-1]
self.extver = None
self.functional = False
self.priority = None
self.progress = None
self.purpose = 'Unknown'
if data:
self.version = data.get('Version')
self.purpose = data.get('Purpose', self.purpose).split('.')[-1]

View File

@ -14,12 +14,14 @@ from docopt import docopt
from common import utils
from common import exceptions as xcat_exception
from hwctl.executor.openbmc_beacon import OpenBMCBeaconTask
from hwctl.executor.openbmc_power import OpenBMCPowerTask
from hwctl.executor.openbmc_setboot import OpenBMCBootTask
from hwctl.executor.openbmc_inventory import OpenBMCInventoryTask
from hwctl.executor.openbmc_power import OpenBMCPowerTask
from hwctl.executor.openbmc_sensor import OpenBMCSensorTask
from hwctl.beacon import DefaultBeaconManager
from hwctl.power import DefaultPowerManager
from hwctl.setboot import DefaultBootManager
from hwctl.inventory import DefaultInventoryManager
from hwctl.power import DefaultPowerManager
from hwctl.sensor import DefaultSensorManager
from xcatagent import base
@ -81,6 +83,9 @@ XCAT_LOG_RFLASH_DIR = XCAT_LOG_DIR + "/rflash/"
# global variable of firmware information
FIRM_URL = PROJECT_URL + "/software/enumerate"
#global variables of rinv
INVENTORY_OPTIONS = ('all', 'cpu', 'dimm', 'firm', 'model', 'serial')
# global variables of rpower
POWER_REBOOT_OPTIONS = ('boot', 'reset')
POWER_SET_OPTIONS = ('on', 'off', 'bmcreboot', 'softoff')
@ -585,6 +590,41 @@ class OpenBMCManager(base.BaseManager):
runner = OpenBMCBeaconTask(nodesinfo, callback=self.messager, debugmode=self.debugmode, verbose=self.verbose)
DefaultBeaconManager().set_beacon_state(runner, beacon_state=action)
def rinv(self, nodesinfo, args):
# 1, parse agrs
if not args:
args = ['all']
rinv_usage = """
Usage:
rinv [-V|--verbose] [all|cpu|dimm|firm|model|serial]
Options:
-V --verbose rinv verbose mode.
"""
try:
opts = docopt(rinv_usage, argv=args)
self.verbose = opts.pop('--verbose')
action = [k for k,v in opts.items() if v][0]
except Exception as e:
self.messager.error("Failed to parse arguments for rinv: %s" % args)
return
# 2, validate the args
if action not in INVENTORY_OPTIONS:
self.messager.error("Not supported subcommand for rinv: %s" % action)
return
# 3, run the subcommands
runner = OpenBMCInventoryTask(nodesinfo, callback=self.messager, debugmode=self.debugmode, verbose=self.verbose)
if action == 'firm':
DefaultInventoryManager().get_firm_info(runner)
else:
DefaultInventoryManager().get_inventory_info(runner, action)
def rpower(self, nodesinfo, args):
# 1, parse args

View File

@ -32,6 +32,7 @@ sub handled_commands {
return {
rbeacon => 'nodehm:mgt=openbmc',
rflash => 'nodehm:mgt=openbmc',
rinv => 'nodehm:mgt=openbmc',
rpower => 'nodehm:mgt=openbmc',
rsetboot => 'nodehm:mgt=openbmc',
rvitals => 'nodehm:mgt=openbmc',
@ -147,7 +148,7 @@ sub parse_args {
return ([ 1, "Error parsing arguments." ]);
}
if (scalar(@ARGV) >= 2 and ($command =~ /rbeacon|rpower|rvitals/)) {
if (scalar(@ARGV) >= 2 and ($command =~ /rbeacon|rinv|rpower|rvitals/)) {
return ([ 1, "Only one option is supported at the same time for $command" ]);
} elsif (scalar(@ARGV) == 0 and $command =~ /rbeacon|rpower|rflash/) {
return ([ 1, "No option specified for $command" ]);
@ -208,6 +209,11 @@ sub parse_args {
if ($list) {
return ([ 1, "Invalid option specified with '-l|--list'."]) if (@ARGV);
}
} elsif ($command eq "rinv") {
$subcommand = "all" if (!defined($ARGV[0]));
unless ($subcommand =~ /^all$|^cpu$|^dimm$|^firm$|^model$|^serial$/) {
return ([ 1, "Unsupported command: $command $subcommand" ]);
}
} elsif ($command eq "rpower") {
unless ($subcommand =~ /^on$|^off$|^softoff$|^reset$|^boot$|^bmcreboot$|^bmcstate$|^status$|^stat$|^state$/) {
return ([ 1, "Unsupported command: $command $subcommand" ]);