mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 03:12:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			373 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			373 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| # 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;
 | |
| 
 | |
| 
 |