HMC alternative: FSPflash (firmware upgrade -- disruptive ,commit, recover)
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@4842 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
parent
12f6766ee4
commit
79faedd0ea
648
perl-xCAT/xCAT/FSPflash.pm
Normal file
648
perl-xCAT/xCAT/FSPflash.pm
Normal file
@ -0,0 +1,648 @@
|
||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
package xCAT::FSPflash;
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR);
|
||||
use xCAT::Usage;
|
||||
use xCAT::PPCinv;
|
||||
use xCAT::DSHCLI;
|
||||
use xCAT::Table;
|
||||
use Getopt::Long;
|
||||
use File::Spec;
|
||||
use xCAT::PPCrflash;
|
||||
use Data::Dumper;
|
||||
use xCAT::Utils;
|
||||
use xCAT::FSPinv;
|
||||
use POSIX "WNOHANG";
|
||||
use Storable qw(freeze thaw);
|
||||
use Thread qw(yield);
|
||||
|
||||
my $packages_dir= ();
|
||||
my $activate = ();
|
||||
my $verbose = 0;
|
||||
$::POWER_DEST_DIR = "/tmp";
|
||||
my $release_level;
|
||||
my $active_level;
|
||||
my @dirlist;
|
||||
|
||||
#######################################
|
||||
# This flag tracks the operation to be performed. If set, it means we need
|
||||
# to commit a previously applied update or else recover from one.
|
||||
#######################################
|
||||
my $housekeeping = undef;
|
||||
|
||||
#####################################
|
||||
#For -V|--verbose,put the $msg into @value
|
||||
###################################
|
||||
sub dpush {
|
||||
my $value = shift;
|
||||
my $msg = shift;
|
||||
|
||||
if($verbose == 1) {
|
||||
push(@$value,$msg);
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Parse the command line for options and operands
|
||||
##########################################################################
|
||||
sub parse_args {
|
||||
xCAT::PPCrflash::parse_args(@_);
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Invokes the callback with the specified message
|
||||
##########################################################################
|
||||
sub send_msg {
|
||||
|
||||
my $request = shift;
|
||||
my $ecode = shift;
|
||||
my %output;
|
||||
|
||||
#################################################
|
||||
# Called from child process - send to parent
|
||||
#################################################
|
||||
if ( exists( $request->{pipe} )) {
|
||||
my $out = $request->{pipe};
|
||||
|
||||
$output{errorcode} = $ecode;
|
||||
$output{data} = \@_;
|
||||
print $out freeze( [\%output] );
|
||||
print $out "\nENDOFFREEZE6sK4ci\n";
|
||||
}
|
||||
#################################################
|
||||
# Called from parent - invoke callback directly
|
||||
#################################################
|
||||
elsif ( exists( $request->{callback} )) {
|
||||
my $callback = $request->{callback};
|
||||
|
||||
$output{errorcode} = $ecode;
|
||||
$output{data} = \@_;
|
||||
$callback->( \%output );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------#
|
||||
# get_lic_filenames - construct and validate the lup filenames for each #
|
||||
# each node #
|
||||
#-------------------------------------------------------------------------#
|
||||
#
|
||||
sub get_lic_filenames {
|
||||
my $mtms = shift;
|
||||
my $upgrade_required = 0;
|
||||
my $msg = undef;
|
||||
my $filename;
|
||||
|
||||
if(! -d $packages_dir) {
|
||||
$msg = "The directory $packages_dir doesn't exist!";
|
||||
return ("","","", $msg, -1);
|
||||
}
|
||||
|
||||
#print "opening directory and reading names\n";
|
||||
opendir DIRHANDLE, $packages_dir;
|
||||
@dirlist= readdir DIRHANDLE;
|
||||
closedir DIRHANDLE;
|
||||
|
||||
@dirlist = File::Spec->no_upwards( @dirlist );
|
||||
|
||||
# Make sure we have some files to process
|
||||
#
|
||||
if( !scalar( @dirlist ) ) {
|
||||
$msg = "directory $packages_dir is empty";
|
||||
return ("","","",$msg, -1);
|
||||
}
|
||||
|
||||
$release_level =~/(\w{4})(\d{3})/;
|
||||
my $pns = $1;
|
||||
my $fff = $2;
|
||||
|
||||
#Find the latest version lic file
|
||||
@dirlist = grep /\.rpm$/, @dirlist;
|
||||
@dirlist = grep /$1/, @dirlist;
|
||||
if( !scalar( @dirlist ) ) {
|
||||
$msg = "There isn't a package suitable for $mtms";
|
||||
return ("","","",$msg, -1);
|
||||
}
|
||||
if( scalar(@dirlist) > 1) {
|
||||
# Need to find the latest version package.
|
||||
@dirlist =reverse sort(@dirlist);
|
||||
my $t = "\n";
|
||||
foreach $t(@dirlist) {
|
||||
$msg =$msg."$t\t";
|
||||
}
|
||||
}
|
||||
|
||||
$filename = File::Spec->catfile( $packages_dir, $dirlist[0] );
|
||||
$dirlist[0] =~ /(\w{4})(\d{3})_(\w{3})_(\d{3}).rpm$/;
|
||||
##############
|
||||
#If the release levels are different, it will be upgrade_required.
|
||||
#############
|
||||
if($fff ne $2) {
|
||||
$upgrade_required = 1;
|
||||
} else {
|
||||
|
||||
if(($pns eq $1) && ($4 <= $active_level)) {
|
||||
$msg = $msg. "Upgrade $mtms $activate!";
|
||||
# if($activate ne "concurrent") {
|
||||
# $msg = "Option --actviate's value should be disruptive";
|
||||
# return ("", "","", $msg, -1);
|
||||
# }
|
||||
} else {
|
||||
$msg = $msg . "Upgrade $mtms disruptively!";
|
||||
if($activate ne "disruptive") {
|
||||
$msg = "Option --activate's value shouldn't be concurrent, and it must be disruptive";
|
||||
return ("", "","", $msg, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#print "filename is $filename\n";
|
||||
my $xml_file_name = $filename;
|
||||
$xml_file_name =~ s/(.+\.)rpm/\1xml/;
|
||||
#print "check_licdd_update: source xml file is $xml_file_name\n";
|
||||
|
||||
if( ( -z $filename)|| ( -z $xml_file_name) ) {
|
||||
$msg = "The package $filename or xml $xml_file_name is empty" ;
|
||||
return ("", "", "", $msg, -1);
|
||||
}
|
||||
|
||||
return ($filename, $xml_file_name ,$upgrade_required, $msg, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub get_one_mtms {
|
||||
my $exp = shift;
|
||||
my $bpa = shift;
|
||||
my $cmd = "lssyscfg -r cage -e $bpa";
|
||||
my $mtms;
|
||||
my $msg;
|
||||
|
||||
my $values = xCAT::PPCcli::send_cmd( $exp, $cmd );
|
||||
my $Rc = shift(@$values);
|
||||
|
||||
#####################################
|
||||
# Return error
|
||||
#####################################
|
||||
if ( $Rc != SUCCESS ) {
|
||||
$msg = "ERROR: Failed to find a CEC managed by $bpa on the HMC";
|
||||
return ("", $msg);
|
||||
}
|
||||
|
||||
foreach (@$values) {
|
||||
if( $_ =~ /cage_num=(\w*),contents=sys,type_model_serial_num=(\w+)-(\w+)\*(\w+),loc_code=(\w+).(\w+).(\w+)/) {
|
||||
$mtms = "$2-$3*$4";
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#print "the managed system is $mtms!\n";
|
||||
return ($mtms, $msg);
|
||||
}
|
||||
|
||||
sub process_node {
|
||||
my $req = shift;
|
||||
my $node = shift;
|
||||
|
||||
my $tab = xCAT::Table->new("vpd");
|
||||
my $msg;
|
||||
unless ($tab) {
|
||||
$msg = "ERROR: Unable to open basic ppc table for configuration";
|
||||
return ("", $msg);
|
||||
}
|
||||
|
||||
print "in process_node1, node $node\n";
|
||||
print Dumper($node);
|
||||
my $ent = $tab->getNodeAttribs($node, ['serial', 'mtm']);
|
||||
print "in process_node\n";
|
||||
print Dumper($ent);
|
||||
|
||||
my $serial = $ent->{'serial'};
|
||||
my $mtm = $ent->{'mtm'};
|
||||
#################################
|
||||
#Get node
|
||||
#################################
|
||||
print "in get_related_fsp_bpa(), serial = $serial, mtm= $mtm\n";
|
||||
my @ents = $tab->getAllAttribsWhere("serial=\"$serial\" and mtm=\"$mtm\"", 'node');
|
||||
if (@ents < 0) {
|
||||
$msg = "failed to get the FSPs or BPAs whose mtm is $mtm, serial is $serial!";
|
||||
return ("", $msg);
|
||||
}
|
||||
my $e;
|
||||
print Dumper(@ents);
|
||||
foreach $e (@ents) {
|
||||
if($e->{node} ne $node) {
|
||||
# push @{$req->{node}},$e->{node};
|
||||
push @{$req->{noderange}},$e->{node};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub get_related_fsp_bpa {
|
||||
my $mtm = shift;
|
||||
my $serial = shift;
|
||||
my $tab = xCAT::Table->new("vpd");
|
||||
my $msg;
|
||||
unless ($tab) {
|
||||
$msg = "ERROR: Unable to open basic ppc table for configuration";
|
||||
return ("", $msg);
|
||||
}
|
||||
#################################
|
||||
#Get node
|
||||
#################################
|
||||
print "in get_related_fsp_bpa(), serial = $serial, mtm= $mtm\n";
|
||||
my @ent = $tab->getAllAttribsWhere("serial=\"$serial\" and mtm=\"$mtm\"", 'node');
|
||||
if (@ent < 0) {
|
||||
$msg = "failed to get the FSPs or BPAs whose mtm is $mtm, serial is $serial!";
|
||||
return ("", $msg);
|
||||
}
|
||||
return(\@ent);
|
||||
|
||||
}
|
||||
|
||||
sub get_hcp_id {
|
||||
my $node = shift;
|
||||
|
||||
my $tab = xCAT::Table->new("ppc");
|
||||
my $msg;
|
||||
unless ($tab) {
|
||||
$msg = "ERROR: Unable to open basic ppc table for configuration";
|
||||
return ("", $msg);
|
||||
}
|
||||
#################################
|
||||
#Get node
|
||||
#################################
|
||||
my @ent = $tab->getNodeAttribs($node, ['hcp', 'id']);
|
||||
if (@ent < 0) {
|
||||
$msg = "failed to get the hcp and id of $node!";
|
||||
return ("", $msg);
|
||||
}
|
||||
return($ent[0]->{hcp}, $ent[0]->{id});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##########################################################################
|
||||
# Forks a process to run the action command
|
||||
##########################################################################
|
||||
sub fork_cmd {
|
||||
|
||||
my $node_name = shift;
|
||||
my $attrs = shift;
|
||||
my $action = shift;
|
||||
my $pipe ;
|
||||
|
||||
#######################################
|
||||
# Pipe childs output back to parent
|
||||
#######################################
|
||||
my $parent;
|
||||
my $child;
|
||||
pipe $parent, $child;
|
||||
my $pid = xCAT::Utils->xfork;
|
||||
my $res;
|
||||
|
||||
if ( !defined($pid) ) {
|
||||
###################################
|
||||
# Fork error
|
||||
###################################
|
||||
print "Fork error:!";
|
||||
return undef;
|
||||
}
|
||||
elsif ( $pid == 0 ) {
|
||||
###################################
|
||||
# Child process
|
||||
###################################
|
||||
close( $parent );
|
||||
$pipe = $child;
|
||||
|
||||
$res = action( $node_name, $attrs, $action );
|
||||
print "res\n";
|
||||
print Dumper($res);
|
||||
my %output;
|
||||
$output{node} = $node_name;
|
||||
$output{ret} = @$res[2];
|
||||
$output{contents} = @$res[1];
|
||||
# print $pipe %output;
|
||||
# print $pipe freeze(\%output);
|
||||
my @outhash;
|
||||
push @outhash,\%output;
|
||||
print $pipe freeze([@outhash]);
|
||||
# print $pipe "good";
|
||||
print $pipe "\nENDOFFREEZE6sK4ci\n";
|
||||
exit(0);
|
||||
}
|
||||
else {
|
||||
###################################
|
||||
# Parent process
|
||||
###################################
|
||||
close( $child );
|
||||
return( $parent, $pid );
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sub action {
|
||||
my $node_name = shift;
|
||||
my $attrs = shift;
|
||||
my $action = shift;
|
||||
# my $user = "HMC";
|
||||
# my $password = "abc123";
|
||||
my $fsp_api ="/home/fsp-api";
|
||||
my $id = 1;
|
||||
my $fsp_name = ();
|
||||
my $fsp_ip = ();
|
||||
my $target_list=();
|
||||
my $type = (); # fsp|lpar -- 0. BPA -- 1
|
||||
my @result;
|
||||
my $Rc = 0 ;
|
||||
my %outhash = ();
|
||||
my $res;
|
||||
|
||||
$id = $$attrs[0];
|
||||
$fsp_name = $$attrs[3];
|
||||
|
||||
my %objhash = ();
|
||||
$objhash{$fsp_name} = "node";
|
||||
my %myhash = xCAT::DBobjUtils->getobjdefs(\%objhash);
|
||||
my $password = $myhash{$fsp_name}{"passwd.hscroot"};
|
||||
print "fspname:$fsp_name password:$password\n";
|
||||
print Dumper(%myhash);
|
||||
if(!$password ) {
|
||||
$res = "The password.hscroot of $fsp_name in ppcdirect table is empty";
|
||||
return ([$node_name, $res, -1]);
|
||||
}
|
||||
# my $user = "HMC";
|
||||
my $user = "hscroot";
|
||||
# my $cred = $request->{$fsp_name}{cred};
|
||||
# my $user = @$cred[0];
|
||||
# my $password = @$cred[1];
|
||||
|
||||
if($action =~ /^commit$/) { $action = "code_commit"}
|
||||
if($action =~ /^recover$/) { $action = "code_reject"}
|
||||
if($action =~ /^disruptive$/) { $action = "code_update"}
|
||||
if($action =~ /^concurrent$/) {
|
||||
$res = "\'$action\' option not supported in FSPflash.Please use disruptive mode";
|
||||
return ([$node_name, $res, -1]);
|
||||
}
|
||||
|
||||
|
||||
if($$attrs[4] =~ /^fsp$/) {
|
||||
$type = 0;
|
||||
$id = 0;
|
||||
} else {
|
||||
$type = 1;
|
||||
}
|
||||
|
||||
############################
|
||||
# Get IP address
|
||||
############################
|
||||
$fsp_ip = xCAT::Utils::get_hdwr_ip($fsp_name);
|
||||
if($fsp_ip == -1) {
|
||||
$res = "Failed to get the $fsp_name\'s ip";
|
||||
return ([$node_name, $res, -1]);
|
||||
}
|
||||
|
||||
print "fsp name: $fsp_name\n";
|
||||
print "fsp ip: $fsp_ip\n";
|
||||
|
||||
my $cmd = "$fsp_api -a $action -u $user -p $password -t $type:$fsp_ip:$id:$node_name: -d /install/packages_fw/";
|
||||
|
||||
print "cmd: $cmd\n";
|
||||
$SIG{CHLD} = ();
|
||||
my $res = xCAT::Utils->runcmd($cmd, -1);
|
||||
#my $res = "good";
|
||||
$Rc = $::RUNCMD_RC;
|
||||
#$Rc = -1;
|
||||
##################
|
||||
# output the prompt
|
||||
#################
|
||||
#$outhash{ $node_name } = $res;
|
||||
|
||||
return( [$node_name,$res, $Rc] );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
##########################
|
||||
#Performs Licensed Internal Code (LIC) update support for HMC-attached POWER5 and POWER6 Systems
|
||||
###########################
|
||||
sub rflash {
|
||||
|
||||
my $request = shift;
|
||||
my $hash = shift;
|
||||
my $exp = shift;
|
||||
my $subreq = $request->{subreq};
|
||||
my $hwtype = @$exp[2];
|
||||
my @result;
|
||||
my $timeout = $request->{ppctimeout};
|
||||
my $housekeeping = $request->{housekeeping};
|
||||
$packages_dir = $request->{opt}->{p};
|
||||
$activate = $request->{opt}->{activate};
|
||||
|
||||
my $mtms;
|
||||
my $h;
|
||||
my $user;
|
||||
|
||||
my $tmp_file; #the file handle of the stanza
|
||||
my $rpm_file;
|
||||
my $xml_file;
|
||||
my @rpm_files;
|
||||
my @xml_files;
|
||||
my $upgrade_required;
|
||||
my $stanza = undef;
|
||||
my $mtms_t;
|
||||
my @value;
|
||||
my %infor;
|
||||
my $role ; #0x01: BPC A, BPC B; 0x01: Primary or only FSP, 0x02: Backup FSP
|
||||
|
||||
print "in Directflash \n";
|
||||
print Dumper($request);
|
||||
print Dumper($hash);
|
||||
|
||||
####################################
|
||||
# Power commands are grouped by hardware control point
|
||||
# In Direct attach support, the hcp is the related fsp.
|
||||
####################################
|
||||
|
||||
# Example of $hash.
|
||||
#VAR1 = {
|
||||
# '9110-51A*1075ECF' => {
|
||||
# 'Server-9110-51A-SN1075ECF' => [
|
||||
# 0,
|
||||
# 0,
|
||||
# '9110-51A*1075ECF',
|
||||
# 'Server-9110-51A-SN1075ECF',
|
||||
# 'fsp',
|
||||
# 0
|
||||
# ]
|
||||
# }
|
||||
# };
|
||||
my $flag = 0;
|
||||
my $flag2 = 0;
|
||||
while (my ($mtms,$h) = each(%$hash) ) {
|
||||
#
|
||||
#For one mtms, it just needs to do the operation one time.
|
||||
#
|
||||
$flag += 1;
|
||||
if($flag > 1) {
|
||||
last;
|
||||
}
|
||||
|
||||
$mtms =~ /(\w+)-(\w+)\*(\w+)/;
|
||||
my $mtm = "$1-$2";
|
||||
my $serial = $3;
|
||||
|
||||
|
||||
while (my ($name,$d) = each(%$h) ) {
|
||||
$flag2 += 1;
|
||||
if($flag2 > 1) {
|
||||
last;
|
||||
}
|
||||
my $values = xCAT::FSPinv::action( $name, $d, "list_firmware_level");
|
||||
# my $level = xCAT::PPCcli::lslic( $exp, $d, $timeout );
|
||||
my $Rc = shift(@$values);
|
||||
my $level = $$values[0]->{$name};
|
||||
#####################################
|
||||
# Return error
|
||||
#####################################
|
||||
if ( $Rc != SUCCESS ) {
|
||||
push @value, [$name,$level,$Rc];
|
||||
next;
|
||||
}
|
||||
|
||||
if (( $level =~ /curr_level_primary/ ) || ( $level =~ /curr_level_a/ )) {
|
||||
$role = 0x01;
|
||||
} else {
|
||||
$role = 0x02;
|
||||
}
|
||||
|
||||
if ( $level =~ /ecnumber=(\w+)/ ) {
|
||||
$release_level = $1;
|
||||
&dpush( \@value, [$name,"$mtms :release level:$1"]);
|
||||
}
|
||||
|
||||
if ( $level =~ /activated_level=(\w+)/ ) {
|
||||
$active_level = $1;
|
||||
&dpush( \@value, [$name,"$mtms :activated level:$1"]);
|
||||
}
|
||||
|
||||
my $msg;
|
||||
if(!defined($housekeeping)) {
|
||||
my $flag = 0;
|
||||
($rpm_file, $xml_file, $upgrade_required,$msg, $flag) = &get_lic_filenames($mtms);
|
||||
if( $flag == -1) {
|
||||
push (@value, [$name,"$mtms: $msg"]);
|
||||
push (@value, [$name,"Failed to upgrade the firmware of $name"]);
|
||||
return (\@value);
|
||||
}
|
||||
dpush ( \@value, [$name, $msg]);
|
||||
}
|
||||
my $nodes = get_related_fsp_bpa( $mtm, $serial);
|
||||
print Dumper($nodes);
|
||||
my $i = 0;
|
||||
my $flag = 0;
|
||||
my $c = @$nodes;
|
||||
my $name2 = undef;
|
||||
if ($c == 1 && $role == 0x01 ) {
|
||||
|
||||
}
|
||||
if ($c == 1 && $role == 0x02 ) {
|
||||
|
||||
push(@result,[$name, "$name\'s role is Backup FSP or BPC side B). Please configure the Primary FSP or BPC side A.", -1]);
|
||||
}
|
||||
if($c == 2 && $role == 0x01 ) {
|
||||
if($$nodes[0]->{node} eq $name) {
|
||||
$i = 0;
|
||||
$name2 = $$nodes[1]->{node}; #Secondary FSP or BPC side B.
|
||||
} else {
|
||||
$name2 = $name; #Secondary FSP or BPC side B.
|
||||
$name = $$nodes[1]->{node}; #the Primary FSP or BPC side A.
|
||||
}
|
||||
}
|
||||
|
||||
if($c ==2 && $role == 0x02) {
|
||||
if($$nodes[0]->{node} eq $name) {
|
||||
$name2 = $name; # Secondary FSP or BPC side B.
|
||||
$name = $$nodes[1]->{node};#the Primary FSP or BPC side A.
|
||||
} else {
|
||||
$name2 = $$nodes[1]->{node}; #Secondary FSP or BPC side B.
|
||||
}
|
||||
}
|
||||
print "name: $name, name2: $name2\n";
|
||||
|
||||
my $children = 0;
|
||||
$SIG{CHLD} = sub { while (waitpid(-1, WNOHANG) > 0) {print "child exit\n";$children--;} };
|
||||
my $fds = new IO::Select;
|
||||
my $pipe;
|
||||
if(defined($name2) ) {
|
||||
my($hcp, $id) = get_hcp_id($name2);
|
||||
my @dt = ($id, @$d[1], $mtms, $hcp, @$d[4], 0);
|
||||
|
||||
if( defined( $housekeeping ) ) {
|
||||
($pipe) = fork_cmd( $name2, \@dt, $housekeeping );
|
||||
|
||||
} else {
|
||||
($pipe) = fork_cmd( $name2, \@dt, $activate);
|
||||
}
|
||||
if ( $pipe ) {
|
||||
$fds->add( $pipe );
|
||||
$children++;
|
||||
}
|
||||
sleep(5);
|
||||
}
|
||||
$pipe = undef;
|
||||
if( defined( $housekeeping ) ) {
|
||||
($pipe) = fork_cmd( $name, $d, $housekeeping );
|
||||
|
||||
} else {
|
||||
($pipe) = fork_cmd( $name, $d, $activate );
|
||||
}
|
||||
if ( $pipe ) {
|
||||
$fds->add( $pipe );
|
||||
$children++;
|
||||
}
|
||||
print "count:\n";
|
||||
print $fds->count;
|
||||
print "children:$children\n";
|
||||
while ( $fds->count > 0 or $children > 0 ) {
|
||||
my @ready_fds = $fds->can_read(1);
|
||||
foreach my $rfh (@ready_fds) {
|
||||
my $val = <$rfh>;
|
||||
if( defined($val)) {
|
||||
while($val !~ /ENDOFFREEZE6sK4ci/) {
|
||||
$val .= <$rfh>;
|
||||
}
|
||||
my $resp = thaw($val);
|
||||
foreach my $t( @$resp ) {
|
||||
print Dumper($t);
|
||||
push @result, [$t->{node}, $t->{contents}, $t->{ret}];
|
||||
}
|
||||
next;
|
||||
}
|
||||
$fds->remove($rfh);
|
||||
close($rfh);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
push(@value, @result);
|
||||
return (\@value);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
@ -94,7 +94,7 @@ sub firmware {
|
||||
# Return error
|
||||
#####################################
|
||||
if ( $Rc != SUCCESS ) {
|
||||
push @result, [$name,@$values[0],$Rc];
|
||||
push @result, [$name,$data->{$name},$Rc];
|
||||
next;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ use xCAT::Table;
|
||||
use Getopt::Long;
|
||||
use File::Spec;
|
||||
use POSIX qw(tmpnam);
|
||||
use xCAT::FSPflash.pm;
|
||||
use xCAT::FSPflash;
|
||||
|
||||
|
||||
my $packages_dir= ();
|
||||
|
Loading…
x
Reference in New Issue
Block a user