2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-05-30 09:36:41 +00:00

Add pdu support

This commit is contained in:
Casandra Qiu 2017-02-13 16:33:11 -05:00
parent 48af0de2b9
commit c4e0f637c9
19 changed files with 680 additions and 2 deletions

View File

@ -25,7 +25,7 @@ BMC/MPA specific:
=================
\ **rinv**\ \ *noderange*\ {\ **pci | model | serial | asset | vpd | mprom | deviceid | guid | firm | diag | bios | mparom | mac | all**\ }
\ **rinv**\ \ *noderange*\ {\ **pci | model | serial | asset | vpd | mprom | deviceid | guid | firm | diag | dimm | bios | mparom | mac | all**\ }
OpenPOWER server specific:
@ -65,6 +65,13 @@ VMware specific:
\ **rinv**\ \ *noderange*\ [\ **-t**\ ]
pdu specific:
=============
\ **rinv**\ \ *noderange*\
zVM specific:
=============

View File

@ -29,6 +29,8 @@ BMC (using IPMI) specific:
\ **rpower**\ \ *noderange*\ [\ **on | off | softoff | reset | boot | stat | state | status | wake | suspend**\ [\ **-w**\ \ *timeout*\ ] [\ **-o**\ ] [\ **-r**\ ]]
\ **rpower**\ \ *noderange*\ [\ **pduon | pduoff | pdustat**\ ]
PPC (with IVM or HMC) specific:
===============================
@ -102,6 +104,13 @@ docker specific:
\ **rpower**\ \ *noderange*\ [\ **start | stop | restart | pause | unpause | state**\ ]
pdu specific:
=============
\ **rpower**\ \ *noderange*\ [\ **stat | off | on**\ ]
***********
DESCRIPTION

View File

@ -0,0 +1,82 @@
#####
pdu.5
#####
.. highlight:: perl
****
NAME
****
\ **pdu**\ - a table in the xCAT database.
********
SYNOPSIS
********
\ **pdu Attributes:**\ \ *pdu*\ , \ *machinetype*\ , \ *modelnum*\ , \ *serialnum*\ , \ *outletCount*\ , \ *comments*\ , \ *disable*\
***********
DESCRIPTION
***********
Parameters to use when interrogating pdus
***************
pdu Attributes:
***************
\ **pdu**\
The hostname/address of the pdu to which the settings apply
\ **machinetype**\
The pdu machine type
\ **modelnum**\
The pdu model number
\ **serialnum**\
The pdu serial number
\ **outletCount**\
\ **comments**\
\ **disable**\
********
SEE ALSO
********
\ **nodels(1)**\ , \ **chtab(8)**\ , \ **tabdump(8)**\ , \ **tabedit(8)**\

View File

@ -0,0 +1,70 @@
###########
pduoutlet.5
###########
.. highlight:: perl
****
NAME
****
\ **pduoutlet**\ - a table in the xCAT database.
********
SYNOPSIS
********
\ **pduoutlet Attributes:**\ \ *node*\ , \ *pdu*\ , \ *comments*\ , \ *disable*\
***********
DESCRIPTION
***********
Contains list of outlet numbers on the pdu each node is connected to.
*********************
pduoutlet Attributes:
*********************
\ **node**\
The node name or group name.
\ **pdu**\
a comma-separated list of outlet number for each PDU, ex: pdu1:outlet1,pdu2:outlet1
\ **comments**\
Any user-written notes.
\ **disable**\
Set to 'yes' or '1' to comment out this row.
********
SEE ALSO
********
\ **nodels(1)**\ , \ **chtab(8)**\ , \ **tabdump(8)**\ , \ **tabedit(8)**\

View File

@ -678,6 +678,19 @@ passed as argument rather than by table value',
disable => "Set to 'yes' or '1' to comment out this row.",
},
},
pdu => {
cols => [qw(pdu machinetype modelnum serialnum outletCount comments disable)],
keys => [qw(pdu)],
nodecol => "pdu",
table_desc => 'Parameters to use when interrogating pdus',
descriptions => {
pdu => 'The hostname/address of the pdu to which the settings apply',
machinetype => 'The pdu machine type',
modelnum => 'The pdu model number',
serialnum => 'The pdu serial number',
outletcount => 'The pdu outlet count',
},
},
switches => {
cols => [qw(switch snmpversion username password privacy auth linkports sshusername sshpassword protocol switchtype comments disable)],
keys => [qw(switch)],
@ -1255,6 +1268,17 @@ passed as argument rather than by table value',
disable => "Set to 'yes' or '1' to comment out this row.",
},
},
pduoutlet => {
cols => [qw(node pdu comments disable)],
keys => [qw(node)],
table_desc => 'Contains list of outlet numbers on the pdu each node is connected to.',
descriptions => {
node => 'The node name or group name.',
pdu => 'a comma-separated list of outlet number for each PDU, ex: pdu1:outlet1,pdu2:outlet1',
comments => 'Any user-written notes.',
disable => "Set to 'yes' or '1' to comment out this row.",
}
},
switch => {
cols => [qw(node switch port vlan interface comments disable)],
keys => [qw(node switch port)],
@ -2699,6 +2723,14 @@ my @nodeattrs = (
tabentry => 'websrv.password',
access_tabentry => 'websrv.node=attr:node',
},
######################
# pduoutlet table #
######################
{ attr_name => 'pdu',
tabentry => 'pduoutlet.pdu',
access_tabentry => 'pduoutlet.node=attr:node',
},
######################
# switch table #
######################
@ -2817,6 +2849,30 @@ my @nodeattrs = (
access_tabentry => 'hwinv.node=attr:node',
},
#########################
## pdu table #
#########################
{ attr_name => 'machinetype',
only_if => 'nodetype=pdu',
tabentry => 'pdu.machinetype',
access_tabentry => 'pdu.pdu=attr:node',
},
{ attr_name => 'modelnum',
only_if => 'nodetype=pdu',
tabentry => 'pdu.modelnum',
access_tabentry => 'pdu.pdu=attr:node',
},
{ attr_name => 'serialnum',
only_if => 'nodetype=pdu',
tabentry => 'pdu.serialnum',
access_tabentry => 'pdu.pdu=attr:node',
},
{ attr_name => 'outletcount',
only_if => 'nodetype=pdu',
tabentry => 'pdu.outletcount',
access_tabentry => 'pdu.pdu=attr:node',
},
#########################
## switches table #
#########################

View File

@ -50,6 +50,9 @@ my %usage = (
rpower noderange [stat|state|on|off|reset|boot]
docker specific:
rpower noderange [start|stop|restart|pause|unpause|state]
pdu specific:
rpower noderange [off|on|stat]
rpower noderange [pduoff|pduon|pdustat]
",
"rbeacon" =>
"Usage: rbeacon <noderange> [on|off|stat] [-V|--verbose]
@ -100,7 +103,9 @@ my %usage = (
zVM specific:
rinv noderange [all|config]
MIC specific:
rinv noderange [system|ver|board|core|gddr|all]",
rinv noderange [system|ver|board|core|gddr|all]
pdu specific:
rinv noderange ",
"rsetboot" =>
"Usage: rsetboot <noderange> [net|hd|cd|floppy|def|stat] [-V|--verbose] [-u] [-p]
rsetboot [-h|--help|-v|--version]",

View File

@ -32,6 +32,11 @@ B<rinv> I<noderange> {B<mtm>|B<serial>|B<mac>|B<bios>|B<diag>|B<mprom>|B<mparom>
B<rinv> I<noderange> [B<-t>]
=head2 pdu specific:
B<rinv> I<noderange>
=head2 zVM specific:
B<rinv> I<noderange> [B<config>|B<all>]

View File

@ -12,6 +12,8 @@ B<rpower> [B<-h>|B<--help>|B<-v>|B<--version>]
B<rpower> I<noderange> [B<on>|B<off>|B<softoff>|B<reset>|B<boot>|B<stat>|B<state>|B<status>|B<wake>|B<suspend> [B<-w> I<timeout>] [B<-o>] [B<-r>]]
B<rpower> I<noderange> [B<pduon>|B<pduoff>|B<pdustat>]
=head2 PPC (with IVM or HMC) specific:
B<rpower> I<noderange> [B<--nodeps>] {B<of>}
@ -54,6 +56,10 @@ B<rpower> I<noderange> [B<on>|B<off>|B<reset>|B<stat>|B<softoff>]
B<rpower> I<noderange> [B<start>|B<stop>|B<restart>|B<pause>|B<unpause>|B<state>]
=head2 pdu specific:
B<rpower> I<noderange> [B<stat>|B<off>|B<on>]
=head1 DESCRIPTION
B<rpower> controls the power for a single or range of nodes, via the out-of-band path.

View File

@ -233,6 +233,12 @@ sub process_command {
if (($command eq 'rpower') || ($command eq 'rnetboot')) {
my $subcommand = "temp";
if ($command eq 'rpower') { $subcommand = $request->{op}; }
#pdu commands will be handled in the pdu plugin
if(($subcmd eq 'pduoff') || ($subcmd eq 'pduon') || ($subcmd eq 'pdustat')){
return 0;
}
if (($global_check) && ($subcommand ne 'stat') && ($subcommand ne 'status') && ($subcommand ne 'state')) {
$check = 1;
my $noderange = $request->{node};

View File

@ -4400,6 +4400,11 @@ sub process_request {
if ($request->{moreinfo}) { $moreinfo = $request->{moreinfo}; }
else { $moreinfo = build_more_info($noderange, $callback); }
#pdu commands will be handled in the pdu plugin
if ($command eq "rpower" and grep(/^pduon|pduoff|pdustat$/, @exargs)) {
return;
}
if ($command eq "rpower" and grep(/^on|off|boot|reset|cycle$/, @exargs)) {
if (my ($index) = grep($exargs[$_] =~ /^--nodeps$/, 0 .. $#exargs)) {

View File

@ -406,6 +406,10 @@ sub process_request {
@exargs = ($request->{arg});
}
#pdu commands will be handled in the pdu plugin
if ($command eq "rpower" and grep(/^pduon|pduoff|pdustat/, @exargs)) {
return;
}
#my $sitetab = xCAT::Table->new('site');
#if($sitetab){
#(my $ref) = $sitetab->getAttribs({key => 'usehostnamesforvcenter'}, 'value');

View File

@ -646,6 +646,11 @@ sub process_request {
if ($request->{moreinfo}) { $moreinfo = $request->{moreinfo}; }
else { $moreinfo = build_more_info($noderange, $callback); }
#pdu commands will be handled in the pdu plugin
if ($command eq "rpower" and grep(/^pduon|pduoff|pdustat$/, @exargs)) {
return;
}
if ($command eq "rpower" and grep(/^on|off|boot|reset|cycle$/, @exargs)) {
if (my ($index) = grep($exargs[$_] =~ /^--nodeps$/, 0 .. $#exargs)) {

View File

@ -360,6 +360,12 @@ sub process_request {
if (ref($extrargs)) {
@exargs = @$extrargs;
}
#pdu commands will be handled in the pdu plugin
if (($extrargs->[0] eq 'pdustat') || ($extrargs->[0] eq 'pduon') || ($extrargs->[0] eq 'pduoff')) {
return;
}
my $ipmitab = xCAT::Table->new('ipmi');
my $ilouser = "USERID";

View File

@ -7681,6 +7681,11 @@ sub preprocess_request {
return 0;
}
#pdu commands will be handled in the pdu plugin
if(($subcmd eq 'pduoff') || ($subcmd eq 'pduon') || ($subcmd eq 'pdustat')){
return 0;
}
if (($subcmd ne 'reseat') && ($subcmd ne 'stat') && ($subcmd ne 'state') && ($subcmd ne 'status') && ($subcmd ne 'on') && ($subcmd ne 'off') && ($subcmd ne 'softoff') && ($subcmd ne 'nmi') && ($subcmd ne 'cycle') && ($subcmd ne 'reset') && ($subcmd ne 'boot') && ($subcmd ne 'wake') && ($subcmd ne 'suspend')) {
#$callback->({data=>["Unsupported command: $command $subcmd", $usage_string]});

View File

@ -3660,6 +3660,13 @@ sub process_request {
} else {
@exargs = ($request->{arg});
}
#pdu commands will be handled in the pdu plugin
if ($command eq "rpower" and grep(/^pduon|pduoff|pdustat/, @exargs)) {
return;
}
my $forcemode = 0;
my %orphans = ();
if ($command eq 'vmstatenotify') {

View File

@ -0,0 +1,383 @@
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#-------------------------------------------------------
=head1
xCAT plugin package to handle pdu
Supported command:
rpower
rinv
=cut
#-------------------------------------------------------
package xCAT_plugin::pdu;
BEGIN {
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr';
}
use lib "$::XCATROOT/lib/perl";
use xCAT::Table;
use xCAT::Utils;
use xCAT::FifoPipe;
use xCAT::MsgUtils;
use xCAT::State;
use xCAT::SvrUtils;
use xCAT::Usage;
use xCAT::NodeRange;
use Data::Dumper;
use Getopt::Long;
use File::Path;
use Term::ANSIColor;
use Time::Local;
use strict;
use Class::Struct;
use XML::Simple;
use Storable qw(dclone);
use SNMP;
my $VERBOSE = 0;
my %allerrornodes = ();
my $callback;
#-------------------------------------------------------
=head3 handled_commands
Return list of commands handled by this plugin
=cut
#-------------------------------------------------------
sub handled_commands
{
return {
rpower => ["nodehm:mgt","pduoutlet:pdu=\.\*"],
rinv => ["nodehm:mgt"],
nodeset => ["nodehm:mgt"],
};
}
#--------------------------------------------------------------------------------
=head3 preprocess_request
Parse the arguments and display the usage or the version string.
=cut
#--------------------------------------------------------------------------------
sub preprocess_request {
my $req = shift;
if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; }
my $callback=shift;
my @requests;
my $command = $req->{command}->[0];
my $noderange = $req->{node}; #Should be arrayref
my $extrargs = $req->{arg};
my @exargs=($req->{arg});
if (ref($extrargs)) {
@exargs=@$extrargs;
}
my $usage_string=xCAT::Usage->parseCommand($command, @exargs);
if ($usage_string) {
$callback->({data=>[$usage_string]});
$req = {};
return;
}
if (!$noderange) {
$usage_string = xCAT::Usage->getUsage($command);
$callback->({ data => $usage_string });
$req = {};
return;
}
my @result = ();
my $mncopy = {%$req};
push @result, $mncopy;
return \@result;
}
#-------------------------------------------------------
=head3 process_request
Process the command.
=cut
#-------------------------------------------------------
sub process_request
{
my $request = shift;
my $callback = shift;
my $subreq = shift;
my $command = $request->{command}->[0];
my $noderange = $request->{node}; #Should be arrayref
my $extrargs = $request->{arg};
my @exargs = ($request->{arg});
if (ref($extrargs)) {
@exargs = @$extrargs;
}
if( $command eq "rinv") {
#for higher performance, handle node in batch
return powerstat($noderange, $callback);
}elsif ($command eq "rpower") {
my $subcmd = $exargs[0];
if(($subcmd eq 'on') || ($subcmd eq 'off') || ($subcmd eq 'stat')){
#-------------------------------------------
#there are 2 cases will enter this black
#one is if node's mgt is pdu
#another is if node has pdu attribute but mgt isn't pdu
#if the node has pdu attribute but mgt isn't pdu,
#should do nothing for this node, let other plugin to hanle this node
#-------------------------------------------
my @allpdunodes=();
my $nodehm = xCAT::Table->new('nodehm');
my $nodehmhash = $nodehm->getNodesAttribs($noderange, ['mgt']);
foreach my $node (@$noderange) {
if($nodehmhash->{$node}->[0]->{mgt} eq 'pdu'){
push @allpdunodes, $node;
}
}
return powerpdu(\@allpdunodes, $subcmd, $callback);
}elsif(($subcmd eq 'pduoff') || ($subcmd eq 'pduon') || ($subcmd eq 'pdustat')){
#if one day, pdu node have pdu attribute, handle in this section too
return powerpduoutlet($noderange, $subcmd, $callback);
}else{
$callback->({ errorcode => [1],error => "The input command $subcmd is not support for pdu"});
}
}elsif($command eq "nodeset") {
$callback->({ errorcode => [1],error => "The input $command is not support for pdu"});
}else{
#reserve for other new command in future
}
return;
}
#-------------------------------------------------------
=head3 powerpdu
Process power command (stat/off/on) for pdu/pdus
=cut
#-------------------------------------------------------
sub powerpdu {
my $noderange = shift;
my $subcmd = shift;
my $callback = shift;
my $outletnum = ".1.3.6.1.4.1.2.6.223.8.2.1.0";
if ($subcmd eq "stat") {
return powerstat($noderange, $callback);
}
foreach my $node (@$noderange) {
my $session = connectTopdu($node,$callback);
my $count = $session->get("$outletnum");
my $value;
my $statstr;
if ($subcmd eq "off") {
$value = 0;
$statstr = "off";
} else {
$value = 1;
$statstr = "on";
}
for (my $outlet =1; $outlet <= $count; $outlet++)
{
outletpower($session, $outlet, $value);
if ($session->{ErrorStr}) {
$callback->({ error => "$session->{ErrorStr}"});
} else {
my $output = " outlet $outlet is $statstr";
xCAT::SvrUtils::sendmsg($output, $callback, $node, %allerrornodes);
}
}
}
}
#-------------------------------------------------------
=head3 powerpduoutlet
Process power command (pdustat/pduoff/pduon) for compute nodes,
the pdu attribute needs to be set
=cut
#-------------------------------------------------------
sub powerpduoutlet {
my $noderange = shift;
my $subcmd = shift;
my $callback = shift;
my $output;
my $value;
my $statstr;
my $oid = ".1.3.6.1.4.1.2.6.223.8.2.2.1.11";
my $type = "INTEGER";
my $tmpnodestr = join(",", @$noderange);
my $nodetab = xCAT::Table->new('pduoutlet');
my $nodepdu = $nodetab->getNodesAttribs($noderange,['pdu']);
foreach my $node (@$noderange) {
# the pdu attribute needs to be set
if(! $nodepdu->{$node}->[0]->{pdu}){
$callback->({ error => "$node: without pdu attribute"});
next;
}
my @pdus = split /,/, $nodepdu->{$node}->[0]->{pdu};
foreach my $pdu_outlet (@pdus) {
my ($pdu, $outlet) = split /:/, $pdu_outlet;
my $session = connectTopdu($pdu,$callback);
my $cmd;
if ($subcmd eq "pdustat") {
$statstr=outletstat($session, $outlet);
} elsif ($subcmd eq "pduoff") {
$value = 0;
$statstr = "off";
outletpower($session, $outlet, $value);
} elsif ($subcmd eq "pduon") {
$value = 1;
$statstr = "on";
outletpower($session, $outlet, $value);
} else {
$callback->({ error => "$subcmd is not support"});
}
if ($session->{ErrorStr}) {
$callback->({ error => "$session->{ErrorStr}"});
} else {
$output = "$pdu outlet $outlet is $statstr";
xCAT::SvrUtils::sendmsg($output, $callback, $node, %allerrornodes);
}
}
}
}
#-------------------------------------------------------
=head3 outletpower
Process power command for one pdu outlet,
=cut
#-------------------------------------------------------
sub outletpower {
my $session = shift;
my $outlet = shift;
my $value = shift;
my $oid = ".1.3.6.1.4.1.2.6.223.8.2.2.1.11";
my $type = "INTEGER";
my $varbind = new SNMP::Varbind([ $oid, $outlet, $value, $type ]);
return $session->set($varbind);
}
#-------------------------------------------------------
=head3 powerstat
Process command to query status of pdu
=cut
#-------------------------------------------------------
sub powerstat {
my $noderange = shift;
my $callback = shift;
my $output;
my $outletnum = ".1.3.6.1.4.1.2.6.223.8.2.1.0";
foreach my $pdu (@$noderange) {
my $session = connectTopdu($pdu,$callback);
my $count = $session->get("$outletnum");
for (my $outlet =1; $outlet <= $count; $outlet++)
{
my $statstr = outletstat($session, $outlet);
my $msg = " outlet $outlet is $statstr";
xCAT::SvrUtils::sendmsg($msg, $callback, $pdu, %allerrornodes);
}
}
}
#-------------------------------------------------------
=head3 outletstat
Process command to query status of one pdu outlet
=cut
#-------------------------------------------------------
sub outletstat {
my $session = shift;
my $outlet = shift;
my $oid = ".1.3.6.1.4.1.2.6.223.8.2.2.1.11";
my $output;
my $statstr;
$output = $session->get("$oid.$outlet");
if ($output eq 1) {
$statstr = "on";
} else {
$statstr = "off";
}
return $statstr;
}
#-------------------------------------------------------
=head3 connectTopdu
connect pdu via snmp session
=cut
#-------------------------------------------------------
sub connectTopdu {
my $pdu = shift;
my $callback = shift;
my $snmpver = "1";
my $community = "public";
my $session;
my $msg = "connectTopdu";
$session = new SNMP::Session(
DestHost => $pdu,
Version => $snmpver,
Community => $community,
UseSprintValue => 1,
);
unless ($session) {
$msg = "Failed to connect to $pdu";
xCAT::SvrUtils::sendmsg($msg, $callback, $pdu, %allerrornodes);
return;
}
return $session;
}
1;

View File

@ -103,6 +103,7 @@ sub preprocess_request {
my $command = $request->{command}->[0];
my $extraargs = $request->{arg};
if ($extraargs) {
@ARGV = @{$extraargs};
my $help;
@ -125,6 +126,11 @@ sub preprocess_request {
}
}
#pdu commands will be handled in the pdu plugin
if (($extrargs->[0] eq 'pdustat') || ($extrargs->[0] eq 'pduon') || ($extrargs->[0] eq 'pduoff')) {
return;
}
# Read the user password for the rhevm
# Only support the general password in passwd table
my $passtab = xCAT::Table->new('passwd');

View File

@ -704,6 +704,12 @@ sub process_request {
} else {
@exargs = ($request->{arg});
}
#pdu commands will be handled in the pdu plugin
if ($command eq "rpower" and grep(/^pduon|pduoff|pdustat$/, @exargs)) {
return;
}
if ($command eq 'revacuate') {
my $newnoderange;
foreach (@$noderange) {

View File

@ -2317,6 +2317,11 @@ sub powerVM {
# Output string
my $out;
##pdu commands will be handled in the pdu plugin
if ($args->[0] eq 'pduon' || $args->[0] eq 'pduoff' || $args->[0] eq 'pdustat') {
return;
}
# Power on virtual server
if ($args->[0] eq 'on') {