2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-05-23 20:22:05 +00:00
Victor Hu 6133755f27 Seems like for discovery of FSP and TUL servers, there is no bmcuser
name so adding the code from commit 3f54b456d2f2479489386b9291fa1867dd22c32d
and d82e14b56656482279d58e38295a9900e82ba056 to set the default user breaks
that function.  Reverting back to the old ways
2016-08-30 13:42:21 -04:00

964 lines
28 KiB
Perl

# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#-------------------------------------------------------
=head1
xCAT plugin package to handle BMC discovery
=cut
#-------------------------------------------------------
package xCAT_plugin::bmcdiscover;
BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use lib "$::XCATROOT/lib/perl";
use IO::Socket;
use Thread qw(yield);
use POSIX "WNOHANG";
use Storable qw(store_fd fd_retrieve);
use strict;
use warnings "all";
use Getopt::Long;
use xCAT::Table;
use xCAT::Utils;
use xCAT::MsgUtils;
use Getopt::Long;
use Data::Dumper;
use File::Basename;
use File::Path;
use Cwd;
my $nmap_path;
my $debianflag = 0;
my $tempstring = xCAT::Utils->osver();
if ($tempstring =~ /debian/ || $tempstring =~ /ubuntu/) {
$debianflag = 1;
}
my $parent_fd;
my $bmc_user;
my $bmc_pass;
#-------------------------------------------------------
=head3 handled_commands
Return list of commands handled by this plugin
=cut
#-------------------------------------------------------
sub handled_commands
{
return {
bmcdiscover => "bmcdiscover",
};
}
#-------------------------------------------------------
=head3 process_request
Process the command
=cut
#-------------------------------------------------------
sub process_request
{
my $request = shift;
my $callback = shift;
my $request_command = shift;
$::CALLBACK = $callback;
#$::args = $request->{arg};
unless (defined($request->{arg})) {
bmcdiscovery_usage();
return 2;
}
@ARGV = @{ $request->{arg} };
if ($#ARGV == -1) {
return 2;
}
my $command = $request->{command}->[0];
my $rc;
if ($command eq "bmcdiscover") {
$rc = bmcdiscovery($request, $callback, $request_command);
} else {
$callback->({ error => ["Error: $command not found in this module."], errorcode => [1] });
return 1;
}
}
#----------------------------------------------------------------------------
=head3 bmcdiscover_usage
Display the bmcdiscover usage
=cut
#-----------------------------------------------------------------------------
sub bmcdiscovery_usage {
my $rsp;
push @{ $rsp->{data} }, "\nbmcdiscover - Discover BMC (Baseboard Management Controller) using the specified scan method\n";
push @{ $rsp->{data} }, "Usage:";
push @{ $rsp->{data} }, "\tbmcdiscover [-?|-h|--help]";
push @{ $rsp->{data} }, "\tbmcdiscover [-v|--version]";
push @{ $rsp->{data} }, "\tbmcdiscover [-s scan_method] [-u bmc_user] [-p bmc_passwd] [-z] [-w] [-t] --range ip_range\n";
push @{ $rsp->{data} }, "\tCheck BMC administrator User/Password:\n";
push @{ $rsp->{data} }, "\t\tbmcdiscover -u bmc_user -p bmc_password -i bmc_ip --check\n";
push @{ $rsp->{data} }, "\tDisplay the BMC IP configuration:\n";
push @{ $rsp->{data} }, "\t\tbmcdiscover [-u bmc_user] [-p bmc_passwd] -i bmc_ip --ipsource";
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
return 0;
}
#----------------------------------------------------------------------------
=head3 bmcdiscovery_processargs
Process the bmcdiscovery command line
Returns:
0 - OK
1 - just print version
2 - just print help
3 - error
=cut
#-----------------------------------------------------------------------------
sub bmcdiscovery_processargs {
#if ( defined ($::args) && @{$::args} ){
# @ARGV = @{$::args};
#}
my $request = shift;
my $callback = shift;
my $request_command = shift;
my $rc = 0;
# parse the options
# options can be bundled up like -v, flag unsupported options
Getopt::Long::Configure("bundling", "no_ignore_case", "no_pass_through");
my $getopt_success = Getopt::Long::GetOptions(
'help|h|?' => \$::opt_h,
's=s' => \$::opt_M,
'm=s' => \$::opt_M,
'range=s' => \$::opt_R,
'bmcip|i=s' => \$::opt_I,
'z' => \$::opt_Z,
'w' => \$::opt_W,
'check' => \$::opt_C,
'bmcuser|u=s' => \$::opt_U,
'bmcpasswd|p=s' => \$::opt_P,
'ipsource' => \$::opt_S,
'version|v' => \$::opt_v,
't' => \$::opt_T,
);
if (!$getopt_success) {
return 3;
}
#########################################
# This command is for linux
#########################################
if ($^O ne 'linux') {
my $rsp = {};
push @{ $rsp->{data} }, "The bmcdiscovery command is only supported on Linux.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
##########################################
# Option -h for Help
##########################################
if (defined($::opt_h)) {
bmcdiscovery_usage;
return 0;
}
#########################################
# Option -v for version
#########################################
if (defined($::opt_v)) {
create_version_response('bmcdiscover');
# no usage - just exit
return 1;
}
#########################################
# Option -s -r should be together
######################################
if (defined($::opt_R))
{
# Option -c should not be used with -r
if (defined($::opt_C)) {
my $msg = "The 'check' and 'range' option cannot be used together.";
my $rsp = {};
push @{ $rsp->{data} }, "$msg";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 2;
}
######################################
# check if there is nmap or not
######################################
if (-x '/usr/bin/nmap')
{
$nmap_path = "/usr/bin/nmap";
}
elsif (-x '/usr/local/bin/nmap')
{
$nmap_path = "/usr/local/bin/nmap";
}
else
{
my $rsp;
push @{ $rsp->{data} }, "\tThere is no nmap in /usr/bin/ or /usr/local/bin/. \n ";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
#
# Get the default bmc account from passwd table, this is only done for the
# discovery process
#
($bmc_user, $bmc_pass) = bmcaccount_from_passwd();
# overwrite the default password if one is provided
if ($::opt_U) {
$bmc_user = $::opt_U;
} else {
# If password is provided, but no user, set the user to blank
# Support older FSP and Tuletta machines
$bmc_user = '';
}
if ($::opt_P) {
$bmc_pass = $::opt_P;
}
scan_process($::opt_M, $::opt_R, $::opt_Z, $::opt_W, $request_command);
return 0;
}
if (defined($::opt_C) && defined($::opt_S)) {
my $msg = "The 'check' and 'ipsource' option cannot be used together.";
my $rsp = {};
push @{ $rsp->{data} }, "$msg";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 2;
}
#########################################################
# --check option, requires -i, -u, and -p to be specified
#########################################################
if (defined($::opt_C)) {
if (defined($::opt_P) && defined($::opt_U) && defined($::opt_I)) {
my $res = check_auth_process($::opt_I, $::opt_U, $::opt_P);
return $res;
}
else {
my $msg = "";
if (!defined($::opt_I)) {
$msg = "The check option requires a BMC IP. Specify the IP using the -i|--bmcip option.";
} elsif (!defined($::opt_U)) {
$msg = "The check option requires a user. Specify the user with the -u|--bmcuser option.";
} elsif (!defined($::opt_P)) {
$msg = "The check option requires a password. Specify the password with the -p|--bmcpasswd option.";
}
my $rsp = {};
push @{ $rsp->{data} }, "$msg";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 2;
}
}
####################################################
# --ipsource option, requires -i, -p to be specified
####################################################
if (defined($::opt_S)) {
if (defined($bmc_user) && defined($bmc_pass) && defined($::opt_I)) {
my $res = get_bmc_ip_source($::opt_I, $bmc_user, $bmc_pass);
return $res;
}
else {
my $msg = "";
if (!defined($::opt_I)) {
$msg = "The ipsource option requires a BMC IP. Specify the IP using the -i|--bmcip option.";
} elsif (!defined($::opt_P)) {
$msg = "The ipsource option requires a password. Specify the password with the -p|--bmcpasswd option.";
}
my $rsp = {};
push @{ $rsp->{data} }, "$msg";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 2;
}
}
#########################################
# Other attributes are not allowed
#########################################
return 4;
}
my $bmc_str1 = "RAKP 2 message indicates an error : unauthorized name";
my $bmc_resp1 = "Wrong BMC username";
my $bmc_str2 = "RAKP 2 HMAC is invalid";
my $bmc_resp2 = "Wrong BMC password";
#----------------------------------------------------------------------------
=head3 get_bmc_ip_source
get bmc ip address source
Returns:
0 - OK
2 - Error
=cut
#-----------------------------------------------------------------------------
sub get_bmc_ip_source {
my $bmcip = shift;
my $bmcuser = shift;
my $bmcpw = shift;
my $callback = $::CALLBACK;
my $pcmd;
if ($bmcuser eq "none") {
$pcmd = "/opt/xcat/bin/ipmitool-xcat -vv -I lanplus -P $bmcpw -H $bmcip lan print ";
}
else {
$pcmd = "/opt/xcat/bin/ipmitool-xcat -vv -I lanplus -U $bmcuser -P $bmcpw -H $bmcip lan print ";
}
my $output = xCAT::Utils->runcmd("$pcmd", -1);
if ($output =~ "IP Address Source") {
# success case
my $rsp = {};
my $ipsource = `echo "$output"|grep "IP Address Source"`;
chomp($ipsource);
push @{ $rsp->{data} }, "$ipsource";
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
return 0;
}
else {
my $rsp = {};
if ($output =~ $bmc_str1) {
# Error: RAKP 2 message indicates an error : unauthorized name <== incorrect username
push @{ $rsp->{data} }, "$bmc_resp1";
} elsif ($output =~ $bmc_str2) {
# Error: RAKP 2 HMAC is invalid <== incorrect password
push @{ $rsp->{data} }, "$bmc_resp2";
} else {
# all other errors
push @{ $rsp->{data} }, "Error: Can not find IP Address Source";
}
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 2;
}
}
#----------------------------------------------------------------------------
=head3 check_auth_process
check bmc user and password
Returns:
0 - OK
2 - Error
=cut
#-----------------------------------------------------------------------------
sub check_auth_process {
my $bmcip = shift;
my $bmcuser = shift;
my $bmcpw = shift;
my $bmc_str4 = "BMC Session ID";
my $callback = $::CALLBACK;
my $icmd;
if ($bmcuser eq "none") {
$icmd = "/opt/xcat/bin/ipmitool-xcat -vv -I lanplus -P $bmcpw -H $bmcip chassis status ";
}
else {
$icmd = "/opt/xcat/bin/ipmitool-xcat -vv -I lanplus -U $bmcuser -P $bmcpw -H $bmcip chassis status ";
}
my $output = xCAT::Utils->runcmd("$icmd", -1);
if ($output =~ "Set Session Privilege Level to ADMINISTRATOR") {
# Success case
my $rsp = {};
push @{ $rsp->{data} }, "Correct ADMINISTRATOR";
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
return 0;
} else {
# handle the various error scenarios
my $rsp = {};
if ($output =~ $bmc_str1) {
# Error: RAKP 2 message indicates an error : unauthorized name <== incorrect username
push @{ $rsp->{data} }, "$bmc_resp1";
}
elsif ($output =~ $bmc_str2) {
# Error: RAKP 2 HMAC is invalid <== incorrect password
push @{ $rsp->{data} }, "$bmc_resp2";
}
elsif ($output !~ $bmc_str4) {
# Did not find "BMC Session ID" in the response
push @{ $rsp->{data} }, "Not a BMC, please verify the correct IP address";
}
else {
push @{ $rsp->{data} }, "Unknown Error: $output";
}
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 2;
}
}
#----------------------------------------------------------------------------
=head3 scan_process
Process the bmcdiscovery command line
Returns:
0 - OK
1 - just print version
2 - just print help
3 - error
=cut
#-----------------------------------------------------------------------------
sub scan_process {
my $method = shift;
my $range = shift;
my $opz = shift;
my $opw = shift;
my $request_command = shift;
my $callback = $::CALLBACK;
my $children; # The number of child process
my %sp_children; # Record the pid of child process
my $bcmd;
my $sub_fds = new IO::Select; # Record the parent fd for each child process
if (!defined($method))
{
$method = "nmap";
}
# Handle commas in $range for nmap
$range =~ tr/,/ /;
my $ip_list;
############################################################
# get live ip list
###########################################################
if ($method eq "nmap") {
#check nmap version first
my $nmap_version = xCAT::Utils->get_nmapversion();
# the output of nmap is different for version under 5.10
if (xCAT::Utils->version_cmp($nmap_version, "5.10") < 0) {
$bcmd = join(" ", $nmap_path, " -sP -n $range | grep \"appears to be up\" |cut -d ' ' -f2 |tr -s '\n' ' ' ");
} else {
$bcmd = join(" ", $nmap_path, " -sn -n $range | grep -B1 up | grep \"Nmap scan report\" |cut -d ' ' -f5 |tr -s '\n' ' ' ");
}
$ip_list = xCAT::Utils->runcmd("$bcmd", -1);
if ($::RUNCMD_RC != 0) {
my $rsp = {};
push @{ $rsp->{data} }, "Nmap scan is failed.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 2;
}
}
else
{
my $rsp = {};
push @{ $rsp->{data} }, "The bmcdiscover method should be nmap.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 2;
}
my $live_ip = split_comma_delim_str($ip_list);
if (scalar(@{$live_ip}) > 0)
{
###############################
# Set the signal handler for ^c
###############################
$SIG{TERM} = $SIG{INT} = sub {
foreach (keys %sp_children) {
kill 2, $_;
}
$SIG{ALRM} = sub {
while (wait() > 0) {
yield;
}
exit @_;
};
alarm(1); # wait 1s for grace exit
};
######################################################
# Set the singal handler for child process finished it's work
######################################################
$SIG{CHLD} = sub {
my $cpid;
while (($cpid = waitpid(-1, WNOHANG)) > 0) {
if ($sp_children{$cpid}) {
delete $sp_children{$cpid};
$children--;
}
}
};
for (my $i = 0 ; $i < scalar(@{$live_ip}) ; $i++) {
# fork a sub process to handle the communication with service processor
$children++;
my $cfd;
# the $parent_fd will be used by &send_rep() to send response from child process to parent process
socketpair($parent_fd, $cfd, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!";
$cfd->autoflush(1);
$parent_fd->autoflush(1);
my $child = xCAT::Utils->xfork;
if ($child == 0) {
close($cfd);
$callback = \&send_rep;
# Set child process default, if not the function runcmd may return error
$SIG{CHLD} = 'DEFAULT';
bmcdiscovery_ipmi(${$live_ip}[$i], $opz, $opw, $request_command);
exit 0;
} else {
# in the main process, record the created child process and add parent fd for the child process to an IO:Select object
# the main process will check all the parent fd and receive response
$sp_children{$child} = 1;
close($parent_fd);
$sub_fds->add($cfd);
}
do {
sleep(1);
} until ($children < 32);
}
#################################################
# receive data from child processes
################################################
while ($sub_fds->count > 0 or $children > 0) {
forward_data($callback, $sub_fds);
}
while (forward_data($callback, $sub_fds)) {
}
}
else
{
my $rsp = {};
push @{ $rsp->{data} }, "No bmc found.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 2;
}
}
#----------------------------------------------------------------------------
=head3 format_stanza
list the stanza format for node
Arguments:
bmc ip
Returns:
lists as stanza format for nodes
=cut
#--------------------------------------------------------------------------------
sub format_stanza {
my $node = shift;
my $data = shift;
my ($bmcip, $bmcmtm, $bmcserial, $bmcuser, $bmcpass, $nodetype, $hwtype) = split(/,/, $data);
my $result;
if (defined($bmcip)) {
$result .= "$node:\n\tobjtype=node\n";
$result .= "\tgroups=all\n";
$result .= "\tbmc=$bmcip\n";
$result .= "\tcons=ipmi\n";
$result .= "\tmgt=ipmi\n";
if ($bmcmtm) {
$result .= "\tmtm=$bmcmtm\n";
}
if ($bmcserial) {
$result .= "\tserial=$bmcserial\n";
}
if ($bmcuser) {
$result .= "\tbmcusername=$bmcuser\n";
}
if ($bmcpass) {
$result .= "\tbmcpassword=$bmcpass\n";
}
if ($nodetype && $hwtype) {
$result .= "\tnodetype=$nodetype\n";
$result .= "\thwtype=$hwtype\n";
}
my $rsp = {};
push @{ $rsp->{data} }, "$result";
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
}
return ($result);
}
#----------------------------------------------------------------------------
=head3 write_to_xcatdb
write node definition into xcatdb
Arguments:
$node_stanza:
Returns:
=cut
#--------------------------------------------------------------------------------
sub write_to_xcatdb {
my $node = shift;
my $data = shift;
my ($bmcip, $bmcmtm, $bmcserial, $bmcuser, $bmcpass, $nodetype, $hwtype) = split(/,/, $data);
my $request_command = shift;
my $ret;
$ret = xCAT::Utils->runxcmd({ command => ['chdef'], arg => [ '-t', 'node', '-o', $node, "bmc=$bmcip", "cons=ipmi", "mgt=ipmi", "mtm=$bmcmtm", "serial=$bmcserial", "bmcusername=$bmcuser", "bmcpassword=$bmcpass", "nodetype=$nodetype", "hwtype=$hwtype", "groups=all" ] }, $request_command, 0, 1);
if ($::RUNCMD_RC != 0) {
my $rsp = {};
push @{ $rsp->{data} }, "create or modify node is failed.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 2;
}
}
#----------------------------------------------------------------------------
=head3 send_rep
DESCRIPTION:
Send date from forked child process to parent process.
This subroutine will be replace the original $callback in the forked child process
ARGUMENTS:
$resp - The response which generated in xCAT::Utils->message();
=cut
#----------------------------------------------------------------------------
sub send_rep {
my $resp = shift;
unless ($resp) { return; }
store_fd($resp, $parent_fd);
}
#----------------------------------------------------------------------------
=head3 forward_data
DESCRIPTION:
Receive data from forked child process and call the original $callback to forward data to xcat client
=cut
#----------------------------------------------------------------------------
sub forward_data {
my $callback = shift;
my $fds = shift;
my @ready_fds = $fds->can_read(1);
my $rfh;
my $rc = @ready_fds;
foreach $rfh (@ready_fds) {
my $data;
my $responses;
eval {
$responses = fd_retrieve($rfh);
};
if ($@ and $@ =~ /^Magic number checking on storable file/) { #this most likely means we ran over the end of available input
$fds->remove($rfh);
close($rfh);
} else {
eval { print $rfh "ACK\n"; }; #Ignore ack loss due to child giving up and exiting, we don't actually explicitly care about the acks
$callback->($responses);
}
}
yield; #Try to avoid useless iterations as much as possible
return $rc;
}
#----------------------------------------------------------------------------
=head3 split_comma_delim_str
Split comma-delimited list of strings into an array.
Arguments: comma-delimited string
Returns: Returns list of strings (ref)
=cut
#-----------------------------------------------------------------------------
sub split_comma_delim_str {
my $input_str = shift;
my @result = split(/ /, $input_str);
return \@result;
}
#----------------------------------------------------------------------------
=head3 create_version_response
Create a response containing the command name and version
=cut
#-----------------------------------------------------------------------------
sub create_version_response {
my $command = shift;
my $rsp;
my $version = xCAT::Utils->Version();
push @{ $rsp->{data} }, "$command - xCAT $version";
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
}
#----------------------------------------------------------------------------
=head3 create_error_response
Create a response containing a single error message
Arguments: error message
=cut
#-----------------------------------------------------------------------------
sub create_error_response {
my $error_msg = shift;
my $rsp;
push @{ $rsp->{data} }, $error_msg;
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
}
#----------------------------------------------------------------------------
=head3 bmcdiscovery
Support for discovering bmc
Returns:
0 - OK
1 - help
2 - error
=cut
#-----------------------------------------------------------------------------
sub bmcdiscovery {
my $request = shift;
my $callback = shift;
my $request_command = shift;
my $rc = 0;
##############################################################
# process the command line
# 0=success, 1=version, 2=error for check_auth_, other=error
##############################################################
$rc = bmcdiscovery_processargs($request, $callback, $request_command);
if ($rc != 0) {
if ($rc != 1)
{
if ($rc != 2)
{
bmcdiscovery_usage(@_);
}
}
return ($rc - 1);
}
#scan_process($::opt_M,$::opt_R);
return $rc;
}
#----------------------------------------------------------------------------
=head3 get bmc account in passwd table
Returns:
username/password pair
Notes:
The default username/password is ADMIN/admin
=cut
#----------------------------------------------------------------------------
sub bmcaccount_from_passwd {
my $bmcusername = "ADMIN";
my $bmcpassword = "admin";
my $passwdtab = xCAT::Table->new("passwd", -create => 0);
if ($passwdtab) {
my $bmcentry = $passwdtab->getAttribs({ 'key' => 'ipmi' }, 'username', 'password');
if (defined($bmcentry)) {
$bmcusername = $bmcentry->{'username'};
$bmcpassword = $bmcentry->{'password'};
unless ($bmcusername) {
$bmcusername = '';
}
unless ($bmcpassword) {
$bmcpassword = '';
}
}
}
return ($bmcusername, $bmcpassword);
}
#----------------------------------------------------------------------------
=head3 bmcdiscovery_ipmi
Support for discovering bmc using ipmi
Returns:
if it is bmc, it returns bmc ip or host;
if it is not bmc, it returns nothing;
=cut
#-----------------------------------------------------------------------------
sub bmcdiscovery_ipmi {
my $ip = shift;
my $opz = shift;
my $opw = shift;
my $request_command = shift;
my $node = sprintf("node-%08x", unpack("N*", inet_aton($ip)));
my $bmcstr = "BMC Session ID";
my $bmcusername = '';
my $bmcpassword = '';
if ($bmc_user) {
$bmcusername = "-U $bmc_user";
}
if ($bmc_pass) {
$bmcpassword = "-P $bmc_pass";
}
my $icmd = "/opt/xcat/bin/ipmitool-xcat -vv -I lanplus $bmcusername $bmcpassword -H $ip chassis status ";
my $output = xCAT::Utils->runcmd("$icmd", -1);
if ($output =~ $bmcstr) {
# The output contains System Power indicated the username/password is correct, then try to get MTMS
if ($output =~ /System Power\s*:\s*\S*/) {
my $mtm = '';
my $serial = '';
# For system X and Tuleta, the fru 0 will contain the MTMS; For firestone, fru 3; For habanero, fru 2
my @fru_num = (0, 2, 3);
foreach my $fru_cmd_num (@fru_num) {
my $fru_cmd = "$::XCATROOT/bin/ipmitool-xcat -I lanplus $bmcusername $bmcpassword " .
"\-H $ip fru print $fru_cmd_num";
my @fru_output_array = xCAT::Utils->runcmd($fru_cmd, -1);
if (($::RUNCMD_RC eq 0) && @fru_output_array) {
my $fru_output = join(" ", @fru_output_array);
if ($fru_cmd_num == 0) {
if (($fru_output =~ /Product Part Number :\s*(\S*).*Product Serial :\s*(\S*)/)) {
$mtm = $1;
$serial = $2;
last;
}
}
else {
if (($fru_output =~ /Chassis Part Number\s*:\s*(\S*).*Chassis Serial\s*:\s*(\S*)/)) {
$mtm = $1;
$serial = $2;
last;
}
}
}
}
$ip .= ",$mtm";
$ip .= ",$serial";
if ($::opt_P) {
if ($::opt_U) {
$ip .= ",$::opt_U,$::opt_P";
} else {
$ip .= ",,$::opt_P";
}
} else {
$ip .= ",,";
}
if ($::opt_T) {
$ip .= ",mp,bmc";
}
if ($mtm and $serial) {
$node = "node-$mtm-$serial";
$node =~ s/(.*)/\L$1/g;
}
} elsif ($output =~ /error : unauthorized name/) {
xCAT::MsgUtils->message("E", { data => ["BMC username is incorrect for $ip"] }, $::CALLBACK);
return 1;
} elsif ($output =~ /RAKP \S* \S* is invalid/) {
xCAT::MsgUtils->message("E", { data => ["BMC password is incorrect for $ip"] }, $::CALLBACK);
return 1;
}
if (defined($opz) || defined($opw))
{
format_stanza($node, $ip);
if (defined($opw))
{
write_to_xcatdb($node, $ip, $request_command);
}
}
else {
my $rsp = {};
push @{ $rsp->{data} }, "$ip";
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
}
}
}
1;