git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/branches/2.7@11814 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			3206 lines
		
	
	
		
			104 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			3206 lines
		
	
	
		
			104 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
#!/usr/bin/env perl
 | 
						|
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
#
 | 
						|
 | 
						|
package xCAT::LparNetbootExp;
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head1   LparNetbootExp
 | 
						|
Usage: Install partition
 | 
						|
        lpar_netboot [-v] [-x] [-f] [-w set_boot_order] [-A -D | [-D] | [-D] -m macaddress] -t ent -s speed -d duplex
 | 
						|
                -S server -G gateway -C client hostname profile managed_system lparid remote_host
 | 
						|
 | 
						|
Usage: Return macaddress
 | 
						|
        lpar_netboot -M -n [-v] -t ent [-f] [-x] [-D -s speed -d duplex -S server -G gateway -C client] hostname profile managed_system lparid remote_host
 | 
						|
 | 
						|
        -n      Do not boot partition
 | 
						|
        -t      Specifies network type ent
 | 
						|
        -D      Perform ping test, use adapter that successfully ping the server
 | 
						|
        -s      Network adapter speed
 | 
						|
        -d      Network adapter duplex
 | 
						|
        -S      Server IP address
 | 
						|
        -G      Gateway IP address
 | 
						|
        -C      Client IP address
 | 
						|
        -m      MAC Address
 | 
						|
        -v      Verbose output
 | 
						|
        -x      Debug output
 | 
						|
        -f      Force close virtual terminal session
 | 
						|
        -w      Set boot device order
 | 
						|
                        0: Don't set boot device order
 | 
						|
                        1: Set network as boot device
 | 
						|
                        2: Set network as 1st boot device, disk as 2nd boot device
 | 
						|
                        3: Set disk as 1st boot device, network as 2nd boot device
 | 
						|
                        4: set disk as boot device
 | 
						|
        -M      Discovery ethernet adapter mac address and location code
 | 
						|
        --help  Prints this help
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
BEGIN
 | 
						|
{
 | 
						|
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | 
						|
    $::XCATDIR  = $ENV{'XCATDIR'}  ? $ENV{'XCATDIR'}  : '/etc/xcat';
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
use lib "$::XCATROOT/lib/perl";
 | 
						|
use xCAT::Utils;
 | 
						|
use Getopt::Long;
 | 
						|
use xCAT::MsgUtils;
 | 
						|
use Expect;
 | 
						|
use strict;
 | 
						|
use Data::Dumper;
 | 
						|
my $adapter_found = 0;
 | 
						|
my @adap_type;
 | 
						|
my @full_path_name_array;
 | 
						|
my @phandle_array;
 | 
						|
my $macaddress;
 | 
						|
my $phys_loc;
 | 
						|
my $client_ip;
 | 
						|
my $gateway_ip;
 | 
						|
my $device_type;
 | 
						|
my $server_ip;
 | 
						|
 | 
						|
# List supported network adapters here.  dev_pat is an array of regexp patterns
 | 
						|
# the script searches for in the device tree listing.  dev_type is the type
 | 
						|
# of device displayed in the output.
 | 
						|
my @dev_pat = (
 | 
						|
        "ethernet",
 | 
						|
        "token-ring",
 | 
						|
        "fddi"
 | 
						|
        );
 | 
						|
my @dev_type = (
 | 
						|
        "ent",
 | 
						|
        "tok",
 | 
						|
        "fddi"
 | 
						|
        );
 | 
						|
my $dev_count = scalar(@dev_type); #number of supported device type
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    nc_msg
 | 
						|
 | 
						|
    PROCEDURE
 | 
						|
 | 
						|
    Declare procedure to write status/error messages
 | 
						|
    We do it this way so that if /var is full (or some other error occurs)
 | 
						|
    we can trap it in a common section of code.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
 | 
						|
sub nc_msg
 | 
						|
{
 | 
						|
    my $verbose = shift;
 | 
						|
    my $msg = shift;
 | 
						|
    my $rsp;
 | 
						|
 | 
						|
    if ( $verbose eq 1 ) {
 | 
						|
        $rsp->{data}->[0] = $msg;
 | 
						|
        xCAT::MsgUtils->message("I", $rsp ,$::CALLBACK);
 | 
						|
    }
 | 
						|
 | 
						|
    if ( $verbose eq 2 ) {
 | 
						|
        $rsp->{data}->[0] = $msg;
 | 
						|
        xCAT::MsgUtils->message("E", $rsp ,$::CALLBACK);
 | 
						|
    }
 | 
						|
}
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    run_lssyscfg
 | 
						|
 | 
						|
      Procedure to run the rpower command
 | 
						|
      test its return code and capture its output
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
 | 
						|
sub run_lssyscfg
 | 
						|
{
 | 
						|
    my $req = shift;
 | 
						|
    if (($req) && ($req =~ /xCAT::/))
 | 
						|
    {
 | 
						|
        $req = shift;
 | 
						|
    }
 | 
						|
    my $verbose = shift;
 | 
						|
    my $node = shift;
 | 
						|
    my $cmd;
 | 
						|
    my $out;
 | 
						|
 | 
						|
    $out = xCAT::Utils->runxcmd(
 | 
						|
        {
 | 
						|
            command => ['rpower'],
 | 
						|
            node    => [$node],
 | 
						|
            arg     => ['state']
 | 
						|
        },
 | 
						|
    $req, 0, 1);
 | 
						|
    if ($::RUNCMD_RC != 0)   {
 | 
						|
        nc_msg($verbose, "Unable to run rpower $node state.\n");
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
    my $output = join ',', @$out;
 | 
						|
    nc_msg($verbose, "Status: run_lssyscg : partition status : $output\n");
 | 
						|
 | 
						|
    nc_msg($verbose, "####msg:$output#########\n" );
 | 
						|
 | 
						|
 | 
						|
    ###################################################################
 | 
						|
    # Slow down the requests speed to hcp, so that hcp will not busy on
 | 
						|
    # query.  Instead, hcp should put more time on other activities.
 | 
						|
    # Another reason to set this sleep is giving some time to the lpars
 | 
						|
    # to be more stable.
 | 
						|
    ###################################################################
 | 
						|
    sleep 4;
 | 
						|
 | 
						|
    return $output;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    usage
 | 
						|
 | 
						|
 | 
						|
    PROCEDURE
 | 
						|
 | 
						|
    Declare procedure to write usage message and exit
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
 | 
						|
sub usage {
 | 
						|
 | 
						|
    my $msg = "Usage: Install partition \
 | 
						|
            \n\t \[-v\] \[-x\] \[-f\] \[-w set_boot_order\] \[-A -D | \[-D\] | \[-D\] -m macaddress\] -t ent -s speed -d duplex \
 | 
						|
            \n\t\t-S server -G gateway -C client hostname profile managed_system lparid remote_host\
 | 
						|
            \n \
 | 
						|
            \nUsage: Return macaddress \
 | 
						|
            \n\t -M -n \[-v\] -t ent \[-f] \[-x] \[-D -s speed -d duplex -S server -G gateway -C client\] hostname profile managed_system lparid remote_host\
 | 
						|
            \n \
 | 
						|
            \n\t-n\tDo not boot partition \
 | 
						|
            \n\t-t\tSpecifies network type ent \
 | 
						|
            \n\t-D\tPerform ping test, use adapter that successfully ping the server \
 | 
						|
            \n\t-s\tNetwork adapter speed \
 | 
						|
            \n\t-d\tNetwork adapter duplex \
 | 
						|
            \n\t-S\tServer IP address \
 | 
						|
            \n\t-G\tGateway IP address \
 | 
						|
            \n\t-C\tClient IP address \
 | 
						|
            \n\t-m\tMAC Address \
 | 
						|
            \n\t-v\tVerbose output \
 | 
						|
            \n\t-x\tDebug output \
 | 
						|
            \n\t-f\tForce close virtual terminal session \
 | 
						|
            \n\t-w\tSet boot device order \
 | 
						|
            \n\t\t\t0: Don't set boot device order \
 | 
						|
            \n\t\t\t1: Set network as boot device \
 | 
						|
            \n\t\t\t2: Set network as 1st boot device, disk as 2nd boot device \
 | 
						|
            \n\t\t\t3: Set disk as 1st boot device, network as 2nd boot device \
 | 
						|
            \n\t\t\t4: set disk as boot device \
 | 
						|
            \n\t-M\tDiscovery ethernet adapter mac address and location code \
 | 
						|
            \n\t--help\tPrints this help\n";
 | 
						|
    nc_msg(1, $msg);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    ck_args
 | 
						|
 | 
						|
 PROCEDURE
 | 
						|
 | 
						|
 Check command line arguments
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub ck_args {
 | 
						|
 | 
						|
    my $opt = shift;
 | 
						|
    if (($opt) && ($opt =~ /xCAT::/))
 | 
						|
    {
 | 
						|
        $opt = shift;
 | 
						|
    }
 | 
						|
    my $verbose = shift;
 | 
						|
    my $node = $opt->{node};
 | 
						|
    my $mtms = $opt->{fsp};
 | 
						|
    my $hcp = $opt->{hcp};
 | 
						|
    my $lparid = $opt->{id};
 | 
						|
    my $profile = $opt->{pprofile};
 | 
						|
 | 
						|
    if (exists( $opt->{D}) and (!exists ($opt->{s}) or !exists ($opt->{d} ))) {
 | 
						|
        nc_msg($verbose, "Speed and duplex required\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (exists ($opt->{D}) and !exists ($opt->{C}))  {
 | 
						|
        nc_msg($verbose, "Client IP is required\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    if (exists( $opt->{D}) and !exists($opt->{S})) {
 | 
						|
        nc_msg($verbose, "Server IP is required\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (exists( $opt->{D}) and !exists($opt->{G})) {
 | 
						|
        nc_msg($verbose, "Gateway IP is required\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    unless($node) {
 | 
						|
        nc_msg($verbose, "Node is required\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    } else {
 | 
						|
        nc_msg($verbose, "Node is $node\n");
 | 
						|
    }
 | 
						|
 | 
						|
    unless($mtms) {
 | 
						|
        nc_msg($verbose, "Managed system is required\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    } else {
 | 
						|
        nc_msg($verbose, "Managed system is $mtms.\n");
 | 
						|
    }
 | 
						|
 | 
						|
    unless ($hcp) {
 | 
						|
        nc_msg($verbose, "Hardware control point address is required\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    } else {
 | 
						|
        nc_msg($verbose, "Hardware control point address is $hcp.\n");
 | 
						|
    }
 | 
						|
 | 
						|
    unless ($lparid) {
 | 
						|
        nc_msg($verbose, "Lpar Id is required.\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    } else {
 | 
						|
        nc_msg($verbose, "LPAR Id is $lparid.\n");
 | 
						|
    }
 | 
						|
 | 
						|
    unless ($profile) {
 | 
						|
        nc_msg($verbose, "Profile is required.\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    } else {
 | 
						|
        nc_msg($verbose, "profile $profile.\n");
 | 
						|
    }
 | 
						|
 | 
						|
    if ($opt->{M} and $opt->{g}) {
 | 
						|
        nc_msg($verbose, "Can not specify -M and -g flags together.\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    if ($opt->{M} and ($opt->{m} or $opt->{l})) {
 | 
						|
        nc_msg($verbose, "Can not specify -M and -l or -m flags together.\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($opt->{m} and $opt->{l}) {
 | 
						|
        nc_msg($verbose, "Can not specify -l and -m flags together.\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($opt->{A} and ($opt->{m} or $opt->{l})) {
 | 
						|
        nc_msg($verbose, "Can not specify -A and -m or -l flags together.\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($opt->{A} and !exists($opt->{D}) and !exists($opt->{n})) {
 | 
						|
        nc_msg($verbose, "Flag -A must be specify with flag -D for booting.\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($opt->{M} and $opt->{D} and (!exists($opt->{S}) or !exists($opt->{G}) or !exists($opt->{C}) or !exists( $opt->{s}) or !exists($opt->{d}))) {
 | 
						|
        nc_msg($verbose, "Flag -M with -D require arguments for -C, -S, -G, -s and -d.\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($opt->{M} and !exists($opt->{D}) and (!exists($opt->{S}) or !exists($opt->{G}) or !exists($opt->{C}) or !exists($opt->{s}) or !exists($opt->{d}))){
 | 
						|
        nc_msg($verbose, "Flag -M with arguments for -C, -S, -G, -s and -d require -D flag.\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($opt->{M} and !exists($opt->{n})) {
 | 
						|
        nc_msg($verbose, "-M flag requires -n.\n");
 | 
						|
        usage;
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($node =~ /(\[ ]+)-/) {
 | 
						|
        nc_msg($verbose, "Error : $node, node is required\n");
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($mtms =~ /(\[ ]+)-/) {
 | 
						|
        nc_msg($verbose, "Error : $mtms, Managed system is required\n");
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    #if ($profile =~ /(\[ ]+)-/) {
 | 
						|
    #    nc_msg($verbose, "Error : $profile, profile is required\n");
 | 
						|
    #    return 1;
 | 
						|
    #}
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    send_command
 | 
						|
 | 
						|
 | 
						|
        PROCEDURE
 | 
						|
 | 
						|
        Declare procedure to send commands slowly. This is needed because
 | 
						|
        some bytes are missed by the service processor when sent at top speed.
 | 
						|
        The sleep was needed because a command was sent sometimes before the
 | 
						|
        results of the previous command had been received.
 | 
						|
 | 
						|
        The Open Firmware is constrained on how quickly it can process input streams.
 | 
						|
        The following code causes expect to send 10 characters and then wait 1 second
 | 
						|
        before sending another 10 bytes.
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
 | 
						|
sub send_command  {
 | 
						|
    my $verbose = shift;
 | 
						|
    my $rconsole = shift;
 | 
						|
    my $cmd = shift;
 | 
						|
    nc_msg($verbose, "sending commands $cmd to expect \n");
 | 
						|
    my $msg;
 | 
						|
 | 
						|
    $msg = $rconsole->send($cmd);
 | 
						|
    sleep 1;
 | 
						|
    return $msg;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    get_phandle
 | 
						|
 | 
						|
 PROCEDURE
 | 
						|
 | 
						|
 Declare procedure to parse the full device tree that is displayed as a result
 | 
						|
 of an ls command. The information needed is the phandle and full device name
 | 
						|
 of a supported network card found in the device tree. The phandle is used in
 | 
						|
 other procedures to get and change properties of the network card. The full
 | 
						|
 device name is used to network boot from the network adapter.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
 | 
						|
sub get_phandle {
 | 
						|
    my $rconsole = shift;
 | 
						|
    my $node = shift;
 | 
						|
    my $verbose = shift;
 | 
						|
    my $timeout = 30;
 | 
						|
    my $done = 0;
 | 
						|
    my @result;
 | 
						|
    my $expect_out;
 | 
						|
    my $retry_count;
 | 
						|
    my %path;
 | 
						|
    my $rc = 0;
 | 
						|
 | 
						|
 | 
						|
    # This is the first procedure entered after getting to the ok prompt. On entry
 | 
						|
    # the current device is not root. The command 'dev /' is sent to get to the
 | 
						|
    # root of the device tree. There is no output from the dev command. The expected
 | 
						|
    # output is the ok prompt ('>').
 | 
						|
    #
 | 
						|
    # The pwd command can be used to determine what the current device is.
 | 
						|
    #
 | 
						|
 | 
						|
    send_command($verbose, $rconsole,  "dev /\r");
 | 
						|
 | 
						|
    @result = $rconsole->expect(
 | 
						|
        $timeout,
 | 
						|
        [qr/ok/=>
 | 
						|
        sub {
 | 
						|
            nc_msg($verbose, "Status: at root\n");
 | 
						|
            $rconsole->clear_accum();
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [qr/]/=>
 | 
						|
        sub {
 | 
						|
            nc_msg($verbose, "Unexpected prompt\n");
 | 
						|
            $rconsole->clear_accum();
 | 
						|
            $rc = 1;
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [timeout =>
 | 
						|
        sub {
 | 
						|
            $rconsole->send("\r");
 | 
						|
            $rconsole->clear_accum();
 | 
						|
            $rc = 1;
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [eof =>
 | 
						|
        sub {
 | 
						|
            nc_msg($verbose, "Cannot connect to $node");
 | 
						|
            $rconsole->clear_accum();
 | 
						|
            $rc = 1;
 | 
						|
            }
 | 
						|
        ],
 | 
						|
    );
 | 
						|
    return 1 if ($rc eq 1);
 | 
						|
    # Next, the 'ls' command is sent. The result is a display of the entire
 | 
						|
    # device tree. The code then looks at the
 | 
						|
    # output from the ls command one line at a time, trying to match it with the
 | 
						|
    # regexp pattern in dev_pat, an array that contains all the supported network
 | 
						|
    # adapters. When found, the adapter type, the phandle and path name are saved
 | 
						|
    # in array variables.
 | 
						|
    #
 | 
						|
    # The complicated part is that the full path name may be spread over more than
 | 
						|
    # one line. Each line contains information about a node. If the supported
 | 
						|
    # network adapter is found on an nth level node, the full path name is the
 | 
						|
    # concatenation of the node information from the 0th level to the nth level.
 | 
						|
    # Hence, the path name from each level of the device tree needs to be saved.
 | 
						|
    #
 | 
						|
    # The pattern "\n(\[^\r]*)\r" is worth a second look. It took
 | 
						|
    # many hours of debug and reading the expect book to get it right. When more
 | 
						|
    # than one line of data is returned to expect at once, it is tricky getting
 | 
						|
    # exactly one line of data to look at. This pattern works because it looks
 | 
						|
    # for a newline(\n), any character other than a carriage return(\[^\r]*), and
 | 
						|
    # then for a carriage return. This causes expect to match a single line.
 | 
						|
    # If (.*) is used instead of (\[^\r]*), multiple lines are matched. (that was
 | 
						|
    # attempt number 1)
 | 
						|
    #
 | 
						|
    # Once a single line is found, it tries to determine what level in the device
 | 
						|
    # tree this line is.
 | 
						|
    # searching through subsequent lines and subsequent levels until an
 | 
						|
    # adapter is found.
 | 
						|
    # The level of the current line, which
 | 
						|
    # is calculated based on the assumption of "Level = (Leading Spaces - 1)/2".
 | 
						|
    # Leading Spaces is the number of spaces between the first colon ':' and the
 | 
						|
    # first non-space character of each line.
 | 
						|
    #
 | 
						|
    # Using the -d flag helped a lot in finding the correct pattern.
 | 
						|
    #
 | 
						|
 | 
						|
    send_command($verbose, $rconsole,  "ls \r");
 | 
						|
 | 
						|
    $timeout = 60;
 | 
						|
    $done = 0;
 | 
						|
    while (!$done) {
 | 
						|
        # this expect call isolates single lines
 | 
						|
        # This code uses the tcl regexp to parse the single line
 | 
						|
        # isolated by expect.
 | 
						|
        #
 | 
						|
        # When the ok prompt ('>') is matched, this indicates the end of
 | 
						|
        # the ls output, at which point the done variable is set, to break
 | 
						|
        # out of the loop.
 | 
						|
        #
 | 
						|
        # All other lines are ignored.
 | 
						|
        #
 | 
						|
        @result = ();
 | 
						|
        @result = $rconsole->expect(
 | 
						|
            $timeout,
 | 
						|
            [qr/(\n)([^\r]*)(\r)/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Parsing network adapters... \n");
 | 
						|
                #$rconsole->clear_accum();
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/>/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "finished \n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $done = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [timeout=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Timeout isolating single line of ls output\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [eof =>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Cannot connect to $node");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
        );
 | 
						|
        return 1 if ($rc eq 1);
 | 
						|
        if ($result[2] =~ /(\w*)\:(\s*)\/(\S*)/) {
 | 
						|
 | 
						|
            my $x1 = $1;
 | 
						|
            my $x2 = $2; #number of space
 | 
						|
            my $x3 = $3; #device
 | 
						|
            # Each level is inspected for a match
 | 
						|
            my $level = (length($x2)-1)/2;
 | 
						|
            $path{$level} = $x3;
 | 
						|
            my $j = 0;
 | 
						|
 | 
						|
            for ($j = 0; $j < $dev_count; $j++) {
 | 
						|
                if ($x3 =~ /$dev_pat[$j]/) {
 | 
						|
                    if ( $x3 =~ /hfi-ethernet/ and $dev_pat[$j] eq "ethernet" ){
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
                    my $i = 0;
 | 
						|
                    for ($i = 0; $i <= $level; $i++)
 | 
						|
                    {
 | 
						|
                        $full_path_name_array[$adapter_found] .= "/" . $path{$i};
 | 
						|
                    }
 | 
						|
                    $phandle_array[$adapter_found] = $x1;
 | 
						|
                    $adap_type[$adapter_found] = $dev_type[$j];
 | 
						|
                    $adapter_found ++;
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    # Did we find one or more adapters?
 | 
						|
    if ( $adapter_found > 0 ) {
 | 
						|
        return 0;
 | 
						|
    } else {
 | 
						|
        nc_msg($verbose, "No network adapters found\n" );
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    get_adap_prop
 | 
						|
 | 
						|
 PROCEDURE
 | 
						|
 | 
						|
 Declare procedure to obtain the list of valid adapter connector properties
 | 
						|
 from the adapter card.  Connector types can be rj45, sc, 9pin, aui,
 | 
						|
 bnc, or mic.  Speeds can be 10, 100, or 1000.  Duplex can be half or
 | 
						|
 full.  This procedure will use the "supported-network-types"
 | 
						|
 argument to the get-package-property command to get the list of
 | 
						|
 properties for the given adapter.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub  get_adap_prop    {
 | 
						|
    my $phandle = shift;
 | 
						|
    my $rconsole = shift;
 | 
						|
    my $node = shift;
 | 
						|
    my $verbose = shift;
 | 
						|
    my $timeout = 120;
 | 
						|
    my $rc = 0;
 | 
						|
    my $state = 0;
 | 
						|
    my @cmd;
 | 
						|
    my @done;
 | 
						|
    my @msg;
 | 
						|
    my @pattern;
 | 
						|
    my @newstate;
 | 
						|
    my @result;
 | 
						|
    my @adap_prop_array;
 | 
						|
    my $nw_type;
 | 
						|
    my $nw_speed;
 | 
						|
    my $nw_conn;
 | 
						|
    my $nw_duplex;
 | 
						|
 | 
						|
    nc_msg($verbose, " Status: get_adap_prop start\n");
 | 
						|
 | 
						|
    # state 0, stack count 0
 | 
						|
    $done[0] = 0;
 | 
						|
    $cmd[0] = "\" supported-network-types\" " . $phandle . " get-package-property\r";
 | 
						|
    $msg[0] = "Status: rc and all supported network types now on stack\n";
 | 
						|
    #$pattern[0] = "(.*)3 >(.*)";
 | 
						|
    $pattern[0] = "3 >";
 | 
						|
    $newstate[0] = 1;
 | 
						|
 | 
						|
    # state 1, return code and string on stack
 | 
						|
    $done[1] = 0;
 | 
						|
    $cmd[1] = ".\r";
 | 
						|
    $msg[1] = "Status: All supported network types now on stack\n";
 | 
						|
    #$pattern[1] = "(.*)2 >(.*)";
 | 
						|
    $pattern[1] = "2 >";
 | 
						|
    $newstate[1] = 2;
 | 
						|
 | 
						|
    # state 2, data ready to decode
 | 
						|
    $done[2] = 0;
 | 
						|
    $cmd[2] = "decode-string\r";
 | 
						|
    $msg[2] = "Status: supported network type isolated on stack\n";
 | 
						|
    #$pattern[2] = "(.*)ok(.*)4 >(.*)";
 | 
						|
    $pattern[2] = "4 >";
 | 
						|
    $newstate[2] = 3;
 | 
						|
 | 
						|
    # state 3, decoded string on stack
 | 
						|
    $done[3]= 0;
 | 
						|
    $cmd[3] = "dump\r";
 | 
						|
    $msg[3] = "Status: supported network type off stack\n";
 | 
						|
    #$pattern[3] = ".*:.*:(.*):.*:.*:(.*):.*(2 >)(.*)";
 | 
						|
    $pattern[3] = "ok";
 | 
						|
    $newstate[3] = 4;
 | 
						|
 | 
						|
    # state 4, need to check for more data to decode
 | 
						|
    $done[4] = 0;
 | 
						|
    $cmd[4] = ".s\r";
 | 
						|
    $msg[4] = "Status: checking for more supported network types\n";
 | 
						|
    #$pattern[4] = ".s (\[0-9a-f]* )(.*)>";
 | 
						|
    $pattern[4] = "ok";
 | 
						|
    $newstate[4]= 5;
 | 
						|
 | 
						|
    # state 5, done decoding string, clear stack
 | 
						|
    $done[5] = 0;
 | 
						|
    $cmd[5]  = ".\r";
 | 
						|
    $msg[5]  = "Status: one entry on stack cleared\n";
 | 
						|
    #$pattern[5] = "(.*)ok(.*)1 >(.*)";
 | 
						|
    $pattern[5] = "ok";
 | 
						|
    $newstate[5] = 6;
 | 
						|
 | 
						|
    # state 6, finish clearing stack, choose correct adapter type
 | 
						|
    $done[6]= 0;
 | 
						|
    $cmd[6] = ".\r";
 | 
						|
    $msg[6] = "Status: finished clearing stack\n";
 | 
						|
    #$pattern[6] = "(.*)ok(.*)0 >(.*)";
 | 
						|
    $pattern[6] = "ok";
 | 
						|
    $newstate[6]= 7;
 | 
						|
 | 
						|
    # state 7, done
 | 
						|
    $done[7] = 1;
 | 
						|
 | 
						|
    while($done[$state] eq 0) {
 | 
						|
        nc_msg($verbose, "Status: command is $cmd[$state]\n");
 | 
						|
        send_command($verbose, $rconsole, $cmd[$state]);
 | 
						|
        @result = ();
 | 
						|
        @result = $rconsole->expect(
 | 
						|
        $timeout,
 | 
						|
        [ qr/$pattern[$state]/i,
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, $msg[$state]);
 | 
						|
                $state = $newstate[$state];
 | 
						|
                $rconsole->clear_accum();
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [ qr/]/,
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Unexpected prompt\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [ qr/(.*)DEFAULT(.*)/,
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, " Default catch error\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [ timeout=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Timeout in getting adapter properpties\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [ eof =>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Cannot connect to $node\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
            }
 | 
						|
        ]
 | 
						|
        );
 | 
						|
        return 1 if ($rc eq 1);
 | 
						|
        # After state 3, the network type is parsed and the connector
 | 
						|
        # type extracted.  If the type hasn't been found, add it to
 | 
						|
        # the list of supported connector types.
 | 
						|
        if ( $state eq 4 ) {
 | 
						|
            #  Build the adapter properties from the string
 | 
						|
            #regexp .*,(.*),(.*),(.*) $nw_type dummy nw_speed nw_conn nw_duplex
 | 
						|
            #set adap_prop "$nw_speed,$nw_conn,$nw_duplex"
 | 
						|
            #nc_msg "Status: Adapter properties are $adap_prop\n"
 | 
						|
 | 
						|
            # if it's not in the list, add it, otherwise continue
 | 
						|
            if ( $result[3] =~ /(\w*):(.*):(\w*)\,(\w*)\,(\w*):/) {
 | 
						|
                $nw_type = $3;
 | 
						|
                $nw_speed = $4;
 | 
						|
                $nw_conn = $5;
 | 
						|
                nc_msg($verbose, "nwtype is $3, nwspeed is $4, nwconn is $5\n");
 | 
						|
            }
 | 
						|
            if ( $result[3] =~ /(\w*):(.*):(\w*)\,(\w*):/) {
 | 
						|
                $nw_duplex = $4;
 | 
						|
                nc_msg($verbose, "nwduplex is $4\n");
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #push @adap_prop_array, $nw_type.",".$nw_speed.",".$nw_conn.",".$nw_duplex;
 | 
						|
        push @adap_prop_array, $nw_speed.",".$nw_conn.",".$nw_duplex;
 | 
						|
        nc_msg($verbose, "Status: Adding adapter properties to list\n");
 | 
						|
 | 
						|
        # After state 4, a test is done to see if all of the supported
 | 
						|
        # network types have been decoded. If they have been, the
 | 
						|
        # state variable is left alone. if not, the state variable is
 | 
						|
        # set to 2, causing a loop back to the step where the
 | 
						|
        # decode-string command is sent.
 | 
						|
        if ( $state eq 5 ) {
 | 
						|
            if ($result[3] =~/2 > \.s \w+ (\w*)/) {
 | 
						|
                $state = 2 if ($1 != 0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (scalar(@adap_prop_array) != 0) {
 | 
						|
        return \@adap_prop_array;
 | 
						|
    } else {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    get_mac_addr
 | 
						|
 | 
						|
 | 
						|
  PROCEDURE
 | 
						|
 | 
						|
  Declare procedure to obtain the ethernet or mac address property from the
 | 
						|
  ethernet card.
 | 
						|
 | 
						|
  3 commands lines containing a total of 6 commands are used.
 | 
						|
 | 
						|
  The get-package-property command is an example of a command
 | 
						|
  that takes it's arguments off the stack and puts the results back onto the
 | 
						|
  stack. Because of this, the arguments for the get-package-property command
 | 
						|
  are in front of the command verb.
 | 
						|
 | 
						|
 | 
						|
  The only reason this procedure is implemented in a loop is to avoid coding
 | 
						|
  3 expect commands.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub get_mac_addr {
 | 
						|
    my $phandle = shift;
 | 
						|
    my $rconsole = shift;
 | 
						|
    my $node = shift;
 | 
						|
    my $verbose = shift;
 | 
						|
    my $timeout = 60;
 | 
						|
    my $state = 0;
 | 
						|
    my @result;
 | 
						|
    my $mac_rc;
 | 
						|
    my @cmd;
 | 
						|
    my @done;
 | 
						|
    my @msg;
 | 
						|
    my @pattern;
 | 
						|
    my @newstate;
 | 
						|
    my $mac_address;
 | 
						|
    my $rc = 0;
 | 
						|
 | 
						|
 | 
						|
    nc_msg($verbose, "Status: get_mac_addr start\n");
 | 
						|
 | 
						|
    # cmd(0) could have been sent as 3 commands. " mac-address" (tcl forces
 | 
						|
    # the use of \") is the first command on this line. The result of entering
 | 
						|
    # " mac-address" is that 2 stack entries are created, and address and a length.
 | 
						|
    #
 | 
						|
    # The next command in cmd(0) is the phandle with no quotes. This results in
 | 
						|
    # one stack entry because the phandle is an address.
 | 
						|
    #
 | 
						|
    # the third command in cmd(0) is get-package-property. After this command, there
 | 
						|
    # are 3 stack entries (return code, address and length of mac-address).
 | 
						|
    # state 0, stack count 0, send command
 | 
						|
    $done[0] = 0;
 | 
						|
    $cmd[0] = "\" local-mac-address\" ". $phandle . " get-package-property\r";
 | 
						|
    $msg[0] = "Status: return code and mac-address now on stack\n";
 | 
						|
    $pattern[0] = "ok";#"\s*3 >";
 | 
						|
    $newstate[0] = 1;
 | 
						|
 | 
						|
    # cmd(1) is a dot (.). This is a stack manipulation command that removes one
 | 
						|
    # thing from the stack. pattern(1) is looking for a prompt with the 2 indicating
 | 
						|
    # that there are 2 things left on the stack.
 | 
						|
    # state 1, return code and mac-address on stack
 | 
						|
    $done[1]= 0;
 | 
						|
    $cmd[1] = ".\r";
 | 
						|
    $msg[1] = "Status: mac-address now on stack\n";
 | 
						|
    #$pattern[1] = "(.*)2 >(.*)";
 | 
						|
    $pattern[1] = "ok"; #"2 >";
 | 
						|
    $newstate[1]= 2;
 | 
						|
 | 
						|
    # cmd(2) is the dump command. This takes an address and a length off the stack
 | 
						|
    # and displays the contents of that storage in ascii and hex. The long pattern
 | 
						|
    # puts the hex into the variable expect_out(3,string). The tcl verb 'join' is
 | 
						|
    # used to eliminate the spaces put in by the dump command.
 | 
						|
    # state 2, mac-address on stack
 | 
						|
    $done[2] = 0;
 | 
						|
    $cmd[2] = ": dump-mac ( prop-addr prop-len -- ) \
 | 
						|
                cr  \
 | 
						|
                dup decode-bytes  2swap 2drop   ( data-addr data-len ) \
 | 
						|
                ( data-len ) 0 ?do \
 | 
						|
                    dup c@ 2 u.r                  ( data-addr ) \
 | 
						|
                    char+                        ( data-addr' ) \
 | 
						|
                loop \
 | 
						|
                drop \
 | 
						|
                cr \
 | 
						|
                ; \r";
 | 
						|
    $msg[2] = "Status: set command\n";
 | 
						|
    $pattern[2] = "ok";
 | 
						|
    $newstate[2]= 3;
 | 
						|
 | 
						|
    $done[3]= 0;
 | 
						|
    $cmd[3] = "dump-mac\r";
 | 
						|
    $msg[3] = "Status: mac-address displayed, stack empty\n";
 | 
						|
    $pattern[3] = "dump-mac(\\s*)(\\w*)(\\s*)ok";
 | 
						|
    $newstate[3] = 4 ;
 | 
						|
 | 
						|
 | 
						|
    # state 4, all done
 | 
						|
    $done[4] = 1;
 | 
						|
 | 
						|
    while($done[$state] eq 0) {
 | 
						|
        @result = ();
 | 
						|
        send_command($verbose, $rconsole, $cmd[$state]);
 | 
						|
        @result = $rconsole->expect(
 | 
						|
            $timeout,
 | 
						|
            [qr/$pattern[$state]/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, $msg[$state]);
 | 
						|
                $state = $newstate[$state];
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/1 > /=>
 | 
						|
            sub {
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                if( $state eq 0 ) {
 | 
						|
                    # An error occurred while obtaining the mac address.  Log the error,
 | 
						|
                    # but don't quit nodecond.  instead, return NA for the address
 | 
						|
                    #
 | 
						|
                    send_command($verbose, $rconsole, ".\r");
 | 
						|
                    $rconsole->expect(
 | 
						|
                        $timeout,
 | 
						|
                        #[ qr/(-*\[0-9\]*)  ok(.*)0 >(.*)/i,
 | 
						|
                        [ qr/0 >/i,
 | 
						|
                            sub {
 | 
						|
                                #$mac_rc = $expect_out;
 | 
						|
                                nc_msg($verbose, "Status: Error getting MAC address for phandle=$phandle. RC=$mac_rc.\n");
 | 
						|
                                nc_msg($verbose, "Could not obtain MAC address; setting MAX to NA\n" );
 | 
						|
                                $rconsole->clear_accum();
 | 
						|
                                $rc = 1;
 | 
						|
                            }
 | 
						|
                        ],
 | 
						|
                        [ timeout=>
 | 
						|
                            sub {
 | 
						|
                                nc_msg($verbose, "Timeout when getting mac address\n");
 | 
						|
                                $rconsole->clear_accum();
 | 
						|
                                $rc = 1;
 | 
						|
                            }
 | 
						|
                        ],
 | 
						|
                        [ eof =>
 | 
						|
                            sub {
 | 
						|
                                nc_msg($verbose, " Cannot connect to $node\n");
 | 
						|
                                $rconsole->clear_accum();
 | 
						|
                                $rc = 1;
 | 
						|
                            }
 | 
						|
                        ]
 | 
						|
                    );
 | 
						|
                }
 | 
						|
            }
 | 
						|
            ],
 | 
						|
            [qr/]/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Unexpected prompt\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/(.*)DEFAULT(.*)/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Default catch error\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [timeout=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Timeout in getting mac address\n");
 | 
						|
                nc_msg($verbose, "timeout state is $state\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [eof =>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Cannot connect to $node");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
        );
 | 
						|
        return undef if ($rc eq 1);
 | 
						|
    }
 | 
						|
    # if the state is 0, 1, or 2, an error occurred and the join will fail
 | 
						|
    if ($state eq 4) {
 | 
						|
        if ($result[2] =~ /dump-mac\s*(\w*)\s*ok/) {
 | 
						|
            $mac_address = $1;
 | 
						|
        }
 | 
						|
        return $mac_address;
 | 
						|
    } else {
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    get_adaptr_loc
 | 
						|
 | 
						|
 | 
						|
  PROCEDURE
 | 
						|
 | 
						|
  Declare procedure to obtain the list of ethernet adapters, their physical
 | 
						|
  location codes and MAC addresses.
 | 
						|
 | 
						|
  The get-package-property command is an example of a command
 | 
						|
  that takes it's arguments off the stack and puts the results back onto the
 | 
						|
  stack. Because of this, the arguments for the get-package-property command
 | 
						|
  are in front of the command verb.
 | 
						|
 | 
						|
  The only reason this procedure is implemented in a loop is to avoid coding
 | 
						|
  3 expect commands.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
 sub get_adaptr_loc {
 | 
						|
    my $phandle = shift;
 | 
						|
    my $rconsole = shift;
 | 
						|
    my $node = shift;
 | 
						|
    my $verbose = shift;
 | 
						|
    my @cmd;
 | 
						|
    my @done;
 | 
						|
    my @msg;
 | 
						|
    my @pattern;
 | 
						|
    my @newstate;
 | 
						|
    my $state = 0;
 | 
						|
    my $timeout = 60; # shouldn't take long
 | 
						|
    my @result;
 | 
						|
    my @path;
 | 
						|
    my $loc_code;
 | 
						|
    my $rc = 0;
 | 
						|
 | 
						|
    nc_msg($verbose, "Status: get_adaptr_loc start\n");
 | 
						|
    # cmd(0) could have been sent as 3 commands. " ibm,loc-code" (tcl forces
 | 
						|
    # the use of \") is the first command on this line. The result of entering
 | 
						|
    # " ibm,loc-code" is that 2 stack entries are created, and address and a length.
 | 
						|
    #
 | 
						|
    # The next command in cmd(0) is the phandle with no quotes. This results in
 | 
						|
    # one stack entry because the phandle is an address.
 | 
						|
    #
 | 
						|
    # the third command in cmd(0) is get-package-property. After this command, there
 | 
						|
    # are 3 stack entries (return code, address and length of mac-address).
 | 
						|
    # state 0, stack count 0, send command
 | 
						|
    $done[0] = 0;
 | 
						|
    $cmd[0] = "\" ibm,loc-code\" $phandle get-package-property\r";
 | 
						|
    $msg[0] = "Status:  return code and loc-code now on stack\n";
 | 
						|
    #$pattern[0] = "(.*)3 >(.*)";
 | 
						|
    $pattern[0] = "3 >";
 | 
						|
    $newstate[0] = 1;
 | 
						|
 | 
						|
    # cmd(1) is a dot (.). This is a stack manipulation command that removes one
 | 
						|
    # thing from the stack. pattern(1) is looking for a prompt with the 2 indicating
 | 
						|
    # that there are 2 things left on the stack.
 | 
						|
    # state 1, return code and loc-code on stack
 | 
						|
    $done[1]= 0;
 | 
						|
    $cmd[1] = ".\r";
 | 
						|
    $msg[1] = "Status: loc-code now on stack\n";
 | 
						|
    #$pattern[1] = "(.*)2 >(.*)";
 | 
						|
    $pattern[1] = "ok"; #"2 >";
 | 
						|
    $newstate[1]= 2;
 | 
						|
 | 
						|
    # state 2, loc-code on stack
 | 
						|
    $done[2]= 0;
 | 
						|
    $cmd[2] = "dump\r";
 | 
						|
    $msg[2] = "Status: loc-code displayed, stack empty\n";
 | 
						|
    #$pattern[2] = "(.*)(: )(.*)( :)(.*)(\.: ok)";
 | 
						|
     $pattern[2] = "ok";
 | 
						|
    $newstate[2]= 3;
 | 
						|
 | 
						|
    # state 3, all done
 | 
						|
    $done[3] = 1;
 | 
						|
 | 
						|
    while($done[$state] eq 0) {
 | 
						|
        @result = ();
 | 
						|
        nc_msg($verbose, "PROGRAM Status: command is $cmd[$state]\n");
 | 
						|
        send_command($verbose, $rconsole, $cmd[$state]);
 | 
						|
        @result = $rconsole->expect(
 | 
						|
            $timeout,
 | 
						|
            [qr/$pattern[$state]/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, $msg[$state]);
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $state = $newstate[$state];
 | 
						|
            }
 | 
						|
            ],
 | 
						|
            [qr/1 >/=>
 | 
						|
            sub {
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                my $exp = shift;
 | 
						|
                if($state eq 0) {
 | 
						|
                    send_command($verbose, $rconsole, ".\r");
 | 
						|
                    $exp->expect(
 | 
						|
                        #[qr/(-*\[0-9\]*)  ok(.*)0 >(.*)/=>
 | 
						|
                        [qr/0 >/=>
 | 
						|
                        sub {
 | 
						|
                            $rconsole->clear_accum();
 | 
						|
                            my $loc_rc = shift;
 | 
						|
                            nc_msg($verbose, "Error getting adapter physical location.\n");
 | 
						|
                            nc_msg($verbose, "Status: Error getting physical location for phandle=$phandle. RC=$loc_rc.\n");
 | 
						|
                            $rc = 1;
 | 
						|
                            }
 | 
						|
                        ],
 | 
						|
                        [timeout=>
 | 
						|
                        sub {
 | 
						|
                            $rconsole->clear_accum();
 | 
						|
                            nc_msg($verbose, "Timeout when openning console\n");
 | 
						|
                            $rc = 1;
 | 
						|
                            }
 | 
						|
                        ],
 | 
						|
                        [eof=>
 | 
						|
                        sub {
 | 
						|
                            $rconsole->clear_accum();
 | 
						|
                            nc_msg($verbose, "Cannot connect to the $node\n");
 | 
						|
                            $rc = 1;
 | 
						|
                            }
 | 
						|
                        ],
 | 
						|
                    );
 | 
						|
 | 
						|
                }
 | 
						|
            }
 | 
						|
            ],
 | 
						|
            [qr/]/=>
 | 
						|
            sub {
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                nc_msg($verbose, "Unexpected prompt\n");
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/(.*)DEFAULT(.*)/=>
 | 
						|
            sub {
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                nc_msg($verbose, "Default catch error\n");
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [timeout=>
 | 
						|
            sub {
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                nc_msg($verbose, "Timeout when openning console\n");
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [eof =>
 | 
						|
            sub {
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                nc_msg($verbose, "Cannot connect to the $node\n");
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
        );
 | 
						|
        return undef if ($rc eq 1);
 | 
						|
    }
 | 
						|
    # Did we find one or more adapters?
 | 
						|
 | 
						|
    if ($result[3] =~ /(\w*):(.*):(\w*\.\w*\.\w*):/) {
 | 
						|
        $loc_code = $3;
 | 
						|
    }else {
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    ping_server
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 PROCEDURE
 | 
						|
 | 
						|
 Declare procedure to obtain the list of valid adapter connector properties
 | 
						|
 from the adapter card.  Connector types can be rj45, sc, 9pin, aui,
 | 
						|
 bnc, or mic.  Speeds can be 10, 100, or 1000.  Duplex can be half or
 | 
						|
 full.  This procedure will use the "supported-network-types"
 | 
						|
 argument to the get-package-property command to get the list of
 | 
						|
 properties for the given adapter.
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub  ping_server{
 | 
						|
    my $phandle = shift;
 | 
						|
    my $full_path_name = shift;
 | 
						|
    my $rconsole = shift;
 | 
						|
    my $node = shift;
 | 
						|
    my $mac_address = shift;
 | 
						|
    my $verbose = shift;
 | 
						|
    my $adap_speed = shift;
 | 
						|
    my $adap_duplex = shift;
 | 
						|
    my $list_type = shift;
 | 
						|
    my $server_ip = shift;
 | 
						|
    my $client_ip = shift;
 | 
						|
    my $gateway_ip = shift;
 | 
						|
    my $adap_prop_list_array;
 | 
						|
    #my %env = shift;
 | 
						|
    my $command;
 | 
						|
    my $linklocal_ip;
 | 
						|
    my @result;
 | 
						|
    my @done;
 | 
						|
    my @cmd;
 | 
						|
    my @msg;
 | 
						|
    my @pattern;
 | 
						|
    my @newstate;
 | 
						|
    my $state = 0;
 | 
						|
    my $timeout;
 | 
						|
 | 
						|
    nc_msg($verbose, "Status: ping_server start\n");
 | 
						|
 | 
						|
    #if (exists($env{'FIRMWARE_DUMP'})) {
 | 
						|
    #    $full_path_name = Firmware_Dump($phandle);
 | 
						|
    #}
 | 
						|
    my $j = 0;
 | 
						|
    my $tty_do_ping = 0;
 | 
						|
    my $stack_level = 0;
 | 
						|
    my $properties_matched = 0;
 | 
						|
    my $adap_conn;
 | 
						|
    my $speed_list;
 | 
						|
    my $duplex_list;
 | 
						|
    my @adap_conn_list;
 | 
						|
    my $i;
 | 
						|
    my $ping_debug;
 | 
						|
    my $ping_rc;
 | 
						|
    my $rc = 0;
 | 
						|
 | 
						|
    # If the adapter type chosen is ethernet, need to set the speed and duplex
 | 
						|
    # of the adapter before we perform the ping.  If token ring or fddi,
 | 
						|
    # this is not required, so begin with state 2.
 | 
						|
    #
 | 
						|
    # cmd(0) sets the given adapter as active, to allow setting of speed
 | 
						|
    # and duplex
 | 
						|
    #
 | 
						|
    # cmd(1) writes the settings to the current adapter
 | 
						|
    #
 | 
						|
    # cmd(2) selects the /packages/net node as the active package to access the
 | 
						|
    # ping command.
 | 
						|
    #
 | 
						|
    # The next command in cmd(3) is the ping command. This places the return code
 | 
						|
    # on the stack. A return code of 0 indicates success.
 | 
						|
    #
 | 
						|
    # state 0, set the current adapter
 | 
						|
    $done[0] = 0;
 | 
						|
    $cmd[0] = "dev $full_path_name\r";
 | 
						|
    $msg[0] = "Status: selected $full_path_name as the active adapter\n";
 | 
						|
    #$pattern[0] = ".*dev(.*)0 >(.*)";
 | 
						|
    $pattern[0] = "0 >";
 | 
						|
    $newstate[0] = 1;
 | 
						|
 | 
						|
    # state 1, send property command to $selected type;
 | 
						|
    $done[1] = 0;
 | 
						|
    $cmd[1] = "\" ethernet,$adap_speed,$adap_conn,$adap_duplex\" encode-string \" chosen-network-type\" property\r";
 | 
						|
    $msg[1] = "Status: chosen network type set\n";
 | 
						|
    #$pattern[1] =".*ethernet(.*)0 >(.*)";
 | 
						|
    $pattern[1] ="0 >";
 | 
						|
    $newstate[1]= 2;
 | 
						|
 | 
						|
    # state 2, activate /packages/net
 | 
						|
    $done[2] = 0;
 | 
						|
    $cmd[2] = "dev /packages/net\r";
 | 
						|
    $msg[2] = "Status: selected the /packages/net node as the active package\n";
 | 
						|
    #$pattern[2] = ".*dev(.*)ok(.*)0 >(.*)";
 | 
						|
    $pattern[2] = "ok";
 | 
						|
    $newstate[2]= 3;
 | 
						|
 | 
						|
    # state 3, ping the server
 | 
						|
    $done[3] = 0;
 | 
						|
    $msg[3] = "Status: ping return code now on stack\n";
 | 
						|
    $newstate[3] = 4;
 | 
						|
 | 
						|
    #IPv6
 | 
						|
    if ( $server_ip =~ /:/ ) {
 | 
						|
        #::1, calculate link local address
 | 
						|
        if ($client_ip eq "::1") {
 | 
						|
            my $command = "/opt/xcat/share/xcat/tools/mac2linklocal -m $mac_address";
 | 
						|
            $linklocal_ip = $rconsole->send($command);
 | 
						|
        } else {
 | 
						|
            $linklocal_ip = $client_ip;
 | 
						|
        }
 | 
						|
        $cmd[3] = "ping $full_path_name:ipv6,$server_ip,$linklocal_ip,$gateway_ip\r";
 | 
						|
    } else {
 | 
						|
        $cmd[3] = "ping $full_path_name:$server_ip,$client_ip,$gateway_ip\r";
 | 
						|
    }
 | 
						|
    $pattern[3] = ".*ping(.*)ok(.*)0 >(.*)";
 | 
						|
 | 
						|
    # state 4, all done
 | 
						|
    $done[4] = 0;
 | 
						|
    $cmd[4] = "0 to my-self\r";
 | 
						|
    $msg[4] = "Status: resetting pointer\n";
 | 
						|
    #$pattern[4] = "(.*)ok(.*)0 >(.*)";
 | 
						|
    $pattern[4] = "ok";
 | 
						|
    $newstate[4] = 5;
 | 
						|
 | 
						|
    # state 5, all done
 | 
						|
    $done[5] = 1;
 | 
						|
 | 
						|
    # for ping, only need to set speed and duplex for ethernet adapters
 | 
						|
    #
 | 
						|
    if ( $list_type eq "ent" ) {
 | 
						|
        $state = 0;
 | 
						|
 | 
						|
        # Get the list of properties for this adapter
 | 
						|
        #
 | 
						|
        $adap_prop_list_array = get_adap_prop($phandle, $rconsole, $node, $verbose);
 | 
						|
        if ( $adap_prop_list_array eq 1 ) {
 | 
						|
            nc_msg($verbose, "ERROR return from get_adap_prop\n");
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
 | 
						|
        if ( $adap_prop_list_array eq 0 ) {
 | 
						|
            nc_msg($verbose, "No properties found for adapter '$full_path_name'\n");
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
 | 
						|
        # Now need to verify that the network params we were passed are valid for
 | 
						|
        # the given adapter
 | 
						|
        #
 | 
						|
        my $a_speed;
 | 
						|
        my $a_conn;
 | 
						|
        my $a_duplex;
 | 
						|
        for my $prop (@$adap_prop_list_array) {
 | 
						|
            if( $prop =~ /(.*),(.*),(.*)/) {
 | 
						|
                $a_speed = $1;
 | 
						|
                $a_conn = $2;
 | 
						|
                $a_duplex = $3;
 | 
						|
                if ( ( $a_speed eq $adap_speed ) && ( $a_duplex eq $adap_duplex ) ) {
 | 
						|
                    $properties_matched = 1;
 | 
						|
                    if ( grep {$_ eq $a_conn } @adap_conn_list) {
 | 
						|
                        push @adap_conn_list, $a_conn;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if ( $properties_matched eq 0 ) {
 | 
						|
            $adap_speed = $a_speed;
 | 
						|
            $adap_duplex = $a_duplex;
 | 
						|
            $properties_matched = 1;
 | 
						|
            push @adap_conn_list, $a_conn;
 | 
						|
        }
 | 
						|
 | 
						|
        $i = scalar(@adap_conn_list);
 | 
						|
 | 
						|
        if ( $properties_matched eq 0 ) {
 | 
						|
            nc_msg($verbose, "'$adap_speed/$adap_duplex' settings are not supported on this adapter\n");
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        $state = 2;
 | 
						|
    }
 | 
						|
 | 
						|
    $timeout = 300;
 | 
						|
    while ( $done[$state] eq 0 ) {
 | 
						|
        send_command($verbose, $rconsole, $cmd[$state]);
 | 
						|
        @result = $rconsole->expect(
 | 
						|
            $timeout,
 | 
						|
            [qr/$pattern[$state]/s=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, $msg[$state]);
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $state = $newstate[$state];
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/]/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Unexpected prompt\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/(.*)DEFAULT(.*)/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Default catch error\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [timeout=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Timeout when openning console\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [eof=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Cannot connect to the $node\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
        );
 | 
						|
        return 1 if ($rc eq 1);
 | 
						|
        if ( $state eq 1 ) {
 | 
						|
            $adap_conn = $adap_conn_list[$j];
 | 
						|
            $cmd[1] = "\" ethernet,$adap_speed,$adap_conn,$adap_duplex\" encode-string \" chosen-network-type\" property\r";
 | 
						|
            nc_msg($verbose, "Status: Trying connector type $adap_conn\n");
 | 
						|
            $j++;
 | 
						|
        }
 | 
						|
        if ((($tty_do_ping eq 1) && ($state eq 4)) || ($tty_do_ping != 1) && ($state eq 3) ) {
 | 
						|
            $ping_debug = $result[2];
 | 
						|
        }
 | 
						|
        if ( ( ($tty_do_ping eq 1) && ($state eq 5) ) || ($tty_do_ping != 1) && ($state eq 4) ) {
 | 
						|
            if ( ($tty_do_ping eq 1) && ($state eq 5) ) {
 | 
						|
                #$ping_rc = $result[2];
 | 
						|
                $stack_level = length($result[4]);
 | 
						|
            } elsif ( ($state eq 4) && ($tty_do_ping != 1) && ($result[2] =~ /PING SUCCESS/)) {
 | 
						|
                $ping_rc = 0;
 | 
						|
            #} elsif ( $result[2] =~ /unknown word/ ) {
 | 
						|
            #    nc_msg($verbose, "Status: try tty-do-ping.\n");
 | 
						|
            #    $ping_rc = 1;
 | 
						|
            #    $tty_do_ping = 1;
 | 
						|
            #    $state = 3 ;
 | 
						|
            #    $cmd[3] = "\"" . $full_path_name . ":" . $client_ip . "," . $server_ip . "," . $gateway_ip . "\" tty-do-ping\r";
 | 
						|
            #    $pattern[3] = "(.*)ok(.*)(\[1-2\]) >(.*)";
 | 
						|
            #
 | 
						|
            #    # state 4, get the return code off the stack
 | 
						|
            #    $done[4] = 0;
 | 
						|
            #    $cmd[4] = ".\r";
 | 
						|
            #    $msg[4] = "Status: return code displayed, stack empty\n";
 | 
						|
            #    $pattern[4] = "(\[0-9\]*)  ok(.*)(\[0-1\]) >(.*)";
 | 
						|
            #    $newstate[4] = 5;
 | 
						|
            #
 | 
						|
            #    # this command is used to work around a default catch problem in open
 | 
						|
            #    # firmware.  Without it, a default catch occurs if we try to set
 | 
						|
            #    # adapter properties again after a ping
 | 
						|
            #    #
 | 
						|
            #    # state 5, re$pointer
 | 
						|
            #    $done[5] = 0;
 | 
						|
            #    $cmd[5] = "0 to my-self\r";
 | 
						|
            #    $msg[5] = "Status: resetting pointer\n" ;
 | 
						|
            #    $pattern[5] = "(.*)ok(.*)0 >(.*)";
 | 
						|
            #    $newstate[5] = 6 ;
 | 
						|
            #
 | 
						|
            #    # state 6, all done
 | 
						|
            #    $done[6] = 1;
 | 
						|
            } else {
 | 
						|
                $ping_rc = 1;
 | 
						|
            }
 | 
						|
 | 
						|
            if ( $ping_rc eq 0 ) {
 | 
						|
                nc_msg($verbose, "# $full_path_name ping successful.\n");
 | 
						|
            } elsif ( $ping_rc eq  1 ) {
 | 
						|
                nc_msg($verbose, "# $full_path_name ping unsuccessful.\n");
 | 
						|
                nc_msg($verbose, "# $full_path_name ping unsuccessful.\n");
 | 
						|
                nc_msg($verbose, "$ping_debug\n");
 | 
						|
 | 
						|
                # An unsuccessful return may leave another item on the stack to
 | 
						|
                # be removed.  Check for it, and remove if necessary
 | 
						|
                my $matchexp = 0;
 | 
						|
                my @exp_out;
 | 
						|
                while ( $stack_level != 0 ) {
 | 
						|
                    @exp_out = ();
 | 
						|
                    send_command($verbose, $rconsole, ".\r");
 | 
						|
                    @exp_out = $rconsole->expect(
 | 
						|
                        [qr/(\[0-9\]*)  ok(.*)(\[0-1\]) >(.*)/s=>
 | 
						|
                        sub {
 | 
						|
                            $rconsole->clear_accum();
 | 
						|
                            $matchexp = 1;
 | 
						|
                            }
 | 
						|
                        ],
 | 
						|
                        [qr/]/=>
 | 
						|
                        sub {
 | 
						|
                            nc_msg($verbose, "Unexpected prompt\n");
 | 
						|
                            $rconsole->clear_accum();
 | 
						|
                            $rc = 1;
 | 
						|
                            }
 | 
						|
                        ],
 | 
						|
                        [qr/(.*)DEFAULT(.*)/=>
 | 
						|
                        sub {
 | 
						|
                            nc_msg($verbose, "Default catch error\n");
 | 
						|
                            $rconsole->clear_accum();
 | 
						|
                            $rc = 1;
 | 
						|
                            }
 | 
						|
                        ],
 | 
						|
                        [timeout=>
 | 
						|
                        sub {
 | 
						|
                            nc_msg($verbose, "Timeout in ping server\n");
 | 
						|
                            $rconsole->clear_accum();
 | 
						|
                            $rc = 1;
 | 
						|
                            }
 | 
						|
                        ],
 | 
						|
                        [eof =>
 | 
						|
                        sub {
 | 
						|
                            nc_msg($verbose, "Cannot connect to $node\n");
 | 
						|
                            $rconsole->clear_accum();
 | 
						|
                            $rc = 1;
 | 
						|
                            }
 | 
						|
                        ],
 | 
						|
                    );
 | 
						|
                    if ($matchexp) {
 | 
						|
                        $matchexp = 0;
 | 
						|
                        $stack_level = length($exp_out[4]);
 | 
						|
                        nc_msg($verbose, "Status: stack_level is <$stack_level>\n");
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                # Check if there are any more adapter connector types
 | 
						|
                # to try
 | 
						|
                #
 | 
						|
                if ( ( $list_type eq "ent" ) && ( $j < $i ) ) {
 | 
						|
                    $adap_conn = $adap_conn_list[$j];
 | 
						|
                    nc_msg($verbose, "Status: Trying connector type $adap_conn\n");
 | 
						|
                    $j++;
 | 
						|
 | 
						|
                    # Need to work around a default catch problem in open
 | 
						|
                    # firmware by sending a "0 to my-self" instruction
 | 
						|
                    # following the ping.  To make sure this happens in
 | 
						|
                    # this rare case where we have an adapter with multiple connectors,
 | 
						|
                    # we have to force the instruction into the 0th slot in
 | 
						|
                    # the array.  This is OK, since we only set the current
 | 
						|
                    # adapter once, upon entering this procedure.
 | 
						|
                    #
 | 
						|
                    $done[0] = 0;
 | 
						|
                    $cmd[0] = "0 to my-self\r";
 | 
						|
                    $msg[0] = "Status: resetting pointer\n";
 | 
						|
                    $pattern[0] = "(.*)ok(.*)0 >(.*)";
 | 
						|
                    $newstate[0] = 1;
 | 
						|
 | 
						|
                    $state = 0;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                nc_msg($verbose, "Unexpected ping return code\n");
 | 
						|
                return 1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return $ping_rc;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    set_disk_boot
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 PROCEDURE
 | 
						|
 | 
						|
 Declare procedure to obtain the list of valid adapter connector properties
 | 
						|
 from the adapter card.  Connector types can be rj45, sc, 9pin, aui,
 | 
						|
 bnc, or mic.  Speeds can be 10, 100, or 1000.  Duplex can be half or
 | 
						|
 full.  This procedure will use the "supported-network-types"
 | 
						|
 argument to the get-package-property command to get the list of
 | 
						|
 properties for the given adapter.
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub set_disk_boot {
 | 
						|
    my @expect_out = shift;
 | 
						|
    my $rconsole = shift;
 | 
						|
    my $node = shift;
 | 
						|
    my $verbose = shift;
 | 
						|
    my $x0;
 | 
						|
    my $x1;
 | 
						|
    my $x2;
 | 
						|
    my $command;
 | 
						|
    my @done;
 | 
						|
    my @cmd;
 | 
						|
    my @msg;
 | 
						|
    my @pattern;
 | 
						|
    my @newstate;
 | 
						|
    my $timeout;
 | 
						|
    my $state;
 | 
						|
    my $rc = 0;
 | 
						|
 | 
						|
    # state 0, get SMS screen
 | 
						|
    $done[0] = 0;
 | 
						|
    if($expect_out[0] =~ /(\n)(\[ ])(\[0-9])(\[.])(\[ ]+)Select Boot Options(\r)/){
 | 
						|
        $x0 = $1;
 | 
						|
        $x1 = $2;
 | 
						|
        $x2 = $3;
 | 
						|
        $command = $4;
 | 
						|
    }
 | 
						|
    $cmd[0] = "$command\r";
 | 
						|
    $msg[0] = "Status: sending return to repaint SMS screen\n";
 | 
						|
    $pattern[0] = "(\n)(\[ ])(\[0-9])(\[.])(\[ ]+)Configure Boot Device Order(\r)";
 | 
						|
    $newstate[0] = 1;
 | 
						|
 | 
						|
    # state 1, Multiboot
 | 
						|
    $done[1] = 0;
 | 
						|
    $msg[1] = "Status: Multiboot\n";
 | 
						|
    $pattern[1] = "(\n)(\[ ])(\[0-9])(\[.])(\[ ]+)Select 1st Boot Device(\r)";
 | 
						|
    $newstate[1] = 2;
 | 
						|
 | 
						|
    # state 2, Configure Boot Device Order
 | 
						|
    $done[2] = 0;
 | 
						|
    $msg[2] = "Status: Configure Boot Device Order";
 | 
						|
    $pattern[2] = "(\n)(\[ ])(\[0-9])(\[.])(\[ ]+)Hard Drive(.*)";
 | 
						|
    $newstate[2] = 3;
 | 
						|
 | 
						|
    # state 3, Select Device Type
 | 
						|
    $done[3] = 0;
 | 
						|
    $msg[3] = "Status: Select Device Type";
 | 
						|
    $pattern[3] = "(\n)(\[ ])(\[0-9])(\[.])(\[ ]+)SCSI(.*)";
 | 
						|
    $newstate[3] = 4;
 | 
						|
 | 
						|
    # state 4, Select Media Type
 | 
						|
    $done[4] = 0;
 | 
						|
    $msg[4] = "Status: Select Media Type";
 | 
						|
    $pattern[4] = "(\n)(\[ ])(\[1])(\[.])(\[ ]+)(\\S+)(.*)";
 | 
						|
    $newstate[4] = 5 ;
 | 
						|
 | 
						|
    # state 5, Select Media Adapter
 | 
						|
    $done[5] = 0;
 | 
						|
    $msg[5] = "Status: Select Media Adapter";
 | 
						|
    $pattern[5] = "(\n)(\[ ])(\[0-9])(\[.])(\[ ]+)(\\S)(\[ ]+)SCSI (\[0-9]+) MB Harddisk(.*)loc=(.*)\[)]";
 | 
						|
    $newstate[5] = 6;
 | 
						|
 | 
						|
    # state 6, Select Device
 | 
						|
    $done[6] = 0;
 | 
						|
    $msg[6] = "Status: Select Device";
 | 
						|
    $pattern[6] = "(\n)(\[ ])(\[0-9])(\[.])(\[ ]+)Set Boot Sequence(.*)";
 | 
						|
    $newstate[6] = 7;
 | 
						|
 | 
						|
    # state 7, Select Task
 | 
						|
    $done[7] = 0;
 | 
						|
    $msg[7] = "Status: Select Task";
 | 
						|
    $pattern[7] = "(.*)Current Boot Sequence(.*)";
 | 
						|
    $newstate[7] = 8 ;
 | 
						|
 | 
						|
    # state 8, Return to Main Menu
 | 
						|
    $done[8] = 0;
 | 
						|
    $cmd[8] = "M";
 | 
						|
    $msg[8] = "Status: Restored Default Setting.\n" ;
 | 
						|
    $pattern[8] = "(.*)Navigation key(.*)";
 | 
						|
    $newstate[8] = 9;
 | 
						|
 | 
						|
    # state 9, Getting to SMS Main Menu
 | 
						|
    $done[9] = 0;
 | 
						|
    $cmd[9] = "0\r";
 | 
						|
    $msg[9] = "Status: Getting to SMS Main Menu.\n";
 | 
						|
    $pattern[9] = "(.*)Exit SMS(.*)Prompt?(.*)";
 | 
						|
    $newstate[9] = 10;
 | 
						|
 | 
						|
    # state 10, Exiting SMS
 | 
						|
    $done[10] = 0;
 | 
						|
    $cmd[10] = "Y";
 | 
						|
    $msg[10] = "Status: Exiting SMS.\n";
 | 
						|
    $pattern[10] = "(.*)ok(.*)0 >(.*)";
 | 
						|
    $newstate[10] = 11;
 | 
						|
 | 
						|
    # state 11, all done
 | 
						|
    $done[11] = 1;
 | 
						|
 | 
						|
    $timeout = 30;
 | 
						|
    $state = 0;
 | 
						|
 | 
						|
    while ( $done[$state] eq 0 ) {
 | 
						|
        send_command($verbose, $rconsole, $cmd[$state]);
 | 
						|
        $rconsole->expect(
 | 
						|
            [qr/$pattern[$state]/=>
 | 
						|
                sub {
 | 
						|
                    $rconsole->clear_accum();
 | 
						|
                    if ( $state eq 4 ) {
 | 
						|
                        if ( $expect_out[6] eq "None" ) {
 | 
						|
                            $state = 8;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    $state = $newstate[$state];
 | 
						|
                    if ( ($state != 8) && ($state != 9) && ($state != 10) ) {
 | 
						|
                        $cmd[$state] = "$expect_out[3]\r";
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/THE SELECTED DEVICES WERE NOT DETECTED IN THE SYSTEM/=>
 | 
						|
                sub {
 | 
						|
                    $rconsole->clear_accum();
 | 
						|
                    nc_msg($verbose, " Status: THE hard disk WERE NOT DETECTED IN THE SYSTEM!\n");
 | 
						|
                    $rc = 1;
 | 
						|
                 }
 | 
						|
            ],
 | 
						|
            [timeout =>
 | 
						|
                sub {
 | 
						|
                    $rconsole->clear_accum();
 | 
						|
                    nc_msg($verbose, "Timeout in settin boot order\n");
 | 
						|
                    $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [eof =>
 | 
						|
                sub {
 | 
						|
                    $rconsole->clear_accum();
 | 
						|
                    nc_msg($verbose, "Cannot connect to $node\n");
 | 
						|
                    $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
        );
 | 
						|
        if ($rc eq 1) {
 | 
						|
            return 1;
 | 
						|
        } else {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
###################################################################
 | 
						|
#
 | 
						|
# PROCEDURE
 | 
						|
#
 | 
						|
# Declare procedure to boot the system from the selected ethernet card.
 | 
						|
#
 | 
						|
# This routine does the following:
 | 
						|
# 1. Initiates the boot across the network. (state 0 or 1)
 | 
						|
#
 | 
						|
# state 99 is normal exit and state -1 is error exit.
 | 
						|
###################################################################
 | 
						|
sub boot_network {
 | 
						|
    my $rconsole = shift;
 | 
						|
    if (($rconsole) && ($rconsole =~ /xCAT::/))
 | 
						|
    {
 | 
						|
        $rconsole = shift;
 | 
						|
    }
 | 
						|
    my $full_path_name = shift;
 | 
						|
    my $speed = shift;
 | 
						|
    my $duplex = shift;
 | 
						|
    my $chosen_adap_type = shift;
 | 
						|
    my $server_ip = shift;
 | 
						|
    my $client_ip = shift;
 | 
						|
    my $gateway_ip = shift;
 | 
						|
    my $netmask = shift;
 | 
						|
    my $dump_target = shift;
 | 
						|
    my $dump_lun = shift;
 | 
						|
    my $dump_port = shift;
 | 
						|
    my $verbose = shift;
 | 
						|
    my $extra_args = shift;
 | 
						|
    my $node = shift;
 | 
						|
    my $set_boot_order = shift;
 | 
						|
    my @net_device;
 | 
						|
    my @pattern;
 | 
						|
    my @cmd;
 | 
						|
    my @msg;
 | 
						|
    my @newstate;
 | 
						|
    my @done;
 | 
						|
    my $state = 0;
 | 
						|
    my $timeout;
 | 
						|
    my $boot_device_bk;
 | 
						|
    my $rc = 0;
 | 
						|
 | 
						|
 | 
						|
    nc_msg($verbose, "Status: boot_network start\n");
 | 
						|
    ###################################################################
 | 
						|
    # Variables associated with each of the commands sent by this routine
 | 
						|
    # are defined below.
 | 
						|
    #
 | 
						|
    # The done variable is flag that is set to 1 to break out of the loop
 | 
						|
    #
 | 
						|
    # The cmd variable is the command to be sent to the chrp interface.
 | 
						|
    #     In one case it set in the special processing code because the
 | 
						|
    #     ihandle is not available then this code is executes.
 | 
						|
    #
 | 
						|
    # The msg variable contains the message sent after a successful pattern match
 | 
						|
    #
 | 
						|
    # The pattern variable is the pattern passed to expect
 | 
						|
    #
 | 
						|
    # The newstate variable indicates what command is to be issued next
 | 
						|
    ###################################################################
 | 
						|
 | 
						|
    # If the install adapter is Ethernet or Token Ring, set the speed and
 | 
						|
    # duplex during boot.
 | 
						|
    # state 0, stack count 0
 | 
						|
    $done[0] = 0;
 | 
						|
    if ($dump_target ne "") {
 | 
						|
        $net_device[0] = "$full_path_name:iscsi,ciaddr=$client_ip,subnet-mask=$netmask,itname=dummy,iport=$dump_port,ilun=$dump_lun,iname=$dump_target,siaddr=$server_ip,2";
 | 
						|
        $pattern[0] = "iSCSI";
 | 
						|
    } else {
 | 
						|
        if ($extra_args ne "" ) {
 | 
						|
            if ( $server_ip =~ /:/ ) { #ipv6
 | 
						|
                $net_device[0] = "$full_path_name:ipv6,speed=$speed,duplex=$duplex,siaddr=$server_ip,ciaddr=$client_ip,giaddr=$gateway_ip,filename=$node,$extra_args";
 | 
						|
            } else {
 | 
						|
                $net_device[0] = "$full_path_name:speed=$speed,duplex=$duplex,bootp,$server_ip,,$client_ip,$gateway_ip $extra_args";
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            if ( $server_ip =~ /:/ ) { #ipv6
 | 
						|
                $net_device[0] = "$full_path_name:ipv6,speed=$speed,duplex=$duplex,siaddr=$server_ip,ciaddr=$client_ip,giaddr=$gateway_ip,filename=$node";
 | 
						|
            } else {
 | 
						|
                $net_device[0] = "$full_path_name:speed=$speed,duplex=$duplex,bootp,$server_ip,,$client_ip,$gateway_ip";
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $pattern[0] = "BOOTP";
 | 
						|
    }
 | 
						|
 | 
						|
    $cmd[0] = "boot $net_device[0]\r";
 | 
						|
    $msg[0] = "Status: network boot initiated\n";
 | 
						|
    $newstate[0] = 99;
 | 
						|
 | 
						|
    # If the install adapter is FDDI, don't set the speed and duplex
 | 
						|
    # state 1
 | 
						|
    $done[1] = 0;
 | 
						|
    $net_device[1] = "$full_path_name:bootp,$server_ip,,$client_ip,$gateway_ip";
 | 
						|
    $cmd[1] = "boot $net_device[1]\r";
 | 
						|
    $msg[1] = "Status: network boot initiated\n";
 | 
						|
    $pattern[1] = "BOOTP";
 | 
						|
    $newstate[1] = 99;
 | 
						|
 | 
						|
    # state 99, all done
 | 
						|
    $done[99] = 1;
 | 
						|
 | 
						|
    # state -1, all done
 | 
						|
    $done[100] = 1; #-1???
 | 
						|
 | 
						|
    if ($chosen_adap_type eq  "fddi" ) {
 | 
						|
        $state = 1;
 | 
						|
    } else {
 | 
						|
        if ($speed eq "" || $duplex eq "" ) {
 | 
						|
            nc_msg($verbose, "Cannot set speed or duplex for network boot\n");
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
        $state = 0;
 | 
						|
    }
 | 
						|
    ##################################################################
 | 
						|
    # Set the boot device order.
 | 
						|
    ##################################################################
 | 
						|
    if ( $set_boot_order > 0 ) {
 | 
						|
        $done[2] =  0;
 | 
						|
        $msg[2] =  "Status: read original boot-device\n";
 | 
						|
        $cmd[2] =  "printenv boot-device\r";
 | 
						|
        $pattern[2] =  ".*boot-device\\s+(\\S+)(.*)ok(.*)";
 | 
						|
        $newstate[2] =  3;
 | 
						|
 | 
						|
        $done[3] =  0;
 | 
						|
        $msg[3] =  "Status: set the environment variable boot-device\n";
 | 
						|
        $pattern[3] =  "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
        if (  $state eq 0 ) {
 | 
						|
            $newstate[3] =  0;
 | 
						|
        } else {
 | 
						|
            $newstate[3] =  1;
 | 
						|
        }
 | 
						|
        $state = 2;
 | 
						|
    }
 | 
						|
 | 
						|
    $timeout = 30;        # shouldn't take long
 | 
						|
    while ( $done[$state] eq 0 ) {
 | 
						|
        send_command($verbose, $rconsole, $cmd[$state]);
 | 
						|
        $rconsole->expect(
 | 
						|
            [qr/$pattern[$state]/=>
 | 
						|
                sub {
 | 
						|
                    $rconsole->clear_accum();
 | 
						|
                    my @expect_out = shift;
 | 
						|
                    if ( $state eq 2 ) {
 | 
						|
                        if ( $set_boot_order eq 1 ) {
 | 
						|
                            ########################################
 | 
						|
                            # Set network as boot device
 | 
						|
                            ########################################
 | 
						|
                            $cmd[3] = "setenv boot-device $net_device[$newstate[3]]\r";
 | 
						|
                        } elsif ( $set_boot_order eq 2 ) {
 | 
						|
                            ########################################
 | 
						|
                            # Set network as 1st boot device,disk as 2nd boot device
 | 
						|
                            ########################################
 | 
						|
                            $boot_device_bk = $expect_out[1];
 | 
						|
                            $cmd[3] =  "setenv boot-device $net_device[$newstate[3]] $boot_device_bk\r";
 | 
						|
                        } elsif ( $set_boot_order eq 3 ) {
 | 
						|
                            ########################################
 | 
						|
                            # Set disk as 1st boot device,network as 2nd boot device
 | 
						|
                            ########################################
 | 
						|
                            $boot_device_bk = $expect_out[1];
 | 
						|
                            $cmd[3] =  "setenv boot-device $boot_device_bk $net_device[$newstate[3]]\r";
 | 
						|
                        } elsif ( $set_boot_order eq 4 ) {
 | 
						|
                            ########################################
 | 
						|
                            # set disk as boot device
 | 
						|
                            ########################################
 | 
						|
                            $boot_device_bk = $expect_out[1];
 | 
						|
                            $cmd[3] =  "setenv boot-device $boot_device_bk\r";
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    nc_msg($verbose, $msg[$state]);
 | 
						|
                    $state = $newstate[$state];
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/----/=>
 | 
						|
                sub {
 | 
						|
                nc_msg ($verbose, $msg[$state]);
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $state = $newstate[$state];
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/]/=>
 | 
						|
                sub {
 | 
						|
                nc_msg($verbose, "Unexpected prompt\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/(.*)DEFAULT(.*)/=>
 | 
						|
                sub {
 | 
						|
                    nc_msg($verbose, "Default catch error\n");
 | 
						|
                    $rconsole->clear_accum();
 | 
						|
                    $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [timeout=>
 | 
						|
                sub {
 | 
						|
                    nc_msg($verbose, "Timeout when openning console\n");
 | 
						|
                    $rconsole->clear_accum();
 | 
						|
                    $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [eof=>
 | 
						|
                sub {
 | 
						|
                    nc_msg($verbose, "Cannot connect to the $node\n");
 | 
						|
                    $rconsole->clear_accum();
 | 
						|
                    $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
        );
 | 
						|
        return 1 if ($rc eq 1);
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
#
 | 
						|
# PROCEDURE
 | 
						|
#
 | 
						|
#
 | 
						|
sub Boot {
 | 
						|
    my $rconsole = shift;
 | 
						|
    my $node = shift;
 | 
						|
    my $verbose = shift;
 | 
						|
    #my @expect_out = shift;
 | 
						|
    my $rc = 0;
 | 
						|
    my $timeout;
 | 
						|
    my $state;
 | 
						|
 | 
						|
    nc_msg($verbose, "Status: waiting for the boot image to boot up.\n");
 | 
						|
 | 
						|
    $timeout = 1200;      # could take a while depending on configuration
 | 
						|
    $rconsole->expect(
 | 
						|
        [qr/RESTART-CMD/=>
 | 
						|
            sub {
 | 
						|
                # If we see a "problem doing RESTART-CMD" message, we re-hit the OPEN-DEV
 | 
						|
                # issue after firmware rebooted itself and we need to retry the netboot once more
 | 
						|
                nc_msg($verbose, "The network boot ended in an error.\nError : RESTART-CMD\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        #[!(qr/[0-9A-F]+/)=>
 | 
						|
        #    sub {
 | 
						|
        #        nc_msg($verbose, "The network boot ended in an error.\n");
 | 
						|
        #        #nc_msg($verbose, $expect_out[buffer]);
 | 
						|
        #        $rc = 1;
 | 
						|
        #     }
 | 
						|
        #],
 | 
						|
        [qr/BOOTP/=>      #-ex
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "# Network boot proceeding, exiting.\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [qr/------/=>      #-ex
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "# Network boot proceeding, exiting.\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [timeout=>
 | 
						|
        sub {
 | 
						|
            my $mins = $timeout/60;
 | 
						|
            nc_msg($verbose, "Timeout waiting for the boot image to boot up. \
 | 
						|
                  \n waited '$mins' minutes for the boot image to boot. \
 | 
						|
                  \nEither the boot up has taken longer than expected or \
 | 
						|
                  \nthere is a problem with system boot.  Check the boot \
 | 
						|
                  \nof the node to determine if there is a problem.\n");
 | 
						|
            $rconsole->clear_accum();
 | 
						|
            #nc_msg($verbose, $expect_out[buffer]);
 | 
						|
            $rc = 1;
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [eof=>
 | 
						|
        sub {
 | 
						|
            nc_msg($verbose, "Port closed waiting for boot image to boot.\n");
 | 
						|
            $rconsole->clear_accum();
 | 
						|
            $rc = 1;
 | 
						|
            }
 | 
						|
        ],
 | 
						|
    );
 | 
						|
    return $rc;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
###################################################################
 | 
						|
#
 | 
						|
# PROCEDURE
 | 
						|
#
 | 
						|
# Create multiple open-dev function in Open Firmware to try open
 | 
						|
# a device.  The original problem is a firmware issue which fails
 | 
						|
# to open a device.  This procedure will create multiple sub
 | 
						|
# function in firmware to circumvent the problem.
 | 
						|
#
 | 
						|
###################################################################
 | 
						|
sub multiple_open_dev {
 | 
						|
    my $rconsole = shift;
 | 
						|
    if (($rconsole) && ($rconsole =~ /xCAT::/))
 | 
						|
    {
 | 
						|
        $rconsole = shift;
 | 
						|
    }
 | 
						|
    my $node = shift;
 | 
						|
    my $verbose = shift;
 | 
						|
    my $expect_out;
 | 
						|
    my $command;
 | 
						|
    my $timeout;
 | 
						|
    my $rc = 0;
 | 
						|
 | 
						|
    send_command($verbose, $rconsole, "dev /packages/net \r");
 | 
						|
    send_command($verbose, $rconsole, "FALSE value OPEN-DEV_DEBUG \r");
 | 
						|
 | 
						|
    if (exists $ENV{'OPEN_DEV_DEBUG'}) {
 | 
						|
       send_command($verbose, $rconsole, "TRUE to OPEN-DEV_DEBUG \r");
 | 
						|
    }
 | 
						|
 | 
						|
    $command = ": new-open-dev ( str len -- true|false ) \
 | 
						|
                  open-dev_debug if cr .\" NEW-OPEN-DEV: Entering, Device : \" 2dup type cr then \
 | 
						|
                  { _str _len ; _n } \
 | 
						|
                  0 -> _n \
 | 
						|
                  get-msecs dup d# 60000 + ( start timeout ) \
 | 
						|
                  begin \
 | 
						|
                     ( start timeout ) get-msecs over > if \
 | 
						|
                        open-dev_debug if \
 | 
						|
                           ( start timeout ) drop get-msecs swap - \
 | 
						|
                           cr .\" FAILED TO OPEN DEVICE\" \
 | 
						|
                           cr .\" NUMBER OF TRIES \" _n .d \
 | 
						|
                           cr .\" TIME ELAPSED \" ( time ) .d .\"  MSECONDS\" cr \
 | 
						|
                        else \
 | 
						|
                           ( start timout ) 2drop \
 | 
						|
                        then \
 | 
						|
                        false exit \
 | 
						|
                     else \
 | 
						|
                        true \
 | 
						|
                     then \
 | 
						|
                     while \
 | 
						|
                        ( start timeout ) \
 | 
						|
                        _n 1 + -> _n \
 | 
						|
                        _str _len open-dev ( ihandle|false ) ?dup if \
 | 
						|
                        -rot ( ihandle start timeout ) \
 | 
						|
                        open-dev_debug if \
 | 
						|
                           ( start timeout ) drop get-msecs swap - \
 | 
						|
                           cr .\" SUCCESSFULLY OPENED DEVICE\" \
 | 
						|
                           cr .\" NUMBER OF TRIES \" _n .d \
 | 
						|
                           cr .\" TIME ELAPSED \" ( time ) .d .\" MSECONDS\" cr \
 | 
						|
                        else \
 | 
						|
                           ( start timeout ) 2drop \
 | 
						|
                        then \
 | 
						|
                        ( ihandle ) exit \
 | 
						|
                 then \
 | 
						|
                 ( start timeout ) \
 | 
						|
                 repeat \
 | 
						|
                 ; \r";
 | 
						|
    send_command($verbose, $rconsole, $command);
 | 
						|
 | 
						|
    $command = "patch new-open-dev open-dev net-ping \r";
 | 
						|
    send_command($verbose, $rconsole, $command);
 | 
						|
 | 
						|
    $timeout = 30;
 | 
						|
    $rconsole->expect(
 | 
						|
        $timeout,
 | 
						|
        #[qr/patch new-open-dev(.*)>/=>
 | 
						|
        [qr/>/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Status: at End of multiple_open_dev \n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                return 0;
 | 
						|
             }
 | 
						|
        ],
 | 
						|
        [qr/]/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Unexpected prompt\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
             }
 | 
						|
        ],
 | 
						|
        [timeout =>
 | 
						|
            sub {
 | 
						|
                send_user(2, "Timeout\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [eof =>
 | 
						|
            sub {
 | 
						|
                send_user(2, "Cannot connect to $node\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
            }
 | 
						|
        ],
 | 
						|
    );
 | 
						|
    return $rc;
 | 
						|
}
 | 
						|
###################################################################
 | 
						|
#
 | 
						|
# PROCEDURE
 | 
						|
#
 | 
						|
# Declare procedure to get additional firmware debug statement.
 | 
						|
#
 | 
						|
###################################################################
 | 
						|
sub  Firmware_Dump {
 | 
						|
    my $rconsole = shift;
 | 
						|
    my $node = shift;
 | 
						|
    my $verbose = shift;
 | 
						|
    my $device_path = shift;
 | 
						|
    my $phandle = shift;
 | 
						|
    my $expect_out;
 | 
						|
    my @done;
 | 
						|
    my @cmd;
 | 
						|
    my @msg;
 | 
						|
    my @pattern;
 | 
						|
    my @newstate;
 | 
						|
    my $timeout;
 | 
						|
    my $state = 0;
 | 
						|
    my $rc = 0;
 | 
						|
 | 
						|
    nc_msg($verbose,"Status: Firmware_Dump start\n");
 | 
						|
 | 
						|
    # state 0
 | 
						|
    $done[0] = 0;
 | 
						|
    $cmd[0] = "dev /packages/obp-tftp\r";
 | 
						|
    $msg[0] = "Status: selected /packages/obp_tftp\n";
 | 
						|
    $pattern[0] = "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
    $newstate[0] = 1;
 | 
						|
 | 
						|
    # state 1
 | 
						|
    $done[1] = 0;
 | 
						|
    $cmd[1] = ": testing1 .\" OBP-TFTP entry\" cr init-nvram-adptr-parms ;\r";
 | 
						|
    $msg[1] = "Status: running test - OBP-TFTP entry\n";
 | 
						|
    $pattern[1] = "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
    $newstate[1] = 2;
 | 
						|
 | 
						|
    # state 2
 | 
						|
    $done[2] = 0;
 | 
						|
    $cmd[2] = ": testing2 .\" OBP-TFTP exit, TRUE\" cr true ;\r";
 | 
						|
    $msg[2] = "Status: running test - OBP-TFTP exit\n";
 | 
						|
    $pattern[2] = "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
    $newstate[2] = 3;
 | 
						|
 | 
						|
    # state 3
 | 
						|
    $done[3] = 0;
 | 
						|
    $cmd[3] = "patch testing1 init-nvram-adptr-parms open\r";
 | 
						|
    $msg[3] = "Status: running test - patch testing1\n";
 | 
						|
    $pattern[3] = "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
    $newstate[3] = 4;
 | 
						|
 | 
						|
    # state 4
 | 
						|
    $done[4] = 0;
 | 
						|
    $cmd[4] = "patch testing2 true open\r";
 | 
						|
    $msg[4] = "Status: running test - patch testing2\n";
 | 
						|
    $pattern[4] = "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
    $newstate[4] = 5;
 | 
						|
 | 
						|
    # state 5
 | 
						|
    $done[5] = 0;
 | 
						|
    $cmd[5] = "dev $device_path\r";
 | 
						|
    $msg[5] = "Status: running test - dev $device_path\n";
 | 
						|
    $pattern[5] = "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
    $newstate[5] = 6;
 | 
						|
 | 
						|
    # state 6
 | 
						|
    $done[6] = 0;
 | 
						|
    $cmd[6] = "true to debug-init\r";
 | 
						|
    $msg[6] = "Status: running test - true to debug-init\n";
 | 
						|
    $pattern[6] = "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
    $newstate[6] = 7;
 | 
						|
 | 
						|
    # state 7
 | 
						|
    $done[7] = 0;
 | 
						|
    $cmd[7] = "true to debug-error\r";
 | 
						|
    $msg[7] = "Status: running test - true to debug-error\n";
 | 
						|
    $pattern[7] = "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
    $newstate[7] = 8;
 | 
						|
 | 
						|
    # state 8
 | 
						|
    $done[8] = 0;
 | 
						|
    $cmd[8] = "$phandle to active-package\r";
 | 
						|
    $msg[8] = "Status: running $phandle to active-package\n";
 | 
						|
    $pattern[8] = "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
    $newstate[8] = 9;
 | 
						|
 | 
						|
    # state 9
 | 
						|
    $done[9] = 0;
 | 
						|
    $cmd[9] = ".properties\r";
 | 
						|
    $msg[9] = "Status: running .properies\n";
 | 
						|
    $pattern[9] = "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
    $newstate[9] = 10;
 | 
						|
 | 
						|
    # state 10
 | 
						|
    $done[10] = 0;
 | 
						|
    $cmd[10] = "clear\r";
 | 
						|
    $msg[10] = "Status: running clear\n";
 | 
						|
    $pattern[10] = "(.*)ok(.*)(\[0-9]) >(.*)";
 | 
						|
    $newstate[10] = 11;
 | 
						|
 | 
						|
    # state 11, all done
 | 
						|
    $done[11] = 1;
 | 
						|
 | 
						|
    $state = 0;
 | 
						|
    $timeout = 30;       # shouldn't take long
 | 
						|
    while ($done[$state] == 0) {
 | 
						|
        send_command($verbose, $rconsole, $cmd[$state]);
 | 
						|
        $rconsole->expect(
 | 
						|
            [qr/$pattern[$state]/ =>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, $msg[$state]);
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $state = $newstate[$state];
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/]/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Unexpected prompt\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/(.*)DEFAULT(.*)/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Default catch error\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [timeout=>
 | 
						|
                sub {
 | 
						|
                nc_msg($verbose, "Timeout\n");
 | 
						|
                nc_msg($verbose, "Status: timeout state is $state\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [eof =>
 | 
						|
                sub {
 | 
						|
                nc_msg($verbose, "Cannot connect to $node\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
        );
 | 
						|
        return 1 if ($rc eq 1);
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3    lparnetbootexp
 | 
						|
 | 
						|
    Function:
 | 
						|
      Same function as the lpar_netboot.exp
 | 
						|
 | 
						|
    Return:
 | 
						|
        0  - good
 | 
						|
        1  - abort
 | 
						|
        2  - usage error
 | 
						|
 | 
						|
=cut
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub lparnetbootexp
 | 
						|
{
 | 
						|
    my $opt = shift;
 | 
						|
    if (($opt) && ($opt =~ /xCAT::/))
 | 
						|
    {
 | 
						|
        $opt = shift;
 | 
						|
    }
 | 
						|
    my $CONSOLEBIN = "/opt/xcat/bin/rcons";
 | 
						|
    my $PROGRAM = "lpar_netboot";
 | 
						|
    my $noboot = 0;   #default is to boot
 | 
						|
    my $Boot_timeout = 3000;
 | 
						|
    my @expect_out;
 | 
						|
    my $req = shift;
 | 
						|
    my $cmd;
 | 
						|
    my $timeout;
 | 
						|
    my $output;
 | 
						|
    my $done;
 | 
						|
    my $retry_count;
 | 
						|
    my $query_count;
 | 
						|
    my $match_pat;
 | 
						|
    my $loc_code;
 | 
						|
    my $ping_rc;
 | 
						|
    my $ping_result;
 | 
						|
    my $chosen_adap_type;
 | 
						|
    my $i;
 | 
						|
    my $phandle;
 | 
						|
    my $match;
 | 
						|
    my $list_type;
 | 
						|
    my $sysoutput;
 | 
						|
    my $exp_internal;
 | 
						|
# Flags and initial variable
 | 
						|
    my $discovery = 0;
 | 
						|
    my $discover_all = 0;
 | 
						|
    my $verbose = 0;
 | 
						|
    my $discover_macaddr = 0;
 | 
						|
    my $rc = 0;
 | 
						|
    my $debug_flag = 0;
 | 
						|
    my $rmvterm_flag = 0;
 | 
						|
    my $immed_flag = 0;
 | 
						|
    my $from_of = 0;
 | 
						|
    my $dev_type_found = 0;
 | 
						|
    my $list_physical = 0;
 | 
						|
    my $set_boot_order = 0;
 | 
						|
    my $colon = 0;
 | 
						|
    my $choice = 0;
 | 
						|
    my $full_path_name;
 | 
						|
    my $adap_speed;
 | 
						|
    my $adap_duplex;
 | 
						|
    my $client_ip;
 | 
						|
    my $server_ip;
 | 
						|
    my $gateway_ip;
 | 
						|
    my $extra_args;
 | 
						|
    my $macaddress;
 | 
						|
    my $netmask;
 | 
						|
    my $dump_target;
 | 
						|
    my $dump_lun;
 | 
						|
    my $dump_port;
 | 
						|
    my $phys_loc;
 | 
						|
    my $userid;
 | 
						|
    my $passwd;
 | 
						|
    my $prompt = "\\\$ \$";
 | 
						|
    my $ssh_spawn_id = 0;
 | 
						|
    my $mac_address;
 | 
						|
    my @outputarray;
 | 
						|
    my $outputarrayindex = 0;
 | 
						|
 | 
						|
    $::CALLBACK = $req->{callback};
 | 
						|
#
 | 
						|
# Log the process id
 | 
						|
#
 | 
						|
    my $proc_id = getppid;
 | 
						|
    nc_msg($verbose, "$PROGRAM Status: process id is $proc_id\n");
 | 
						|
 | 
						|
#
 | 
						|
#
 | 
						|
# Process command line options and parameters
 | 
						|
#
 | 
						|
#
 | 
						|
#done==
 | 
						|
 | 
						|
    if ( exists ($opt->{A})) {
 | 
						|
        $discover_all = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{C})) {
 | 
						|
        $client_ip = $opt->{C};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{D})) {
 | 
						|
        $discovery = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{G})) {
 | 
						|
        $gateway_ip = $opt->{G};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{P})) {
 | 
						|
        $list_physical = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{M})) {
 | 
						|
        $discover_macaddr = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{N})) {
 | 
						|
        $netmask = $opt->{N};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{S})) {
 | 
						|
        $server_ip = $opt->{S};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{c})) {
 | 
						|
        $colon = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{d})) {
 | 
						|
        $adap_duplex = $opt->{d};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{f})) {
 | 
						|
        $rmvterm_flag = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{g})) {
 | 
						|
        $extra_args = $opt->{g};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{i})) {
 | 
						|
        $immed_flag = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{o})) {
 | 
						|
        $from_of = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{w})) {
 | 
						|
        $set_boot_order = $opt->{w};
 | 
						|
    }
 | 
						|
     if ( exists ($opt->{L})) {
 | 
						|
        $dump_lun = $opt->{L};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{l})) {
 | 
						|
        $phys_loc = $opt->{l};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{m})) {
 | 
						|
        $macaddress = $opt->{m};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{n})) {
 | 
						|
        $noboot = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{p})) {
 | 
						|
        $dump_port = $opt->{p};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{s})) {
 | 
						|
        $adap_speed = $opt->{s};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{T})) {
 | 
						|
        $dump_target = $opt->{T};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{t})) {
 | 
						|
        $list_type = $opt->{t};
 | 
						|
        if ( $list_type eq "hfi-ent" ) {
 | 
						|
            $dev_pat[0] = "hfi-ethernet";
 | 
						|
            $dev_type[0] = "hfi-ent";
 | 
						|
        }
 | 
						|
        #
 | 
						|
        # Validate the argument
 | 
						|
        #
 | 
						|
        $dev_type_found = 0;
 | 
						|
        foreach my $dev (@dev_type) {
 | 
						|
            if ( $dev eq $list_type) {
 | 
						|
                $dev_type_found = 1;
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if ( $dev_type_found eq 0 ) {
 | 
						|
           nc_msg($verbose, "$PROGRAM:$dev_type_found, '$list_type' is not a valid adapter choice\n");
 | 
						|
           return [1];
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists ($opt->{v})) {
 | 
						|
        $verbose = 1;
 | 
						|
    } else {
 | 
						|
        $verbose = 0;
 | 
						|
    }
 | 
						|
    if ( exists ($opt->{x})) {
 | 
						|
        $debug_flag = 1;
 | 
						|
    }
 | 
						|
    if ( exists ($opt->{help})) {
 | 
						|
        usage;
 | 
						|
    }
 | 
						|
    #set arg0 [lindex $argv 0]
 | 
						|
    #set arg1 [lindex $argv 1]
 | 
						|
    #if ( scalar(%$opt) > 10 ) {
 | 
						|
    #    nc_msg($verbose, "$PROGRAM: Extraneous parameter(s)\n");
 | 
						|
    #    usage;
 | 
						|
    #}
 | 
						|
 | 
						|
    if ( $list_physical eq 0 ) {
 | 
						|
        $dev_pat[3] = "l-lan";
 | 
						|
        $dev_type[3] = "ent";
 | 
						|
        $dev_count = scalar(@dev_pat);
 | 
						|
    } else {
 | 
						|
        $dev_pat[3] = "";
 | 
						|
        $dev_type[3] = "";
 | 
						|
        $dev_count = scalar(@dev_pat);
 | 
						|
    }
 | 
						|
 | 
						|
    if ( $set_boot_order > 1 ) {
 | 
						|
        $dev_pat[4] = "scsi";
 | 
						|
        $dev_type[4] = "disk";
 | 
						|
        $dev_count = scalar(@dev_pat);
 | 
						|
    }
 | 
						|
    my $node = $opt->{node};
 | 
						|
    my $profile = $opt->{pprofile};
 | 
						|
    my $manage = $opt->{fsp};
 | 
						|
    my $lparid = $opt->{id};
 | 
						|
    my $hcp = $opt->{hcp};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    if ($dev_type_found)    { nc_msg($verbose, "$PROGRAM Status: List only $list_type adapters\n");               }
 | 
						|
    if ($noboot)            { nc_msg($verbose, "$PROGRAM Status: -n (no boot) flag detected\n");                  }
 | 
						|
    if ($discovery)         { nc_msg($verbose, "$PROGRAM Status: -D (discovery) flag detected\n");                }
 | 
						|
    if ($discover_all)      { nc_msg($verbose, "$PROGRAM Status: -A (discover all) flag detected\n" );            }
 | 
						|
    if ($verbose)           { nc_msg($verbose, "$PROGRAM Status: -v (verbose debug) flag detected\n");            }
 | 
						|
    if ($discover_macaddr)  { nc_msg($verbose, "$PROGRAM Status: -M (discover mac address) flag detected\n");     }
 | 
						|
    if ($immed_flag)        { nc_msg($verbose, "$PROGRAM Status: -i (force immediate shutdown) flag detected\n"); }
 | 
						|
    if ($list_physical)     { nc_msg($verbose, "$PROGRAM Status: -P (list only phsical network) flag detected\n");}
 | 
						|
    if ($colon)             { nc_msg($verbose, "$PROGRAM Status: -c (list colon separated ) flag detected\n" );   }
 | 
						|
    if ($debug_flag)        {
 | 
						|
        nc_msg($verbose, "$PROGRAM Status: -d (debug) flag detected\n");
 | 
						|
        #$exp_internal = 1;
 | 
						|
        #$log_user = 1;
 | 
						|
    }
 | 
						|
    if ($discovery and $adap_speed )  { nc_msg($verbose, "$PROGRAM Status: using adapter speed of $adap_speed\n" );       }
 | 
						|
    if ($discovery and $adap_duplex ) { nc_msg($verbose, "$PROGRAM Status: using adapter duplex of $adap_duplex\n" );     }
 | 
						|
    if ($discovery and $server_ip )   { nc_msg($verbose, "$PROGRAM Status: using server IP address of $server_ip\n");     }
 | 
						|
    if ($discovery and $client_ip)    { nc_msg($verbose, "$PROGRAM Status: using client IP address of $client_ip\n" );    }
 | 
						|
    if ($discovery and $gateway_ip)   { nc_msg($verbose, "$PROGRAM Status: using gateway IP address of $gateway_ip\n");   }
 | 
						|
    if ($discovery and $macaddress)   { nc_msg($verbose, "$PROGRAM Status: using macaddress of $macaddress\n"  );         }
 | 
						|
    if ($discovery and $phys_loc )    { nc_msg($verbose, "$PROGRAM Status: using physical location code of $phys_loc\n"); }
 | 
						|
    nc_msg($verbose, "node:".$node);
 | 
						|
    ####################################
 | 
						|
    # process the arguments
 | 
						|
    ####################################
 | 
						|
    $rc = xCAT::LparNetbootExp->ck_args($opt, $node, $verbose);
 | 
						|
    if ($rc != 0) {
 | 
						|
        nc_msg($verbose, "ck_args failed. \n");
 | 
						|
        return [1];
 | 
						|
    }
 | 
						|
 | 
						|
    ####################################
 | 
						|
    # decide if need to do the connect
 | 
						|
    ####################################
 | 
						|
 | 
						|
 | 
						|
    ####################################
 | 
						|
    # open the console
 | 
						|
    ####################################
 | 
						|
    nc_msg($verbose, "open port\n");
 | 
						|
    $cmd = $::XCATROOT . '/bin/rcons ' . $node . ' -f';
 | 
						|
    my $rconsole = Expect->new;
 | 
						|
    ##################################################
 | 
						|
    # raw_pty() disables command echoing and CRLF
 | 
						|
    # translation and gives a more pipe-like behaviour.
 | 
						|
    # Note that this must be set before spawning
 | 
						|
    # the process. Unfortunately, this does not work
 | 
						|
    # with AIX (IVM). stty(qw(-echo)) will at least
 | 
						|
    # disable command echoing on all platforms but
 | 
						|
    # will not suppress CRLF translation.
 | 
						|
    ##################################################
 | 
						|
    #$rconsole->raw_pty(1);
 | 
						|
    #$rconsole->slave->stty(qw(sane -echo));        #hidden information return from rcons
 | 
						|
 | 
						|
    ##################################################
 | 
						|
    # exp_internal(1) sets exp_internal debugging
 | 
						|
    # to STDERR.
 | 
						|
    ##################################################
 | 
						|
    #$rconsole->exp_internal( $verbose );          #hidden information return from rcons
 | 
						|
 | 
						|
    ##################################################
 | 
						|
    # log_stdout(0) disables logging to STDOUT.
 | 
						|
    # This corresponds to the Tcl log_user variable.
 | 
						|
    ##################################################
 | 
						|
    #$rconsole->log_stdout( $verbose );           #hidden information return from rcons
 | 
						|
    $rconsole->log_stdout(0);           #hidden information return from rcons
 | 
						|
 | 
						|
    my $consolefork = $rconsole->spawn($cmd);
 | 
						|
    #$rconsole->log_file("/tmp/consolelog");
 | 
						|
    my $console_pid = $rconsole->pid;
 | 
						|
    unless ($console_pid) {
 | 
						|
        nc_msg($verbose, "Unable to open console.\n");
 | 
						|
        return [1];
 | 
						|
    }
 | 
						|
    nc_msg($verbose, "spawn_id is $console_pid.\n");
 | 
						|
    ####################################
 | 
						|
    #kill the process after received the signal
 | 
						|
    ####################################
 | 
						|
 | 
						|
    ####################################
 | 
						|
    # check the result of rcons
 | 
						|
    ####################################
 | 
						|
    nc_msg($verbose, "Connecting to the $node.\n");
 | 
						|
    sleep 3;
 | 
						|
    $timeout = 2;
 | 
						|
    $rconsole->expect(
 | 
						|
        $timeout,
 | 
						|
        [ qr/Enter.* for help.*/i =>
 | 
						|
            sub {
 | 
						|
                $rc = 0;
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                nc_msg($verbose, "Connected.\n");
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [ timeout =>
 | 
						|
            sub {
 | 
						|
                $rc = 1;
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                nc_msg($verbose, "Timeout waiting for console connection.\n");
 | 
						|
            }
 | 
						|
        ],
 | 
						|
        [ eof =>
 | 
						|
            sub {
 | 
						|
                $rc = 2;
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                nc_msg($verbose, "Please make sure rcons $node works.\n");
 | 
						|
            }
 | 
						|
        ],
 | 
						|
    );
 | 
						|
 | 
						|
    unless ($rc eq 0) {
 | 
						|
        return [1];
 | 
						|
    }
 | 
						|
    ####################################
 | 
						|
    # check the node state
 | 
						|
    ####################################
 | 
						|
    nc_msg($verbose, "Checking for power off.\n");
 | 
						|
    my $subreq = $req->{subreq};
 | 
						|
    $output = xCAT::LparNetbootExp->run_lssyscfg($subreq, $verbose, $node);
 | 
						|
    if ($output =~ /Not Available/) {
 | 
						|
        nc_msg($verbose, "LPAR is Not Available. Please make sure the CEC's state.\n");
 | 
						|
        return [1];
 | 
						|
    } else {
 | 
						|
        nc_msg($verbose, "The lpar state is $output.\n");
 | 
						|
    }
 | 
						|
 | 
						|
    if ($from_of) {
 | 
						|
        unless($output =~ /open firmware/i){
 | 
						|
            nc_msg(2, "You are using the -o option. Please make sure the LPAR's initial state is open firmware.\n");
 | 
						|
            return [1];
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    ####################################
 | 
						|
    # if -o is not used, power node of
 | 
						|
    ####################################
 | 
						|
    unless ($from_of) {
 | 
						|
        if (($output =~ /^off$/i) or ($output =~ /Not Activated/i) ) {
 | 
						|
            nc_msg($verbose, "# Power off complete.\n");
 | 
						|
        } else {
 | 
						|
            nc_msg($verbose, "# Begin to Power off the node.\n");
 | 
						|
            $sysoutput = xCAT::Utils->runxcmd(
 | 
						|
                {
 | 
						|
                    command => ['rpower'],
 | 
						|
                    node    => [$node],
 | 
						|
                    arg     => ['off']
 | 
						|
                },
 | 
						|
            $subreq, 0, 1);
 | 
						|
            $output = join ',', @$sysoutput;
 | 
						|
            if ($::RUNCMD_RC != 0) {    #$::RUNCMD_RC  will get its value from runxcmd_output
 | 
						|
                nc_msg($verbose, "Unable to run rpower $node off.\n");
 | 
						|
                return [1];
 | 
						|
            }
 | 
						|
 | 
						|
            unless ($output =~ /Success/) {
 | 
						|
                nc_msg($verbose, "Power off failed.\n");
 | 
						|
                return [1];
 | 
						|
            } else {
 | 
						|
                nc_msg($verbose, "Wait for power off.\n");
 | 
						|
            }
 | 
						|
 | 
						|
            $done = 0;
 | 
						|
            $query_count = 0;
 | 
						|
            while (!$done) {
 | 
						|
                $output = xCAT::LparNetbootExp->run_lssyscfg($subreq, $verbose, $node);
 | 
						|
                if (($output =~ /^off$/i) or ($output =~ /Not Activated/)) {
 | 
						|
                    nc_msg($verbose, "Power off complete.\n");
 | 
						|
                    $done = 1;
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                $query_count++;
 | 
						|
                if ($query_count > 300) {
 | 
						|
                    nc_msg($verbose, "Power off failed.\n");
 | 
						|
                    return [1];
 | 
						|
                }
 | 
						|
                sleep 1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
        #################################################
 | 
						|
        # if set_boot_order is set, set the boot order
 | 
						|
        # if not set, power the node to open firmware
 | 
						|
        #################################################
 | 
						|
        $done = 0;
 | 
						|
        $retry_count = 0;
 | 
						|
        if ($set_boot_order > 1) {
 | 
						|
            nc_msg($verbose, "Power on $node to SMS.\n");
 | 
						|
            while (!$done) {
 | 
						|
                $sysoutput = xCAT::Utils->runxcmd(
 | 
						|
                    {
 | 
						|
                        command => ['rpower'],
 | 
						|
                        node    => [$node],
 | 
						|
                        arg     => ['sms']
 | 
						|
                    },
 | 
						|
                $subreq, 0, 1);
 | 
						|
                $output = join ',', @$sysoutput;
 | 
						|
                nc_msg($verbose, "Waiting for power on...\n");
 | 
						|
 | 
						|
                if ($::RUNCMD_RC != 0) {
 | 
						|
                    nc_msg($verbose, "Unable to run rpower $node sms\n");
 | 
						|
                    return [1];
 | 
						|
                }
 | 
						|
                unless ($output =~ /Success/) {
 | 
						|
                    if ($retry_count eq 3) {
 | 
						|
                        nc_msg($verbose, "Power off failed, msg is $output.\n");
 | 
						|
                        return [1];
 | 
						|
                    }
 | 
						|
                    sleep 1;
 | 
						|
                    $retry_count ++;
 | 
						|
                } else {
 | 
						|
                    $done = 1;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            nc_msg($verbose, "Power on the $node to the Open Firmware.\n");
 | 
						|
            while (!$done) {
 | 
						|
                $sysoutput = xCAT::Utils->runxcmd(
 | 
						|
                    {
 | 
						|
                        command => ['rpower'],
 | 
						|
                        node    => [$node],
 | 
						|
                        arg     => ['of']
 | 
						|
                    },
 | 
						|
                $subreq, 0, 1);
 | 
						|
                $output = join ',', @$sysoutput;
 | 
						|
                nc_msg($verbose, "Waiting for power on...\n");
 | 
						|
 | 
						|
                if ($::RUNCMD_RC != 0) {
 | 
						|
                    nc_msg($verbose, "Unable to run rpower $node open firmware.\n");
 | 
						|
                    return [1];
 | 
						|
                }
 | 
						|
                unless ($output =~ /Success/) {
 | 
						|
                    if ($retry_count eq 3) {
 | 
						|
                        nc_msg($verbose, "Power off failed, msg is $output.\n");
 | 
						|
                        return [1];
 | 
						|
                    }
 | 
						|
                    sleep 1;
 | 
						|
                    $retry_count ++;
 | 
						|
                } else {
 | 
						|
                    $done = 1;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        ###########################
 | 
						|
        # Check the node state
 | 
						|
        ###########################
 | 
						|
        $done = 0;
 | 
						|
        $query_count = 0;
 | 
						|
        $timeout = 1;
 | 
						|
        nc_msg($verbose, "Check the node state again;");
 | 
						|
        while(!$done) {
 | 
						|
            $output = xCAT::LparNetbootExp->run_lssyscfg($subreq, $verbose, $node);
 | 
						|
            nc_msg($verbose, "The node state is $output.\n");
 | 
						|
            if ($output =~ /Open Firmware/i) {
 | 
						|
                nc_msg($verbose, "Power on complete.\n");
 | 
						|
                $done = 1;
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            $query_count++;
 | 
						|
            # if the node is not in openfirmware state, just wait for it
 | 
						|
            my @result = $rconsole->expect(
 | 
						|
                $timeout,
 | 
						|
                [ qr/(.*)elect this consol(.*)/=>
 | 
						|
                sub {
 | 
						|
                    $rconsole->send("0\r");
 | 
						|
                    $rconsole->clear_accum();
 | 
						|
                    #$rconsole->exp_continue();
 | 
						|
                    }
 | 
						|
                ],
 | 
						|
            );
 | 
						|
 | 
						|
            if ($query_count > 300 ) {
 | 
						|
                nc_msg($verbose, "Timed out waiting for power on of $node");
 | 
						|
                nc_msg($verbose, "error from rpower command : \"$output\" \n");
 | 
						|
                return [1];
 | 
						|
            }
 | 
						|
            sleep 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    ##############################
 | 
						|
    # Check for active console
 | 
						|
    ##############################
 | 
						|
    nc_msg($verbose, "Check for active console.\n");
 | 
						|
    $done = 0;
 | 
						|
    $retry_count = 0;
 | 
						|
 | 
						|
    while (!$done) {
 | 
						|
        my @result = $rconsole->expect(
 | 
						|
            $timeout,
 | 
						|
            #[qr/ok(.*)0 >/=>
 | 
						|
            [qr/0(.*)ok/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, " at ok prompt\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $done = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/(.*)elect this consol(.*)/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, " selecting active console\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rconsole->send("0\r");
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/English|French|German|Italian|Spanish|Portuguese|Chinese|Japanese|Korean/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Languagae Selection Panel received\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $rconsole->send("2\r");
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/admin/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "No password specified\n");
 | 
						|
                $rconsole->soft_close();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/Invalid Password/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "FSP password is invalid.\n");
 | 
						|
                $rconsole->soft_close();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [qr/SMS(.*)Navigation Keys/=>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "SMS\n");
 | 
						|
                $rconsole->clear_accum();
 | 
						|
                $done = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [timeout=>
 | 
						|
            sub {
 | 
						|
                $rconsole->send("\r");
 | 
						|
                $retry_count++;
 | 
						|
                if ($retry_count eq 9) {
 | 
						|
                    nc_msg($verbose, "Timeout waiting for ok prompt; exiting.\n");
 | 
						|
                    $rconsole->soft_close();
 | 
						|
                    $rc = 1;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            ],
 | 
						|
            [eof =>
 | 
						|
            sub {
 | 
						|
                nc_msg($verbose, "Cannot connect to $node");
 | 
						|
                $rconsole->soft_close();
 | 
						|
                $rc = 1;
 | 
						|
                }
 | 
						|
            ],
 | 
						|
        );
 | 
						|
        return [1] if ($rc eq 1);
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    ##############################
 | 
						|
    # Set the node boot order
 | 
						|
    ##############################
 | 
						|
    if ($set_boot_order) {            #rnetboot node will not go here
 | 
						|
        nc_msg($verbose, "begin to set disk boot");
 | 
						|
        my $result = set_disk_boot( $rconsole, $node, $verbose);#@expect_out, $rconsole, $node, $verbose);
 | 
						|
        unless( $result ) {
 | 
						|
            nc_msg($verbose, "Unable to set $node boot order");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    sleep 1;
 | 
						|
 | 
						|
    ##############################
 | 
						|
    # Call get_phandle to gather
 | 
						|
    # information for all the
 | 
						|
    # supported network adapters
 | 
						|
    # in the device tree.
 | 
						|
    ##############################
 | 
						|
    $done = 0;
 | 
						|
    $retry_count = 0;
 | 
						|
    nc_msg($verbose, "begin to run get_phandle");
 | 
						|
    while (!$done) {
 | 
						|
        my $result = get_phandle($rconsole, $node, $verbose);
 | 
						|
        if ( $result eq 1) {
 | 
						|
            $retry_count++;
 | 
						|
            $rconsole->send("\r");
 | 
						|
            if ( $retry_count eq 3) {
 | 
						|
                nc_msg($verbose, "Unable to obtain network adapter information.  Quitting.\n");
 | 
						|
                return [1];
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            $done = 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    ##############################
 | 
						|
    # Call multiple_open_dev to
 | 
						|
    # circumvent firmware OPEN-DEV
 | 
						|
    # failure
 | 
						|
    ##############################
 | 
						|
    nc_msg($verbose, "begin to run multiple_open_dev");
 | 
						|
    my $result = xCAT::LparNetbootExp->multiple_open_dev($rconsole, $node, $verbose);
 | 
						|
    if ( $result eq 1) {
 | 
						|
       nc_msg($verbose, "Unable to obtain network adapter information.  Quitting.\n");
 | 
						|
       return [1];
 | 
						|
    }
 | 
						|
 | 
						|
    ##############################
 | 
						|
    #
 | 
						|
    ##############################
 | 
						|
    nc_msg($verbose, "begin to process opt-discovery");
 | 
						|
    if ($discovery) {              #rnetboot node will not go here
 | 
						|
        nc_msg($verbose, "# Client IP address is $client_ip\n");
 | 
						|
        nc_msg($verbose, "# Server IP address is $server_ip\n");
 | 
						|
        nc_msg($verbose, "# Gateway IP address is $gateway_ip\n");
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    ##############################
 | 
						|
    # Display information for all
 | 
						|
    # supported adapters
 | 
						|
    ##############################
 | 
						|
    if ($noboot) {  #if not do net boot
 | 
						|
        if ($list_type) {
 | 
						|
            $match_pat = $list_type;
 | 
						|
        } else {
 | 
						|
            $match_pat = ".*";
 | 
						|
        }
 | 
						|
 | 
						|
        if($colon) {
 | 
						|
            nc_msg($verbose, "#Type:Location_Code:MAC_Address:Full_Path_Name:Ping_Result:Device_Type:Size_MB:OS:OS_Version:\n");
 | 
						|
            $outputarrayindex++;  # start from 1, 0 is used to set as 0
 | 
						|
            $outputarray[$outputarrayindex] = "#Type:Location_Code:MAC_Address:Full_Path_Name:Ping_Result:Device_Type:Size_MB:OS:OS_Version:";
 | 
						|
        } else {
 | 
						|
            nc_msg($verbose, "# Type \tLocation Code \tMAC Address\t Full Path Name\t Ping Result\n");
 | 
						|
            $outputarrayindex++;
 | 
						|
            $outputarray[$outputarrayindex] = "# Type \tLocation Code \tMAC Address\t Full Path Name\t Ping Result";
 | 
						|
        }
 | 
						|
 | 
						|
        if ( $discover_all ) {    #getmacs here
 | 
						|
            for( $i = 0; $i < $adapter_found; $i++) {
 | 
						|
                if ($adap_type[$i] =~ /$match_pat/) {
 | 
						|
                    if (!($adap_type[$i] eq "hfi-ent")) {
 | 
						|
                        $mac_address = get_mac_addr($phandle_array[$i], $rconsole, $node, $verbose);
 | 
						|
                        $loc_code = get_adaptr_loc($phandle_array[$i], $rconsole, $node, $verbose);
 | 
						|
                    }
 | 
						|
                    $ping_result = "";
 | 
						|
                    if ($discovery) {
 | 
						|
                        $ping_rc = ping_server($phandle_array[$i], $full_path_name_array[$i], $rconsole, $node, $mac_address, $verbose, $adap_speed, $adap_duplex, $list_type, $server_ip, $client_ip, $gateway_ip);
 | 
						|
                        nc_msg($verbose, "ping_server returns $ping_rc\n");
 | 
						|
                        unless( $ping_rc eq 0) {
 | 
						|
                            $ping_result = "unsuccessful";
 | 
						|
                        } else {
 | 
						|
                            $ping_result = "successful";
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    if ( $adap_type[$i] eq "hfi-ent") {
 | 
						|
                        $mac_address = get_mac_addr($phandle_array[$i], $rconsole, $node, $verbose);
 | 
						|
                        $loc_code = get_adaptr_loc($phandle_array[$i], $rconsole, $node, $verbose);
 | 
						|
                    }
 | 
						|
 | 
						|
                    if ($full_path_name_array[$i] =~ /vdevice/)  {
 | 
						|
                        $device_type = "virtual";
 | 
						|
                    } else {
 | 
						|
                        $device_type = "physical";
 | 
						|
                    }
 | 
						|
 | 
						|
                    if($colon) {
 | 
						|
                        nc_msg($verbose, "$adap_type[$i]\:$loc_code\:$mac_address\:$full_path_name_array[$i]\:$ping_result\:$device_type\:\:\:\:\n");
 | 
						|
                        $outputarrayindex++;
 | 
						|
                        $outputarray[$outputarrayindex] = "$adap_type[$i]\:$loc_code\:$mac_address\:$full_path_name_array[$i]\:$ping_result\:$device_type\:\:\:\:";
 | 
						|
                    } else {
 | 
						|
                        nc_msg($verbose, "$adap_type[$i] $loc_code $mac_address $full_path_name_array[$i] $ping_result $device_type\n");
 | 
						|
                        $outputarrayindex++;
 | 
						|
                        $outputarray[$outputarrayindex] = "$adap_type[$i] $loc_code $mac_address $full_path_name_array[$i] $ping_result $device_type";
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            for( $i = 0; $i < $adapter_found; $i++) {
 | 
						|
                if ($adap_type[$i] =~ /$match_pat/) {
 | 
						|
                    if ($adap_type[$i] eq "hfi-ent") {
 | 
						|
                        $mac_address = get_mac_addr($phandle_array[$i], $rconsole, $node, $verbose);
 | 
						|
                        $loc_code = get_adaptr_loc($phandle_array[$i], $rconsole, $node, $verbose);
 | 
						|
                    }
 | 
						|
                    $ping_result = "";
 | 
						|
                    if ($discovery) {
 | 
						|
                        $ping_rc = ping_server($phandle_array[$i], $full_path_name_array[$i], $rconsole, $node, $mac_address, $verbose, $adap_speed, $adap_duplex, $list_type, $server_ip, $client_ip, $gateway_ip);
 | 
						|
                        nc_msg($verbose, "ping_server returns $ping_rc\n");
 | 
						|
                        unless( $ping_rc eq 0) {
 | 
						|
                            $ping_result = "unsuccessful";
 | 
						|
                        } else {
 | 
						|
                            $ping_result = "successful";
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    if ( $adap_type[$i] eq "hfi-ent") {
 | 
						|
                        $mac_address = get_mac_addr($phandle_array[$i], $rconsole, $node, $verbose);
 | 
						|
                        $loc_code = get_adaptr_loc($phandle_array[$i], $rconsole, $node, $verbose);
 | 
						|
                    }
 | 
						|
 | 
						|
                    if ($full_path_name_array[$i] =~ /vdevice/)  {
 | 
						|
                        $device_type = "virtual";
 | 
						|
                    } else {
 | 
						|
                        $device_type = "physical";
 | 
						|
                    }
 | 
						|
 | 
						|
                    if($colon) {
 | 
						|
                        nc_msg($verbose, "$adap_type[$i]\:$loc_code\:$mac_address\:$full_path_name_array[$i]\:$ping_result\:$device_type\:\:\:\:\n");
 | 
						|
                    } else {
 | 
						|
                        nc_msg($verbose, "$adap_type[$i] $loc_code $mac_address $full_path_name_array[$i] $ping_result $device_type\n");
 | 
						|
                    }
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if ($from_of != 1) {
 | 
						|
            nc_msg($verbose, "power off the node after noboot eq 1\n");
 | 
						|
            $sysoutput = xCAT::Utils->runxcmd(
 | 
						|
                {
 | 
						|
                    command => ['rpower'],
 | 
						|
                    node    => [$node],
 | 
						|
                    arg     => ['off']
 | 
						|
                },
 | 
						|
            $subreq, 0, 1);
 | 
						|
            $output = join ',', @$sysoutput;
 | 
						|
            if ($::RUNCMD_RC != 0) {
 | 
						|
                nc_msg($verbose, "Unable to run rpower $node sms.\n");
 | 
						|
                nc_msg($verbose, "Status: error from rpower command\n");
 | 
						|
                nc_msg($verbose, "Error : $output\n");
 | 
						|
                return [1];
 | 
						|
            }
 | 
						|
        }
 | 
						|
    } else { # Do a network boot
 | 
						|
    # Loop throught the adapters and perform a ping test to discover an
 | 
						|
    # adapter that pings successfully, then use that adapter to network boot.
 | 
						|
        if ($discover_all) {  #rnetboot should not use -A
 | 
						|
            for ($i = 0; $i < $adapter_found; $i++) {
 | 
						|
                $ping_rc = ping_server($phandle_array[$i], $full_path_name_array[$i], $rconsole, $node, $mac_address, $verbose, $adap_speed, $adap_duplex, $list_type, $server_ip, $client_ip, $gateway_ip);
 | 
						|
 | 
						|
 | 
						|
                if ( $ping_rc eq 0) {
 | 
						|
                    $phandle = $phandle_array[$i];
 | 
						|
                    $full_path_name = $full_path_name_array[$i];
 | 
						|
                    $chosen_adap_type = $adap_type[$i];
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } elsif ( $macaddress ne "" ) {          #rnetboot here     
 | 
						|
            $match = 0;
 | 
						|
            for ($i = 0; $i < $adapter_found; $i++) {
 | 
						|
                if ($adap_type[$i] =~ /hfi-ent/) {
 | 
						|
                    $ping_rc = ping_server($phandle_array[$i], $full_path_name_array[$i], $rconsole, $node, $mac_address, $verbose, $adap_speed, $adap_duplex, $list_type, $server_ip, $client_ip, $gateway_ip);
 | 
						|
                }
 | 
						|
                $mac_address = get_mac_addr($phandle_array[$i], $rconsole, $node, $verbose);
 | 
						|
                if ( $macaddress =~ /$mac_address/ ) {
 | 
						|
                    if ($discovery eq 1) {
 | 
						|
                        unless ( $adap_type[$i] eq "hfi-ent" ) {
 | 
						|
                           $ping_rc = ping_server($phandle_array[$i], $full_path_name_array[$i], $rconsole, $node, $mac_address, $verbose, $adap_speed, $adap_duplex, $list_type, $server_ip, $client_ip, $gateway_ip);
 | 
						|
                        }
 | 
						|
                        unless ( $ping_rc eq 0) {
 | 
						|
                            nc_msg($verbose, "Unable to boot network adapter.\n" );
 | 
						|
                            return [1];
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                $phandle =  $phandle_array[$i];
 | 
						|
                $full_path_name = $full_path_name_array[$i];
 | 
						|
                $chosen_adap_type = $adap_type[$i];
 | 
						|
                $match = 1;
 | 
						|
                last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            unless($match) {
 | 
						|
                nc_msg($verbose, "Can not find mac address '$macaddress'\n");
 | 
						|
                return [1];
 | 
						|
            }
 | 
						|
        } elsif ( $phys_loc ne "") {
 | 
						|
            $match = 0;
 | 
						|
            for ($i = 0; $i < $adapter_found; $i++) {
 | 
						|
                $loc_code = get_adaptr_loc($phandle_array[$i], $rconsole, $node, $verbose);
 | 
						|
                if ($loc_code =~ /$phys_loc/) {
 | 
						|
                    if ($discovery) {
 | 
						|
                        $ping_rc = ping_server($phandle_array[$i], $full_path_name_array[$i], $rconsole, $node, $mac_address, $verbose, $adap_speed, $adap_duplex, $list_type, $server_ip, $client_ip, $gateway_ip);
 | 
						|
                        unless ($ping_rc eq 0) {
 | 
						|
                            nc_msg($verbose, "Unable to boot network adapter.\n");
 | 
						|
                            return [1];
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    $phandle =  $phandle_array[$i];
 | 
						|
                    $full_path_name = $full_path_name_array[$i];
 | 
						|
                    $chosen_adap_type = $adap_type[$i];
 | 
						|
                    $match = 1;
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if (!$match) {
 | 
						|
                nc_msg($verbose, "Can not find physical location '$phys_loc'\n");
 | 
						|
                return [1];
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
        #
 | 
						|
        # Use the first ethernet adapter in the
 | 
						|
        # device tree.
 | 
						|
        #
 | 
						|
            for ($i = 0; $i < $adapter_found; $i++) {
 | 
						|
            nc_msg($verbose, " begint to boot from first adapter in the device tree \n");
 | 
						|
                if ($adap_type[$i] eq $list_type ) {
 | 
						|
                    if ( $discovery eq 1 ){
 | 
						|
                        $ping_rc = ping_server($phandle_array[$i], $full_path_name_array[$i], $rconsole, $node, $mac_address, $verbose, $adap_speed, $adap_duplex, $list_type, $server_ip, $client_ip, $gateway_ip);
 | 
						|
                        unless ($ping_rc eq 0) {
 | 
						|
                            return [1];
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    $phandle = $phandle_array[$i];
 | 
						|
                    $full_path_name = $full_path_name_array[$i];
 | 
						|
                    $chosen_adap_type = $adap_type[$i];
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        my $result;
 | 
						|
        if ($full_path_name eq "") {
 | 
						|
            nc_msg($verbose, "Unable to boot network adapter.\n");
 | 
						|
            return [1];
 | 
						|
        } else {
 | 
						|
            nc_msg($verbose, "# Network booting install adapter.\n");
 | 
						|
            $result = xCAT::LparNetbootExp->boot_network($rconsole, $full_path_name, $adap_speed, $adap_duplex , $chosen_adap_type, $server_ip, $client_ip, $gateway_ip, $netmask, $dump_target, $dump_lun, $dump_port, $verbose, $extra_args, $node, $set_boot_order );
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        if ($result eq 0) {
 | 
						|
            nc_msg($verbose, "bootp sent over netowrk.\n");
 | 
						|
            my $res = Boot($rconsole, $node, $verbose);#, @expect_out);
 | 
						|
            unless ($res eq 0) {
 | 
						|
                nc_msg($verbose, "Can not boot, result = $res. \n");
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            nc_msg($verbose, "return code $result from boot_network\n");
 | 
						|
        }
 | 
						|
 | 
						|
        ###########################################################################
 | 
						|
        # Need to retry network boot because of intermittant network failure
 | 
						|
        # after partition reboot.  Force partition to stop at Open Firmware prompt.
 | 
						|
        ###########################################################################
 | 
						|
        if ($result eq 5) {
 | 
						|
 | 
						|
            $timeout = 300;
 | 
						|
            $rconsole->expect(
 | 
						|
                $timeout,
 | 
						|
                [ qr/keyboard/i,
 | 
						|
                    sub {
 | 
						|
                        $rconsole->send("8\r");
 | 
						|
                        $rconsole->clear_accum();
 | 
						|
                        sleep 10;
 | 
						|
                    }
 | 
						|
                ],
 | 
						|
                [ qr/timeout/i,
 | 
						|
                    sub {
 | 
						|
                        nc_msg($verbose, "Timeout; exiting.\n");
 | 
						|
                        $rconsole->clear_accum();
 | 
						|
                        $rc = 1;
 | 
						|
                    }
 | 
						|
                ],
 | 
						|
                [ eof =>
 | 
						|
                    sub {
 | 
						|
                        nc_msg($verbose, "cannot connect to $node.\n");
 | 
						|
                        $rconsole->clear_accum();
 | 
						|
                        $rc = 1;
 | 
						|
                    }
 | 
						|
                ],
 | 
						|
                [
 | 
						|
                    sub {
 | 
						|
                        nc_msg($verbose, "# Network booting install adapter.\n");
 | 
						|
                        nc_msg($verbose, "Retrying network-boot from RESTART-CMD error.\n");
 | 
						|
                        $done = 0;
 | 
						|
                        while (! $done ) {
 | 
						|
                            my $res = xCAT::LparNetbootExp->boot_network($node,);
 | 
						|
                            if ($res eq 0) {
 | 
						|
                                $done = 1;
 | 
						|
                            } else {
 | 
						|
                                sleep 10;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                ],
 | 
						|
            );
 | 
						|
        return [1] if ($rc eq 1);
 | 
						|
        }
 | 
						|
        nc_msg($verbose, "# bootp sent over network.\n");
 | 
						|
        $rc = Boot($rconsole, $node, $verbose);#, @expect_out);
 | 
						|
        unless ($rc eq 0) {
 | 
						|
            nc_msg($verbose, "Can't boot here. \n");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    ################################################
 | 
						|
    # mission accomplished, beam me up scotty.
 | 
						|
    #################################################
 | 
						|
    unless ($noboot) {  #if do the rnetboot, just return
 | 
						|
        if ( $rc eq 0) {
 | 
						|
            nc_msg($verbose, "# Finished.\n" );
 | 
						|
            $outputarrayindex++;
 | 
						|
            $outputarray[$outputarrayindex] = "Finished.";
 | 
						|
        } else {
 | 
						|
            nc_msg($verbose, "# Finished in an error.\n");
 | 
						|
            $outputarrayindex++;
 | 
						|
            $outputarray[$outputarrayindex] = "Finished in an error.";
 | 
						|
        }
 | 
						|
    } else {   #if not rnetboot, for example, getmacs, power off the node
 | 
						|
        $done = 0;
 | 
						|
        $query_count = 0;
 | 
						|
        while(!$done) {
 | 
						|
            $output = xCAT::LparNetbootExp->run_lssyscfg($subreq, $verbose, $node);
 | 
						|
 | 
						|
            ##############################################
 | 
						|
            # separate the nodename from the query status
 | 
						|
            ##############################################
 | 
						|
            if ($from_of != 1) {
 | 
						|
                if (( $output =~ /^off$/i ) or ($output =~ /Not Activated/i)) {
 | 
						|
                    $done = 1;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                if ( $output =~ /firmware/i ) {
 | 
						|
                    $done = 1;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            $query_count++;
 | 
						|
            if ( $query_count > 60 ){
 | 
						|
                $done = 1;
 | 
						|
            }
 | 
						|
            sleep 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    $cmd = "~.";
 | 
						|
    send_command($verbose, $rconsole, $cmd);
 | 
						|
 | 
						|
    $outputarray[0] = 0;
 | 
						|
    return \@outputarray;
 | 
						|
 | 
						|
}
 | 
						|
 |