# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html package xCAT::FSPinv; use strict; use Getopt::Long; use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR); require xCAT::Usage; require xCAT::PPCinv; require xCAT::FSPUtils; use XML::Simple; #use Data::Dumper; ########################################## # Maps fsp-api attributes to text ########################################## my @licmap = ( [ "ecnumber", "Release Level " ], [ "activated_level", "Active Level " ], [ "installed_level", "Installed Level" ], [ "accepted_level", "Accepted Level " ], [ "curr_ecnumber_a", "Release Level A" ], [ "curr_level_a", "Level A " ], [ "curr_power_on_side_a", "Current Power on side A" ], [ "curr_ecnumber_b", "Release Level B" ], [ "curr_level_b", "Level B " ], [ "curr_power_on_side_b", "Current Power on side B" ], [ "curr_ecnumber_primary", "Release Level Primary" ], [ "curr_level_primary", "Level Primary " ], [ "curr_power_on_side_primary", "Current Power on side Primary" ], [ "curr_ecnumber_secondary", "Release Level Secondary" ], [ "curr_level_secondary", "Level Secondary" ], [ "curr_power_on_side_secondary", "Current Power on side Secondary" ] ); ########################################################################## # Parse the command line for options and operands ########################################################################## sub parse_args { # xCAT::PPCinv::parse_args(@_); my $request = shift; my $command = $request->{command}; my $args = $request->{arg}; my %opt = (); # my @rinv = qw(bus config model serial firm all); my @rinv = qw( deconfig firm ); ############################################# # Responds with usage statement ############################################# local *usage = sub { my $usage_string = xCAT::Usage->getUsage($command); return ([ $_[0], $usage_string ]); }; ############################################# # Process command-line arguments ############################################# if (!defined($args)) { return (usage("No command specified")); } ############################################# # Checks case in GetOptions, allows opts # to be grouped (e.g. -vx), and terminates # at the first unrecognized option. ############################################# @ARGV = @$args; $Getopt::Long::ignorecase = 0; Getopt::Long::Configure("bundling"); if (!GetOptions(\%opt, qw(V|verbose x))) { return (usage()); } #################################### # Check for "-" with no option #################################### if (grep(/^-$/, @ARGV)) { return (usage("Missing option: -")); } #################################### # Unsupported command #################################### my ($cmd) = grep(/^$ARGV[0]$/, @rinv); if (!defined($cmd)) { return (usage("Invalid command: $ARGV[0]")); } #################################### # Check for an extra argument #################################### shift @ARGV; if (defined($ARGV[0])) { return (usage("Invalid Argument: $ARGV[0]")); } if (exists($opt{x}) and $cmd !~ /^deconfig$/) { return (usage("Option '-x' can't work with '$cmd'")); } #################################### # Set method to invoke #################################### $request->{method} = $cmd; return (\%opt); } ########################################################################## # Returns FSP/BPA firmware information ########################################################################## sub firmware { my $request = shift; my $hash = shift; my @result; # print "in FSPinv \n"; #print Dumper($request); #print Dumper($hash); #################################### # FSPinv with firm command is grouped by hardware control point # In FSPinv, the hcp is the related fsp. #################################### # Example of $hash. #VAR1 = { # '9110-51A*1075ECF' => { # 'Server-9110-51A-SN1075ECF' => [ # 0, # 0, # '9110-51A*1075ECF', # 'fsp1_name', # 'fsp', # 0 # ] # } # }; while (my ($mtms, $h) = each(%$hash)) { while (my ($name, $d) = each(%$h)) { ##################################### # Command only supported on FSP/BPA/LPARs ##################################### if (@$d[4] !~ /^(cec|frame|fsp|bpa|lpar|blade)$/) { push @result, [ $name, "Information only available for CEC/FSP/Frame/BPA/LPAR", RC_ERROR ]; next; } ################# #For support on Lpars, the flag need to be changed. ########## if (@$d[4] eq "lpar") { @$d[4] = "fsp"; @$d[0] = 0; } my $values = xCAT::FSPUtils::fsp_api_action($request, $name, $d, "list_firmware_level"); my $Rc = @$values[2]; my $data = @$values[1]; #print "values"; #print Dumper($values); ##################################### # Return error ##################################### if ($Rc != SUCCESS) { push @result, [ $name, $data, $Rc ]; next; } ##################################### # Format fsp-api results ##################################### my $val; foreach $val (@licmap) { if ($data =~ /@$val[0]=(\w+)/) { push @result, [ $name, "@$val[1]: $1", $Rc ]; } } } } return (\@result); } ########################################################################## # Returns firmware version ########################################################################## sub firm { return (firmware(@_)); } ########################################################################## # Returns serial-number ########################################################################## sub serial { } sub vpd { } sub bus { } sub deconfig { my $request = shift; my $hash = shift; my @result; # print "in FSPinv \n"; #print Dumper($request); #print Dumper($hash); #################################### # FSPinv with deconfig command is grouped by hardware control point # In FSPinv, the hcp is the related fsp. #################################### # Example of $hash. #VAR1 = { # '9110-51A*1075ECF' => { # 'Server-9110-51A-SN1075ECF' => [ # 0, # 0, # '9110-51A*1075ECF', # 'fsp1_name', # 'fsp', # 0 # ] # } # }; while (my ($mtms, $h) = each(%$hash)) { while (my ($name, $d) = each(%$h)) { ##################################### # Command only supported on FSP/BPA/LPARs ##################################### if (@$d[4] !~ /^(cec|fsp)$/) { push @result, [ $name, "Deconfigured resource information only available for CEC/FSP", RC_ERROR ]; next; } ################# #For support on Lpars, the flag need to be changed. ########## #if(@$d[4] eq "lpar") { # @$d[4] = "fsp"; # @$d[0] = 0; #} my $values = xCAT::FSPUtils::fsp_api_action($request, $name, $d, "get_cec_deconfigured"); my $Rc = @$values[2]; my $data = @$values[1]; #print "values"; #print Dumper($values); ##################################### # Return error ##################################### if ($Rc != SUCCESS) { push @result, [ $name, $data, $Rc ]; next; } ##################################### # Format fsp-api results ##################################### #my $decfg = XMLin($data); my $decfg; eval { $decfg = XMLin($data); }; if ($@) { push @result, [ $name, "Error: there are some unreadable XML data from the firmware. It can't be parsed by 'xcatd'.", -1 ]; return (\@result); } if (exists($request->{opt}->{x})) { push @result, [ $name, "\n" . $data, -1 ]; next; } #print "decfg"; #print Dumper($decfg); my $node = $decfg->{NODE}; if (defined($node) && exists($node->{Location_code})) { my $Call_Out_Hardware_State; my $Call_Out_Method; my $Location_code; my $RID; my $TYPE; my $dres; if (ref($node->{GARDRECORD}) eq "ARRAY") { $dres = $node->{GARDRECORD}; } elsif (ref($node->{GARDRECORD}) eq "HASH") { push @$dres, $node->{GARDRECORD}; } else { push @result, [ $name, "NO Deconfigured resources", 0 ]; return (\@result); } push @result, [ $name, "Deconfigured resources", 0 ]; push @result, [ $name, "Location_code RID Call_Out_Method Call_Out_Hardware_State TYPE", 0 ]; push @result, [ $name, "$node->{Location_code} $node->{RID}", 0 ]; #foreach my $unit(@{$node->{GARDRECORD}}) { foreach my $unit (@$dres) { while (my ($key, $unit3) = each(%$unit)) { if ($key eq "GARDUNIT") { if (ref($unit3) eq "HASH") { $Call_Out_Hardware_State = $unit3->{Call_Out_Hardware_State}; $Call_Out_Method = $unit3->{Call_Out_Method}; $Location_code = $unit3->{Location_code}; $RID = $unit3->{RID}; $TYPE = $unit3->{TYPE}; push @result, [ $name, "$Location_code $RID $Call_Out_Method $Call_Out_Hardware_State $TYPE", 0 ]; } elsif (ref($unit3) eq "ARRAY") { foreach my $unit4 (@$unit3) { $Call_Out_Hardware_State = $unit4->{Call_Out_Hardware_State}; $Call_Out_Method = $unit4->{Call_Out_Method}; $Location_code = $unit4->{Location_code}; $RID = $unit4->{RID}; $TYPE = $unit4->{TYPE}; push @result, [ $name, "$Location_code $RID $Call_Out_Method $Call_Out_Hardware_State $TYPE", 0 ]; } } } } } } else { push @result, [ $name, "NO Deconfigured resources", 0 ]; } } } return (\@result); } ########################################################################## # Returns machine-type-model ########################################################################## sub model { } ########################################################################## # Returns all inventory information ########################################################################## sub all { my @result = ( @{ deconfig(@_) }, @{ firmware(@_) } ); return (\@result); } 1;