git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@11670 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			4245 lines
		
	
	
		
			148 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			4245 lines
		
	
	
		
			148 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | |
| 
 | |
| package xCAT_plugin::lsslp;
 | |
| use lib "/opt/xcat/lib/perl";
 | |
| use strict;
 | |
| use Getopt::Long;
 | |
| use Socket;
 | |
| use xCAT::Usage;
 | |
| use POSIX "WNOHANG";
 | |
| use Storable qw(freeze thaw);
 | |
| use Time::HiRes qw(gettimeofday);
 | |
| use IO::Select;
 | |
| use XML::Simple;
 | |
| $XML::Simple::PREFERRED_PARSER='XML::Parser';
 | |
| use xCAT::PPCdb;
 | |
| use xCAT::NodeRange;
 | |
| use xCAT::Utils;
 | |
| 
 | |
| require xCAT::MacMap;
 | |
| require xCAT_plugin::blade;
 | |
| 
 | |
| #######################################
 | |
| # Constants
 | |
| #######################################
 | |
| use constant {
 | |
|     HARDWARE_SERVICE => "service:management-hardware.IBM",
 | |
|     SOFTWARE_SERVICE => "service:management-software.IBM",
 | |
|     WILDCARD_SERVICE => "service:management-*",
 | |
|     P6_SERVICE       => "service:management-hardware.IBM",
 | |
|     P7_SERVICE       => "service:management-software.IBM",
 | |
|     SERVICE_FSP      => "cec-service-processor",
 | |
|     SERVICE_BPA      => "bulk-power-controller",
 | |
|     SERVICE_CEC      => "cec-service-processor",
 | |
|     SERVICE_FRAME    => "bulk-power-controller",
 | |
|     SERVICE_HMC      => "hardware-management-console",
 | |
|     SERVICE_IVM      => "integrated-virtualization-manager",
 | |
|     SERVICE_MM       => "management-module",
 | |
|     SERVICE_CMM      => "chassis-management-module",
 | |
|     SERVICE_RSA      => "remote-supervisor-adapter",
 | |
|     SERVICE_RSA2     => "remote-supervisor-adapter-2",
 | |
|     SLP_CONF         => "/usr/local/etc/slp.conf",
 | |
|     SLPTOOL          => "/usr/local/bin/slptool",
 | |
|     TYPE_MM          => "MM",
 | |
|     TYPE_CMM         => "CMM",
 | |
|     TYPE_RSA         => "RSA",
 | |
|     TYPE_BPA         => "BPA",
 | |
|     TYPE_HMC         => "HMC",
 | |
|     TYPE_IVM         => "IVM",
 | |
|     TYPE_FSP         => "FSP",
 | |
|     TYPE_CEC         => "CEC",
 | |
|     TYPE_FRAME       => "FRAME",
 | |
|     IP_ADDRESSES     => 4,
 | |
|     TEXT             => 0,
 | |
|     FORMAT           => 1,
 | |
|     SUCCESS          => 0,
 | |
|     RC_ERROR         => 1
 | |
| };
 | |
| 
 | |
| #######################################
 | |
| # Globals
 | |
| #######################################
 | |
| my %service_slp = (
 | |
|     @{[ SERVICE_FSP    ]} => TYPE_FSP,
 | |
|     @{[ SERVICE_BPA    ]} => TYPE_BPA,
 | |
|     @{[ SERVICE_CEC    ]} => TYPE_CEC,
 | |
|     @{[ SERVICE_FRAME  ]} => TYPE_FRAME,
 | |
|     @{[ SERVICE_HMC    ]} => TYPE_HMC,
 | |
|     @{[ SERVICE_IVM    ]} => TYPE_IVM,
 | |
|     @{[ SERVICE_MM     ]} => TYPE_MM,
 | |
|     @{[ SERVICE_CMM    ]} => TYPE_CMM,
 | |
|     @{[ SERVICE_RSA    ]} => TYPE_RSA,
 | |
|     @{[ SERVICE_RSA2   ]} => TYPE_RSA
 | |
| );
 | |
| 
 | |
| #######################################
 | |
| # SLP display header
 | |
| #######################################
 | |
| my @header = (
 | |
|     ["device",        "%-8s" ],
 | |
|     ["type-model",    "%-12s"],
 | |
|     ["serial-number", "%-15s"],
 | |
|     ["side",          "%-6s" ],
 | |
|     ["ip-addresses",  "placeholder"],
 | |
|     ["hostname",      "%s"]
 | |
| );
 | |
| 
 | |
| #######################################
 | |
| # Invalid IP address list
 | |
| #######################################
 | |
| my @invalidiplist = (
 | |
|         "192.168.2.144",
 | |
|         "192.168.2.145",
 | |
|         "192.168.2.146",
 | |
|         "192.168.2.147",
 | |
|         "192.168.2.148",
 | |
|         "192.168.2.149",
 | |
|         "192.168.3.144",
 | |
|         "192.168.3.145",
 | |
|         "192.168.3.146",
 | |
|         "192.168.3.147",
 | |
|         "192.168.3.148",
 | |
|         "192.168.3.149",
 | |
|         "169.254.",
 | |
|         "127.0.0.0",
 | |
|         "127",
 | |
|         0,
 | |
|         );
 | |
| ########################################
 | |
| ## Hardware specific SLP attributes
 | |
| ########################################
 | |
| #my %exattr = (
 | |
| #  @{[ SERVICE_FSP ]} => [
 | |
| #      "bpc-machinetype-model",
 | |
| #      "bpc-serial-number",
 | |
| #      "cage-number"
 | |
| #    ],
 | |
| #  @{[ SERVICE_BPA ]} => [
 | |
| #      "frame-number"
 | |
| #    ]
 | |
| #);
 | |
| 
 | |
| #######################################
 | |
| # Power methods
 | |
| #######################################
 | |
| my %mgt = (
 | |
|     lc(TYPE_FSP)   => "fsp",
 | |
|     lc(TYPE_BPA)   => "bpa",
 | |
|     lc(TYPE_CEC)   => "cec",
 | |
|     lc(TYPE_FRAME) => "frame",
 | |
|     lc(TYPE_MM)    => "blade",
 | |
|     lc(TYPE_HMC)   => "hmc",
 | |
|     lc(TYPE_IVM)   => "ivm",
 | |
|     lc(TYPE_RSA)   => "blade",
 | |
|     lc(TYPE_CMM)   => "blade",
 | |
| );
 | |
| 
 | |
| my @attribs    = qw(nodetype mtm serial side ip groups mgt id parent mac hidden otherinterfaces hwtype);
 | |
| my $verbose    = 0;
 | |
| my %ip_addr    = ();
 | |
| my %slp_result = ();
 | |
| my %rsp_result = ();
 | |
| my %opt        = ();
 | |
| my $maxtries   = 1;
 | |
| my $openSLP    = 1;
 | |
| my @converge;
 | |
| my $macmap;
 | |
| my $expect_ent = 0;
 | |
| my $time_out = 300;
 | |
| my $enter_time = 0;
 | |
| my @filternodes;
 | |
| my %otherinterfacehash;
 | |
| my $TRACE = 0;
 | |
| my $DEBUG_MATCH = 0;
 | |
| my %globlehwtype = (
 | |
|     fsp   => $::NODETYPE_FSP,
 | |
|     bpa   => $::NODETYPE_BPA,
 | |
|     lpar  => $::NODETYPE_LPAR,
 | |
|     hmc   => $::NODETYPE_HMC,
 | |
|     ivm   => $::NODETYPE_IVM,
 | |
|     frame => $::NODETYPE_FRAME,
 | |
|     cec   => $::NODETYPE_CEC,
 | |
|     cmm   => $::NODETYPE_CMM,
 | |
| );
 | |
| my %globalnodetype = (
 | |
|     fsp   => $::NODETYPE_PPC,
 | |
|     bpa   => $::NODETYPE_PPC,
 | |
|     cec   => $::NODETYPE_PPC,
 | |
|     frame => $::NODETYPE_PPC,
 | |
|     hmc   => $::NODETYPE_PPC,
 | |
|     ivm   => $::NODETYPE_PPC,
 | |
|     cmm   => $::NODETYPE_MP,
 | |
|     lpar  =>"$::NODETYPE_PPC,$::NODETYPE_OSI"
 | |
| );
 | |
| ##########################################################################
 | |
| # Command handler method from tables
 | |
| ##########################################################################
 | |
| sub handled_commands {
 | |
| 
 | |
|     return( {lsslp=>"lsslp"} );
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # 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 );
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Parse the command line options and operands
 | |
| ##########################################################################
 | |
| sub parse_args {
 | |
| 
 | |
|     my $request  = shift;
 | |
|     my $args     = $request->{arg};
 | |
|     my $cmd      = $request->{command};
 | |
|     my %services = (
 | |
|         HMC   => SOFTWARE_SERVICE.":".SERVICE_HMC.":",
 | |
|         IVM   => SOFTWARE_SERVICE.":".SERVICE_IVM.":",
 | |
|         BPA   => HARDWARE_SERVICE.":".SERVICE_BPA,
 | |
|         FSP   => HARDWARE_SERVICE.":".SERVICE_FSP,
 | |
|         CEC   => HARDWARE_SERVICE.":".SERVICE_CEC,
 | |
|         FRAME => HARDWARE_SERVICE.":".SERVICE_FRAME,
 | |
|         RSA   => HARDWARE_SERVICE.":".SERVICE_RSA.":",
 | |
|         CMM   => HARDWARE_SERVICE.":".SERVICE_CMM,
 | |
|         MM    => HARDWARE_SERVICE.":".SERVICE_MM.":"
 | |
|     );
 | |
|     #############################################
 | |
|     # Responds with usage statement
 | |
|     #############################################
 | |
|     local *usage = sub {
 | |
|         my $usage_string = xCAT::Usage->getUsage($cmd);
 | |
|         return( [$_[0], $usage_string] );
 | |
|     };
 | |
|     #############################################
 | |
|     # No command-line arguments - use defaults
 | |
|     #############################################
 | |
|     if ( !defined( $args )) {
 | |
|         return(0);
 | |
|     }
 | |
|     #############################################
 | |
|     # 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" );
 | |
| 
 | |
|     #############################################
 | |
|     # Process command-line flags
 | |
|     #############################################
 | |
|     if (!GetOptions( \%opt,
 | |
|             qw(h|help V|Verbose v|version i=s x z w r s=s e=s t=s m c n C=s T=s I updatehosts makedhcp resetnet vpdtable))) {
 | |
|         return( usage() );
 | |
|     }
 | |
|     ####################################
 | |
|     # Check for an extra argument
 | |
|     ####################################
 | |
|     #if ( defined( $ARGV[0] )) {
 | |
|     #    return(usage( "Invalid Argument: $ARGV[0]" ));
 | |
|     #}
 | |
| 
 | |
| 
 | |
|     #############################################
 | |
|     # Check for switch "-" with no option
 | |
|     #############################################
 | |
|     #if ( grep(/^-$/, @ARGV )) {
 | |
|     #    return(usage( "Missing option: -" ));
 | |
|     #}
 | |
|     #############################################
 | |
|     # Check for node range
 | |
|     #############################################
 | |
|     if ( scalar(@ARGV) eq 1 ) {
 | |
|         my @nodes = xCAT::NodeRange::noderange( @ARGV );
 | |
|         foreach (@nodes)  {
 | |
|             push @filternodes, $_;
 | |
|         }
 | |
|         unless (@filternodes) {
 | |
|             return(usage( "Invalid Argument: $ARGV[0]" ));
 | |
|         }
 | |
|     } elsif ( scalar(@ARGV) > 1 ) {
 | |
|         return(usage( "Invalid flag, please check and retry." ));
 | |
|     }
 | |
| 
 | |
|     #############################################
 | |
|     # Set convergence
 | |
|     #############################################
 | |
|     if ( exists( $opt{c} )) {
 | |
| 
 | |
|         #################################
 | |
|         # Use values set in slp.conf
 | |
|         #################################
 | |
|         if ( !defined( $ARGV[0] )) {
 | |
|             @converge = (0);
 | |
|         }
 | |
|         #################################
 | |
|         # Use new values
 | |
|         #################################
 | |
|         else {
 | |
|             @converge = split /,/,$ARGV[0];
 | |
|             if ( scalar( @converge ) > 5 ) {
 | |
|                 return(usage( "Convergence timeouts limited to 5 maximum" ));
 | |
|             }
 | |
|             foreach ( @converge ) {
 | |
|                 unless ( /^[1-9]{1}$|^[1-9]{1}[0-9]{1,4}$/) {
 | |
|                     return(usage( "Invalid convergence timeout: $_" ));
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     #############################################
 | |
|     # Check for an argument
 | |
|     #############################################
 | |
|     #elsif ( defined( $ARGV[0] )) {
 | |
|     #    return(usage( "Invalid Argument: $ARGV[0]" ));
 | |
|     #}
 | |
|     #############################################
 | |
|     # Option -V for verbose output
 | |
|     #############################################
 | |
|     if ( exists( $opt{V} )) {
 | |
|         $verbose = 1;
 | |
|     }
 | |
|     #############################################
 | |
|     # Check for mutually-exclusive formatting
 | |
|     #############################################
 | |
|     if ( (exists($opt{r}) + exists($opt{x}) + exists($opt{z}) + exists($opt{vpdtable}) ) > 1 ) {
 | |
|         return( usage() );
 | |
|     }
 | |
|     #############################################
 | |
|     # Command tries
 | |
|     #############################################
 | |
|     if ( exists( $opt{t} )) {
 | |
|        $maxtries = $opt{t};
 | |
| 
 | |
|        if ( $maxtries !~ /^0?[1-9]$/ ) {
 | |
|            return( usage( "Invalid command tries (1-9)" ));
 | |
|        }
 | |
|     }
 | |
|     #############################################
 | |
|     # Select SLP command
 | |
|     #############################################
 | |
|     if ( exists( $opt{e} )) {
 | |
|        if ( $opt{e} !~ /slptool/ ) {
 | |
|            $openSLP = 0;
 | |
|        }
 | |
|     }
 | |
|     #############################################
 | |
|     # Check for unsupported service type
 | |
|     #############################################
 | |
|     if ( exists( $opt{s} )) {
 | |
|         if ( !exists( $services{$opt{s}} )) {
 | |
|             return(usage( "Invalid service: $opt{s}" ));
 | |
|         }
 | |
|         $request->{service} = $services{$opt{s}};
 | |
|     }
 | |
| 
 | |
|     #############################################
 | |
|     # Check the dependency of makedhcp option
 | |
|     #############################################
 | |
|     if ( exists( $opt{makedhcp} ) and !exists( $opt{w} ) ) {
 | |
|         return( usage("'makedhcp' should work with '-w' option"  ) );
 | |
|     }
 | |
| 
 | |
|     #############################################
 | |
|     # Check the validation of -M option
 | |
|     #############################################
 | |
|     #if ( exists( $opt{M} ) and ($opt{M} !~ /^vpd$/) and ($opt{M} !~ /^switchport$/) ) {
 | |
|     #    return( usage("Invalid value for '-M' option. Acceptable value is 'vpd' or 'switchport'") );
 | |
|     #}
 | |
| 
 | |
|     #############################################
 | |
|     # Check the validation of -T option
 | |
|     #############################################
 | |
|     if ( exists( $opt{T} )) {
 | |
|         $time_out = $opt{T};
 | |
|         if ( $time_out !~ /^\d+$/ ) {
 | |
|             return( usage( "Invalid timeout value, should be number" ));
 | |
|         }
 | |
|         if (!exists( $opt{C} )) {
 | |
|             return ( usage( "-T should be used with -C" ));
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     #############################################
 | |
|     # Check the validation of -C option
 | |
|     #############################################
 | |
|     if ( exists( $opt{C} )) {
 | |
|         $expect_ent = $opt{C};
 | |
| 
 | |
|         if ( $expect_ent !~ /^\d+$/ ) {
 | |
|             return( usage( "Invalid expect entries, should be number" ));
 | |
|         }
 | |
|         if ( !exists($opt{i} )) {
 | |
|             return( usage( "-C should be used with -i" ));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Validate comma-seperated list of IPs
 | |
| ##########################################################################
 | |
| sub validate_ip {
 | |
| 
 | |
|     my $request = shift;
 | |
| 
 | |
|     ###########################################
 | |
|     # Option -i not specified (no IPs specified)
 | |
|     ###########################################
 | |
|     if ( !exists( $opt{i} )) {
 | |
| 
 | |
|         #######################################
 | |
|         # Determine interfaces
 | |
|         #######################################
 | |
|         my $ips = $openSLP ?
 | |
|                   slptool_ifconfig( $request ) : slpquery_ifconfig( $request );
 | |
| 
 | |
|         #######################################
 | |
|         # Command failed
 | |
|         #######################################
 | |
|         if ( @$ips[0] ) {
 | |
|             return( $ips );
 | |
|         }
 | |
|         return( [0] );
 | |
|     }
 | |
|     ###########################################
 | |
|     # Option -i specified - validate entries
 | |
|     ###########################################
 | |
|     foreach ( split /,/, $opt{i} ) {
 | |
|         my $ip = $_;
 | |
| 
 | |
|         ###################################
 | |
|         # Length for IPv4 addresses
 | |
|         ###################################
 | |
|         my (@octets) = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
 | |
|         if ( scalar(@octets) != 4 ) {
 | |
|             return( [1,"Invalid IP address: $ip"] );
 | |
|         }
 | |
|         foreach my $octet ( @octets ) {
 | |
|             if (( $octet < 0 ) or ( $octet > 255 )) {
 | |
|                 return( [1,"Invalid IP address: $ip"] );
 | |
|             }
 | |
|         }
 | |
|         $ip_addr{$ip} = 1;
 | |
|     }
 | |
|     return( [0] );
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Verbose mode (-V)
 | |
| ##########################################################################
 | |
| sub trace {
 | |
| 
 | |
|     my $request = shift;
 | |
|     my $msg     = shift;
 | |
|     my $sig     = shift;
 | |
| 
 | |
|     if ($sig) {
 | |
|         if ($TRACE) {
 | |
|             my ($sec,$min,$hour,$mday,$mon,$yr,$wday,$yday,$dst) = localtime(time);
 | |
|             my $msg = sprintf "%02d:%02d:%02d %5d %s", $hour,$min,$sec,$$,$msg;
 | |
|             send_msg( $request, 0, $msg );
 | |
|         }
 | |
|     } else {
 | |
|         if ( $verbose ) {
 | |
|             my ($sec,$min,$hour,$mday,$mon,$yr,$wday,$yday,$dst) = localtime(time);
 | |
|             my $msg = sprintf "%02d:%02d:%02d %5d %s", $hour,$min,$sec,$$,$msg;
 | |
|             send_msg( $request, 0, $msg );
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Determine adapters available - slptool always uses adapter IP
 | |
| ##########################################################################
 | |
| sub slptool_ifconfig {
 | |
| 
 | |
|     my $request = shift;
 | |
|     my $cmd     = "ifconfig -a";
 | |
|     my $result  = `$cmd`;
 | |
|     my $mode    = "MULTICAST";
 | |
| 
 | |
|     #############################################
 | |
|     # Display broadcast IPs, but use adapter IP
 | |
|     #############################################
 | |
|     if ( !exists( $opt{m} )) {
 | |
|         $mode = "BROADCAST";
 | |
|     }
 | |
|     #############################################
 | |
|     # Error running command
 | |
|     #############################################
 | |
|     if ( !$result ) {
 | |
|         return( [1, "Error running '$cmd': $!"] );
 | |
|     }
 | |
|     if ( $verbose ) {
 | |
|         trace( $request, $cmd );
 | |
|         trace( $request, "$mode Interfaces:" );
 | |
|     }
 | |
|     if (xCAT::Utils->isAIX()) {
 | |
|         ##############################################################
 | |
|         # Should look like this for AIX:
 | |
|         # en0: flags=4e080863,80<UP,BROADCAST,NOTRAILERS,RUNNING,
 | |
|         #      SIMPLEX,MULTICAST,GROUPRT,64BIT,PSEG,CHAIN>
 | |
|         #      inet 30.0.0.1    netmask 0xffffff00 broadcast 30.0.0.255
 | |
|         #      inet 192.168.2.1 netmask 0xffffff00 broadcast 192.168.2.255
 | |
|         # en1: ...
 | |
|         #
 | |
|         ##############################################################
 | |
|         my @adapter = split /\w+\d+:\s+flags=/, $result;
 | |
|         foreach ( @adapter ) {
 | |
|             if ( !($_ =~ /LOOPBACK/ ) and
 | |
|                    $_ =~ /UP(,|>)/ and
 | |
|                    $_ =~ /$mode/ ) {
 | |
|                 my @ip = split /\n/;
 | |
|                 foreach ( @ip ) {
 | |
|                     if ( $mode eq "BROADCAST" ) {
 | |
|                         if ( $_ =~ /^\s*inet\s+/ and
 | |
|                              $_ =~ /broadcast\s+(\d+\.\d+\.\d+\.\d+)/ ) {
 | |
| 
 | |
|                             if ( $verbose ) {
 | |
|                                 trace( $request, "\t\t$1\tUP,$mode" );
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                     if ( $_ =~ /^\s*inet\s*(\d+\.\d+\.\d+\.\d+)/ ) {
 | |
|                         $ip_addr{$1} = 1;
 | |
| 
 | |
|                         if ( exists( $opt{m} )) {
 | |
|                             trace( $request, "\t\t$1\tUP,$mode" );
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         ##############################################################
 | |
|         # Should look like this for Linux:
 | |
|         # eth0 Link encap:Ethernet  HWaddr 00:02:55:7B:06:30
 | |
|         #      inet addr:9.114.154.193  Bcast:9.114.154.223
 | |
|         #      inet6 addr: fe80::202:55ff:fe7b:630/64 Scope:Link
 | |
|         #      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
 | |
|         #      RX packets:1280982 errors:0 dropped:0 overruns:0 frame:0
 | |
|         #      TX packets:3535776 errors:0 dropped:0 overruns:0 carrier:0
 | |
|         #      collisions:0 txqueuelen:1000
 | |
|         #      RX bytes:343489371 (327.5 MiB)  TX bytes:870969610 (830.6 MiB)
 | |
|         #      Base address:0x2600 Memory:fbfe0000-fc0000080
 | |
|         #
 | |
|         # eth1 ...
 | |
|         #
 | |
|         ##############################################################
 | |
|         my @adapter= split /\n{2,}/, $result;
 | |
|         foreach ( @adapter ) {
 | |
|             if ( !($_ =~ /LOOPBACK / ) and
 | |
|                    $_ =~ /UP / and
 | |
|                    $_ =~ /$mode / ) {
 | |
| 
 | |
|                 my @ip = split /\n/;
 | |
|                 foreach ( @ip ) {
 | |
|                     if ( $mode eq "BROADCAST" ) {
 | |
|                         if ( $_ =~ /^\s*inet addr:/ and
 | |
|                              $_ =~ /Bcast:(\d+\.\d+\.\d+\.\d+)/ ) {
 | |
| 
 | |
|                             if ( $verbose ) {
 | |
|                                 trace( $request, "\t\t$1\tUP,$mode" );
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                     if ( $_ =~ /^\s*inet addr:\s*(\d+\.\d+\.\d+\.\d+)/ ) {
 | |
|                         $ip_addr{$1} = 1;
 | |
| 
 | |
|                         if ( exists( $opt{m} )) {
 | |
|                             trace( $request, "\t\t$1\tUP,$mode" );
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     if ( (keys %ip_addr) == 0 ) {
 | |
|         return( [1,"No adapters configured for $mode"] );
 | |
|     }
 | |
|     #########################
 | |
|     # Log results
 | |
|     #########################
 | |
|     if ( $verbose ) {
 | |
|         if ( (keys %ip_addr) == 0 ) {
 | |
|             trace( $request, "$cmd\n$result" );
 | |
|         }
 | |
|     }
 | |
|     return([0]);
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Determine adapters available - slp_query always used broadcast IP
 | |
| ##########################################################################
 | |
| sub slpquery_ifconfig {
 | |
| 
 | |
|     my $request = shift;
 | |
|     my $cmd     = "ifconfig -a";
 | |
|     my $result  = `$cmd`;
 | |
|     my $mode    = "BROADCAST";
 | |
| 
 | |
|     ######################################
 | |
|     # Error running command
 | |
|     ######################################
 | |
|     if ( !$result ) {
 | |
|         return( [1, "Error running '$cmd': $!"] );
 | |
|     }
 | |
|     if ( $verbose ) {
 | |
|         trace( $request, $cmd );
 | |
|         trace( $request, "$mode Interfaces:" );
 | |
|     }
 | |
|     if (xCAT::Utils->isAIX()) {
 | |
|         ##############################################################
 | |
|         # Should look like this for AIX:
 | |
|         # en0: flags=4e080863,80<UP,BROADCAST,NOTRAILERS,RUNNING,
 | |
|         #      SIMPLEX,MULTICAST,GROUPRT,64BIT,PSEG,CHAIN>
 | |
|         #      inet 30.0.0.1    netmask 0xffffff00 broadcast 30.0.0.255
 | |
|         #      inet 192.168.2.1 netmask 0xffffff00 broadcast 192.168.2.255
 | |
|         # en1: ...
 | |
|         #
 | |
|         ##############################################################
 | |
|         my @adapter = split /\w+\d+:\s+flags=/, $result;
 | |
|         foreach ( @adapter ) {
 | |
|             if ( !($_ =~ /LOOPBACK/ ) and
 | |
|                    $_ =~ /UP(,|>)/ and
 | |
|                    $_ =~ /$mode/ ) {
 | |
| 
 | |
|                 my @ip = split /\n/;
 | |
|                 foreach ( @ip ) {
 | |
|                     if ( $_ =~ /^\s*inet\s+/ and
 | |
|                          $_ =~ /broadcast\s+(\d+\.\d+\.\d+\.\d+)/ ) {
 | |
|                         $ip_addr{$1} = 1;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         ##############################################################
 | |
|         # Should look like this for Linux:
 | |
|         # eth0 Link encap:Ethernet  HWaddr 00:02:55:7B:06:30
 | |
|         #      inet addr:9.114.154.193  Bcast:9.114.154.223
 | |
|         #      inet6 addr: fe80::202:55ff:fe7b:630/64 Scope:Link
 | |
|         #      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
 | |
|         #      RX packets:1280982 errors:0 dropped:0 overruns:0 frame:0
 | |
|         #      TX packets:3535776 errors:0 dropped:0 overruns:0 carrier:0
 | |
|         #      collisions:0 txqueuelen:1000
 | |
|         #      RX bytes:343489371 (327.5 MiB)  TX bytes:870969610 (830.6 MiB)
 | |
|         #      Base address:0x2600 Memory:fbfe0000-fc0000080
 | |
|         #
 | |
|         # eth1 ...
 | |
|         #
 | |
|         ##############################################################
 | |
|         my @adapter= split /\n{2,}/, $result;
 | |
|         foreach ( @adapter ) {
 | |
|             if ( !($_ =~ /LOOPBACK / ) and
 | |
|                    $_ =~ /UP / and
 | |
|                    $_ =~ /$mode / ) {
 | |
| 
 | |
|                 my @ip = split /\n/;
 | |
|                 foreach ( @ip ) {
 | |
|                     if ( $_ =~ /^\s*inet addr:/ and
 | |
|                          $_ =~ /Bcast:(\d+\.\d+\.\d+\.\d+)/ ) {
 | |
|                         $ip_addr{$1} = 1;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     if ( (keys %ip_addr) == 0 ) {
 | |
|         return( [1,"No adapters configured for $mode"] );
 | |
|     }
 | |
|     #########################
 | |
|     # Log results
 | |
|     #########################
 | |
|     if ( $verbose ) {
 | |
|         foreach ( keys %ip_addr ) {
 | |
|             trace( $request, "\t\t$_\tUP,BROADCAST" );
 | |
|         }
 | |
|         if ( (keys %ip_addr) == 0 ) {
 | |
|             trace( $request, "$cmd\n$result" );
 | |
|         }
 | |
|     }
 | |
|     return([0]);
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Forks a process to run the slp command (1 per adapter)
 | |
| ##########################################################################
 | |
| sub fork_cmd {
 | |
| 
 | |
|     my $request  = shift;
 | |
|     my $ip       = shift;
 | |
|     my $arg      = shift;
 | |
|     my $services = shift;
 | |
| 
 | |
|     #######################################
 | |
|     # Pipe childs output back to parent
 | |
|     #######################################
 | |
|     my $parent;
 | |
|     my $child;
 | |
|     pipe $parent, $child;
 | |
|     my $pid = xCAT::Utils->xfork();
 | |
| 
 | |
|     if ( !defined($pid) ) {
 | |
|         ###################################
 | |
|         # Fork error
 | |
|         ###################################
 | |
|         send_msg( $request, 1, "Fork error: $!" );
 | |
|         return undef;
 | |
|     }
 | |
|     elsif ( $pid == 0 ) {
 | |
|         ###################################
 | |
|         # Child process
 | |
|         ###################################
 | |
|         close( $parent );
 | |
|         $request->{pipe} = $child;
 | |
| 
 | |
|         invoke_cmd( $request, $ip, $arg, $services );
 | |
|         exit(0);
 | |
|     }
 | |
|     else {
 | |
|         ###################################
 | |
|         # Parent process
 | |
|         ###################################
 | |
|         close( $child );
 | |
|         return( $parent );
 | |
|     }
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Run the forked command and send reply to parent
 | |
| ##########################################################################
 | |
| sub invoke_cmd {
 | |
| 
 | |
|     my $request  = shift;
 | |
|     my $ip       = shift;
 | |
|     my $args     = shift;
 | |
|     my $services = shift;
 | |
| 
 | |
|     ########################################
 | |
|     # Telnet (rspconfig) command
 | |
|     ########################################
 | |
|     if ( !defined( $services )) {
 | |
|         my $target_dev = $args->{$ip};
 | |
|         my @cmds;
 | |
|         my $result;
 | |
|         if ( $verbose ) {
 | |
|             trace( $request, "Forked: ($ip)->($target_dev->{args})" );
 | |
|         }
 | |
|         if ($target_dev->{'type'} eq 'mm')
 | |
|         {
 | |
|             @cmds = (
 | |
|                     "snmpcfg=enable",
 | |
|                     "sshcfg=enable",
 | |
|                     "network_reset=$target_dev->{args}"
 | |
|                     );
 | |
|             $result = xCAT_plugin::blade::telnetcmds(
 | |
|                     $ip,
 | |
|                     $target_dev->{username},
 | |
|                     $target_dev->{password},
 | |
|                     0,
 | |
|                     @cmds );
 | |
|         }
 | |
|         elsif($target_dev->{'type'} eq 'hmc')
 | |
|         {
 | |
|             @cmds = ("network_reset=$target_dev->{args}");
 | |
|             trace( $request, "sshcmds on hmc $ip");
 | |
|             $result = xCAT::PPC::sshcmds_on_hmc(
 | |
|                     $ip,
 | |
|                     $target_dev->{username},
 | |
|                     $target_dev->{password},
 | |
|                     @cmds );
 | |
|        }
 | |
|         else #The rest must be fsp or bpa
 | |
|         {
 | |
|             @cmds = ("network=$ip,$target_dev->{args}");
 | |
|             trace( $request, "update config on $target_dev->{'type'} $ip");
 | |
|             $result = xCAT::PPC::updconf_in_asm(
 | |
|                     $ip,
 | |
|                     $target_dev,
 | |
|                     @cmds );
 | |
|         }
 | |
| 
 | |
|         ####################################
 | |
|         # Pass result array back to parent
 | |
|         ####################################
 | |
|         my @data = ("RSPCONFIG6sK4ci", $ip, @$result[0], @$result[2]);
 | |
|         my $out = $request->{pipe};
 | |
| 
 | |
| 
 | |
|         print $out freeze( \@data );
 | |
|         print $out "\nENDOFFREEZE6sK4ci\n";
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     ########################################
 | |
|     # SLP command
 | |
|     ########################################
 | |
|     my $result  = runslp( $args, $ip, $services, $request );
 | |
|     my $unicast = @$result[0];
 | |
|     my $values  = @$result[1];
 | |
|     #prt_result( $request, $values);
 | |
| 
 | |
|     ########################################
 | |
|     # May have to send additional unicasts
 | |
|     ########################################
 | |
|     if ( keys (%$unicast) )  {
 | |
|         foreach my $url ( keys %$unicast ) {
 | |
|             my ($service,$addr) = split "://", $url;
 | |
|             next if ($addr =~ /:/);#skip IPV6
 | |
| 
 | |
|             ####################################
 | |
|             # Strip off trailing ",lifetime"
 | |
|             ####################################
 | |
|             $addr =~ s/,*\d*$//;
 | |
|             my $sockaddr = inet_aton( $addr );
 | |
|             $url =~ s/,*\d*$//;
 | |
| 
 | |
|             ####################################
 | |
|             # Make sure can resolve if hostname
 | |
|             ####################################
 | |
|             if  ( !defined( $sockaddr )) {
 | |
|                 if ( $verbose ) {
 | |
|                     trace( $request, "Cannot convert '$addr' to dot-notation" );
 | |
|                 }
 | |
|                 next;
 | |
|             }
 | |
|             $addr = inet_ntoa( $sockaddr );
 | |
| 
 | |
|             ####################################
 | |
|             # Select command format
 | |
|             ####################################
 | |
|             if ( $openSLP ) {
 | |
|                 $result = runslp( $args, $ip, [$url], $request, 1 );
 | |
|             } else {
 | |
|                 $result = runslp( $args, $addr, [$service], $request, 1 );
 | |
|             }
 | |
|             my $data   = @$result[1];
 | |
|             my ($attr) = keys %$data;
 | |
| 
 | |
|             ####################################
 | |
|             # Save results
 | |
|             ####################################
 | |
|             if ( defined($attr) ) {
 | |
|                 $values->{"URL: $url\n$attr\n"} = 1;
 | |
|                 prt_result( $values);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     ########################################
 | |
|     # Need to check if the result is enough
 | |
|     ########################################
 | |
|     if ( exists( $opt{C}) ) {
 | |
|         send_msg( $request, 0, "\n Begin to try again, this may takes long time \n" );
 | |
|         #my $uni_tmp = $unicast;
 | |
|         my %val_tmp = %$values;
 | |
|         my %found_cec;
 | |
|         for my $v (keys %val_tmp) {
 | |
|             $v =~ /type=([^\)]+)\)\,\(serial-number=([^\)]+)\)\,\(machinetype-model=([^\)]+)\)\,/;
 | |
|             if ( $found_cec{$2.'*'.$3} ne 1 and $1  eq SERVICE_FSP)  {
 | |
|                 $found_cec{$2.'*'.$3} = 1;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         my $rlt;
 | |
|         my $val;
 | |
|         my $start_time = Time::HiRes::gettimeofday();
 | |
|         my $elapse;
 | |
|         my $found = scalar(keys %found_cec);
 | |
|         while ( $found < $expect_ent ) {
 | |
|             $rlt = runslp( $args, $ip, $services, $request );
 | |
|             $val =  @$rlt[1];
 | |
|             for my $v (keys %$val) {
 | |
|                 $v =~ /type=([^\)]+)\)\,\(serial-number=([^\)]+)\)\,\(machinetype-model=([^\)]+)\)\,/;
 | |
|                 if ( $found_cec{$2.'*'.$3} ne 1 and $1  eq SERVICE_FSP)  {
 | |
|                     $found_cec{$2.'*'.$3} = 1;
 | |
|                     $val_tmp{$v} = 1;
 | |
|                 }
 | |
|             }
 | |
|             $found = scalar(keys %val_tmp);
 | |
|             $elapse = Time::HiRes::gettimeofday() - $start_time;
 | |
|             if ( $elapse > $time_out ) {
 | |
|                 send_msg( $request, 0, "Time out, Force return.\n" );
 | |
|                 last;
 | |
|             }
 | |
|         }
 | |
|         send_msg( $request, 0, "Discovered $found nodes \n" );
 | |
|         $values = \%val_tmp;
 | |
|         #my @re = [$uni_tmp, \%val_tmp];
 | |
|         #$result = \@re;
 | |
|     }
 | |
|     prt_result( $request, $values);
 | |
|     ########################################
 | |
|     # No valid responses received
 | |
|     ########################################
 | |
|     if (( keys (%$values )) == 0 ) {
 | |
|         return;
 | |
|     }
 | |
|     ########################################
 | |
|     # Pass result array back to parent
 | |
|     ########################################
 | |
|     my @results = ("FORMATDATA6sK4ci", $values );
 | |
|     my $out = $request->{pipe};
 | |
| 
 | |
|     print $out freeze( \@results );
 | |
|     print $out "\nENDOFFREEZE6sK4ci\n";
 | |
| }
 | |
| 
 | |
| #########################################################
 | |
| # print the slp result
 | |
| #########################################################
 | |
| sub prt_result
 | |
| {
 | |
|     my $request = shift;
 | |
|     my $values = shift;
 | |
|     my $nets = xCAT::Utils::my_nets();
 | |
|     for my $v (keys %$values)
 | |
|     {
 | |
|         # remove the process of finding ping-able ip to save time.
 | |
|         #if ( $v =~ /ip-address=([^\)]+)/g)
 | |
|         if ($v =~ /.*URL: .*\:\/\/(\d+\.\d+\.\d+\.\d+)/)
 | |
|         {
 | |
|             #my $iplist = $1;
 | |
|             #my $ip = getip_from_iplist( $iplist, $nets, $opt{i});
 | |
|             my $ip = $1;
 | |
|             if ( $ip)
 | |
|             {
 | |
|                 #send_msg($request, "Received SLP response from $ip.");
 | |
|                 #print "Received SLP response from $ip.\n";
 | |
|                 xCAT::MsgUtils->message("I", "Received SLP response from $ip.", $::callback);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Run the SLP command, process the response, and send to parent
 | |
| ##########################################################################
 | |
| sub runslp {
 | |
| 
 | |
|     my $slpcmd   = shift;
 | |
|     my $ip       = shift;
 | |
|     my $services = shift;
 | |
|     my $request  = shift;
 | |
|     my $attreq   = shift;
 | |
|     my %result   = ();
 | |
|     my %unicast  = ();
 | |
|     my $cmd;
 | |
| 
 | |
|     foreach my $type ( @$services ) {
 | |
|         my $try = 0;
 | |
| 
 | |
|         ###########################################
 | |
|         # OpenSLP - slptool command
 | |
|         ###########################################
 | |
|         if ( $openSLP ) {
 | |
|             $cmd = $attreq ?
 | |
|                "$slpcmd findattrsusingiflist $ip $type" :
 | |
|                "$slpcmd findsrvsusingiflist $ip $type";
 | |
|         }
 | |
|         ###########################################
 | |
|         # IBM SLP - slp_query command
 | |
|         ###########################################
 | |
|         else {
 | |
|             $cmd = $attreq ?
 | |
|                "$slpcmd --address=$ip --type=$type" :
 | |
|                "$slpcmd --address=$ip --type=$type --converge=1";
 | |
|         }
 | |
| 
 | |
|         ###########################################
 | |
|         # Run the command
 | |
|         ###########################################
 | |
|         while ( $try++ < $maxtries ) {
 | |
|             if ( $verbose ) {
 | |
|                 trace( $request, $cmd );
 | |
|                 trace( $request, "Attempt $try of $maxtries\t( $ip\t$type )" );
 | |
|             }
 | |
|             #######################################
 | |
|             # Serialize transmits out each adapter
 | |
|             #######################################
 | |
|             if ( !open( OUTPUT, "$cmd 2>&1 |")) {
 | |
|                 send_msg( $request, 1, "Fork error: $!" );
 | |
|                 return undef;
 | |
|             }
 | |
|             ###############################
 | |
|             # Get command output
 | |
|             ###############################
 | |
|             my $rsp;
 | |
|             while ( <OUTPUT> ) {
 | |
|                 $rsp.=$_;
 | |
|             }
 | |
|             close OUTPUT;
 | |
| 
 | |
|             ###############################
 | |
|             # No replies
 | |
|             ###############################
 | |
|             if ( !$rsp ) {
 | |
|                 if ( $verbose ) {
 | |
|                     trace( $request, ">>>>>> No Response" );
 | |
|                 }
 | |
|                 next;
 | |
|             }
 | |
|             ###########################################
 | |
|             # For IVM, running AIX 53J (6/07) release,
 | |
|             # there is an AIX SLP bug where IVM will
 | |
|             # respond to SLP service-requests with its
 | |
|             # URL only and not its attributes. An SLP
 | |
|             # unicast to the URL address is necessary
 | |
|             # to acquire the attributes. This was fixed
 | |
|             # in AIX 53L (11/07).
 | |
|             #
 | |
|             ###########################################
 | |
| 
 | |
|             ###########################################
 | |
|             # OpenSLP response format:
 | |
|             #   service:management-software.IBM...
 | |
|             #   (type=hardware-management-cons...
 | |
|             #   (serial-number=KPHHK24),(name=c76v2h...
 | |
|             #   1ab1dd89ca8e0763e),(ip-address=192.1...
 | |
|             #   0CR3*KPHHK24),(web-management-interf...
 | |
|             #   2.ppd.pok.ibm.com:8443),(cimom-port=...
 | |
|             #   ...
 | |
|             ###########################################
 | |
|             if ( $openSLP ) {
 | |
|                 my @data = split /\n/,$rsp;
 | |
|                 my $length = scalar( @data );
 | |
|                 my $i = 0;
 | |
| 
 | |
|                 while ($i < $length ) {
 | |
|                     ###################################
 | |
|                     # Service-Request response
 | |
|                     ###################################
 | |
|                     if ( $data[$i] =~
 | |
|                         /^service\:management-(software|hardware)\.IBM\:([^\:]+)/) {
 | |
| 
 | |
|                         ###############################
 | |
|                         # Invalid service-type
 | |
|                         ###############################
 | |
|                         if ( !exists( $service_slp{$2} )) {
 | |
|                             if ( $verbose ) {
 | |
|                                 trace( $request, "DISCARDING: $data[$i]" );
 | |
|                             }
 | |
|                             $i++;
 | |
|                             next;
 | |
|                         }
 | |
|                         my $url  = $data[$i++];
 | |
|                         my $attr = $data[$i];
 | |
| 
 | |
|                         #Give some intermediate output
 | |
|                         my ($url_ip) = $url =~ /:\/\/(\d+\.\d+\.\d+\.\d+)/;
 | |
|                         if ( ! $::DISCOVERED_HOST{$url_ip})
 | |
|                         {
 | |
|                             $::DISCOVERED_HOST{$url_ip} = 1;
 | |
|                         }
 | |
|                         if ( $verbose ) {
 | |
|                             trace( $request, ">>>> SrvRqst Response" );
 | |
|                             trace( $request, "URL: $url" );
 | |
|                         }
 | |
|                         ###############################
 | |
|                         # No "ATTR" - have to unicast
 | |
|                         ###############################
 | |
|                         if ( $attr !~ /^(\(type=.*)$/ ) {
 | |
|                            $unicast{$url} = $url;
 | |
|                         }
 | |
|                         ###############################
 | |
|                         # Response has "ATTR" field
 | |
|                         ###############################
 | |
|                         else {
 | |
|                             if ( $verbose ) {
 | |
|                                 trace( $request, "ATTR: $attr\n" );
 | |
|                             }
 | |
|                             my $val = "URL: $url\nATTR: $attr";
 | |
|                             $result{$val} = 1;
 | |
|                             $i++;
 | |
|                         }
 | |
|                     }
 | |
|                     ###################################
 | |
|                     # Attribute-Request response
 | |
|                     ###################################
 | |
|                     elsif ( $data[$i] =~ /(\(type=.*)$/ ) {
 | |
|                         my $attr = "ATTR: $data[$i++]";
 | |
| 
 | |
|                         if ( $verbose ) {
 | |
|                             trace( $request, ">>>> AttrRqst Response" );
 | |
|                             trace( $request, $attr );
 | |
|                         }
 | |
|                         $result{$attr} = 1;
 | |
|                     }
 | |
|                     ###################################
 | |
|                     # Unrecognized response
 | |
|                     ###################################
 | |
|                     else {
 | |
|                         if ( $verbose ) {
 | |
|                             trace( $request, "DISCARDING: $data[$i]" );
 | |
|                         }
 | |
|                         $i++;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             ###########################################
 | |
|             # IBM SLP response format:
 | |
|             #   0
 | |
|             #   1
 | |
|             #   75
 | |
|             #   URL: service:management-software.IBM...
 | |
|             #   ATTR: (type=hardware-management-cons...
 | |
|             #   (serial-number=KPHHK24),(name=c76v2h...
 | |
|             #   1ab1dd89ca8e0763e),(ip-address=192.1...
 | |
|             #   0CR3*KPHHK24),(web-management-interf...
 | |
|             #   2.ppd.pok.ibm.com:8443),(cimom-port=...
 | |
|             #
 | |
|             #   0
 | |
|             #   1
 | |
|             #   69
 | |
|             #   URL:...
 | |
|             #   ATTR:..
 | |
|             #   ..
 | |
|             ###########################################
 | |
|             else {
 | |
|                 foreach ( split /\n{2,}/,$rsp ) {
 | |
|                     if ( $_ =~ s/(\d+)\n(\d+)\n(\d+)\n// ) {
 | |
|                         if ( $verbose ) {
 | |
|                             trace( $request, "SrvRqst Response ($1)($2)($3)" );
 | |
|                             trace( $request, "$_\n" );
 | |
|                         }
 | |
|                         ###############################
 | |
|                         # Response has "ATTR" field
 | |
|                         ###############################
 | |
|                         if ( /ATTR: /  ) {
 | |
|                             $result{$_} = 1;
 | |
|                         }
 | |
|                         ###############################
 | |
|                         # No "ATTR" - have to unicast
 | |
|                         ###############################
 | |
|                         elsif ( /.*URL: (.*)/ ) {
 | |
|                             $unicast{$1} = $1;
 | |
|                         }
 | |
|                     }
 | |
|                     elsif ( $verbose ) {
 | |
|                         trace( $request, "DISCARDING: $_" );
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return( [\%unicast,\%result] );
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Formats slp responses
 | |
| ##########################################################################
 | |
| sub format_output {
 | |
| 
 | |
|     my $request = shift;
 | |
|     my $values  = shift;
 | |
|     my $length  = length( $header[IP_ADDRESSES][TEXT] );
 | |
|     my $result;
 | |
| 
 | |
|     ###########################################
 | |
|     # Parse responses and add to hash
 | |
|     ###########################################
 | |
|     my $outhash = parse_responses( $request, $values, \$length );
 | |
| 
 | |
| 
 | |
|     ###########################################
 | |
|     # filter the result and keep the specified nodes
 | |
|     ###########################################
 | |
|     if ( scalar(@filternodes)) {
 | |
|         my $outhash1 = filter( $outhash );
 | |
|         $outhash = $outhash1;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     ###########################################
 | |
|     # filter the result in the same vlan
 | |
|     ###########################################
 | |
|     if ( exists( $opt{i} )) {
 | |
|         my $outhash1 = filtersamevlan( $outhash );
 | |
|         $outhash = $outhash1;
 | |
|     }
 | |
| 
 | |
|     ###########################################
 | |
|     # No responses
 | |
|     ###########################################
 | |
|     if (( keys %$outhash ) == 0 ){
 | |
|         send_msg( $request, 0, "No responses" );
 | |
|         return;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     ###########################################
 | |
|     # -w flag for write to xCat database
 | |
|     ###########################################
 | |
|     if ( exists( $opt{w} )) {
 | |
|         send_msg( $request, 0, "Begin to write into Database, this may change node name" );
 | |
|         xCATdB( $outhash );
 | |
|     }
 | |
| 
 | |
|     ###########################################
 | |
|     # --makedhcp flag to issue xCAT command
 | |
|     # makedhcp internally.
 | |
|     ###########################################
 | |
|     if ( exists( $opt{makedhcp} ) ) {
 | |
|         do_makedhcp( $request, $outhash );
 | |
|     }
 | |
| 
 | |
|     ###########################################
 | |
|     # --resetnet flag to reset the network
 | |
|     # interface of the node
 | |
|     ###########################################
 | |
|     if ( exists( $opt{resetnet} ) ) {
 | |
|         #do_resetnet( $request, $outhash );
 | |
|         send_msg( $request, 0, "the flag --resetnet has been moved to rspconfig, please see the rspconfig man page for more details" );
 | |
|     }
 | |
| 
 | |
|     ###########################################
 | |
|     # -I flat give the warning message for
 | |
|     # the no-response nodes
 | |
|     ###########################################
 | |
|     if ( exists( $opt{I} ) ) {
 | |
|         my $outresult = integrity_check( $outhash );
 | |
|         if ($outresult)
 | |
|         {
 | |
|             send_msg( $request, 0, $outresult );
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     ###########################################
 | |
|     # -r flag for raw response format
 | |
|     ###########################################
 | |
|     my %rawhash = ();
 | |
|     if ( exists( $opt{r} )) {
 | |
|         foreach ( keys %$outhash ) {
 | |
|             #$result .= "@{ $outhash->{$_}}[9]\n";
 | |
|             my $raw = @{$outhash->{$_}}[9];
 | |
|             $rawhash{$raw} = 1;
 | |
|         }
 | |
| 
 | |
|         foreach ( keys %rawhash ) {
 | |
|             $result .= "$_\n";
 | |
|         }
 | |
| 
 | |
|         send_msg( $request, 0, $result );
 | |
|         return;
 | |
|     }
 | |
|     ###########################################
 | |
|     # -x flag for xml format
 | |
|     ###########################################
 | |
|     if ( exists( $opt{x} )) {
 | |
|         send_msg( $request, 0, format_xml( $outhash ));
 | |
|         return;
 | |
|     }
 | |
|     ###########################################
 | |
|     # -z flag for stanza format
 | |
|     ###########################################
 | |
|     if ( exists( $opt{z} )) {
 | |
|         send_msg( $request, 0, format_stanza( $outhash ));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     ###########################################
 | |
|     # -T flag for vpd table format
 | |
|     ###########################################
 | |
|     if ( exists( $opt{vpdtable} ) ) {
 | |
|         send_msg( $request, 0, format_table( $outhash ) );
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     ###########################################
 | |
|     # Get longest IP for formatting purposes
 | |
|     ###########################################
 | |
|     my $format = sprintf "%%-%ds", ( $length + 2 );
 | |
|     $header[IP_ADDRESSES][FORMAT] = $format;
 | |
| 
 | |
|     ###########################################
 | |
|     # Display header
 | |
|     ###########################################
 | |
|     foreach ( @header ) {
 | |
|         $result .= sprintf @$_[1], @$_[0];
 | |
|     }
 | |
|     $result .= "\n";
 | |
| 
 | |
|     ###########################################
 | |
|     # Display response attributes
 | |
|     ###########################################
 | |
|     foreach my $hostname ( sort keys %$outhash ) {
 | |
|         my $data = $outhash->{$hostname};
 | |
|         my $i = 0;
 | |
| 
 | |
|         foreach ( @header ) {
 | |
|             if ( @$_[0] =~ /^hostname$/ ) {
 | |
|                 $result .= sprintf @$_[1], $hostname;
 | |
|             } else {
 | |
|                 $result .= sprintf @$_[1], @$data[$i++];
 | |
|             }
 | |
|         }
 | |
|         $result .= "\n";
 | |
|     }
 | |
|     send_msg( $request, 0, $result );
 | |
| }
 | |
| ##########################################################################
 | |
| # Give the warning message for the no-response nodes
 | |
| ##########################################################################
 | |
| sub integrity_check {
 | |
|     my $datahash = shift;
 | |
|     my $findflag = 0;
 | |
|     my $result;
 | |
| 
 | |
|     foreach my $existnode ( keys %::OLD_DATA_CACHE )
 | |
|     {
 | |
|         my $tmptype = uc(@{$::OLD_DATA_CACHE{$existnode}}[6]);
 | |
|         my $tmpmtm  = @{$::OLD_DATA_CACHE{$existnode}}[0];
 | |
|         my $tmpsn   = @{$::OLD_DATA_CACHE{$existnode}}[1];
 | |
|         my $tmpside = @{$::OLD_DATA_CACHE{$existnode}}[2];
 | |
|         if ( $tmptype eq TYPE_CEC or $tmptype eq TYPE_FRAME or  $tmptype =~ /lpar/ )
 | |
|         {
 | |
|             next;
 | |
|         }
 | |
|         $findflag = 0;
 | |
|         foreach my $foundnode ( keys %$datahash )
 | |
|         {
 | |
|             my $newdata = $datahash->{$foundnode};
 | |
|             my $newtype = @$newdata[0];
 | |
|             my $newmtm  = @$newdata[1];
 | |
|             my $newsn   = @$newdata[2];
 | |
|             my $newside = @$newdata[3];
 | |
| 
 | |
|             if( !$foundnode or !$newtype or !$newtype or !$newsn )
 | |
|             {
 | |
|                 next;
 | |
|             }
 | |
|             if ( ($newtype eq $tmptype) and ($tmptype eq TYPE_BPA or $tmptype eq TYPE_FSP) )
 | |
|             {
 | |
|                 # begin to match fsp/bpa
 | |
|                 if (($newmtm eq $tmpmtm) and ($newsn eq $tmpsn) and ($newside eq $tmpside))
 | |
|                 {
 | |
|                     $findflag = 1;
 | |
|                     last;
 | |
|                 }
 | |
|             }elsif ( ($newtype eq $tmptype) and ($tmptype eq TYPE_HMC) )
 | |
|             {
 | |
|                 # begin to match hmc
 | |
|                 if (($newmtm eq $tmpmtm) and ($newsn eq $tmpsn))
 | |
|                 {
 | |
|                     $findflag = 1;
 | |
|                     last;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if ($findflag eq 0 and $existnode ne "")
 | |
|         {
 | |
|             $result .= "\n Warning: The node $existnode has no response. \n";
 | |
|         }
 | |
|     }
 | |
|     return $result;
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Get IP from SLP URL response
 | |
| ##########################################################################
 | |
| sub getip_from_url {
 | |
| 
 | |
|     my $request = shift;
 | |
|     my $url     = shift;
 | |
| 
 | |
|     ######################################################################
 | |
|     # Extract the IP from the URL. Generally, the URL
 | |
|     # should be in the following format (the ":0" port number
 | |
|     # may or may not be present):
 | |
|     # service:management-hardware.IBM:management-module://9.114.113.78:0
 | |
|     # service:management-software.IBM:integrated-virtualization-manager://zd21p1.rchland.ibm.com
 | |
|     ######################################################################
 | |
|     if (($url !~ /service:.*:\/\/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*/ )) {
 | |
|         return undef;
 | |
|     }
 | |
|     return( $1 );
 | |
| }
 | |
| 
 | |
| sub read_from_table {
 | |
|     my %idhash;
 | |
|     my %typehash;
 | |
|     my %iphash;
 | |
|     my %vpdhash;
 | |
|     if ( !defined(%::OLD_DATA_CACHE))
 | |
|     {
 | |
|         # find out all the existed nodes' ipaddresses
 | |
|         my $hoststab  = xCAT::Table->new('hosts');
 | |
|         if ( $hoststab ) {
 | |
|             my @ipentries = $hoststab->getAllNodeAttribs( ['node','ip'] );
 | |
|             for my $ipentry ( @ipentries ) {
 | |
|                 $iphash{$ipentry->{node}} = $ipentry->{ip};
 | |
|             }
 | |
|         } else {
 | |
|             return 1;
 | |
|         }
 | |
| 
 | |
|         #find out all the existed nodes' type
 | |
|         my $nodetypetab  = xCAT::Table->new('nodetype');
 | |
|         if ( $nodetypetab ) {
 | |
|             my @typeentries = $nodetypetab->getAllNodeAttribs( ['node','nodetype'] );
 | |
|             for my $typeentry ( @typeentries) {
 | |
|                 $typehash{$typeentry->{node}} = $typeentry->{nodetype};
 | |
|             }
 | |
|         } else {
 | |
|             return 2;
 | |
|         }
 | |
| 
 | |
|         # find out all the existed nodes' mtms and side
 | |
|         my $vpdtab  = xCAT::Table->new( 'vpd' );
 | |
|         if ( $vpdtab )  {
 | |
|             my @vpdentries = $vpdtab->getAllNodeAttribs(['node','mtm','serial','side']);
 | |
|             for my $entry ( @vpdentries ) {
 | |
|                 @{$vpdhash{$entry->{node}}}[0] = $entry->{mtm};
 | |
|                 @{$vpdhash{$entry->{node}}}[1] = $entry->{serial}; 
 | |
|                 @{$vpdhash{$entry->{node}}}[2] = $entry->{side};
 | |
|             }
 | |
|         } else {
 | |
|             return 3;
 | |
|         }
 | |
|         # find out all the existed nodes' attributes
 | |
|         my $ppctab  = xCAT::Table->new('ppc');
 | |
|         if ( $ppctab ) {
 | |
|             my @identries = $ppctab->getAllNodeAttribs( ['node','id','parent','nodetype'] );
 | |
|             for my $entry ( @identries ) {
 | |
|                 next if ($entry->{nodetype} =~ /lpar/);
 | |
|                 @{$::OLD_DATA_CACHE{$entry->{node}}}[0] = @{$vpdhash{$entry->{node}}}[0];#mtm
 | |
|                 @{$::OLD_DATA_CACHE{$entry->{node}}}[1] = @{$vpdhash{$entry->{node}}}[1];#sn
 | |
|                 @{$::OLD_DATA_CACHE{$entry->{node}}}[2] = @{$vpdhash{$entry->{node}}}[2];#side
 | |
|                 # find node ip address, check node name first, then check hosts table
 | |
|                 my $ifip = xCAT::Utils->isIpaddr($entry->{node});
 | |
|                 if ( $ifip )
 | |
|                 {
 | |
|                     @{$::OLD_DATA_CACHE{$entry->{node}}}[3] = $entry->{node};#ip
 | |
|                 } else
 | |
|                 {
 | |
|                     if ( exists ($iphash{$entry->{node}}) ) {
 | |
|                        @{$::OLD_DATA_CACHE{$entry->{node}}}[3] = $iphash{$entry->{node}};#ip
 | |
|                     }
 | |
|                     else  {
 | |
|                         @{$::OLD_DATA_CACHE{$entry->{node}}}[3] = "";#ip
 | |
|                     }
 | |
|                 }
 | |
|                 @{$::OLD_DATA_CACHE{$entry->{node}}}[4] = $entry->{id};#id
 | |
|                 @{$::OLD_DATA_CACHE{$entry->{node}}}[5] = $entry->{parent};#parent
 | |
|                 if ( exists $entry->{nodetype}) {
 | |
|                     @{$::OLD_DATA_CACHE{$entry->{node}}}[6] = $entry->{nodetype};#nodetype
 | |
|                 } else {
 | |
|                     if ( exists ($typehash{$entry->{node}}) ) {
 | |
|                         @{$::OLD_DATA_CACHE{$entry->{node}}}[6] = $typehash{$entry->{node}};
 | |
|                     } else {
 | |
|                         @{$::OLD_DATA_CACHE{$entry->{node}}}[6] = "";
 | |
|                     }
 | |
|                 }    
 | |
|                 @{$::OLD_DATA_CACHE{$entry->{node}}}[7] = 1;
 | |
|             }
 | |
|         } else
 | |
|         {
 | |
|             return 4;
 | |
|         }
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #############################################################################
 | |
| # Get hostname from SLP URL response and match databse meanwhile
 | |
| # used for FSP/BPA redundancy database migration
 | |
| # if return something, it means it will use the old data name
 | |
| # or new data name
 | |
| # if return undef, it means the ip is not invalid and won't make any definition
 | |
| # the global variable %::OLD_DATA_CACHE contans all the data
 | |
| # the global variable %::UPDATE_CACHE records the data need to change name
 | |
| #############################################################################
 | |
| sub gethost_from_url_or_old {
 | |
|     my $nodename        = shift;
 | |
|     my $type            = shift;
 | |
|     my $mtm             = shift;
 | |
|     my $sn              = shift;
 | |
|     my $side            = shift;
 | |
|     my $ip              = shift;
 | |
|     my $cage_number     = shift;
 | |
|     my $parmtm          = shift;
 | |
|     my $parsn           = shift;
 | |
|     my $pname           = shift;
 | |
|     my $flagref         = shift;
 | |
| 
 | |
|     #######################################
 | |
|     # Extract IP from URL
 | |
|     #######################################
 | |
|     if ($ip)
 | |
|     {
 | |
|         my $nets = xCAT::Utils::my_nets();
 | |
|         my $avip = getip_from_iplist( $ip, $nets, $opt{i});
 | |
|         #if ( !defined( $ip )) {
 | |
|         #    return undef;
 | |
|         #}
 | |
|     }
 | |
|     # get the information of existed nodes to do the migration
 | |
| 
 | |
| 
 | |
|     if (($type eq TYPE_BPA or $type eq TYPE_FSP) and  $pname)
 | |
|     {
 | |
|         $enter_time = ($enter_time + 1) % 2;
 | |
|     }
 | |
| 
 | |
|     read_from_table() unless (%::OLD_DATA_CACHE);
 | |
| 
 | |
|     foreach my $oldnode ( keys %::OLD_DATA_CACHE )
 | |
|     {
 | |
|         my $tmpmtm    = @{$::OLD_DATA_CACHE{$oldnode}}[0];
 | |
|         my $tmpsn     = @{$::OLD_DATA_CACHE{$oldnode}}[1];
 | |
|         my $tmpside   = @{$::OLD_DATA_CACHE{$oldnode}}[2];
 | |
|         my $tmpip     = @{$::OLD_DATA_CACHE{$oldnode}}[3];
 | |
|         my $tmpid     = @{$::OLD_DATA_CACHE{$oldnode}}[4];
 | |
|         my $tmpparent = @{$::OLD_DATA_CACHE{$oldnode}}[5];
 | |
|         my $tmptype   = uc(@{$::OLD_DATA_CACHE{$oldnode}}[6]);
 | |
|         my $unmatched = @{$::OLD_DATA_CACHE{$oldnode}}[7];
 | |
| 
 | |
|         # used to match fsp defined by xcatsetup
 | |
|         # should return fast to save time
 | |
|         if (($type eq TYPE_BPA or $type eq TYPE_FSP) and ($tmptype eq $type) and $pname and $side) {
 | |
|             if ($pname eq $tmpparent and $side eq $tmpside)  {
 | |
|                 $$flagref = 1;
 | |
|                 print "1 got old name $oldnode \n" if($DEBUG_MATCH eq 1);                
 | |
|                 return $oldnode;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         # match the existed nodes including old data and user defined data
 | |
|         if ( ($type eq TYPE_BPA or $type eq TYPE_FSP) and ($tmptype eq $type)) {
 | |
|             unless ($tmpmtm) {
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             if ( $tmpmtm eq $mtm  and  $tmpsn eq $sn) {
 | |
|                 my $ifip = xCAT::Utils->isIpaddr($oldnode);
 | |
|                 if ( $ifip )  {# which means that the node is defined by the new lsslp
 | |
|                     if ( $tmpside eq $side ) {# match! which means that node is the same as the new one
 | |
|                         if ( $ip eq $tmpip ) { #which means that the ip is not changed
 | |
|                             # maybe we should check if the ip is invalid and send a warning
 | |
|                             $$flagref = 1;
 | |
|                             print "2 got old name $ip\n" if($DEBUG_MATCH eq 1); 
 | |
|                             return $ip;
 | |
|                         }  else { #which means that the ip is changed
 | |
|                             my $vip = check_ip($ip);
 | |
|                             if ( !$vip )  { #which means the ip is changed and valid
 | |
|                                 # maybe we should check if the old ip is invalid and send a warning
 | |
|                                 # even so we should keep the definition as before
 | |
|                                 # because this case, we can't put check_ip in the end
 | |
|                                 $$flagref = 1;
 | |
|                                 print "3 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                                 return $oldnode;
 | |
|                             } else {
 | |
|                                 return $ip;
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 else { # name is not a ip
 | |
|                     $side =~ /(\w)\-(\w)/;
 | |
|                     my $slot = $1;
 | |
|                     if ( $tmpside and $tmpside !~ /\-/ )  {# side is like A or B
 | |
|                         if ( $slot eq $tmpside ) {
 | |
|                             if ( $oldnode =~ /^Server\-/)  {#judge if need to change node's name
 | |
|                                 if ( $ip eq $tmpip ) {
 | |
|                                     if ( $oldnode =~ /\-(A|B)$/) {
 | |
|                                         @{$::OLD_DATA_CACHE{$oldnode}}[7] = 0;
 | |
|                                         $$flagref = 1;
 | |
|                                         print "4 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                                         return  $oldnode;
 | |
|                                     } else {
 | |
|                                         @{$::OLD_DATA_CACHE{$oldnode}}[7] = 0;
 | |
|                                         #change node name, need to record the node here
 | |
|                                         $::UPDATE_CACHE{$mtm.'-'.$sn} = $oldnode;
 | |
|                                         $$flagref = 1;
 | |
|                                         print "5 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                                         return $oldnode.'-'.$slot;
 | |
|                                     }
 | |
|                                 } else   {# not find a matched definition, but need to use the old node name
 | |
|                                     if ( $enter_time eq 0 and $unmatched){
 | |
|                                         $$flagref = 1;
 | |
|                                         print "6 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                                         return $oldnode;
 | |
|                                     }
 | |
|                                 }
 | |
|                             } elsif ( $tmpside =~ /\-/ )  {# end of if ( $oldnode =~ /^Server\-/)
 | |
|                                 if ( $ip eq $tmpip ) {
 | |
|                                     @{$::OLD_DATA_CACHE{$oldnode}}[7] = 0;
 | |
|                                     $$flagref = 1;
 | |
|                                     print "7 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                                     return $oldnode;
 | |
|                                 } else{
 | |
|                                     if ( $enter_time eq 0 and $unmatched){
 | |
|                                         $$flagref = 1;
 | |
|                                         print "8 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                                         return $oldnode;
 | |
|                                     }
 | |
|                                 }
 | |
|                             }
 | |
|                         }
 | |
|                     } elsif ( $tmpside =~ /\-/ ){
 | |
|                         if ( $side eq $tmpside ) {
 | |
|                             $$flagref = 1;
 | |
|                             print "9 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                             return $oldnode;
 | |
|                         }
 | |
|                     } elsif ( !$tmpside ) {
 | |
|                         if ( $oldnode =~ /^Server\-/)  {#judge if need to change node's name
 | |
|                             if ( $oldnode !~ /\-(A|B)$/ ) {
 | |
|                                 delete $::OLD_DATA_CACHE{$oldnode};
 | |
|                                 $$flagref = 1;
 | |
|                                 print "10 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                                 return $oldnode."-".$slot;
 | |
|                             }
 | |
|                         }
 | |
|                         # if mtms could match but side not defined, we will trate
 | |
|                         # it as the result by rscan. And alway use its name.
 | |
|                         delete $::OLD_DATA_CACHE{$oldnode};
 | |
|                         $$flagref = 1;
 | |
|                         print "11 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                         return $oldnode;
 | |
|                     }
 | |
|                 }
 | |
|             }# end of if ($tmpmtm eq $mtm  and  $tmpsn eq $sn)
 | |
| 
 | |
| 
 | |
|         } 
 | |
|         if ( ($type eq TYPE_FRAME or $type eq TYPE_CEC) and ($type eq $tmptype)){
 | |
|             if ( !$tmpmtm and !$tmpid)  {
 | |
|                 next;
 | |
|             }
 | |
|             # user may define cec only with parent /id /type
 | |
|             # we should match this situation
 | |
|             if ( ($type eq TYPE_CEC) and $parmtm and $parsn  and  $cage_number ) {
 | |
|                 my $tpparmtm = @{$::OLD_DATA_CACHE{$tmpparent}}[0];
 | |
|                 my $tpparsn  = @{$::OLD_DATA_CACHE{$tmpparent}}[1];
 | |
|                 if ( ($tpparmtm eq $parmtm) and ($tpparsn eq $parsn) and ($cage_number eq $tmpid) and ($type eq $tmptype) ) {
 | |
|                     $$flagref = 1;
 | |
|                     print "12 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                     return $oldnode;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             # user may define cec/frame only with mtms
 | |
|             # but what we consider here is just the data in xCAT 2.6
 | |
|             if ($tmpmtm eq $mtm  and  $tmpsn eq $sn and $tmptype eq $type)  {
 | |
|                 if ( $oldnode =~ /^Server\-/)  {#judge if need to change node's name
 | |
|                     if ( $oldnode =~ /(\-A)$/) {
 | |
|                         $nodename = s/(\-A)$//;
 | |
|                         # should send a warning here
 | |
|                         $$flagref = 1;
 | |
|                         print "13 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                         return $nodename;
 | |
|                     }
 | |
|                     else  {
 | |
|                         $$flagref = 1;
 | |
|                         print "14 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                         return $oldnode;
 | |
|                     }
 | |
|                 } else {
 | |
|                     $$flagref = 1;
 | |
|                     print "15 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                     return $oldnode;
 | |
|                 }
 | |
|             }
 | |
|         } # end of foreach my $oldnode ( keys %::OLD_DATA_CACHE ), not match
 | |
|     }
 | |
| 
 | |
|     # not matched, use the new name
 | |
|     my $ifip = xCAT::Utils->isIpaddr($nodename);
 | |
|     unless ($ifip) {
 | |
|         return $nodename;
 | |
|     }else {
 | |
|         my $vip = check_ip($nodename);
 | |
|         if ( $vip )   {#which means the ip is a valid one
 | |
|             return $nodename;
 | |
|         } else {
 | |
|             return undef;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Makesure the ip in SLP URL is valid
 | |
| # return 1 if valid, 0 if invalid
 | |
| ##########################################################################
 | |
| sub check_ip {
 | |
|     my $myip = shift;
 | |
|     my $firstoctet = $myip;
 | |
|     $firstoctet =~ s/^(\d+)\..*/$1/;
 | |
|     if ($firstoctet >= 224 and $firstoctet <= 239)
 | |
|     {
 | |
|         return 0;
 | |
|     }
 | |
|     foreach (@invalidiplist)
 | |
|     {
 | |
|         if ( $myip =~ /^($_)/ )
 | |
|         {
 | |
|             return 0;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return 1;
 | |
| }
 | |
| ##########################################################################
 | |
| # Get hostname from SLP URL response
 | |
| ##########################################################################
 | |
| sub gethost_from_url {
 | |
| 
 | |
|     my $request = shift;
 | |
|     my $rsp     = shift;
 | |
|     my $flag    = shift;
 | |
|     my $type    = shift;
 | |
|     my $mtm     = shift;
 | |
|     my $sn      = shift;
 | |
|     my $side    = shift;
 | |
|     my $iplist  = shift;
 | |
|     my $bpc_machinetype = shift;
 | |
|     my $bpc_serial      = shift;
 | |
|     my $frame_number    = shift;
 | |
|     my $cage_number     = shift;
 | |
|     my $host;
 | |
| 
 | |
| 
 | |
|     #######################################
 | |
|     # Extract IP from URL
 | |
|     #######################################
 | |
|     my $nets = xCAT::Utils::my_nets();
 | |
|     my $ip = getip_from_iplist( $iplist, $nets, $opt{i});
 | |
|     if ( !defined( $ip )) {
 | |
|         return undef;
 | |
|     }
 | |
| 
 | |
|     #######################################
 | |
|     # Check if valid IP
 | |
|     #######################################
 | |
|     my $packed = inet_aton( $ip );
 | |
|     if ( length( $packed ) != 4 ) {
 | |
|         if ( $verbose ) {
 | |
|             trace( $request, "Invalid IP address in URL: $ip" );
 | |
|         }
 | |
|         return undef;
 | |
|     }
 | |
| 
 | |
|     #######################################
 | |
|     # Get hostname from vpd table
 | |
|     #######################################
 | |
|     $host = match_vpdtable($type, $mtm, $sn, $side, $bpc_machinetype, $bpc_serial, $frame_number, $cage_number);
 | |
|     if ( !$host ) {
 | |
|         $$flag = 0;
 | |
|         $host = getFactoryHostname($type,$mtm,$sn,$side,$ip,$rsp);
 | |
|         #######################################
 | |
|         # Convert hostname to short-hostname
 | |
|         #######################################
 | |
|         if ( $host =~ /([^\.]+)\./ ) {
 | |
|             $host = $1;
 | |
|         }
 | |
|     } else {
 | |
|         $$flag = 1;
 | |
|     }
 | |
| 
 | |
|     return( "$host($ip)" );
 | |
| 
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Match hostnames in vpd table
 | |
| ##########################################################################
 | |
| sub match_vpdtable
 | |
| {
 | |
|     my $type    = shift;
 | |
|     my $mtm     = shift;
 | |
|     my $sn      = shift;
 | |
|     my $side    = shift;
 | |
|     my $bpc_machinetype = shift;
 | |
|     my $bpc_serial      = shift;
 | |
|     my $frame_number    = shift;
 | |
|     my $cage_number     = shift;
 | |
|     my $host;
 | |
| 
 | |
|     #######################################
 | |
|     # Cache ppc table
 | |
|     #######################################
 | |
|     #removed by yinle, no use
 | |
|     #if ( !%::PPC_TAB_CACHE) {
 | |
|     #    my $ppctab = xCAT::Table->new( 'ppc' );
 | |
|     #    my @entries = $ppctab->getAllNodeAttribs(['node','parent','id']);
 | |
|     #    for my $entry ( @entries ) {
 | |
|     #        if ( $entry->{mtm} and $entry->{serial} and defined( $entry->{side} ) ) {
 | |
|     #        }
 | |
|     #    }
 | |
|     #}
 | |
| 
 | |
|     #######################################
 | |
|     # Cache vpd table, now xCAT support defining Frame and CEC with mtms by user.
 | |
|     #######################################
 | |
|     if ( !%::VPD_TAB_CACHE ) {
 | |
|         my $vpdtab  = xCAT::Table->new( 'vpd' );
 | |
|         my @entries = $vpdtab->getAllNodeAttribs(['node','mtm','serial','side']);
 | |
|         #Assuming IP is unique in hosts table
 | |
|         for my $entry ( @entries ) {
 | |
|             if ( $entry->{mtm} and $entry->{serial} and defined( $entry->{side} ) ) {
 | |
|                 $::VPD_TAB_CACHE{$entry->{mtm} . '*' . $entry->{serial} . '-' . $entry->{side}} = $entry->{ 'node'};
 | |
| 
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ( exists( $::VPD_TAB_CACHE{$mtm . '*' . $sn . '-' . $side} ) ) {
 | |
|         $host = $::VPD_TAB_CACHE{$mtm . '*' . $sn . '-' . $side};
 | |
|         return( "$host" );
 | |
|     }
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Match hostnames in switch table
 | |
| ##########################################################################
 | |
| sub match_switchtable
 | |
| {
 | |
|     my $ip   = shift;
 | |
|     my $mac  = shift;
 | |
|     my $type = shift;
 | |
|     my $bpc_model    = shift;
 | |
|     my $bpc_serial   = shift;
 | |
|     my $frame_number = shift;
 | |
|     my $cage_number  = shift;
 | |
|     my $side   = shift;
 | |
|     my $mtm    = shift;
 | |
|     my $serial = shift;
 | |
|     my $name;
 | |
| 
 | |
|     #######################################
 | |
|     # Find the nodenames that match the
 | |
|     # port on switch to their mac
 | |
|     #######################################
 | |
|     my $names = $macmap->find_mac( $mac );
 | |
|     if ( $names =~ /,/ ) {
 | |
|         #######################################
 | |
|         # For High end machines, only BPA have
 | |
|         # connections to switch, FSPs shared the
 | |
|         # port with BPA.  So need to distiguish
 | |
|         # the FSPs on the same port
 | |
|         #######################################
 | |
|         $name = disti_multi_node( $names, $type, $bpc_model, $bpc_serial, $frame_number, $cage_number, $side, $mtm, $serial );
 | |
|         if ( ! $name ) {
 | |
|             return undef;
 | |
|         }
 | |
|     } elsif ( !$names ) {
 | |
|         return undef;
 | |
|     } else {
 | |
|         $name = $names;
 | |
|     }
 | |
| 
 | |
|     return $name;
 | |
| }
 | |
| 
 | |
| sub getFactoryHostname
 | |
| {
 | |
|     my $type = shift;
 | |
|     my $mtm  = shift;
 | |
|     my $sn   = shift;
 | |
|     my $side = shift;
 | |
|     my $ip   = shift;
 | |
|     my $rsp  = shift;
 | |
|     my $host = undef;
 | |
| 
 | |
|     if ( $rsp =~ /\(name=([^\)]+)/ ) {
 | |
|         $host = $1;
 | |
| 
 | |
|     ###################################
 | |
|     # Convert to short-hostname
 | |
|     ###################################
 | |
|         if ( $host =~ /([^\.]+)\./ ) {
 | |
|             $host = $1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ( $type eq SERVICE_FSP or $type eq SERVICE_BPA or $type eq SERVICE_MM )
 | |
|     {
 | |
|         $host = "Server-$mtm-SN$sn-$side";
 | |
|     }
 | |
| 
 | |
|     if ( $ip ) {
 | |
|         my $hname = gethostbyaddr( inet_aton($ip), AF_INET );
 | |
|         if ( $hname ) {
 | |
|             $host = $hname;
 | |
|         }
 | |
|     }
 | |
|     if ( !$host ) {
 | |
|         my $hoststab = xCAT::Table->new( 'hosts' );
 | |
|         my @entries = $hoststab->getAllNodeAttribs(['node','ip']);
 | |
|         foreach my $entry ( @entries ) {
 | |
|             if ( $entry->{ip} and $entry->{ip} eq $ip ) {
 | |
|                 $host = $entry->{node};
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return $host;
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Get correct IP from ip list in SLP Attr
 | |
| ##########################################################################
 | |
| sub getip_from_iplist
 | |
| {
 | |
|     my $iplist  = shift;
 | |
|     my $nets    = shift;
 | |
|     my $inc     = shift;
 | |
| 
 | |
|     my @ips = split /,/, $iplist;
 | |
|     my @ips2 = split /,/, $inc;
 | |
|     if ( $inc)
 | |
|     {
 | |
|         for my $net (keys %$nets)
 | |
|         {
 | |
|             my $flag = 1;
 | |
|             for my $einc (@ips2) {
 | |
|                 if ( $nets->{$net} eq $einc) { 
 | |
|                     $flag = 0;
 | |
|                 }
 | |
|             }
 | |
|             delete $nets->{$net} if ($flag) ;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     for my $ip (@ips)
 | |
|     {
 | |
|         next if ( $ip =~ /:/); #skip IPV6 addresses
 | |
|         for my $net ( keys %$nets)
 | |
|         {
 | |
|             my ($n,$m) = split /\//,$net;
 | |
|             if ( xCAT::Utils::isInSameSubnet( $n, $ip, $m, 1) and
 | |
|                  xCAT::Utils::isPingable( $ip))
 | |
|             {
 | |
|                 return $ip;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return undef;
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Match IP addresses to MAC in arp table
 | |
| ##########################################################################
 | |
| sub match_ip_mac
 | |
| {
 | |
|     my $ips = shift;
 | |
| 
 | |
|     ######################################################
 | |
|     # Cache ARP table entries
 | |
|     ######################################################
 | |
|     if ( !%::ARP_CACHE ) {
 | |
|         my $arp;
 | |
|         if ( $^O eq 'aix' ) {
 | |
|             $arp = `/usr/sbin/arp -a`;
 | |
|         } else {
 | |
|             $arp = `/sbin/arp -n`;
 | |
|         }
 | |
| 
 | |
|         my @arpents = split /\n/, $arp;
 | |
| 
 | |
| 
 | |
|         foreach my $arpent ( @arpents ) {
 | |
|             my ($ip, $mac);
 | |
|             if ( $^O eq 'aix' && $arpent =~ /\((\S+)\)\s+at\s+(\S+)/ ) {
 | |
|                 ($ip, $mac) = ($1,$2);
 | |
|                 ######################################################
 | |
|                 # Change mac format to be same as linux. For example:
 | |
|                 # '0:d:60:f4:f8:22' to '00:0d:60:f4:f8:22'
 | |
|                 ######################################################
 | |
|                 if ( $mac ) {
 | |
|                     my @mac_sections = split /:/, $mac;
 | |
|                     for (@mac_sections ) {
 | |
|                         $_ = "0$_" if ( length($_) == 1) ;
 | |
|                     }
 | |
|                     $mac = join '', @mac_sections;
 | |
|                 }
 | |
|             } elsif ( $arpent =~ /^(\S+)+\s+\S+\s+(\S+)\s/ ) {
 | |
|                 ($ip, $mac) = ($1,$2);
 | |
|             } else {
 | |
|                 ($ip, $mac) = (undef,undef);
 | |
|             }
 | |
| 
 | |
|             if ( defined($ip) and defined($mac) ) {
 | |
|                 $::ARP_CACHE{$ip} = $mac;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ( exists($::ARP_CACHE{$ips}) ) {
 | |
|         return( $::ARP_CACHE{$ips} );
 | |
|     }
 | |
| 
 | |
|     return undef;
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Example OpenSLP slptool "service-request" output. The following
 | |
| # attributes can be returned in any order within an SLP response.
 | |
| #
 | |
| # service:management-hardware.IBM:management-module://192.20.154.19,48659
 | |
| # (type=management-module),(level=3),(serial-number= K10WM39916W),
 | |
| # (fru=73P9297     ),(name=WMN315724834),(ip-address=192.20.154.19),
 | |
| # (enclosure-serial-number=78AG034),(enclosure-fru=59P6609     ),
 | |
| # (enclosure-machinetype-model=86772XX),(status=0),(enclosure-uuid=
 | |
| #  \ff\e6\4f\0b\41\de\0d\11\d7\bd\be\b5\3c\ab\f0\46\04),
 | |
| # (web-url=http://192.20.154.19:80),(snmp-port=161),(slim-port=6090),
 | |
| # (ssh-port=22),(secure-slim-port=0),(secure-slim-port-enabled=false),
 | |
| # (firmware-image-info=BRET86P:16:01-29-08,BRBR82A:16:06-01-05),
 | |
| # (telnet-port=23),(slot=1),0
 | |
| #  ...
 | |
| #
 | |
| # Example OpenSLP slptool "attribute-request" output. The following
 | |
| # attributes can be returned in any order within an SLP response.
 | |
| #
 | |
| # (type=integrated-virtualization-manager),(level=3),(machinetype-model=911051A),
 | |
| # (serial-number=1075ECF),(name=p510ivm.clusters.com)(ip-address=192.168.1.103),
 | |
| # (web-url=http://p510ivm.clusters.com/),(mtms=911051A*1075ECF),
 | |
| # (web-management-interface=TRUE),(secure-web-url=https://p510ivm.clusters.com/),
 | |
| # (cimom-port=5988),(secure-cimom-port=5989),(lparid=1)
 | |
| #  ...
 | |
| #
 | |
| #------------------------------------------------------------------------
 | |
| #
 | |
| # Example IBM SLP slp_query command "service-request" output. The following
 | |
| # attributes can be returned in any order within an SLP response.
 | |
| # Note: The leading 3 numbers preceeding the URL: and ATTR: fields
 | |
| # represent:
 | |
| #        error code,
 | |
| #        URL count,
 | |
| #        URL length, respectively.
 | |
| # 0
 | |
| # 1
 | |
| # 75
 | |
| # URL: service:management-software.IBM:hardware-management-console://192.168.1.110
 | |
| # ATTR: (type=hardware-management-console),(level=3),(machinetype-model=7310CR3),
 | |
| # (serial-number=KPHHK24),(name=c76v2hmc02.ppd.pok.ibm.com),(uuid=de335adf051eb21
 | |
| # 1ab1dd89ca8e0763e),(ip-address=192.168.1.110,9.114.47.154),(web-url=),(mtms=731
 | |
| # 0CR3*KPHHK24),(web-management-interface=true),(secure-web-url=https://c76v2hmc0
 | |
| # 2.ppd.pok.ibm.com:8443),(cimom-port=),(secure-cimom-port=5989)
 | |
| #
 | |
| # 0
 | |
| # 1
 | |
| # 69
 | |
| # ...
 | |
| #
 | |
| # Example IBM SLP slp_query command "attribute-request" output. The following
 | |
| # attributes can be returned in any order within an SLP response.
 | |
| # Note: The leading 3 numbers preceeding the URL: and ATTR: fields
 | |
| # represent:
 | |
| #        error code,
 | |
| #        0, (hardcoded)
 | |
| #        ATTR  length, respectively.
 | |
| # 0
 | |
| # 0
 | |
| # 354
 | |
| # ATTR: (type=integrated-virtualization-manager),(level=3),(machinetype-model=911051A),
 | |
| # (serial-number=1075ECF),(name=p705ivm.clusters.com),(ip-address=192.168.1.103),
 | |
| # (web-url=http://p705ivm.clusters.com/),(mtms=911051A*1075ECF),(web-management-
 | |
| # interface=TRUE),(secure-web-url=https://p705ivm.clusters.com/),(cimom-port=5988),
 | |
| # (secure-cimom-port=5989),(lparid=1)
 | |
| #
 | |
| #########################################################################
 | |
| sub parse_responses {
 | |
| 
 | |
|     my $request = shift;
 | |
|     my $values  = shift;
 | |
|     my $length  = shift;
 | |
|     my $matchflag = 0;
 | |
|     my %outhash;
 | |
|     my %net;
 | |
|     my %addr; 
 | |
|     my $nettab = xCAT::Table->new('networks');
 | |
|     my @nets = $nettab->getAllAttribs('netname', 'net','mask','mgtifname');
 | |
|     if (scalar(@nets) == 0) {
 | |
|         trace( $request, "Can't get networks information from networks table" , 1);
 | |
|     } else {
 | |
|         foreach my $enet (@nets) {
 | |
|             next if ($enet->{'net'} =~ /:/);
 | |
|             $net{$enet->{'mgtifname'}}{subnet} = $enet->{'net'};
 | |
|             $net{$enet->{'mgtifname'}}{netmask} = $enet->{'mask'};
 | |
|         }
 | |
|     }   
 | |
|     my $netref = xCAT::NetworkUtils->get_nic_ip();        
 | |
|     for my $entry (keys %$netref) {
 | |
|         $addr{$netref->{$entry}}{subnet} = $net{$entry}{subnet};
 | |
|         $addr{$netref->{$entry}}{netmask} = $net{$entry}{netmask};
 | |
|     }
 | |
|     my @attrs   = (
 | |
|         "type",
 | |
|         "machinetype-model",
 | |
|         "serial-number",
 | |
|         "slot",
 | |
|         "ip-address",
 | |
|         "bpc-machinetype-model",
 | |
|         "bpc-serial-number",
 | |
|         "frame-number",
 | |
|         "cage-number" );
 | |
| 
 | |
|     #######################################
 | |
|     # RSA/MM Attributes
 | |
|     #######################################
 | |
|     my @xattrs = (
 | |
|        "type",
 | |
|        "enclosure-machinetype-model",
 | |
|        "enclosure-serial-number",
 | |
|        "slot",
 | |
|        "ip-address" );
 | |
| 
 | |
|     #######################################
 | |
|     # NGP CMM Attributes
 | |
|     #######################################
 | |
|     my @cmmattrs = (
 | |
|        "type",
 | |
|        "enclosure-mtm",
 | |
|        "enclosure-serial-number",
 | |
|        "slot",
 | |
|        "ipv4-address",
 | |
|        "mm-name" );
 | |
|     my %fid1;
 | |
|     my %fid2;
 | |
|     my %cid;
 | |
|     my %pmtm;
 | |
|     my %psn;
 | |
|     my @matchnodes;
 | |
|     trace( $request, "Now I will explain how the lsslp parse its response: " , 1);
 | |
|     foreach my $rsp ( @$values ) {
 | |
|         ###########################################
 | |
|         # Get service-type from response
 | |
|         ###########################################
 | |
|         my @result = ();
 | |
|         my $host;
 | |
| 
 | |
|         ###########################################
 | |
|         # service-type attribute not found
 | |
|         ###########################################
 | |
|         if ( $rsp !~ /\(type=([^\)]+)/ ) {
 | |
|             if ( $verbose ) {
 | |
|                 trace( $request, "(type) attribute not found: $rsp" );
 | |
|             }
 | |
|             next;
 | |
|         }
 | |
|         ###########################################
 | |
|         # Valid service-type attribute
 | |
|         ###########################################
 | |
|         my $type = $1;
 | |
| 
 | |
|         ###########################################
 | |
|         # Unsupported service-type
 | |
|         ###########################################
 | |
|         if ( !exists($service_slp{$type} )) {
 | |
|             if ( $verbose ) {
 | |
|                 trace( $request, "Discarding unsupported type: $type" );
 | |
|             }
 | |
|             next;
 | |
|         }
 | |
|         ###########################################
 | |
|         # Extract the attributes
 | |
|         # RSA/MM - slightly different attributes
 | |
|         ###########################################
 | |
|         my $attr;
 | |
|         if (( $type eq SERVICE_RSA ) or ( $type eq SERVICE_RSA2 ) or
 | |
|             ( $type eq SERVICE_MM )) {
 | |
|             $attr = \@xattrs;
 | |
|             foreach ( @$attr ) {
 | |
|                 unless ( $rsp =~ /\($_=([^\)]+)/ ) {
 | |
|                     if ( $verbose ) {
 | |
|                         trace( $request, "Attribute not found: [$_]->($rsp)" );
 | |
|                     } 
 | |
|                     push @result, "N/A";
 | |
|                     next;
 | |
|                 } 
 | |
|                 my $val = $1;
 | |
|                 if (( $_ =~ /^slot$/ ) and ( $val == 0 )) {
 | |
|                     push @result, "B";
 | |
|                 } elsif (( $_ =~ /^slot$/ ) and ( $val == 1 )) {
 | |
|                     push @result, "A";
 | |
|                 } else {
 | |
|                     push @result, $val; 
 | |
|                 }
 | |
|             }
 | |
|         } elsif ($type eq SERVICE_CMM) {
 | |
|             $attr = \@cmmattrs;
 | |
|             foreach ( @$attr ) {
 | |
|                 unless ( $rsp =~ /\($_=([^\)]+)/ ) {
 | |
|                     if ( $verbose ) {
 | |
|                         trace( $request, "Attribute not found: [$_]->($rsp)" );
 | |
|                     }
 | |
|                     push @result, "N/A";
 | |
|                     next;
 | |
|                 }
 | |
|                 my $val = $1;
 | |
|                 push @result, $val;
 | |
|             }
 | |
|             trace( $request, ">>>>>>>>The type is $result[0], en-mtm is $result[1], en-sn is $result[2], slot is $result[3], ip is $result[4]", 1 );
 | |
|         } else {
 | |
|             $attr = \@attrs;
 | |
|             foreach ( @$attr ) {
 | |
|                 unless ( $rsp =~ /\($_=([^\)]+)/ ) {
 | |
|                     if ( $verbose ) {
 | |
|                         trace( $request, "Attribute not found: [$_]->($rsp)" );
 | |
|                     }
 | |
|                     push @result, "N/A";
 | |
|                     next;
 | |
|                 }
 | |
|                 my $val = $1;
 | |
|                 if (( $_ =~ /^slot$/ ) and ( $val == 0 )) {
 | |
|                     push @result, "B";
 | |
|                 } elsif (( $_ =~ /^slot$/ ) and ( $val == 1 )) {
 | |
|                     push @result, "A";
 | |
|                 } else {
 | |
|                     push @result, $val;
 | |
|                 }
 | |
|             }
 | |
|             trace( $request, ">>>>>>>>The type is $result[0], mtm is $result[1], sn is $result[2], side is $result[3], ip is $result[4], parent mtm is $result[5], parent sn is $result[6], frame num is $result[7], cage num is $result[8].", 1 );
 | |
| 
 | |
|         }
 | |
|         # match hosts table
 | |
|         #my %hostip;
 | |
|         #my $hoststab = xCAT::Table->new( 'hosts' );
 | |
|         #my $entry;
 | |
|         #my @entries = $hoststab->getAllNodeAttribs(['node','ip']);
 | |
|         #foreach $entry ( @entries ) {
 | |
|         #    $hostip{$entry->{node}} = $entry->{ip};
 | |
|         #}
 | |
| 
 | |
|         trace( $request, ">>>>>>>>The type is $result[0], mtm is $result[1], sn is $result[2], side is $result[3], ip is $result[4], parent mtm is $result[5], parent sn is $result[6], frame num is $result[7], cage num is $result[8].", 1 );
 | |
| 
 | |
|         # begin to define FSP/BPA/FRAME/CEC
 | |
|         my $typetp;
 | |
|         if ( $type eq SERVICE_BPA )
 | |
|         {
 | |
|             $typetp = TYPE_BPA;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             $typetp = TYPE_FSP;
 | |
|         }
 | |
|         my $hostname = undef;
 | |
|         if ( $type eq SERVICE_BPA or $type eq SERVICE_FSP ) {
 | |
|             trace( $request, "........First define FSP/BPA nodes", 1 );
 | |
|             ###########################################
 | |
|             #  begin to define fsp/bpa, use ip as the hostname of the fsp/bpa
 | |
|             #  for there are redundancy of fsp/bpa,
 | |
|             #  excrete each slp response into two definitions
 | |
|             #  put the definitions into %outhash
 | |
|             ###########################################
 | |
| 
 | |
|             # begin to define fsp/bpa
 | |
|             my (@severnode1, @severnode2);
 | |
|             my @ips = split/,/, $result[4];
 | |
| 
 | |
|             #keep cage id for the secondary fsp definition
 | |
|             #the cash hash is like $fid{mtm*sn}=cageid
 | |
|             #if ($type eq SERVICE_FSP and $severnode1[3] eq "A")
 | |
|             #{
 | |
|             #    $fid1{$severnode1[1]."*".$severnode1[2]} = $severnode1[8];
 | |
|             #}
 | |
|             #if ($type eq SERVICE_FSP and $severnode1[3] eq "B")
 | |
|             #{
 | |
|             #    $fid2{$severnode1[1]."*".$severnode1[2]} = $severnode1[8];
 | |
|             #}
 | |
|             if (!exists($cid{$result[1]."*".$result[2]} ) || ($result[8] > 0)) {
 | |
|                 $cid{$result[1]."*".$result[2]} = $result[8];
 | |
|             }
 | |
|             if (!exists($pmtm{$result[1]."*".$result[2]}) || ($result[5] > 0)) {
 | |
|                 $pmtm{$result[1]."*".$result[2]} = $result[5];
 | |
|                 $psn{$result[1]."*".$result[2]} = $result[6];
 | |
|             }
 | |
| 
 | |
|             foreach (@result) {
 | |
|                 push @severnode1, $_;
 | |
|             }
 | |
| 
 | |
|             $severnode1[3] = $severnode1[3].'-0';
 | |
|             $severnode1[4] = $ips[0];
 | |
|             $severnode1[0] = $typetp;
 | |
|             push @severnode1, $rsp;
 | |
|             $matchflag = 0;
 | |
|             $hostname =  gethost_from_url_or_old($ips[0], $severnode1[0], $severnode1[1], $severnode1[2],
 | |
|                             $severnode1[3], $ips[0], $severnode1[8], $severnode1[5],$severnode1[6], undef, \$matchflag);
 | |
|             trace( $request, "     The node $ips[0] match the old data and got the new name $hostname, $matchflag" , 1);
 | |
|             if ( $hostname ) {
 | |
|                 $outhash{$hostname} = \@severnode1;
 | |
|                 push @matchnodes, $hostname if ($matchflag eq 1) ; 
 | |
|             if ( length( $severnode1[4] ) > $$length ) {
 | |
|                 $$length = length( $severnode1[4] );
 | |
|             }
 | |
|             } 
 | |
| 
 | |
|             #begin to define another fsp/bpa
 | |
|             $hostname = undef;
 | |
|             foreach (@result) {
 | |
|                 push @severnode2, $_;
 | |
|             }
 | |
|             $severnode2[3] = $severnode2[3].'-1';
 | |
|             $severnode2[4] = $ips[1];
 | |
|             $severnode2[0] = $typetp;
 | |
|             push @severnode2, $rsp;
 | |
|             $matchflag = 0;
 | |
|             $hostname =  gethost_from_url_or_old($ips[1], $severnode2[0], $severnode2[1], $severnode2[2],
 | |
|                             $severnode2[3], $ips[1], $severnode2[8], $severnode2[5],$severnode2[6], undef, \$matchflag);
 | |
|             trace( $request, "     The node $ips[1] match the old data and got the new name $hostname, $matchflag" , 1);
 | |
|             if ( $hostname ) {
 | |
|                  $outhash{$hostname} = \@severnode2;
 | |
|                 push @matchnodes, $hostname if ($matchflag eq 1) ; 
 | |
|             if ( length( $severnode2[4] ) > $$length ) {
 | |
|                 $$length = length( $severnode2[4] );
 | |
|             }
 | |
|             }
 | |
|             ###########################################
 | |
|             #  begin to define frame and cec
 | |
|             #  As default, use Server-$result[1]-SN$result[2] as hostname
 | |
|             #  put the definitions into %outhash
 | |
|             ###########################################
 | |
| 
 | |
|             trace( $request, "......Second define frame and cec " , 1);
 | |
|             $hostname = undef;
 | |
|             $host = "Server-$result[1]-SN$result[2]";
 | |
|             unless ( exists( $outhash{$host} ))
 | |
|             {
 | |
|                 if ( $type eq SERVICE_BPA )
 | |
|                 {
 | |
|                     $result[0] = TYPE_FRAME;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     $result[0] = TYPE_CEC;
 | |
|                 }
 | |
|                 # IP of frame and cec should be null
 | |
|                 $result[3] = "";
 | |
|                 # side of frame and cec should be null
 | |
|                 $result[4] = "";
 | |
|                 push @result, $rsp;
 | |
|                 $matchflag = 0;
 | |
|                 $hostname =  gethost_from_url_or_old($host, $result[0], $result[1], $result[2],
 | |
|                              $result[3],$result[4], $result[8],$result[5],$result[6], undef, \$matchflag);
 | |
|                 trace( $request, "     The node $host match the old data and got the new name $hostname, $matchflag" , 1);         
 | |
|                 if ( $hostname ) {
 | |
|                     $outhash{$hostname} = \@result;
 | |
|                     push @matchnodes, $hostname if ($matchflag eq 1);      
 | |
|                 }
 | |
| 
 | |
|             }
 | |
| 
 | |
|         } elsif ($type eq SERVICE_HMC) {
 | |
| 
 | |
|             ###########################################
 | |
|             # for HMC
 | |
|             ###########################################
 | |
|             trace( $request, "......Begin to define hmc ", 1);
 | |
|             $matchflag = 0;
 | |
|             $host = gethost_from_url( $request, $rsp, \$matchflag, @result);
 | |
|             trace( $request, "     The node $host match the old data and got the new name $host, $matchflag" , 1);         
 | |
|             if ( !defined( $host )) {
 | |
|                 next;
 | |
|             }
 | |
|             push @matchnodes, $host if ($matchflag eq 1) ; 
 | |
|             ###########################################
 | |
|             # Find IP for HMC
 | |
|             # 1. If it can match the definintion made by
 | |
|             #    xcatsetup, just return the ip matched
 | |
|             # 2. If there is -i flag, return the ip that
 | |
|             #    within the same subnet with opt{i}
 | |
|             # 3. If no match and no flag -i, return first
 | |
|             ###########################################
 | |
| 
 | |
|             # we need to hide ipv6 ip address temporarily
 | |
|             my @iptmp = split /,/, $result[4];
 | |
|             my @iptmp2;
 | |
|             my $matchhmc = 0;
 | |
|             foreach my $ii (@iptmp){
 | |
|                 if ($ii =~ /\d+\.\d+\.\d+\.\d+/) {
 | |
|                     $matchflag = 1;
 | |
|                     my $newhost = match_ip_defined_by_xcatsetup($ii, \$matchflag);
 | |
|                     push @matchnodes, $host if ($matchflag eq 1) ; 
 | |
|                     if ($newhost) { 
 | |
|                         $host = $newhost;
 | |
|                         $matchhmc = 1; 
 | |
|                         $result[4] = $ii;
 | |
|                     } elsif (exists($opt{i})){
 | |
|                         my @userip = split /,/, $opt{i};
 | |
|                         foreach my $uip (@userip) {
 | |
|                             my $subnet = $addr{$uip}{subnet};
 | |
|                             my $netmask = $addr{$uip}{netmask};
 | |
|                             if(xCAT::NetworkUtils->ishostinsubnet($ii, $netmask, $subnet)) {
 | |
|                                 $matchhmc = 1;
 | |
|                                 $result[4] = $ii;
 | |
|                                 next;
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                     push @iptmp2,$ii;
 | |
|                 }
 | |
|              }
 | |
|             unless($matchhmc) {
 | |
|                 #$result[4] = join( ",", @iptmp2);
 | |
|                 $result[4] = $iptmp2[0];
 | |
|             }		
 | |
|             # end of hidden ipv6 ip address
 | |
| 
 | |
| 
 | |
|             $result[4] =~ s/,/ /g;
 | |
|             my $ip     = $result[4];
 | |
| 
 | |
|             ###########################################
 | |
|             # Save longest IP for formatting purposes
 | |
|             ###########################################
 | |
|             if ( length( $ip ) > $$length ) {
 | |
|                 $$length = length( $ip );
 | |
|             }
 | |
| 
 | |
|             push @result, $rsp;
 | |
| 
 | |
|             $result[0] = $service_slp{$type};
 | |
|             $outhash{$host} = \@result;
 | |
| 
 | |
|         } else {
 | |
|             ###########################################
 | |
|             # for CMM
 | |
|             ###########################################
 | |
|             trace( $request, "......Begin to define cmm ", 1);
 | |
|             $matchflag = 0;
 | |
|             $host = gethost_from_url( $request, $rsp, \$matchflag, @result);
 | |
|             trace( $request, "     The node $host match the old data and got the new name $host, $matchflag" , 1);
 | |
|             if ( !defined( $host )) {
 | |
|                 $host = $result[5];
 | |
|             }
 | |
|             
 | |
|             if ( !defined( $host )) {
 | |
|                 next;
 | |
|             }
 | |
|             push @matchnodes, $host if ($matchflag eq 1) ;
 | |
|             $result[0] = $service_slp{$type};  
 | |
|             if ($host =~ /^(\w+)\(.*\)/) {
 | |
|                 $host = $1;
 | |
|             }                 
 | |
|             $otherinterfacehash{$host}{otherinterfaces} = $result[4]; 
 | |
|             $outhash{$host} = \@result;
 | |
|         }    
 | |
|     }    
 | |
|     ############################################################
 | |
|     # find out the cageid for the cec
 | |
|     ############################################################
 | |
|     #trace( $request, "\n\nThe cageid need to be adjust,because some secondary fsp return wrong side value ( always 0)", 1);
 | |
|     #foreach my $idtmp( keys(%fid1) )
 | |
|     #{
 | |
|     #    if ($fid1{$idtmp} > 0)
 | |
|     #    {
 | |
|     #        $cid{$idtmp} = $fid1{$idtmp};
 | |
|     #    } elsif ($fid2{$idtmp} > 0)
 | |
|     #    {
 | |
|     #        $cid{$idtmp} = $fid2{$idtmp};
 | |
|     #    } else {
 | |
|     #        $cid{$idtmp} = 0;
 | |
|     #    }
 | |
|     #}
 | |
|     #foreach ( keys(%fid2) )
 | |
|     #{
 | |
|     #    if (!defined($cid{$_}))
 | |
|     #    {
 | |
|     #        $cid{$_} = $fid2{$_};
 | |
|     #    }
 | |
|     #}
 | |
| 
 | |
|     ############################################################
 | |
|     # -n flag to skip the existing node
 | |
|     ############################################################
 | |
|     my %vpd_table_hash;
 | |
|     my $vpdtab  = xCAT::Table->new( 'vpd' );
 | |
|     my @entries = $vpdtab->getAllNodeAttribs(['node','mtm','serial','side']);
 | |
|     for my $entry ( @entries ) {
 | |
|         if ( $entry->{mtm} and $entry->{serial} ) {
 | |
|             $vpd_table_hash{$entry->{mtm} . '*' . $entry->{serial} . '-' . $entry->{side}} = $entry->{ 'node'};
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     ##########################################################
 | |
|     # Find the parent and mac and set them as the 10th and 11th
 | |
|     # of the attribute of the server nodes
 | |
|     ##########################################################
 | |
|     my %hash;
 | |
|     my $mac;
 | |
|     my $parent;
 | |
|     my $newhostname;
 | |
|     trace( $request, "\n\n\nBegin to find cec's id, parent and hostname, find frame's hostname", 1);
 | |
|     foreach my $h ( keys %outhash ) {
 | |
|         my $data    = $outhash{$h};
 | |
|         my $type    = @$data[0];
 | |
|         my $mtm     = @$data[1];
 | |
|         my $sn      = @$data[2];
 | |
|         my $side    = @$data[3];
 | |
|         my $ip0;
 | |
|         if ( $h =~ /^([^\(]+)\(([^\)]+)\)$/ ) {
 | |
|             $ip0    = $2;
 | |
|         } else {
 | |
|             $ip0    = @$data[4];
 | |
|         }
 | |
|         my $bpamtm  = @$data[5];
 | |
|         my $bpasn   = @$data[6];
 | |
|         my $cagenum = @$data[8];
 | |
|         if($type eq TYPE_CMM) {
 | |
|             $hash{$h} = $data;
 | |
|             next;
 | |
|         }    
 | |
|         trace( $request, "......The node is $h, type is $type, mtm is $mtm, sn is $sn, side is $side, ip is $ip0, bpamtm is $bpamtm, bpasn is $bpasn, cagenum is $cagenum", 1);
 | |
|         # find cageid for the secondary fsp node
 | |
|         if ( $type =~ /^FSP$/ || $type =~ /^CEC$/) {
 | |
|             @$data[8] = $cid{$mtm."*".$sn};
 | |
|             @$data[5] = $pmtm{$mtm."*".$sn};
 | |
|             @$data[6] = $psn{$mtm."*".$sn};
 | |
|             $bpamtm  = @$data[5];
 | |
|             $bpasn   = @$data[6];
 | |
|             $cagenum = @$data[8];
 | |
| 
 | |
|             trace ( $request, "            Adjust cageid to @$data[8], bpamtm to @$data[5], bpasn to @$data[6]", 1);
 | |
|         }
 | |
| 
 | |
|         # if there is a -n flag, skip the existed nodes
 | |
|         if ($type =~ /^HMC$/) {
 | |
|             $matchflag = 0;
 | |
|             $newhostname = match_hosts_defined_by_xcatsetup($h, $type, $mtm, $sn, $side, $ip0, $cagenum, $bpamtm, $bpasn, $parent, \$matchflag);
 | |
|             if ($newhostname) {
 | |
|                 $hash{$newhostname} = $data;
 | |
|                 push @matchnodes, $newhostname;
 | |
|             } else {
 | |
|                 $hash{$h} = $data;
 | |
|                 }
 | |
|             trace ( $request, "            HMC $h macth the data defined by xcatsetup and got name $newhostname", 1);
 | |
|             }
 | |
| 
 | |
|         # begin to find parent
 | |
|         next unless( $type eq TYPE_CEC or $type eq TYPE_FRAME );
 | |
|         my $newname;
 | |
|         foreach my $h1 ( keys %outhash ) {
 | |
|             my $data1 = $outhash{$h1};
 | |
|             my $type1 = @$data1[0];
 | |
|             my $mtm1  = @$data1[1];
 | |
|             my $sn1   = @$data1[2];
 | |
|             if ($mtm1 eq $bpamtm and $sn1 eq $bpasn and $type1 eq "frame") {
 | |
|                 $parent = $h1;       # CEC's parent is Frame
 | |
|                 last;
 | |
|             } else {
 | |
|                 $parent = undef;   # Frame and HMC have no parent
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if ( !defined( $parent ) ) {
 | |
|             if ( exists $vpd_table_hash{$bpamtm . '*' . $bpasn . '-'} ) {
 | |
|                 my $existing_node = $vpd_table_hash{$bpamtm . '*' . $bpasn . '-'};
 | |
|                 my $type1 = xCAT::DBobjUtils->getnodetype($existing_node);
 | |
|                 if ( $type1 eq "frame" and ($type eq TYPE_BPA or $type eq TYPE_CEC) ) {
 | |
|                     $parent = $existing_node;
 | |
|                 } elsif ( $type1 eq "cec" and $type eq TYPE_FSP ) {
 | |
|                     $parent = $existing_node;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         push @$data, $parent;
 | |
|         push @$data, undef;   #This is for $data[9], which is mac address;
 | |
|         trace ( $request, "            $h find the parent $parent.", 1);
 | |
| 
 | |
|         ##########################################################        
 | |
|         #find the mac address
 | |
|         ##########################################################
 | |
|         $newhostname = match_hosts_defined_by_xcatsetup($h, $type, $mtm, $sn, $side, $ip0, $cagenum, $bpamtm, $bpasn, $parent, \$matchflag);
 | |
|         if ($newhostname) {
 | |
|             $hash{$newhostname} = $data;
 | |
|             push @matchnodes, $newhostname;
 | |
|         } else {
 | |
|             $hash{$h} = $data;
 | |
|         }
 | |
|         trace ( $request, "            CEC $h macth the data defined by xcatsetup and got name $newhostname", 1);
 | |
|     }
 | |
| 
 | |
|     ##########################################################
 | |
|     # Find the parent,hostname and mac address for fsp/bpa
 | |
|     # Find mac address for HMC
 | |
|     ##########################################################
 | |
|     trace( $request, "\n\n\nBegin to find parent and hostname for fsp/bpa: ", 1);
 | |
|     foreach my $h ( keys %outhash ) {
 | |
|         my $data    = $outhash{$h};
 | |
|         my $type    = @$data[0];
 | |
|         my $mtm     = @$data[1];
 | |
|         my $sn      = @$data[2];
 | |
|         my $side    = @$data[3];
 | |
|         my $ip0;
 | |
|         if ( $h =~ /^([^\(]+)\(([^\)]+)\)$/ ) {
 | |
|             $ip0    = $2;
 | |
|         } else {
 | |
|             $ip0    = @$data[4];
 | |
|         }
 | |
|         my $bpamtm  = @$data[5];
 | |
|         my $bpasn   = @$data[6];
 | |
|         my $cagenum = @$data[8];
 | |
| 
 | |
|         next if($type eq TYPE_CMM);
 | |
|         trace( $request, "......The node is $h", 1);
 | |
| 
 | |
|         ##########################################################
 | |
|         # begin to find fsp/bpa's parent
 | |
|         ##########################################################
 | |
|         if ( $type eq TYPE_BPA or $type eq TYPE_FSP) {
 | |
|             foreach my $h1 ( keys %hash ) {
 | |
|                 my $data1 = $hash{$h1};
 | |
|                 my $type1 = @$data1[0];
 | |
|                 my $mtm1  = @$data1[1];
 | |
|                 my $sn1   = @$data1[2];
 | |
|                 if ((( $type1 eq TYPE_FRAME and $type eq TYPE_BPA) or ($type1 eq TYPE_CEC and $type eq TYPE_FSP)) and ($mtm1 eq $mtm and $sn1 eq $sn) ) {
 | |
|                     $parent = $h1;       # FSP's parent is CEC
 | |
|                     last;
 | |
|                 } else {
 | |
|                     $parent = undef;   # HMC have no parent
 | |
|                 }
 | |
|             }
 | |
|             push @$data, $parent; #This is for $data[8];
 | |
|             trace ( $request, "            Find the $h parent $parent.", 1);
 | |
|         } else {
 | |
|             push @$data, undef;
 | |
|         }
 | |
|         
 | |
|         ##########################################################
 | |
|         # match fsp/bpa nodes with the definition made by xcatsetup
 | |
|         # keep the otherinterfaces for the nodes.
 | |
|         ##########################################################
 | |
|         if ( $type eq TYPE_BPA or $type eq TYPE_FSP) {
 | |
|             $newhostname = match_hosts_defined_by_xcatsetup($h, $type, $mtm, $sn, $side, $ip0, $cagenum, $bpamtm, $bpasn, $parent);
 | |
|             if ($newhostname) {
 | |
|                 trace ( $request, "            Find the new hostname $newhostname.", 1);
 | |
|                 $hash{$newhostname} = $data;
 | |
|                 push @matchnodes, $newhostname;
 | |
|                 $otherinterfacehash{$newhostname}{otherinterfaces} = $ip0;
 | |
|                 trace( $request, "            Keep the node ip $ip0 in $newhostname otherinterfaces" , 1);
 | |
|             } else {
 | |
|                 $hash{$h} = $data;
 | |
|                 $otherinterfacehash{$h}{otherinterfaces} = $ip0;
 | |
|                 trace( $request, "            Keep the node ip $ip0 in $h otherinterfaces" , 1);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         ##########################################################
 | |
|         # find the mac address for the fsp/bpa/hmc nodes.
 | |
|         ##########################################################
 | |
|         if ( $type eq TYPE_BPA or $type eq TYPE_FSP or $type eq TYPE_HMC) {
 | |
|             $mac = match_ip_mac( $ip0 );
 | |
|             # This is originally used to check the invalid mac address in AIX, but failed to do it.
 | |
|             #unless ( $mac =~ /\w+\:\w+\:\w+\:\w+\:\w+\:\w+/ ) { $mac = undef;}
 | |
|             push @$data, $mac;  #This is for $data[9], which is mac address;
 | |
|             trace ( $request, "            Find the $h mac $mac.", 1);
 | |
|         } else {
 | |
|             push @$data, undef;
 | |
|         }
 | |
|     }
 | |
|   
 | |
|     ##########################################################
 | |
|     # If there is -n flag, skip the matched nodes
 | |
|     ##########################################################
 | |
|     if (exists($opt{n})) {
 | |
|         trace( $request, "\n\n\nThere is -n flag, skip these nodes:\n", 1);
 | |
|         for my $matchednode (@matchnodes) {
 | |
|             if ($hash{$matchednode}) {
 | |
|                 trace( $request, "$matchednode,", 1);
 | |
|                 delete $hash{$matchednode};
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return( \%hash );
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Write result to xCat database
 | |
| ##########################################################################
 | |
| sub xCATdB {
 | |
|     my $outhash = shift;
 | |
|     my %keyhash = ();
 | |
|     my %updates = ();
 | |
|     my %sn_node = ();
 | |
|     ########################################
 | |
|     # Update database if the name changed
 | |
|     ########################################
 | |
|     my %db       = ();
 | |
|     my @tabs     = qw(ppc vpd nodehm nodelist nodetype ppcdirect hosts mac mp);
 | |
|     foreach ( @tabs ) {
 | |
|         $db{$_} = xCAT::Table->new( $_);
 | |
|         if ( !$db{$_} ) {
 | |
|             return( "Error opening '$_'" );
 | |
|         }
 | |
|     }
 | |
|     my @vpdlist = $db{vpd}->getAllNodeAttribs(['node','serial','mtm','side']);
 | |
|     my @hostslist = $db{hosts}->getAllNodeAttribs(['node','ip']);
 | |
|     my @ppclist = $db{ppc}->getAllNodeAttribs(['node','hcp','id',
 | |
|                                                'pprofile','parent','supernode',
 | |
|                                                'comments', 'disable']);
 | |
|     my @maclist = $db{mac}->getAllNodeAttribs(['node','mac']);
 | |
|     
 | |
|         
 | |
|     ########################################
 | |
|     # Begin to write each node
 | |
|     ########################################
 | |
|     foreach my $hostname ( keys %$outhash ) {
 | |
|         my $data       = $outhash->{$hostname};
 | |
|         my $name       = $hostname;
 | |
|         my $type       = @$data[0];
 | |
|         my $model      = @$data[1];
 | |
|         my $serial     = @$data[2];
 | |
|         my $side       = @$data[3];
 | |
|         my $ip         = @$data[4];
 | |
|         my $frameid    = @$data[7];
 | |
|         my $cageid     = @$data[8];
 | |
|         my $parent     = @$data[10];
 | |
|         my $mac        = @$data[11];
 | |
|         my $otherif    = $otherinterfacehash{$hostname}{otherinterfaces};
 | |
|         my $prof       = "";
 | |
| 
 | |
|         #######################################
 | |
|         # FSP/BPA don't need to be in host table,
 | |
|         # CEC/FRAME have no ip so don't need neither
 | |
|         # only HMC need to be and could be writen to host table
 | |
|         #######################################
 | |
|         if ( $hostname =~ /^([^\(]+)\(([^\)]+)\)$/) {
 | |
|             $name = $1;
 | |
|             $ip  = $2;
 | |
|         }
 | |
| 
 | |
|         ########################################
 | |
|         # Update hosts table
 | |
|         ########################################
 | |
|         if ( exists($opt{updatehosts}) ) {
 | |
|             my $hostip = writehost($name,$ip);
 | |
|         }
 | |
| 
 | |
|         ########################################
 | |
|         # Write result to every tables,
 | |
|         # every entry write once, time-consuming!
 | |
|         ########################################
 | |
|         if ( $type =~ /^BPA$/ ) {
 | |
|             ########################################
 | |
|             # BPA: name=hostname, id=slotid, mtms=mtms
 | |
|             # side=side, prof=null, frame=parent,
 | |
|             # ip=ip, mac=mac
 | |
|             # we will not write ip to hosts table
 | |
|             ########################################
 | |
|             my $ifip = xCAT::Utils->isIpaddr($name);
 | |
|             if ($ifip) {
 | |
|                 my $values = join( ",",
 | |
|                             lc($type),$name,$frameid,$model,$serial,$side,$name,$prof,$parent,"",$mac );
 | |
|                 xCAT::PPCdb::add_ppc( lc($type), [$values], 0, 1 );
 | |
|                 #if ( exists($::UPDATE_CACHE{$name}))
 | |
|                 #{
 | |
|                 #    xCAT::PPCdb::update_node_attribs(
 | |
|                 #            "bpa","bpa",$name,$frameid,$model,$serial,$side,"","",$parent,"",\%db, $::UPDATE_CACHE{$name},\@ppclist);
 | |
|                 #}
 | |
|             } else
 | |
|             {
 | |
|                 my $values = join( ",",
 | |
|                             lc($type),$name,$frameid,$model,$serial,$side,$name,$prof,$parent,$ip,$mac );
 | |
|                 xCAT::PPCdb::add_ppc( lc($type), [$values], 0, 1 );
 | |
|                 #if ( exists($::UPDATE_CACHE{$name}))
 | |
|                 #{
 | |
|                 #    xCAT::PPCdb::update_node_attribs(
 | |
|                 #            "bpa","bpa",$name,$frameid,$model,$serial,$side,"","",$parent,$ip,\%db, $::UPDATE_CACHE{$name},\@ppclist);
 | |
|                 #}
 | |
|             }
 | |
|         } elsif ( $type =~ /^(HMC|IVM)$/ ) {
 | |
|             ########################################
 | |
|             # HMC: name=hostname, ip=ip, mac=mac
 | |
|             ########################################
 | |
|             xCAT::PPCdb::add_ppchcp( lc($type), "$name,$mac,$model,$serial,$ip",1 );
 | |
|         } elsif ( $type =~ /^FSP$/ ) {
 | |
|             ########################################
 | |
|             # FSP: name=hostname, id=slotid, mtms=mtms,
 | |
|             # side=side, prof=null, frame=parent,
 | |
|             # ip=ip, mac=mac
 | |
|             # we will not write ip to hosts table
 | |
|             ########################################
 | |
|             my $ifip = xCAT::Utils->isIpaddr($name);
 | |
|             if ($ifip) {
 | |
|                 my $values = join(
 | |
|                         ",",lc($type),$name,$cageid,$model,$serial,$side,$name,$prof,$parent,"",$mac );
 | |
|                 xCAT::PPCdb::add_ppc( "fsp", [$values], 0, 1 );
 | |
|                 #if ( exists($::UPDATE_CACHE{$name}))
 | |
|                 #{
 | |
|                 #    xCAT::PPCdb::update_node_attribs(
 | |
|                 #        "fsp","fsp",$name,$cageid,$model,$serial,$side,"","",$parent,"",\%db, $::UPDATE_CACHE{$name},\@ppclist);
 | |
|                 #}
 | |
|             } else
 | |
|             {
 | |
|                 my $values = join(
 | |
|                     ",",lc($type),$name,$cageid,$model,$serial,$side,$name,$prof,$parent,$ip,$mac );
 | |
|                 xCAT::PPCdb::add_ppc( "fsp", [$values], 0, 1 );
 | |
|                 #if ( exists($::UPDATE_CACHE{$name}))
 | |
|                 #{
 | |
|                 #    xCAT::PPCdb::update_node_attribs(
 | |
|                 #        "fsp","fsp",$name,$cageid,$model,$serial,$side,"","",$parent,$ip,\%db, $::UPDATE_CACHE{$name},\@ppclist);
 | |
|                 #}
 | |
|             }
 | |
|         } elsif ( $type =~ /^(RSA|MM)$/ ) {
 | |
|             xCAT::PPCdb::add_systemX( $type, $name, $data );
 | |
|         } elsif ( $type =~ /^FRAME$/ ) {
 | |
|             ########################################
 | |
|             # Frame: type=frame, name=hostname, cageid=0,
 | |
|             # mtms=mtms, side=null, prof=null, frame=itself,
 | |
|             # ip=null, mac=null
 | |
|             ########################################
 | |
|             my $mac        = "";
 | |
|             my $side       = "";
 | |
|             my $ip         = "";
 | |
|             my $values = join( ",",
 | |
|                lc($type),$name,$frameid,$model,$serial,$side,$name,$prof,$parent,$ip,$mac );
 | |
|             # we should call update_node_attribs to Frame/CEC
 | |
|             # to make sure the information difined for FSP/BPA
 | |
|             # before can be kept.
 | |
|             if ( exists($::UPDATE_CACHE{$model."-".$serial}))
 | |
|             {
 | |
|                 xCAT::PPCdb::update_node_attribs("frame","frame",$name,$frameid,$model,$serial,"","","",$parent,"",\%db, $::UPDATE_CACHE{$name},\@ppclist);
 | |
|             }
 | |
|             xCAT::PPCdb::add_ppc( "frame", [$values], 0, 1 );
 | |
|             #copy passwd for the bpas.
 | |
|             my $rst = copypasswd($name);
 | |
|             unless ( $rst )
 | |
|             {
 | |
|                 # do something here
 | |
|             }
 | |
|         } elsif ( $type =~ /^CEC$/ ) {
 | |
|             ########################################
 | |
|             # CEC: type=cec, name=hostname, cageid=cageid
 | |
|             # mtms=mtms, side=null, prof=null,frame=parent
 | |
|             # ip=null,mac=mac
 | |
|             ########################################
 | |
|             my $mac        = "";
 | |
|             my $ip         = "";
 | |
|             my $side       = "";
 | |
|             my $values = join( ",",
 | |
|                lc($type),$name,$cageid,$model,$serial,$side,$name,$prof,$parent,$ip,$mac );
 | |
|             # we should call update_node_attribs to Frame/CEC
 | |
|             # to make sure the information difined for FSP/BPA
 | |
|             # before can be kept.
 | |
|             if ( exists($::UPDATE_CACHE{$model."-".$serial}))
 | |
|             {
 | |
|                 xCAT::PPCdb::update_node_attribs("cec","cec",$name,$cageid,$model,$serial,"","","",$parent,"",\%db, $::UPDATE_CACHE{$name},\@ppclist);
 | |
|             }
 | |
|             xCAT::PPCdb::add_ppc( "cec", [$values], 0, 1 );
 | |
|             #copy passwd for the fsps.
 | |
|             my $rst = copypasswd($name);
 | |
|             unless ( $rst )
 | |
|             {
 | |
|                 # do something here
 | |
|             }
 | |
|         }elsif ($type =~ /^CMM$/){
 | |
|             $db{nodelist}->setNodeAttribs($name,{node=>$name, groups=>"cmm,all"});
 | |
|             $db{vpd}->setNodeAttribs($name,{mtm=>$model, serial=>$serial});
 | |
|             $db{nodetype}->setNodeAttribs($name,{nodetype=>"blade"});
 | |
|             $db{nodehm}->setNodeAttribs($name,{mgt=>"blade"});
 | |
|             $db{mp}->setNodeAttribs($name,{nodetype=>"cmm", mpa=>$name, id=>$side});  
 | |
|         }
 | |
|     }
 | |
|     foreach ( @tabs ) {
 | |
|         $db{$_}->close();
 | |
|     }
 | |
|     
 | |
|     ########################################
 | |
|     # Write otherinterface to the host table
 | |
|     ########################################
 | |
|     my $hoststab  = xCAT::Table->new( 'hosts' );
 | |
|     if ($hoststab and %otherinterfacehash) {
 | |
|          $hoststab->setNodesAttribs(\%otherinterfacehash);
 | |
|     }
 | |
|     $hoststab->close();
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Run makedhcp internally
 | |
| ##########################################################################
 | |
| sub do_makedhcp {
 | |
| 
 | |
|     my $request = shift;
 | |
|     my $outhash = shift;
 | |
|     my @nodes;
 | |
|     my $string;
 | |
| 
 | |
|     my @tabs   = qw(hosts mac);
 | |
|     my %db     = ();
 | |
| 
 | |
|     foreach ( @tabs ) {
 | |
|         $db{$_} = xCAT::Table->new( $_, -create=>1, -autocommit=>1 );
 | |
|             if ( !$db{$_} ) {
 | |
|             return( "Error opening '$_'" );
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     $string = "\nStart to do makedhcp..\n";
 | |
|     send_msg( $request, 0, $string );
 | |
| 
 | |
|     #####################################
 | |
|     # Collect nodenames
 | |
|     #####################################
 | |
|     foreach my $name ( keys %$outhash ) {
 | |
|         if ( $name =~ /^([^\(]+)\(([^\)]+)\)$/) {
 | |
|             $name = $1;
 | |
|         }
 | |
| 
 | |
|         #####################################
 | |
|         # Check if IP and mac are both
 | |
|         # existing for this node
 | |
|         #####################################
 | |
|         my $ifip = xCAT::Utils->isIpaddr($name);
 | |
|         unless( $ifip )
 | |
|         {
 | |
|             my ($hostsent) = $db{hosts}->getNodeAttribs( $name, [qw(ip)] );
 | |
|             if ( !$hostsent or !$hostsent->{ip} ) {
 | |
|                 $string = "Cannot find IP address for node $name during makedhcp, skip";
 | |
|                 send_msg( $request, 0, $string );
 | |
|                 next;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         my ($macent) = $db{mac}->getNodeAttribs( $name, [qw(mac)] );
 | |
|         if ( !$macent or !$macent->{mac} ) {
 | |
|             $string = "Cannot find MAC address for node $name during makedhcp, skip";
 | |
|             send_msg( $request, 0, $string );
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         push @nodes, $name;
 | |
|     }
 | |
| 
 | |
|     my $node = join ",", @nodes;
 | |
| 
 | |
|     $string = "Adding following nodes to dhcp server: \n$node\n";
 | |
|     send_msg( $request, 0, $string );
 | |
| 
 | |
|     my $line = `/opt/xcat/sbin/makedhcp $node 2>&1`;
 | |
|     send_msg( $request, 0, $line);
 | |
| 
 | |
|     send_msg( $request, 0, "\nMakedhcp finished.\n" );
 | |
| 
 | |
|     return undef;
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Reset the network interfraces if necessary
 | |
| ##########################################################################
 | |
| sub do_resetnet {
 | |
| 
 | |
|     my $req     = shift;
 | |
|     my $outhash = shift;
 | |
|     my $reset_all = 1;
 | |
|     my $namehash;
 | |
|     my $targets;
 | |
|     my $result;
 | |
|     my $nodetype;
 | |
| 
 | |
|     # this part was used for lsslp output data format.
 | |
|     # when invoked by rspconfig, the input data are different.
 | |
|     # so I re-write this part.
 | |
|     #if ( $outhash ) {
 | |
|     #    $reset_all = 0;
 | |
|     #    foreach my $name ( keys %$outhash ) {
 | |
|     #        my $data = $outhash->{$name};
 | |
|     #        my $ip = @$data[4];
 | |
|     #        if ( $name =~ /^([^\(]+)\(([^\)]+)\)$/) {
 | |
|     #            $name = $1;
 | |
|     #            $ip = $2;
 | |
|     #        }
 | |
|     #        $namehash->{$name} = $ip;
 | |
|     #    }
 | |
|     #}
 | |
|     my $hoststab = xCAT::Table->new( 'hosts' );
 | |
|     if ( !$hoststab ) {
 | |
|         send_msg( $req, 1, "Error open hosts table" );
 | |
|         return( [RC_ERROR] );
 | |
|     }
 | |
| 
 | |
|     my $mactab = xCAT::Table->new( 'mac' );
 | |
|     if ( !$mactab ) {
 | |
|         send_msg( $req, 1, "Error open mac table" );
 | |
|         return( [RC_ERROR] );
 | |
|     }
 | |
| 
 | |
|     if ( $req->{node} ) {
 | |
|         $reset_all = 0;
 | |
|         my $typehash = xCAT::DBobjUtils->getnodetype(\@{ $req->{node}});
 | |
|         foreach my $nn ( @{ $req->{node}} ) {
 | |
|             $nodetype = $$typehash{$nn};
 | |
|             # this brunch is just for the xcat 2.6(+) database
 | |
|             if ( $nodetype =~ /^(cec|frame)$/ )  {
 | |
|                 my $cnodep = xCAT::DBobjUtils->getchildren($nn);
 | |
|                 $nodetype = ( $nodetype =~ /^frame$/i ) ? "bpa" : "fsp";
 | |
|                 if ($cnodep) {
 | |
|                     foreach my $cnode (@$cnodep) {
 | |
|                         my $ip = xCAT::Utils::getNodeIPaddress( $cnode );
 | |
|                         $namehash->{$cnode} = $ip;
 | |
|                     }
 | |
|                 } else {
 | |
|                     send_msg( $req, 1, "Can't get the fsp/bpa nodes for the $nn" );
 | |
|                     return( [RC_ERROR] );
 | |
|                 }
 | |
|             # this brunch is just for the xcat 2.5(-) databse
 | |
|             } elsif ( $nodetype =~ /^(fsp|bpa)$/ )  {
 | |
|                 my $ip = xCAT::Utils::getNodeIPaddress( $nn );
 | |
|                 $namehash->{$nn} = $ip;
 | |
|             } elsif ( !$nodetype ){
 | |
|                 send_msg( $req, 0, "$nn: no nodetype defined, skipping network reset" );
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     send_msg( $req, 0, "\nStart to reset network..\n" );
 | |
| 
 | |
|     my $ip_host;
 | |
|     my @hostslist = $hoststab->getAllNodeAttribs(['node','otherinterfaces']);
 | |
|     foreach my $host ( @hostslist ) {
 | |
|         my $name = $host->{node};
 | |
|         my $oi = $host->{otherinterfaces};
 | |
| 
 | |
|         #####################################
 | |
|         # find the otherinterfaces for the
 | |
|         # specified nodes, or the all nodes
 | |
|         # Skip the node if the IP attributes
 | |
|         # is same as otherinterfaces
 | |
|         #####################################
 | |
|         if ( $reset_all eq 0 && !exists( $namehash->{$name}) ){
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         #if ( $namehash->{$name} ) {
 | |
|         #    $hoststab->setNodeAttribs( $name,{otherinterfaces=>$namehash->{$name}} );
 | |
|         #}
 | |
| 
 | |
|         if (!$oi or $oi eq $namehash->{$name}) {
 | |
|             send_msg( $req, 0, "$name: same ip address, skipping network reset" );
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         my $mac = $mactab->getNodeAttribs( $name, [qw(mac)]);
 | |
|         if ( !$mac or !$mac->{mac} ) {
 | |
|             send_msg( $req, 0, "$name: no mac defined, skipping network reset" );
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         #####################################
 | |
|         # Make the target that will reset its
 | |
|         # network interface
 | |
|         #####################################
 | |
|         $targets->{$nodetype}->{$oi}->{'args'} = "0.0.0.0,$name";
 | |
|         $targets->{$nodetype}->{$oi}->{'mac'} = $mac->{mac};
 | |
|         $targets->{$nodetype}->{$oi}->{'name'} = $name;
 | |
|         $targets->{$nodetype}->{$oi}->{'ip'} = $oi;
 | |
|         $targets->{$nodetype}->{$oi}->{'type'} = $nodetype;
 | |
|         if ( $nodetype !~ /^mm$/ ) {
 | |
|             my %netinfo = xCAT::DBobjUtils->getNetwkInfo( [$oi] );
 | |
|             $targets->{$nodetype}->{$oi}->{'args'} .= ",$netinfo{$oi}{'gateway'},$netinfo{$oi}{'mask'}";
 | |
|         }
 | |
|         $ip_host->{$oi} = $name;
 | |
|     }
 | |
| 
 | |
|     $result = undef;
 | |
|     ###########################################
 | |
|     # Update target hardware w/discovery info
 | |
|     ###########################################
 | |
|     my ($fail_nodes,$succeed_nodes) = rspconfig( $req, $targets );
 | |
|     $result = "\nReset network failed nodes:\n";
 | |
|     foreach my $ip ( @$fail_nodes ) {
 | |
|         if ( $ip_host->{$ip} ) {
 | |
|             $result .= $ip_host->{$ip} . ",";
 | |
|         }
 | |
|     }
 | |
|     $result .= "\nReset network succeed nodes:\n";
 | |
|     foreach my $ip ( @$succeed_nodes ) {
 | |
|         if ( $ip_host->{$ip} ) {
 | |
|             $result .= $ip_host->{$ip} . ",";
 | |
|             my $new_ip = $hoststab->getNodeAttribs( $ip_host->{$ip}, [qw(ip)]);
 | |
|             $hoststab->setNodeAttribs( $ip_host->{$ip},{otherinterfaces=>$new_ip->{ip}} );
 | |
|         }
 | |
|     }
 | |
|     $result .= "\nReset network finished.\n";
 | |
|     $hoststab->close();
 | |
| 
 | |
|     send_msg( $req, 0, $result );
 | |
| 
 | |
|     return undef;
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Stanza formatting
 | |
| ##########################################################################
 | |
| sub format_stanza {
 | |
| 
 | |
|     my $outhash = shift;
 | |
|     my $result;
 | |
| 
 | |
|     #####################################
 | |
|     # Write attributes
 | |
|     #####################################
 | |
|     foreach my $name ( keys %$outhash ) {
 | |
|         my @data = @{$outhash->{$name}};
 | |
|         my $type = lc($data[0]);
 | |
|         my $ip   = $data[4];
 | |
|         my $i = 0;
 | |
| 
 | |
|         if ( $name =~ /^([^\(]+)\(([^\)]+)\)$/) {
 | |
|             $name = $1;
 | |
|             $ip  = $2;
 | |
|         }
 | |
| 
 | |
|         #################################
 | |
|         # Node attributes
 | |
|         #################################
 | |
|         $result .= "$name:\n\tobjtype=node\n";
 | |
| 
 | |
|         #################################
 | |
|         # Add each attribute
 | |
|         #################################
 | |
|         if ($type eq "cmm") {
 | |
|             $result .= "\tmpa=$name\n";
 | |
|         } else {    
 | |
|             $result .= "\thcp=$name\n";
 | |
|         }    
 | |
|         foreach ( @attribs ) {
 | |
|             my $d = $data[$i++];
 | |
| 
 | |
|             if ( /^nodetype$/ ) {
 | |
|                 $d = $globalnodetype{$type};
 | |
|             } elsif ( /^groups$/ ) {
 | |
|                 $d = "$type,all";
 | |
|             } elsif ( /^mgt$/ ) {
 | |
|                 if ($mgt{$type} =~ /^cec$/)  {
 | |
|                     $d = "fsp";
 | |
|                 }elsif ($mgt{$type} =~ /^frame$/)  {
 | |
|                     $d = "bpa";
 | |
|                 }else {
 | |
|                     $d = $mgt{$type};
 | |
|                 }
 | |
|             } elsif ( /^id$/ ) {
 | |
|                 if ( $type =~ /^(fsp|bpa|cec|frame)$/ ) {
 | |
|                     $d = $data[$i++];
 | |
|                 } else {
 | |
|                     $i++;
 | |
|                     next;
 | |
|                 }
 | |
|                 $i++;
 | |
|             } elsif ( /^side$/ ) {
 | |
|                 if ( $type !~ /^(fsp|bpa|cmm)$/ ) {
 | |
|                     next;
 | |
|                 }
 | |
|             } elsif ( /^parent$/ )  {
 | |
|                 if ( $type !~ /^(fsp|bpa|cec)$/ ) {
 | |
|                     next;
 | |
|                 }
 | |
|             } elsif ( /^ip$/ )  {
 | |
|                 if ( $type =~ /^(frame|cec|fsp|bpa|cmm)$/ ) {
 | |
|                     next;
 | |
|                 }
 | |
|             } elsif (/^hidden$/) {
 | |
|                 if ( $type =~ /^(fsp|bpa)$/ ) {
 | |
|                     $d = "1";
 | |
|                 } else {
 | |
|                     $d = "0";
 | |
|                 }
 | |
|             } elsif (/^otherinterfaces$/) {
 | |
|                 $d = $otherinterfacehash{$name}{otherinterfaces};
 | |
|             } elsif (/^hwtype$/) {
 | |
|                 $d = $globlehwtype{$type}
 | |
|             }
 | |
|             if ( !defined($d) ) {
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             $result .= "\t$_=$d\n";
 | |
|         }
 | |
|         if ( exists($opt{updatehosts}) ) {
 | |
|             $result .= "\tip=$ip\n";
 | |
|         }
 | |
|     }
 | |
|     return( $result );
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # XML formatting
 | |
| ##########################################################################
 | |
| sub format_xml {
 | |
| 
 | |
|     my $outhash = shift;
 | |
|     my $xml;
 | |
| 
 | |
|     #####################################
 | |
|     # Create XML formatted attributes
 | |
|     #####################################
 | |
|     foreach my $name ( keys %$outhash ) {
 | |
|         my @data = @{ $outhash->{$name}};
 | |
|         my $type = lc($data[0]);
 | |
|         my $ip   = $data[4];
 | |
|         my $i = 0;
 | |
| 
 | |
|         if ( $name =~ /^([^\(]+)\(([^\)]+)\)$/) {
 | |
|             $name = $1;
 | |
|             $ip  = $2;
 | |
|         }
 | |
| 
 | |
|         #################################
 | |
|         # Initialize hash reference
 | |
|         #################################
 | |
|         my $href = {
 | |
|             Node => { }
 | |
|         };
 | |
|         $href->{Node}->{node} = $name;
 | |
|         if ( exists($opt{updatehosts}) ) {
 | |
|             $href->{Node}->{ip} = $ip;
 | |
|         }
 | |
|         #################################
 | |
|         # Add each attribute
 | |
|         #################################
 | |
|         if ($type eq "cmm") {
 | |
|             $href->{Node}->{"mpa"} = $name;
 | |
|         } else {    
 | |
|             $href->{Node}->{"hcp"} = $name;
 | |
|         } 
 | |
|         foreach ( @attribs ) {
 | |
|             my $d = $data[$i++];
 | |
| 
 | |
|             if ( /^nodetype$/ ) {
 | |
|                 $d = $globalnodetype{$type};
 | |
|             } elsif ( /^groups$/ ) {
 | |
|                 $d = "$type,all";
 | |
|             } elsif ( /^mgt$/ ) {
 | |
|                 if ($mgt{$type} =~ /^cec$/)  {
 | |
|                     $d = "fsp";
 | |
|                 }elsif ($mgt{$type} =~ /^frame$/)  {
 | |
|                     $d = "bpa";
 | |
|                 }else {
 | |
|                     $d = $mgt{$type};
 | |
|                 }
 | |
|             } elsif ( /^id$/ ) {
 | |
|                 if ( $type =~ /^(fsp|bpa|cec|frame)$/ ) {
 | |
|                     $d = $data[$i++];
 | |
|                 } else {
 | |
|                     $i++;
 | |
|                     next;
 | |
|                 }
 | |
|                 $i++;
 | |
|             } elsif ( /^side$/ ) {
 | |
|                 if ( $type !~ /^(fsp|bpa)$/ ) {
 | |
|                     next;
 | |
|                 }
 | |
|             } elsif ( /^parent$/ )  {
 | |
|                 if ( $type !~ /^(fsp|bpa|cec)$/ ) {
 | |
|                     next;
 | |
|                 }
 | |
|             } elsif ( /^ip$/ )  {
 | |
|                 if ( $type =~ /^(frame|cec|fsp|bpa|cmm)$/ ) {
 | |
|                     next;
 | |
|                 }
 | |
|             } elsif (/^hidden$/) {
 | |
|              if ( $type =~ /^(fsp|bpa)$/ ) {
 | |
|                     $d = "1";
 | |
|                 } else {
 | |
|                     $d = "0";
 | |
|                 }
 | |
|             } elsif (/^otherinterfaces$/) {
 | |
|                 $d = $otherinterfacehash{$name}{otherinfterfaces};
 | |
|             } elsif (/^hwtype$/) {
 | |
|                 $d = $globlehwtype{$type}
 | |
|             }
 | |
|             if ( !defined($d) ) {
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             $href->{Node}->{$_} = $d;
 | |
|         }
 | |
|         #################################
 | |
|         # XML encoding
 | |
|         #################################
 | |
|         $xml.= XMLout($href,
 | |
|                      NoAttr   => 1,
 | |
|                      KeyAttr  => [],
 | |
|                      RootName => undef );
 | |
|     }
 | |
|     return( $xml );
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # VPD table formatting
 | |
| ##########################################################################
 | |
| sub format_table {
 | |
| 
 | |
|     my $outhash = shift;
 | |
|     my $result;
 | |
| 
 | |
|     #####################################
 | |
|     # Create XML formatted attributes
 | |
|     #####################################
 | |
|     foreach my $name ( keys %$outhash ) {
 | |
|         my @data = @{ $outhash->{$name}};
 | |
|         my $type = lc($data[0]);
 | |
|         next if ($type =~ /^(fsp|bpa)$/);
 | |
|         $result .= "$name:\n";
 | |
|         #$result .= "groups=frame,all\n";
 | |
|         $result .= "\tobjtype=node\n";
 | |
|         #$result .= "\tnodetype=$type\n";
 | |
|         $result .= "\tmtm=$data[1]\n";
 | |
|         $result .= "\tserial=$data[2]\n";
 | |
|     }
 | |
| 
 | |
|     return( $result );
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # OpenSLP running on:
 | |
| #     P6 FSP
 | |
| #     P6 BPA
 | |
| # IBM SLP running on:
 | |
| #     P5 FSP
 | |
| #     P5 BPA
 | |
| #     HMC
 | |
| #     MM
 | |
| #     RSA
 | |
| # AIX SLP
 | |
| #     IVM
 | |
| #
 | |
| # Notes:
 | |
| # IBM SLP requires trailing ':' (i.e. service:management-hardware.IBM:)
 | |
| # There is one exception to this rule when dealing with FSP
 | |
| # concrete" service types, it will work with/without the trailing ':'
 | |
| # (i.e. "service:management-hardware.IBM:cec-service-processor[:]")
 | |
| #
 | |
| # OpenSLP does not support ':' at the end of services
 | |
| # (i.e. service:management-hardware.IBM:). Unfortunately, IBM SLP
 | |
| # requires it.
 | |
| #
 | |
| # Given the above, to collect all the above service types, it is
 | |
| # necessary to multicast:
 | |
| # (1) "service:management-*" for all IBM SLP hardware
 | |
| # (2) "service:management-hardware.IBM" for OpenSLP hardware (P6 FSP/BPA)
 | |
| #      (IBM SLP hardware will not respond to this since there is no trailing ":")
 | |
| #
 | |
| # * One exception to the above rule is when using FSP concrete
 | |
| #   service type, it will work with/without the trailing ":"
 | |
| #   (i.e. "service:management-hardware.IBM:cec-service-processor[:]"
 | |
| #
 | |
| ##########################################################################
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Run IBM SLP version
 | |
| ##########################################################################
 | |
| sub slp_query {
 | |
| 
 | |
|     my $request  = shift;
 | |
|     my $callback = $request->{callback};
 | |
|     my $cmd      = $opt{e};
 | |
| 
 | |
|     #############################################
 | |
|     # slp_query not installed
 | |
|     #############################################
 | |
|     if ( !-x $cmd ) {
 | |
|         send_msg( $request, 1, "Command not found: $cmd" );
 | |
|         return( [RC_ERROR] );
 | |
|     }
 | |
|     #############################################
 | |
|     # slp_query runnable - dependent on libstdc++
 | |
|     # Test for usage statement.
 | |
|     #############################################
 | |
|     my $output = `$cmd 2>&1`;
 | |
|     if ( $output !~ /slp_query --type=service-type-string/ ) {
 | |
|         send_msg( $request, 1, $output );
 | |
|         return( [RC_ERROR] );
 | |
|     }
 | |
|     my $result = runcmd( $request, $cmd );
 | |
|     return( $result );
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Run OpenSLP version
 | |
| ##########################################################################
 | |
| sub slptool {
 | |
| 
 | |
|     my $request = shift;
 | |
|     my $cmd     = SLPTOOL;
 | |
|     my $start;
 | |
| 
 | |
|     #########################################
 | |
|     # slptool not installed
 | |
|     #########################################
 | |
|     if ( !-x $cmd ) {
 | |
|         send_msg( $request, 1, "Command not found: $cmd" );
 | |
|         return( [RC_ERROR] );
 | |
|     }
 | |
|     #########################################
 | |
|     # slptool runnable - test for version
 | |
|     #########################################
 | |
|     my $output = `$cmd -v 2>&1`;
 | |
|     if ( $output !~ /^slptool version = 1.2.1\nlibslp version = 1.2.1/ ) {
 | |
|         send_msg( $request, 1, "Incorrect 'slptool' command installed" );
 | |
|         return( [RC_ERROR] );
 | |
|     }
 | |
|     #########################################
 | |
|     # Select broadcast, convergence, etc
 | |
|     #########################################
 | |
|     my $mode = selectmode( $request );
 | |
|     if ( defined($mode) ) {
 | |
|         return( $mode );
 | |
|     }
 | |
|     my $result = runcmd( $request, $cmd );
 | |
|     return( $result );
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Select OpenSLP slptool broadcast convergence, etc
 | |
| ##########################################################################
 | |
| sub selectmode {
 | |
| 
 | |
|     my $request = shift;
 | |
|     my $fname   = SLP_CONF;
 | |
|     my $mode;
 | |
|     my $maxtimeout;
 | |
|     my $converge;
 | |
| 
 | |
|     ##################################
 | |
|     # Select convergence
 | |
|     ##################################
 | |
|     if ( exists( $opt{c} )) {
 | |
|         $converge = join( ',',@converge );
 | |
| 
 | |
|         ##############################
 | |
|         # Maximum timeout
 | |
|         ##############################
 | |
|         foreach ( @converge ) {
 | |
|             $maxtimeout += $_;
 | |
|         }
 | |
|     }
 | |
|     ##################################
 | |
|     # Select multicast or broadcast
 | |
|     ##################################
 | |
|     if ( !exists( $opt{m} )) {
 | |
|         $mode = "true";
 | |
|     }
 | |
| 
 | |
|     ##################################
 | |
|     # slp.conf attributes
 | |
|     ##################################
 | |
|     my %attr = (
 | |
|         "net.slp.multicastTimeouts"    => $converge,
 | |
|         "net.slp.isBroadcastOnly"      => $mode,
 | |
|         "net.slp.multicastMaximumWait" => $maxtimeout
 | |
|     );
 | |
| 
 | |
|     if ( $verbose ) {
 | |
|         my $msg = !defined($mode) ? "Multicasting SLP...":"Broadcasting SLP...";
 | |
|         trace( $request, $msg );
 | |
|     }
 | |
|     ##################################
 | |
|     # Open/read slp.conf
 | |
|     ##################################
 | |
|     unless ( open( CONF, $fname )) {
 | |
|         send_msg( $request, 1, "Error opening: '$fname'" );
 | |
|         return( [RC_ERROR] );
 | |
|     }
 | |
|     my @raw_data = <CONF>;
 | |
|     close( CONF );
 | |
| 
 | |
|     ##################################
 | |
|     # Find attribute
 | |
|     ##################################
 | |
|     foreach my $name ( keys %attr ) {
 | |
|         my $found = 0;
 | |
| 
 | |
|         foreach ( @raw_data ) {
 | |
|             if ( /^;*$name\s*=/ ) {
 | |
|                 if ( !defined( $attr{$name} )) {
 | |
|                     s/^;*($name\s*=\s*[\w,]+)/;$1/;
 | |
|                 } elsif ( $attr{$name} == 0 ) {
 | |
|                     s/^;*($name\s*=\s*[\w,]+)/$1/;
 | |
|                 } else {
 | |
|                     s/^;*$name\s*=\s*[\w,]+/$name = $attr{$name}/;
 | |
|                 }
 | |
|                 $found = 1;
 | |
|                 last;
 | |
|             }
 | |
|         }
 | |
|         if ( !$found ) {
 | |
|             send_msg( $request, 1, "'$name' not found in '$fname'" );
 | |
|             return( [RC_ERROR] );
 | |
|         }
 | |
|     }
 | |
|     ##################################
 | |
|     # Rewrite file contents
 | |
|     ##################################
 | |
|     unless ( open( CONF, "+>$fname" )) {
 | |
|         send_msg( $request, 1, "Error opening: '$fname'" );
 | |
|         return( [RC_ERROR] );
 | |
|     }
 | |
|     print CONF @raw_data;
 | |
|     close( CONF );
 | |
|     return undef;
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Run the SLP command
 | |
| ##########################################################################
 | |
| sub runcmd {
 | |
| 
 | |
|     my $request  = shift;
 | |
|     my $cmd      = shift;
 | |
|     my $services = shift;
 | |
|     my $callback = $request->{callback};
 | |
|     my @services = ( WILDCARD_SERVICE, P6_SERVICE, P7_SERVICE );
 | |
|     my $start;
 | |
| 
 | |
|     ###########################################
 | |
|     # Query specific service; otherwise,
 | |
|     # query all hardware/software services
 | |
|     ###########################################
 | |
|     if ( exists( $opt{s} )) {
 | |
|         @services = $request->{service};
 | |
|     }
 | |
| 
 | |
|     if ( $verbose ) {
 | |
|         #######################################
 | |
|         # Write header for trace
 | |
|         #######################################
 | |
|         my $tm  = localtime( time );
 | |
|         my $msg = "\n--------  $tm\nTime     PID";
 | |
|         trace( $request, $msg );
 | |
|     }
 | |
|     ###########################################
 | |
|     # Get/validate broadcast IPs
 | |
|     ###########################################
 | |
|     my $result = validate_ip( $request );
 | |
|     my $Rc = shift(@$result);
 | |
| 
 | |
|     if ( $Rc ) {
 | |
|         send_msg( $request, 1, @$result[0] );
 | |
|         return( [RC_ERROR] );
 | |
|     }
 | |
|     if ( $verbose ) {
 | |
|         $start = Time::HiRes::gettimeofday();
 | |
|     }
 | |
|     ###########################################
 | |
|     # Fork one process per adapter
 | |
|     ###########################################
 | |
|     my $children = 0;
 | |
|     $SIG{CHLD} = sub {
 | |
|        my $rc_bak = $?;
 | |
|        while (waitpid(-1, WNOHANG) > 0) { $children--; }
 | |
|        $? = $rc_bak;
 | |
|     };
 | |
|     my $fds = new IO::Select;
 | |
| 
 | |
|     foreach ( keys %ip_addr ) {
 | |
|         my $pipe = fork_cmd( $request, $_, $cmd, \@services );
 | |
|         if ( $pipe ) {
 | |
|             $fds->add( $pipe );
 | |
|             $children++;
 | |
|         }
 | |
|     }
 | |
|     ###########################################
 | |
|     # Process slp responses from children
 | |
|     ###########################################
 | |
|     while ( $children > 0 ) {
 | |
|         child_response( $callback, $fds );
 | |
|     }
 | |
|     while (child_response($callback,$fds)) {}
 | |
| 
 | |
|     if ( $verbose ) {
 | |
|         my $elapsed = Time::HiRes::gettimeofday() - $start;
 | |
|         my $msg = sprintf( "Total SLP Time: %.3f sec\n", $elapsed );
 | |
|         trace( $request, $msg );
 | |
|     }
 | |
|     ###########################################
 | |
|     # Combined responses from all children
 | |
|     ###########################################
 | |
|     my @all_results = keys %slp_result;
 | |
|     format_output( $request, \@all_results );
 | |
|     return( [SUCCESS,\@all_results] );
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Collect output from the child processes
 | |
| ##########################################################################
 | |
| sub child_response {
 | |
| 
 | |
|     my $callback = shift;
 | |
|     my $fds = shift;
 | |
|     my @ready_fds = $fds->can_read(1);
 | |
| 
 | |
|     foreach my $rfh (@ready_fds) {
 | |
|         my $data = <$rfh>;
 | |
| 
 | |
|         #################################
 | |
|         # Read from child process
 | |
|         #################################
 | |
|         if ( defined( $data )) {
 | |
|             while ($data !~ /ENDOFFREEZE6sK4ci/) {
 | |
|                 $data .= <$rfh>;
 | |
|             }
 | |
|             my $responses = thaw($data);
 | |
| 
 | |
|             #############################
 | |
|             # Formatted SLP results
 | |
|             #############################
 | |
|             if ( @$responses[0] =~ /^FORMATDATA6sK4ci$/ ) {
 | |
|                 my $result = @$responses[1];
 | |
|                 foreach ( keys %$result ) {
 | |
|                     $slp_result{$_} = 1;
 | |
|                 }
 | |
|                 next;
 | |
|             }
 | |
|             #############################
 | |
|             # rspconfig results
 | |
|             #############################
 | |
|             if ( @$responses[0] =~ /^RSPCONFIG6sK4ci$/ ) {
 | |
|                 shift @$responses;
 | |
|                 my $ip = shift(@$responses);
 | |
| 
 | |
|                 $rsp_result{$ip} = $responses;
 | |
|                 next;
 | |
|             }
 | |
|             #############################
 | |
|             # Message or verbose trace
 | |
|             #############################
 | |
|             foreach ( @$responses ) {
 | |
|                 $callback->( $_ );
 | |
|             }
 | |
|             next;
 | |
|         }
 | |
|         #################################
 | |
|         # Done - close handle
 | |
|         #################################
 | |
|         $fds->remove($rfh);
 | |
|         close($rfh);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| #############################################################################
 | |
| # Preprocess request from xCat daemon and send request to service nodes
 | |
| #############################################################################
 | |
| sub preprocess_request {
 | |
| 
 | |
|     my $req = shift;
 | |
|     if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; }
 | |
|     my $callback=shift;
 | |
|     my @requests;
 | |
| 
 | |
| 
 | |
|     my $command = $req->{command}->[0];
 | |
|     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;
 | |
|     }
 | |
|     ###########################################
 | |
|     # find all the service nodes for xCAT cluster
 | |
|     # build an individual request for each service node
 | |
|     ###########################################
 | |
|     my %sv_hash=();
 | |
|     #my @all = xCAT::Utils::getAllSN();
 | |
|     #foreach (@all) {
 | |
|     #    $sv_hash{$_}=1;
 | |
|     #}
 | |
|     ###########################################
 | |
|     # build each request for each service node
 | |
|     ###########################################
 | |
|     my @result = ();
 | |
|     my $mncopy = {%$req};
 | |
|     push @result, $mncopy;
 | |
|     #foreach my $sn (keys (%sv_hash)) {
 | |
|     #  my $reqcopy = {%$req};
 | |
|     #  $reqcopy->{_xcatdest} = $sn;
 | |
|     #  $reqcopy->{_xcatpreprocessed}->[0] = 1;
 | |
|     #  push @result, $reqcopy;
 | |
|     #}
 | |
|     return \@result;
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Distinguish
 | |
| ##########################################################################
 | |
| sub disti_multi_node
 | |
| {
 | |
|     my $names = shift;
 | |
|     my $type  = shift;
 | |
|     my $bpc_model    = shift;
 | |
|     my $bpc_serial   = shift;
 | |
|     my $frame_number = shift;
 | |
|     my $cage_number  = shift;
 | |
|     my $side   = shift;
 | |
|     my $mtm    = shift;
 | |
|     my $serial = shift;
 | |
| 
 | |
|     return undef if ( $type eq 'FSP' and !defined $cage_number );
 | |
|     return undef if ( $type eq 'BPA' and !defined $frame_number );
 | |
| 
 | |
|     my $ppctab = xCAT::Table->new( 'ppc' );
 | |
|     return undef if ( ! $ppctab );
 | |
|     my $nodetypetab = xCAT::Table->new( 'nodetype' );
 | |
|     return undef if ( ! $nodetypetab );
 | |
| 
 | |
|     my $vpdtab = xCAT::Table->new( 'vpd' );
 | |
|     return undef if ( ! $vpdtab );
 | |
| 
 | |
|     my @nodes = split /,/, $names;
 | |
|     my $correct_node = undef;
 | |
|     foreach my $node ( @nodes ) {
 | |
|         my $id_parent = $ppctab->getNodeAttribs( $node, ['id','parent'] );
 | |
|         my $nodetype = $nodetypetab->getNodeAttribs($node, ['nodetype'] );
 | |
|         next if ( !defined $nodetype or !exists $nodetype->{'nodetype'} );
 | |
|         next if ( $nodetype->{'nodetype'} ne lc($type) );
 | |
| 
 | |
|         if ( $nodetype->{'nodetype'} eq 'fsp' ) {
 | |
|             if ( (exists $id_parent->{'id'}) and (exists $id_parent->{'parent'}) ) {
 | |
|                 ###########################################
 | |
|                 # For high end machines.
 | |
|                 # Check if this node's parent and id is the
 | |
|                 # same in SLP response.
 | |
|                 ###########################################
 | |
|                 if ( $id_parent->{'id'} eq $cage_number ) {
 | |
|                     my $vpdnode = $vpdtab->getNodeAttribs($id_parent->{'parent'}, ['serial','mtm']);
 | |
|                     if ( (exists $vpdnode->{'serial'}) and ($vpdnode->{'serial'} ne $bpc_serial) ) {
 | |
|                         next;
 | |
|                     }
 | |
|                     if ( (exists $vpdnode->{'mtm'}) and ($vpdnode->{'mtm'} ne $bpc_model) ) {
 | |
|                         next;
 | |
|                     }
 | |
|                 } else {
 | |
|                     next;
 | |
|                 }
 | |
|             } else {
 | |
|                 ###########################################
 | |
|                 # For low end machines.
 | |
|                 # If there is hub to connect several FSPs
 | |
|                 # with the same switch port, check node's
 | |
|                 # mtms
 | |
|                 ###########################################
 | |
|                 my $vpdnode = $vpdtab->getNodeAttribs($node, ['serial','mtm']);
 | |
|                 if ( (exists $vpdnode->{'serial'}) and ($vpdnode->{'serial'} ne $serial) ) {
 | |
|                     next;
 | |
|                 }
 | |
|                 if ( (exists $vpdnode->{'mtm'}) and ($vpdnode->{'mtm'} ne $mtm) ) {
 | |
|                     next;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             ###########################################
 | |
|             # Check if the side attribute for this node
 | |
|             # is the same in SLP response
 | |
|             # For FSP redundancy.
 | |
|             ###########################################
 | |
|             my $nodeside = $vpdtab->getNodeAttribs($node, ['side']);
 | |
|             if ( (exists $nodeside->{'side'}) and ($nodeside->{'side'} ne $side) ) {
 | |
|                 next;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if ( $nodetype->{'nodetype'} eq 'bpa' or $nodetype->{'nodetype'} eq 'mm' ) {
 | |
|             ###########################################
 | |
|             # If there is a hub to connect several BPAs
 | |
|             # with the same switch port, check this
 | |
|             # node's mtms and side
 | |
|             ###########################################
 | |
|             my $vpdnode = $vpdtab->getNodeAttribs( $node, ['serial','mtm','side'] );
 | |
| 
 | |
|             if ( (exists $vpdnode->{'serial'}) and ($vpdnode->{'serial'} ne $serial) ) {
 | |
|                 next;
 | |
|             }
 | |
|             if ( (exists $vpdnode->{'mtm'}) and ($vpdnode->{'mtm'} ne $mtm) ) {
 | |
|                 next;
 | |
|             }
 | |
|             if ( (exists $vpdnode->{'side'}) and ($vpdnode->{'side'} ne $side) ) {
 | |
|                 next;
 | |
|             }
 | |
|         }
 | |
|         return $node;
 | |
|     }
 | |
| 
 | |
|     return undef;
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Run rspconfig against targets
 | |
| ##########################################################################
 | |
| sub rspconfig {
 | |
| 
 | |
|     my $request   = shift;
 | |
|     my $targets   = shift;
 | |
|     my $callback  = $request->{callback};
 | |
|     my $start = Time::HiRes::gettimeofday();
 | |
| 
 | |
|     my %rsp_dev = get_rsp_dev( $request, $targets);
 | |
|     #############################################
 | |
|     # Fork one process per MM/HMC
 | |
|     #############################################
 | |
|     my $children = 0;
 | |
|     $SIG{CHLD} = sub { while (waitpid(-1, WNOHANG) > 0) { $children--; } };
 | |
|     my $fds = new IO::Select;
 | |
| 
 | |
|     foreach my $ip ( keys %rsp_dev) {
 | |
|         my $pipe = fork_cmd( $request, $ip, \%rsp_dev);
 | |
|         if ( $pipe ) {
 | |
|             $fds->add( $pipe );
 | |
|             $children++;
 | |
|         }
 | |
|     }
 | |
|     #############################################
 | |
|     # Process responses from children
 | |
|     #############################################
 | |
|     while ( $children > 0 ) {
 | |
|         child_response( $callback, $fds );
 | |
|     }
 | |
|     while (child_response($callback,$fds)) {}
 | |
| 
 | |
|     if ( $verbose ) {
 | |
|         my $elapsed = Time::HiRes::gettimeofday() - $start;
 | |
|         my $msg = sprintf( "Total rspconfig Time: %.3f sec\n", $elapsed );
 | |
|         trace( $request, $msg );
 | |
|     }
 | |
| 
 | |
|     my $result;
 | |
|     my @failed_node;
 | |
|     my @succeed_node;
 | |
|     foreach my $ip ( keys %rsp_result ) {
 | |
|         #################################
 | |
|         # Error logging on to MM
 | |
|         #################################
 | |
|         my $result = $rsp_result{$ip};
 | |
|         my $Rc = shift(@$result);
 | |
| 
 | |
|         if ( $Rc != SUCCESS ) {
 | |
|             push @failed_node, $ip;
 | |
|         } else {
 | |
|             push @succeed_node, $ip;
 | |
|         }
 | |
| 
 | |
|         if ( $Rc != SUCCESS ) {
 | |
|             #############################
 | |
|             # MM connect error
 | |
|             #############################
 | |
|             if ( ref(@$result[0]) ne 'ARRAY' ) {
 | |
|                 if ( $verbose ) {
 | |
|                     trace( $request, "$ip: @$result[0]" );
 | |
|                 }
 | |
|                 delete $rsp_dev{$ip};
 | |
|                 next;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         ##################################
 | |
|         # Process each response
 | |
|         ##################################
 | |
|         if ( defined(@$result[0]) ) {
 | |
|             foreach ( @{@$result[0]} ) {
 | |
|                 if ( $verbose ) {
 | |
|                     trace( $request, "$ip: $_" );
 | |
|                 }
 | |
|                 /^(\S+)\s+(\d+)/;
 | |
|                 my $cmd = $1;
 | |
|                 $Rc = $2;
 | |
| 
 | |
|                 if ( $cmd =~ /^network_reset/ ) {
 | |
|                     if ( $Rc != SUCCESS ) {
 | |
|                         delete $rsp_dev{$ip};
 | |
|                         next;
 | |
|                     }
 | |
|                     if ( $verbose ) {
 | |
|                         trace( $request,"Resetting management-module ($ip)...." );
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return( \@failed_node, \@succeed_node );
 | |
| }
 | |
| 
 | |
| #############################################
 | |
| # Get rsp devices and their logon info
 | |
| #############################################
 | |
| sub get_rsp_dev
 | |
| {
 | |
|     my $request = shift;
 | |
|     my $targets = shift;
 | |
| 
 | |
|     my $mm  = $targets->{'mm'}  ? $targets->{'mm'} : {};
 | |
|     my $hmc = $targets->{'hmc'} ? $targets->{'hmc'}: {};
 | |
|     my $fsp = $targets->{'fsp'} ? $targets->{'fsp'}: {};
 | |
|     my $bpa = $targets->{'bpa'} ? $targets->{'bpa'}: {};
 | |
| 
 | |
|     if (%$mm)
 | |
|     {
 | |
|         my $bladeuser = 'USERID';
 | |
|         my $bladepass = 'PASSW0RD';
 | |
|         if ( $verbose ) {
 | |
|             trace( $request, "telneting to management-modules....." );
 | |
|         }
 | |
|         #############################################
 | |
|         # Check passwd table for userid/password
 | |
|         #############################################
 | |
|         my $passtab = xCAT::Table->new('passwd');
 | |
|         if ( $passtab ) {
 | |
|             #my ($ent) = $passtab->getAttribs({key=>'blade'},'username','password');
 | |
|             my $ent = $passtab->getNodeAttribs('blade', ['username','password']);
 | |
|             if ( defined( $ent )) {
 | |
|                 $bladeuser = $ent->{username};
 | |
|                 $bladepass = $ent->{password};
 | |
|             }
 | |
|         }
 | |
|         #############################################
 | |
|         # Get MM userid/password
 | |
|         #############################################
 | |
|         my $mpatab = xCAT::Table->new('mpa');
 | |
|         for my $nd ( keys %$mm ) {
 | |
|             my $user = $bladeuser;
 | |
|             my $pass = $bladepass;
 | |
| 
 | |
|             if ( defined( $mpatab )) {
 | |
|                 #my ($ent) = $mpatab->getAttribs({mpa=>$_},'username','password');
 | |
|                 my $ent = $mpatab->getNodeAttribs($nd, ['username','password']);
 | |
|                 if ( defined( $ent->{password} )) { $pass = $ent->{password}; }
 | |
|                 if ( defined( $ent->{username} )) { $user = $ent->{username}; }
 | |
|             }
 | |
|             $mm->{$nd}->{username} = $user;
 | |
|             $mm->{$nd}->{password} = $pass;
 | |
|         }
 | |
|     }
 | |
|     if (%$hmc )
 | |
|     {
 | |
|         #############################################
 | |
|         # Get HMC userid/password
 | |
|         #############################################
 | |
|         foreach ( keys %$hmc ) {
 | |
|             ( $hmc->{$_}->{username}, $hmc->{$_}->{password}) = xCAT::PPCdb::credentials( $hmc->{$_}->{name}, lc($hmc->{$_}->{'type'}), "hscroot" );
 | |
|             trace( $request, "user/passwd for $_ is $hmc->{$_}->{username} $hmc->{$_}->{password}");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ( %$fsp)
 | |
|     {
 | |
|         #############################################
 | |
|         # Get FSP userid/password
 | |
|         #############################################
 | |
|         foreach ( keys %$fsp ) {
 | |
|             ( $fsp->{$_}->{username}, $fsp->{$_}->{password}) = xCAT::PPCdb::credentials( $fsp->{$_}->{name}, lc($fsp->{$_}->{'type'}), "admin");
 | |
|             trace( $request, "user/passwd for $_ is $fsp->{$_}->{username} $fsp->{$_}->{password}");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ( %$bpa)
 | |
|     {
 | |
|         #############################################
 | |
|         # Get BPA userid/password
 | |
|         #############################################
 | |
|         foreach ( keys %$bpa ) {
 | |
|             ( $bpa->{$_}->{username}, $bpa->{$_}->{password}) = xCAT::PPCdb::credentials( $bpa->{$_}->{name}, lc($bpa->{$_}->{'type'}), "admin");
 | |
|             trace( $request, "user/passwd for $_ is $bpa->{$_}->{username} $bpa->{$_}->{password}");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return (%$mm,%$hmc,%$fsp,%$bpa);
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Process request from xCat daemon
 | |
| ##########################################################################
 | |
| sub process_request {
 | |
| 
 | |
|     my $req      = shift;
 | |
|     my $callback = shift;
 | |
|     my $doreq    = shift;
 | |
|     unless ($macmap) { $macmap = xCAT::MacMap->new(); }
 | |
| 
 | |
|     ###########################################
 | |
|     # Build hash to pass around
 | |
|     ###########################################
 | |
|     my %request;
 | |
|     $request{arg}      = $req->{arg};
 | |
|     $request{callback} = $callback;
 | |
|     $request{command}  = $req->{command}->[0];
 | |
| 
 | |
|     ####################################
 | |
|     # Process command-specific options
 | |
|     ####################################
 | |
|     my $result = parse_args( \%request );
 | |
| 
 | |
|     ####################################
 | |
|     # Return error
 | |
|     ####################################
 | |
|     if ( ref($result) eq 'ARRAY' ) {
 | |
|         send_msg( \%request, 1, @$result );
 | |
|         return(1);
 | |
|     }
 | |
| 
 | |
|     if ( exists($opt{resetnet}) and scalar(keys %opt) eq 1 ) {
 | |
|         #$result = do_resetnet( \%request );
 | |
|         send_msg( \%request, 0, "the flag --resetnet has been moved to rspconfig, please see the rspconfig man page for more details" );
 | |
|         $result = [0];
 | |
|     } else {
 | |
|         ###########################################
 | |
|         # SLP service-request - select program
 | |
|         ###########################################
 | |
|         $result = $openSLP ? slptool( \%request ) : slp_query( \%request );
 | |
|     }
 | |
|     my $Rc  = shift(@$result);
 | |
| 
 | |
|     return( $Rc );
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Write hostnames and IP address to host table.  If an existing entry
 | |
| # with same IP address can be found, return the existing hostname and IP
 | |
| ##########################################################################
 | |
| sub writehost {
 | |
| 
 | |
|     my $hostname = shift;
 | |
|     my $ip       = shift;
 | |
| 
 | |
|     my $hoststab = xCAT::Table->new( "hosts", -create=>1, -autocommit=>1 );
 | |
|     if ( !$hoststab ) {
 | |
|         return( [[$hostname,"Error opening 'hosts' table",RC_ERROR]] );
 | |
|     }
 | |
| 
 | |
|     $hoststab->setNodeAttribs( $hostname,{ip=>$ip} );
 | |
|     $hoststab->close();
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Copy the user/passwd information from CEC/Frame to FSP/BPA
 | |
| # This function should be called after database migration
 | |
| ##########################################################################
 | |
| sub copypasswd {
 | |
|     my $node = shift;
 | |
|     if (($node) && ($node =~ /xCAT::/))
 | |
|     {
 | |
|         $node = shift;
 | |
|     }
 | |
| 
 | |
|     my $children = xCAT::DBobjUtils->getchildren($node);
 | |
|     my %childentry;
 | |
|     my $directtab = xCAT::Table->new('ppcdirect');
 | |
|     if ( $children and $directtab )  {
 | |
|         my $dthash = $directtab->getNodeAttribs($node, [qw(username password disable)]);
 | |
|         my $username = $dthash->{username};
 | |
|         my $passwd   = $dthash->{passwd};
 | |
|         my $disable  = $dthash->{disable};
 | |
|         foreach (@$children) {
 | |
|             $childentry{$_}{username} = $username;
 | |
|             $childentry{$_}{password}   = $passwd;
 | |
|             $childentry{$_}{disable}  = $disable;
 | |
|         }
 | |
|         $directtab->setNodesAttribs(\%childentry);
 | |
|     }
 | |
|     return 1;
 | |
| }
 | |
| ##########################################################################
 | |
| # Filter nodes the user specified
 | |
| ##########################################################################
 | |
| sub filter {
 | |
|     my $oldhash = shift;
 | |
|     my $newhash;
 | |
|     # find HMC/CEC/Frame that the user want to find
 | |
|     foreach my $n(@filternodes) {
 | |
|         for my $foundnode ( keys %$oldhash ) {
 | |
|             if ( $foundnode =~ /^(\w+)\(.*\)/ )  {
 | |
|                 if ( $1 eq $n ) {
 | |
|                     $newhash->{$foundnode} = $oldhash->{$foundnode};
 | |
|                 }
 | |
|             }
 | |
|             elsif ( $foundnode eq $n )  {
 | |
|                 $newhash->{$foundnode} = $oldhash->{$foundnode};
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # fine the FSP/BPA nodes for the CEC/Frame.
 | |
|     for my $cn ( keys %$oldhash ) {
 | |
|         for my $pn ( keys %$newhash ) {
 | |
|             if ( (${$oldhash->{$cn}}[0] =~ /^(FSP|BPA)$/)
 | |
|               and (${$newhash->{$pn}}[2] eq ${$oldhash->{$cn}}[2])
 | |
|               and (${$newhash->{$pn}}[1] eq ${$oldhash->{$cn}}[1]) ) {
 | |
|                 $newhash->{$cn} = $oldhash->{$cn};
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return $newhash;
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Filter nodes not in the user specified vlan
 | |
| ##########################################################################
 | |
| sub filtersamevlan {
 | |
|     my $oldhash = shift;
 | |
|     my $newhash;
 | |
|     my $nets = xCAT::Utils::my_nets();
 | |
|     my $validnets;
 | |
|     for my $net ( keys %$nets) {
 | |
|         for my $nic ( split /,/, $opt{i} ) {
 | |
|             if ( $nets->{$net} eq $nic ) {
 | |
|                 $validnets->{$net} = $nic;
 | |
|             }
 | |
|         }
 | |
|     }        
 | |
|     foreach my $name ( keys %$oldhash ) {
 | |
|         my @data = @{ $oldhash->{$name}};
 | |
|         my $type = lc($data[0]);
 | |
|         if ($type =~ /^(fsp|bpa)$/) {
 | |
|             my $ip = $data[4];
 | |
|             for my $net ( keys %$validnets){
 | |
|                 my ($n,$m) = split /\//,$net;
 | |
|                 if ( xCAT::Utils::isInSameSubnet( $n, $ip, $m, 1) and xCAT::Utils::isPingable( $ip)) {
 | |
|                     $newhash->{$name} = $oldhash->{$name};
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             $newhash->{$name} = $oldhash->{$name};
 | |
|         }
 | |
|     }
 | |
|     return $newhash;
 | |
| }
 | |
| ##########################################################################
 | |
| # Match the nodes defined by xcatsetup
 | |
| # The match rules are:
 | |
| # match Frame nodes with mtms
 | |
| # match CEC nodes with parent name and id
 | |
| # match FSP/BPA nodes with parent name and side
 | |
| ##########################################################################
 | |
| sub match_hosts_defined_by_xcatsetup {
 | |
|     my $nodename        = shift;
 | |
|     my $type            = shift;
 | |
|     my $mtm             = shift;
 | |
|     my $sn              = shift;
 | |
|     my $side            = shift;
 | |
|     my $ip              = shift;
 | |
|     my $cage_number     = shift;
 | |
|     my $parmtm          = shift;
 | |
|     my $parsn           = shift;
 | |
|     my $pname           = shift;
 | |
|     my $flagref         = shift;
 | |
|     
 | |
|     read_from_table() unless (%::OLD_DATA_CACHE);
 | |
|     foreach my $oldnode ( keys %::OLD_DATA_CACHE )
 | |
|     {
 | |
|         my $tmpmtm    = @{$::OLD_DATA_CACHE{$oldnode}}[0];
 | |
|         my $tmpsn     = @{$::OLD_DATA_CACHE{$oldnode}}[1];
 | |
|         my $tmpside   = @{$::OLD_DATA_CACHE{$oldnode}}[2];
 | |
|         my $tmpip     = @{$::OLD_DATA_CACHE{$oldnode}}[3];
 | |
|         my $tmpid     = @{$::OLD_DATA_CACHE{$oldnode}}[4];
 | |
|         my $tmpparent = @{$::OLD_DATA_CACHE{$oldnode}}[5];
 | |
|         my $tmptype   = uc(@{$::OLD_DATA_CACHE{$oldnode}}[6]);
 | |
|         my $unmatched = @{$::OLD_DATA_CACHE{$oldnode}}[7];
 | |
|         if ($type eq TYPE_FRAME)
 | |
|         {
 | |
|             if ($tmpmtm eq $mtm and $tmpsn eq $sn and $type eq $tmptype) {
 | |
|                 $$flagref = 1;
 | |
|                 print "20 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                 return $oldnode;
 | |
|             }    
 | |
|         }
 | |
|         if ($type eq TYPE_CEC)
 | |
|         {
 | |
|             if ($pname eq $tmpparent and $cage_number eq $tmpid  and $type eq $tmptype) {
 | |
|                 $$flagref = 1;
 | |
|                 print "21 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                 return $oldnode;
 | |
|             }    
 | |
|         }
 | |
|         if ($type eq TYPE_BPA or $type eq TYPE_FSP)
 | |
|         {
 | |
|             if ($pname eq $tmpparent and $side eq $tmpside and $type eq $tmptype) {
 | |
|                 $$flagref = 1;
 | |
|                 print "22 got old name $oldnode\n" if($DEBUG_MATCH eq 1); 
 | |
|                 return $oldnode;
 | |
|             }    
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return undef;
 | |
| }
 | |
| ##########################################################################
 | |
| # Match the nodes defined by xcatsetup
 | |
| # Use ip to find HMC defined by the user
 | |
| ##########################################################################
 | |
| sub match_ip_defined_by_xcatsetup {
 | |
|     my $ip = shift;
 | |
|     my $matchflag = shift;
 | |
|     
 | |
|     read_from_table() unless (%::OLD_DATA_CACHE);
 | |
|     foreach my $oldnode ( keys %::OLD_DATA_CACHE ) {
 | |
|         my $tmpip     = @{$::OLD_DATA_CACHE{$oldnode}}[3];
 | |
|         my $tmptype   = uc(@{$::OLD_DATA_CACHE{$oldnode}}[6]);
 | |
|         next unless($tmptype eq TYPE_HMC);
 | |
|         if ($ip eq $tmpip) {
 | |
|             $$matchflag = 1;
 | |
|             return $oldnode;
 | |
|         }
 | |
|     }
 | |
|     return undef;    
 | |
| }
 | |
| 1;
 | |
| 
 |