mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-06-13 09:50:19 +00:00
@ -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
|
||||
|
||||
|
||||
|
||||
|
32
xCAT-openbmc-py/lib/python/agent/hwctl/inventory.py
Normal file
32
xCAT-openbmc-py/lib/python/agent/hwctl/inventory.py
Normal 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
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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" ]);
|
||||
|
Reference in New Issue
Block a user