mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-05-29 17:23:08 +00:00
Merge pull request #5910 from xuweibj/rpower_rf
rpower for redfish support
This commit is contained in:
commit
ee6ecbbc4a
@ -1,34 +0,0 @@
|
||||
#!/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 redfish_client as redfish
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger('xcatagent')
|
||||
|
||||
class RedfishPowerTask(ParallelNodesCommand):
|
||||
"""Executor for power-related actions."""
|
||||
|
||||
def get_state(self, **kw):
|
||||
|
||||
node = kw['node']
|
||||
rf = redfish.RedfishRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
|
||||
debugmode=self.debugmode, verbose=self.verbose)
|
||||
|
||||
state = 'Unknown'
|
||||
try:
|
||||
rf.login()
|
||||
self.callback.info('%s: %s' % (node, state))
|
||||
except (SelfServerException, SelfClientException) as e:
|
||||
self.callback.error(e.message, node)
|
||||
|
||||
return state
|
123
xCAT-openbmc-py/lib/python/agent/hwctl/redfish/redfish_power.py
Normal file
123
xCAT-openbmc-py/lib/python/agent/hwctl/redfish/redfish_power.py
Normal file
@ -0,0 +1,123 @@
|
||||
#!/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 redfish_client as redfish
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger('xcatagent')
|
||||
|
||||
POWER_STATE_DB = {
|
||||
"on" : "powering-on",
|
||||
"off" : "powering-off",
|
||||
"boot" : "powering-on",
|
||||
}
|
||||
|
||||
class RedfishPowerTask(ParallelNodesCommand):
|
||||
"""Executor for power-related actions."""
|
||||
|
||||
def get_state(self, **kw):
|
||||
|
||||
node = kw['node']
|
||||
rf = redfish.RedfishRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
|
||||
debugmode=self.debugmode, verbose=self.verbose)
|
||||
|
||||
state = 'Unknown'
|
||||
try:
|
||||
rf.login()
|
||||
chassis_state = rf.get_chassis_power_state()
|
||||
if chassis_state == 'On':
|
||||
state = rf.get_systems_power_state().lower()
|
||||
else:
|
||||
state = chassis_state.lower()
|
||||
self.callback.info('%s: %s' % (node, state))
|
||||
except (SelfServerException, SelfClientException) as e:
|
||||
self.callback.error(e.message, node)
|
||||
|
||||
return state
|
||||
|
||||
def get_bmcstate (self, **kw):
|
||||
|
||||
node = kw['node']
|
||||
rf = redfish.RedfishRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
|
||||
debugmode=self.debugmode, verbose=self.verbose)
|
||||
|
||||
state = 'Unknown'
|
||||
try:
|
||||
rf.login()
|
||||
state = rf.get_bmc_state().lower()
|
||||
self.callback.info('%s: %s' % (node, state))
|
||||
except (SelfServerException, SelfClientException) as e:
|
||||
self.callback.error(e.message, node)
|
||||
return state
|
||||
|
||||
def set_state(self, state, **kw):
|
||||
|
||||
node = kw['node']
|
||||
rf = redfish.RedfishRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
|
||||
debugmode=self.debugmode, verbose=self.verbose)
|
||||
|
||||
try:
|
||||
rf.login()
|
||||
rf.set_power_state(state)
|
||||
new_status = POWER_STATE_DB.get(state, '')
|
||||
self.callback.info('%s: %s' % (node, state))
|
||||
if new_status:
|
||||
self.callback.update_node_attributes('status', node, new_status)
|
||||
except (SelfServerException, SelfClientException) as e:
|
||||
self.callback.error(e.message, node)
|
||||
|
||||
def reboot(self, optype='boot', **kw):
|
||||
|
||||
node = kw['node']
|
||||
rf = redfish.RedfishRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
|
||||
debugmode=self.debugmode, verbose=self.verbose)
|
||||
resettype = 'boot'
|
||||
|
||||
try:
|
||||
rf.login()
|
||||
chassis_state = rf.get_chassis_power_state()
|
||||
if chassis_state == 'Off':
|
||||
status = chassis_state
|
||||
else:
|
||||
status = rf.get_systems_power_state()
|
||||
|
||||
if status == 'Off':
|
||||
if optype == 'reset':
|
||||
return self.callback.info('%s: %s' % (node, status.lower()))
|
||||
else:
|
||||
resettype = 'on'
|
||||
|
||||
rf.set_power_state(resettype)
|
||||
new_status = POWER_STATE_DB.get(optype, '')
|
||||
self.callback.info('%s: %s' % (node, optype))
|
||||
if new_status:
|
||||
self.callback.update_node_attributes('status', node, new_status)
|
||||
except (SelfServerException, SelfClientException) as e:
|
||||
self.callback.error(e.message, node)
|
||||
|
||||
def reboot_bmc(self, optype='warm', **kw):
|
||||
|
||||
node = kw['node']
|
||||
rf = redfish.RedfishRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
|
||||
debugmode=self.debugmode, verbose=self.verbose)
|
||||
|
||||
try:
|
||||
rf.login()
|
||||
except (SelfServerException, SelfClientException) as e:
|
||||
return self.callback.error(e.message, node)
|
||||
|
||||
try:
|
||||
rf.reboot_bmc(optype)
|
||||
except (SelfServerException, SelfClientException) as e:
|
||||
self.callback.error(e.message, node)
|
||||
else:
|
||||
self.callback.info('%s: %s' % (node, 'bmcreboot'))
|
@ -19,8 +19,23 @@ logger = logging.getLogger('xcatagent')
|
||||
HTTP_PROTOCOL = "https://"
|
||||
PROJECT_URL = "/redfish/v1"
|
||||
|
||||
CHASSIS_URL = PROJECT_URL + "/Chassis"
|
||||
MANAGER_URL = PROJECT_URL + "/Managers"
|
||||
SYSTEMS_URL = PROJECT_URL + "/Systems"
|
||||
SESSION_URL = PROJECT_URL + "/SessionService/Sessions"
|
||||
|
||||
BMC_RESET_TYPE = "ForceRestart"
|
||||
|
||||
POWER_RESET_TYPE = {
|
||||
'boot' : 'ForceRestart',
|
||||
'off' : 'ForceOff',
|
||||
'on' : 'ForceOn',
|
||||
}
|
||||
|
||||
manager_reset_string = '#Manager.Reset'
|
||||
system_reset_string = '#ComputerSystem.Reset'
|
||||
reset_type_string = 'ResetType@Redfish.AllowableValues'
|
||||
|
||||
class RedfishRest(object):
|
||||
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
@ -119,7 +134,10 @@ class RedfishRest(object):
|
||||
if cmd == 'login' and not 'X-Auth-Token' in resp.headers:
|
||||
raise SelfServerException('Login Failed: Did not get Session Token from response')
|
||||
|
||||
self._print_record_log('%s %s' % (code, data['Name']), cmd)
|
||||
if 'Name' in data:
|
||||
self._print_record_log('%s %s' % (code, data['Name']), cmd)
|
||||
elif 'error' in data:
|
||||
self._print_record_log('%s %s' % (code, data['error']['Message']), cmd)
|
||||
return data
|
||||
|
||||
def login(self):
|
||||
@ -127,3 +145,85 @@ class RedfishRest(object):
|
||||
payload = { "UserName": self.username, "Password": self.password }
|
||||
self.request('POST', SESSION_URL, payload=payload, timeout=20, cmd='login')
|
||||
|
||||
def _get_members(self, url):
|
||||
|
||||
data = self.request('GET', url, cmd='get_members')
|
||||
try:
|
||||
return data['Members']
|
||||
except KeyError as e:
|
||||
raise SelfServerException('Get KeyError %s' % e.message)
|
||||
|
||||
def get_bmc_state(self):
|
||||
|
||||
members = self._get_members(MANAGER_URL)
|
||||
target_url = members[0]['@odata.id']
|
||||
data = self.request('GET', target_url, cmd='get_bmc_state')
|
||||
try:
|
||||
return data['PowerState']
|
||||
except KeyError as e:
|
||||
raise SelfServerException('Get KeyError %s' % e.message)
|
||||
|
||||
def get_chassis_power_state(self):
|
||||
|
||||
members = self._get_members(CHASSIS_URL)
|
||||
target_url = members[0]['@odata.id']
|
||||
data = self.request('GET', target_url, cmd='get_chassis_power_state')
|
||||
try:
|
||||
return data['PowerState']
|
||||
except KeyError as e:
|
||||
raise SelfServerException('Get KeyError %s' % e.message)
|
||||
|
||||
def get_systems_power_state(self):
|
||||
|
||||
members = self._get_members(SYSTEMS_URL)
|
||||
target_url = members[0]['@odata.id']
|
||||
data = self.request('GET', target_url, cmd='get_systems_power_state')
|
||||
try:
|
||||
return data['PowerState']
|
||||
except KeyError as e:
|
||||
raise SelfServerException('Get KeyError %s' % e.message)
|
||||
|
||||
def _get_bmc_actions(self):
|
||||
|
||||
members = self._get_members(MANAGER_URL)
|
||||
target_url = members[0]['@odata.id']
|
||||
data = self.request('GET', target_url, cmd='get_bmc_actions')
|
||||
try:
|
||||
actions = data['Actions'][manager_reset_string][reset_type_string]
|
||||
target_url = data['Actions'][manager_reset_string]['target']
|
||||
except KeyError as e:
|
||||
raise SelfServerException('Get KeyError %s' % e.message)
|
||||
|
||||
return (target_url, actions)
|
||||
|
||||
def reboot_bmc(self, optype='warm'):
|
||||
|
||||
target_url, actions = self._get_bmc_actions()
|
||||
if BMC_RESET_TYPE not in actions:
|
||||
raise SelfClientException('Unsupported option: %s' % BMC_RESET_TYPE)
|
||||
|
||||
data = { "ResetType": BMC_RESET_TYPE }
|
||||
return self.request('POST', target_url, payload=data, cmd='set_bmc_state')
|
||||
|
||||
def _get_power_actions(self):
|
||||
|
||||
members = self._get_members(SYSTEMS_URL)
|
||||
target_url = members[0]['@odata.id']
|
||||
data = self.request('GET', target_url, cmd='get_power_actions')
|
||||
try:
|
||||
actions = data['Actions'][system_reset_string][reset_type_string]
|
||||
target_url = data['Actions'][system_reset_string]['target']
|
||||
except KeyError as e:
|
||||
raise SelfServerException('Get KeyError %s' % e.message)
|
||||
|
||||
return (target_url, actions)
|
||||
|
||||
def set_power_state(self, state):
|
||||
|
||||
target_url, actions = self._get_power_actions()
|
||||
if POWER_RESET_TYPE[state] not in actions:
|
||||
raise SelfClientException('Unsupported option: %s' % state)
|
||||
|
||||
data = { "ResetType": POWER_RESET_TYPE[state] }
|
||||
return self.request('POST', target_url, payload=data, cmd='set_power_state')
|
||||
|
||||
|
@ -14,13 +14,13 @@ from docopt import docopt,DocoptExit
|
||||
|
||||
from common import utils
|
||||
from common import exceptions as xcat_exception
|
||||
from hwctl.executor.openbmc_beacon import OpenBMCBeaconTask
|
||||
from hwctl.executor.openbmc_setboot import OpenBMCBootTask
|
||||
from hwctl.executor.openbmc_flash import OpenBMCFlashTask
|
||||
from hwctl.executor.openbmc_inventory import OpenBMCInventoryTask
|
||||
from hwctl.executor.openbmc_power import OpenBMCPowerTask
|
||||
from hwctl.executor.openbmc_sensor import OpenBMCSensorTask
|
||||
from hwctl.executor.openbmc_eventlog import OpenBMCEventlogTask
|
||||
from hwctl.openbmc.openbmc_beacon import OpenBMCBeaconTask
|
||||
from hwctl.openbmc.openbmc_setboot import OpenBMCBootTask
|
||||
from hwctl.openbmc.openbmc_flash import OpenBMCFlashTask
|
||||
from hwctl.openbmc.openbmc_inventory import OpenBMCInventoryTask
|
||||
from hwctl.openbmc.openbmc_power import OpenBMCPowerTask
|
||||
from hwctl.openbmc.openbmc_sensor import OpenBMCSensorTask
|
||||
from hwctl.openbmc.openbmc_eventlog import OpenBMCEventlogTask
|
||||
from hwctl.beacon import DefaultBeaconManager
|
||||
from hwctl.setboot import DefaultBootManager
|
||||
from hwctl.flash import DefaultFlashManager
|
||||
|
@ -13,7 +13,7 @@ from docopt import docopt,DocoptExit
|
||||
|
||||
from common import utils
|
||||
from common import exceptions as xcat_exception
|
||||
from hwctl.executor.redfish_power import RedfishPowerTask
|
||||
from hwctl.redfish.redfish_power import RedfishPowerTask
|
||||
from hwctl.power import DefaultPowerManager
|
||||
|
||||
from xcatagent import base
|
||||
@ -30,7 +30,7 @@ VERBOSE = False
|
||||
|
||||
# global variables of rpower
|
||||
POWER_REBOOT_OPTIONS = ('boot', 'reset')
|
||||
POWER_SET_OPTIONS = ('on', 'off', 'bmcreboot', 'softoff')
|
||||
POWER_SET_OPTIONS = ('on', 'off', 'bmcreboot')
|
||||
POWER_GET_OPTIONS = ('bmcstate', 'state', 'stat', 'status')
|
||||
|
||||
class RedfishManager(base.BaseManager):
|
||||
@ -50,7 +50,7 @@ class RedfishManager(base.BaseManager):
|
||||
# 1, parse args
|
||||
rpower_usage = """
|
||||
Usage:
|
||||
rpower [-V|--verbose] [boot|bmcreboot|bmcstate|off|on|reset|softoff|stat|state|status]
|
||||
rpower [-V|--verbose] [boot|bmcreboot|bmcstate|off|on|reset|stat|state|status]
|
||||
|
||||
Options:
|
||||
-V --verbose rpower verbose mode.
|
||||
@ -73,5 +73,14 @@ class RedfishManager(base.BaseManager):
|
||||
|
||||
# 3, run the subcommands
|
||||
runner = RedfishPowerTask(nodesinfo, callback=self.messager, debugmode=self.debugmode, verbose=self.verbose)
|
||||
DefaultPowerManager().get_power_state(runner)
|
||||
if action == 'bmcstate':
|
||||
DefaultPowerManager().get_bmc_state(runner)
|
||||
elif action == 'bmcreboot':
|
||||
DefaultPowerManager().reboot_bmc(runner)
|
||||
elif action in POWER_GET_OPTIONS:
|
||||
DefaultPowerManager().get_power_state(runner)
|
||||
elif action in POWER_REBOOT_OPTIONS:
|
||||
DefaultPowerManager().reboot(runner, optype=action)
|
||||
else:
|
||||
DefaultPowerManager().set_power_state(runner, power_state=action)
|
||||
|
||||
|
@ -33,6 +33,77 @@ my %module_type = (
|
||||
"redfish" => "Redfish",
|
||||
);
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 parse_node_info
|
||||
|
||||
Parse the node information: bmc, bmcip, username, password
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub parse_node_info {
|
||||
my $noderange = shift;
|
||||
my $module = shift;
|
||||
my $node_info_ref = shift;
|
||||
my $callback = shift;
|
||||
my $rst = 0;
|
||||
|
||||
my $passwd_table = xCAT::Table->new('passwd');
|
||||
my $passwd_hash = $passwd_table->getAttribs({ 'key' => $module }, qw(username password));
|
||||
|
||||
my $openbmc_table = xCAT::Table->new('openbmc');
|
||||
my $openbmc_hash = $openbmc_table->getNodesAttribs(\@$noderange, ['bmc', 'username', 'password']);
|
||||
|
||||
foreach my $node (@$noderange) {
|
||||
if (defined($openbmc_hash->{$node}->[0])) {
|
||||
if ($openbmc_hash->{$node}->[0]->{'bmc'}) {
|
||||
$node_info_ref->{$node}->{bmc} = $openbmc_hash->{$node}->[0]->{'bmc'};
|
||||
$node_info_ref->{$node}->{bmcip} = xCAT::NetworkUtils::getNodeIPaddress($openbmc_hash->{$node}->[0]->{'bmc'});
|
||||
}
|
||||
unless($node_info_ref->{$node}->{bmc}) {
|
||||
xCAT::SvrUtils::sendmsg("Error: Unable to get attribute bmc", $callback, $node);
|
||||
delete $node_info_ref->{$node};
|
||||
$rst = 1;
|
||||
next;
|
||||
}
|
||||
unless($node_info_ref->{$node}->{bmcip}) {
|
||||
xCAT::SvrUtils::sendmsg("Error: Unable to resolve ip address for bmc: $node_info_ref->{$node}->{bmc}", $callback, $node);
|
||||
delete $node_info_ref->{$node};
|
||||
$rst = 1;
|
||||
next;
|
||||
}
|
||||
if ($openbmc_hash->{$node}->[0]->{'username'}) {
|
||||
$node_info_ref->{$node}->{username} = $openbmc_hash->{$node}->[0]->{'username'};
|
||||
} elsif ($passwd_hash and $passwd_hash->{username}) {
|
||||
$node_info_ref->{$node}->{username} = $passwd_hash->{username};
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("Error: Unable to get attribute username", $callback, $node);
|
||||
delete $node_info_ref->{$node};
|
||||
$rst = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
if ($openbmc_hash->{$node}->[0]->{'password'}) {
|
||||
$node_info_ref->{$node}->{password} = $openbmc_hash->{$node}->[0]->{'password'};
|
||||
} elsif ($passwd_hash and $passwd_hash->{password}) {
|
||||
$node_info_ref->{$node}->{password} = $passwd_hash->{password};
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("Error: Unable to get attribute password", $callback, $node);
|
||||
delete $node_info_ref->{$node};
|
||||
$rst = 1;
|
||||
next;
|
||||
}
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("Error: Unable to get information from openbmc table", $callback, $node);
|
||||
$rst = 1;
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
return $rst;
|
||||
}
|
||||
|
||||
sub acquire_lock {
|
||||
my $ppid = shift;
|
||||
$ppid = shift if (($ppid) && ($ppid =~ /AGENT/));
|
||||
|
@ -141,7 +141,7 @@ sub process_request {
|
||||
}
|
||||
|
||||
my $noderange = $request->{node};
|
||||
my $check = parse_node_info($noderange);
|
||||
my $check = xCAT::AGENT::parse_node_info($noderange, "openbmc", \%node_info, $callback);
|
||||
if (&refactor_args($request)) {
|
||||
xCAT::MsgUtils->message("E", { data => ["Failed to refactor arguments"] }, $callback);
|
||||
return;
|
||||
@ -418,74 +418,6 @@ sub parse_args {
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 parse_node_info
|
||||
|
||||
Parse the node information: bmc, bmcip, username, password
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub parse_node_info {
|
||||
my $noderange = shift;
|
||||
my $rst = 0;
|
||||
|
||||
my $passwd_table = xCAT::Table->new('passwd');
|
||||
my $passwd_hash = $passwd_table->getAttribs({ 'key' => 'openbmc' }, qw(username password));
|
||||
|
||||
my $openbmc_table = xCAT::Table->new('openbmc');
|
||||
my $openbmc_hash = $openbmc_table->getNodesAttribs(\@$noderange, ['bmc', 'username', 'password']);
|
||||
|
||||
foreach my $node (@$noderange) {
|
||||
if (defined($openbmc_hash->{$node}->[0])) {
|
||||
if ($openbmc_hash->{$node}->[0]->{'bmc'}) {
|
||||
$node_info{$node}{bmc} = $openbmc_hash->{$node}->[0]->{'bmc'};
|
||||
$node_info{$node}{bmcip} = xCAT::NetworkUtils::getNodeIPaddress($openbmc_hash->{$node}->[0]->{'bmc'});
|
||||
}
|
||||
unless($node_info{$node}{bmc}) {
|
||||
xCAT::SvrUtils::sendmsg("Error: Unable to get attribute bmc", $callback, $node);
|
||||
delete $node_info{$node};
|
||||
$rst = 1;
|
||||
next;
|
||||
}
|
||||
unless($node_info{$node}{bmcip}) {
|
||||
xCAT::SvrUtils::sendmsg("Error: Unable to resolve ip address for bmc: $node_info{$node}{bmc}", $callback, $node);
|
||||
delete $node_info{$node};
|
||||
$rst = 1;
|
||||
next;
|
||||
}
|
||||
if ($openbmc_hash->{$node}->[0]->{'username'}) {
|
||||
$node_info{$node}{username} = $openbmc_hash->{$node}->[0]->{'username'};
|
||||
} elsif ($passwd_hash and $passwd_hash->{username}) {
|
||||
$node_info{$node}{username} = $passwd_hash->{username};
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("Error: Unable to get attribute username", $callback, $node);
|
||||
delete $node_info{$node};
|
||||
$rst = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
if ($openbmc_hash->{$node}->[0]->{'password'}) {
|
||||
$node_info{$node}{password} = $openbmc_hash->{$node}->[0]->{'password'};
|
||||
} elsif ($passwd_hash and $passwd_hash->{password}) {
|
||||
$node_info{$node}{password} = $passwd_hash->{password};
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("Error: Unable to get attribute password", $callback, $node);
|
||||
delete $node_info{$node};
|
||||
$rst = 1;
|
||||
next;
|
||||
}
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("Error: Unable to get information from openbmc table", $callback, $node);
|
||||
$rst = 1;
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
return $rst;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 refactor_args
|
||||
|
||||
refractor args to be easily dealt by python client
|
||||
|
173
xCAT-server/lib/xcat/plugins/redfish.pm
Normal file
173
xCAT-server/lib/xcat/plugins/redfish.pm
Normal file
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/perl
|
||||
### IBM(c) 2017 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
package xCAT_plugin::redfish;
|
||||
|
||||
BEGIN
|
||||
{
|
||||
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
||||
}
|
||||
use lib "$::XCATROOT/lib/perl";
|
||||
use strict;
|
||||
use warnings "all";
|
||||
|
||||
use Getopt::Long;
|
||||
use xCAT::Usage;
|
||||
use xCAT::SvrUtils;
|
||||
use xCAT::AGENT;
|
||||
use Data::Dumper;
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 handled_commands
|
||||
|
||||
Return list of commands handled by this plugin
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub handled_commands {
|
||||
return {
|
||||
rbeacon => 'nodehm:mgt',
|
||||
reventlog => 'nodehm:mgt',
|
||||
rinv => 'nodehm:mgt',
|
||||
rpower => 'nodehm:mgt',
|
||||
rsetboot => 'nodehm:mgt',
|
||||
rspconfig => 'nodehm:mgt',
|
||||
rvitals => 'nodehm:mgt',
|
||||
};
|
||||
}
|
||||
|
||||
my %node_info = ();
|
||||
my $callback;
|
||||
$::VERBOSE = 0;
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 preprocess_request
|
||||
|
||||
preprocess the command
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub preprocess_request {
|
||||
my $request = shift;
|
||||
$callback = shift;
|
||||
my $command = $request->{command}->[0];
|
||||
my $noderange = $request->{node};
|
||||
my $extrargs = $request->{arg};
|
||||
my @exargs = ($request->{arg});
|
||||
my @requests;
|
||||
|
||||
if (ref($extrargs)) {
|
||||
@exargs = @$extrargs;
|
||||
}
|
||||
|
||||
my $usage_string = xCAT::Usage->parseCommand($command, @exargs);
|
||||
if ($usage_string) {
|
||||
$callback->({ data => [$usage_string] });
|
||||
$request = {};
|
||||
return;
|
||||
}
|
||||
|
||||
my $parse_result = parse_args($command, $extrargs, $noderange);
|
||||
if (ref($parse_result) eq 'ARRAY') {
|
||||
my $error_data;
|
||||
foreach my $node (@$noderange) {
|
||||
$error_data .= "\n" if ($error_data);
|
||||
$error_data .= "$node: Error: " . "$parse_result->[1]";
|
||||
}
|
||||
$callback->({ errorcode => [$parse_result->[0]], data => [$error_data] });
|
||||
$request = {};
|
||||
return;
|
||||
}
|
||||
|
||||
my $sn = xCAT::ServiceNodeUtils->get_ServiceNode($noderange, "xcat", "MN");
|
||||
foreach my $snkey (keys %$sn) {
|
||||
my $reqcopy = {%$request};
|
||||
$reqcopy->{node} = $sn->{$snkey};
|
||||
$reqcopy->{'_xcatdest'} = $snkey;
|
||||
$reqcopy->{_xcatpreprocessed}->[0] = 1;
|
||||
push @requests, $reqcopy;
|
||||
}
|
||||
|
||||
return \@requests;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 process_request
|
||||
|
||||
Process the command
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub process_request {
|
||||
my $request = shift;
|
||||
$callback = shift;
|
||||
|
||||
if (!xCAT::AGENT::exists_python_agent()) {
|
||||
xCAT::MsgUtils->message("E", { data => ["The xCAT Python agent does not exist. Check if xCAT-openbmc-py package is installed on management node and service nodes."] }, $callback);
|
||||
return;
|
||||
}
|
||||
|
||||
my $noderange = $request->{node};
|
||||
my $check = xCAT::AGENT::parse_node_info($noderange, "redfish", \%node_info, $callback);
|
||||
$callback->({ errorcode => [$check] }) if ($check);
|
||||
return unless(%node_info);
|
||||
|
||||
my $pid = xCAT::AGENT::start_python_agent();
|
||||
if (!defined($pid)) {
|
||||
xCAT::MsgUtils->message("E", { data => ["Failed to start the xCAT Python agent. Check /var/log/xcat/cluster.log for more information."] }, $callback);
|
||||
return;
|
||||
}
|
||||
|
||||
xCAT::AGENT::submit_agent_request($pid, $request, "redfish", \%node_info, $callback);
|
||||
xCAT::AGENT::wait_agent($pid, $callback);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 parse_args
|
||||
|
||||
Parse the command line options and operands
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub parse_args {
|
||||
my $command = shift;
|
||||
my $extrargs = shift;
|
||||
my $noderange = shift;
|
||||
my $subcommand = undef;
|
||||
|
||||
unless (GetOptions(
|
||||
'V|verbose' => \$::VERBOSE,
|
||||
)) {
|
||||
return ([ 1, "Error parsing arguments." ]);
|
||||
}
|
||||
|
||||
if (scalar(@ARGV) >= 2 and ($command =~ /rbeacon|rpower|rvitals/)) {
|
||||
return ([ 1, "Only one option is supported at the same time for $command" ]);
|
||||
} elsif (scalar(@ARGV) == 0 and $command =~ /rbeacon|rspconfig|rpower/) {
|
||||
return ([ 1, "No option specified for $command" ]);
|
||||
} else {
|
||||
$subcommand = $ARGV[0];
|
||||
}
|
||||
|
||||
if ($command eq "rpower") {
|
||||
unless ($subcommand =~ /^on$|^off$|^reset$|^boot$|^bmcreboot$|^bmcstate$|^status$|^stat$|^state$/) {
|
||||
return ([ 1, "Unsupported command: $command $subcommand" ]);
|
||||
}
|
||||
} else {
|
||||
return ([ 1, "Unsupported command: $command" ]);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
Loading…
x
Reference in New Issue
Block a user