mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-03 21:02:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1370 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			1370 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
 | 
						|
package xCAT::PPCcli;
 | 
						|
use strict;
 | 
						|
require Exporter;
 | 
						|
our @ISA       = qw(Exporter);
 | 
						|
our @EXPORT_OK = qw(SUCCESS RC_ERROR EXPECT_ERROR NR_ERROR);
 | 
						|
use Expect;
 | 
						|
use xCAT::NetworkUtils;
 | 
						|
 | 
						|
#############################################
 | 
						|
# Removes Ctrl characters from term output
 | 
						|
#############################################
 | 
						|
$ENV{'TERM'} = "vt100";
 | 
						|
 | 
						|
##############################################
 | 
						|
# Constants
 | 
						|
##############################################
 | 
						|
use constant {
 | 
						|
    SUCCESS         => 0,
 | 
						|
    RC_ERROR        => 1,
 | 
						|
    EXPECT_ERROR    => 2,
 | 
						|
    NR_ERROR        => 3,
 | 
						|
    DEFAULT_TIMEOUT => 60
 | 
						|
};
 | 
						|
 | 
						|
##############################################
 | 
						|
# lssyscfg supported formats
 | 
						|
##############################################
 | 
						|
my %lssyscfg = (
 | 
						|
    fsp   => "lssyscfg -r sys -m %s -F %s",
 | 
						|
    cec   => "lssyscfg -r sys -m %s -F %s",
 | 
						|
    fsps  => "lssyscfg -r sys -F %s",
 | 
						|
    node  => "lssyscfg -r lpar -m %s -F %s --filter lpar_ids=%s",
 | 
						|
    lpar  => "lssyscfg -r lpar -m %s -F %s",
 | 
						|
    lpar2 => "lssyscfg -r lpar -m %s --filter %s",
 | 
						|
    bpa   => "lssyscfg -r frame -e %s -F %s",
 | 
						|
    frame => "lssyscfg -r frame -e %s -F %s",
 | 
						|
    bpas  => "lssyscfg -r frame -F %s",
 | 
						|
    prof  => "lssyscfg -r prof -m %s --filter %s",
 | 
						|
    profs => "lssyscfg -r prof -m %s -F %s --filter %s",
 | 
						|
    cage  => "lssyscfg -r cage -e %s -F %s"
 | 
						|
);
 | 
						|
 | 
						|
my %chsyscfg = (
 | 
						|
    prof  => "chsyscfg -r prof -m %s -i %s",
 | 
						|
    bpa   => "chsyscfg -r frame -e %s -i %s",
 | 
						|
    fsp   => "chsyscfg -r sys -m %s -i %s",
 | 
						|
    frame => "chsyscfg -r frame -e %s -i %s",
 | 
						|
    cec   => "chsyscfg -r sys -m %s -i %s",
 | 
						|
);
 | 
						|
 | 
						|
##############################################
 | 
						|
# Power control supported formats
 | 
						|
##############################################
 | 
						|
my %powercmd = (
 | 
						|
    lpar => {
 | 
						|
        on    => "chsysstate -r %s -m %s -o on -b norm --id %s -f %s",
 | 
						|
        of    => "chsysstate -r %s -m %s -o on --id %s -f %s -b of",
 | 
						|
        sms   => "chsysstate -r %s -m %s -o on --id %s -f %s -b sms",
 | 
						|
        reset => "chsysstate -r %s -m %s -o shutdown --id %s --immed --restart",
 | 
						|
        off   => "chsysstate -r %s -m %s -o shutdown --id %s --immed",
 | 
						|
        softoff => "chsysstate -r %s -m %s -o shutdown --id %s",
 | 
						|
        boot    => "undetermined" },
 | 
						|
    sys => {
 | 
						|
        reset     => "chsysstate -r %s -m %s -o off --immed --restart",
 | 
						|
        on        => "chsysstate -r %s -m %s -o on",
 | 
						|
        onstandby => "chsysstate -r %s -m %s -o onstandby",
 | 
						|
        off       => "chsysstate -r %s -m %s -o off",
 | 
						|
        boot      => "undetermined" }
 | 
						|
);
 | 
						|
 | 
						|
##############################################
 | 
						|
# lsrefcode supported formats
 | 
						|
##############################################
 | 
						|
my %lsrefcode = (
 | 
						|
    fsp => {
 | 
						|
        pri => "lsrefcode -r sys -m %s -s p",
 | 
						|
        sec => "lsrefcode -r sys -m %s -s s",
 | 
						|
    },
 | 
						|
    cec => {
 | 
						|
        pri => "lsrefcode -r sys -m %s -s p",
 | 
						|
        sec => "lsrefcode -r sys -m %s -s s",
 | 
						|
    },
 | 
						|
    lpar => "lsrefcode -r lpar -m %s --filter lpar_ids=%s",
 | 
						|
);
 | 
						|
 | 
						|
##############################################
 | 
						|
# mksysconn support formats
 | 
						|
##############################################
 | 
						|
my %mksysconn = (
 | 
						|
    fsp   => "mksysconn --ip %s -r sys --passwd %s",
 | 
						|
    cec   => "mksysconn --ip %s -r sys --passwd %s",
 | 
						|
    bpa   => "mksysconn --ip %s -r frame --passwd %s",
 | 
						|
    frame => "mksysconn --ip %s -r frame --passwd %s",
 | 
						|
);
 | 
						|
 | 
						|
##############################################
 | 
						|
# rmsysconn support formats
 | 
						|
##############################################
 | 
						|
my %rmsysconn = (
 | 
						|
    fsp   => "rmsysconn -o remove --ip %s",
 | 
						|
    cec   => "rmsysconn -o remove --ip %s",
 | 
						|
    bpa   => "rmsysconn -o remove --ip %s",
 | 
						|
    frame => "rmsysconn -o remove --ip %s",
 | 
						|
);
 | 
						|
 | 
						|
##############################################
 | 
						|
# lssysconn support formats
 | 
						|
##############################################
 | 
						|
my %lssysconn = (
 | 
						|
    all  => "lssysconn -r all",
 | 
						|
    alls => "lssysconn -r all -F %s"
 | 
						|
);
 | 
						|
 | 
						|
##############################################
 | 
						|
# Change IP address for managed systems
 | 
						|
# or frames
 | 
						|
##############################################
 | 
						|
my %chsyspwd = (
 | 
						|
    fsp   => "chsyspwd -t %s -m %s --passwd %s --newpasswd %s",
 | 
						|
    bpa   => "chsyspwd -t %s -e %s --passwd %s --newpasswd %s",
 | 
						|
    cec   => "chsyspwd -t %s -m %s --passwd %s --newpasswd %s",
 | 
						|
    frame => "chsyspwd -t %s -e %s --passwd %s --newpasswd %s",
 | 
						|
);
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Logon to remote server
 | 
						|
##########################################################################
 | 
						|
sub connect {
 | 
						|
 | 
						|
    my $req        = shift;
 | 
						|
    my $hwtype     = shift;
 | 
						|
    my $server     = shift;
 | 
						|
    my $pwd_prompt = 'assword: $';
 | 
						|
    my $continue   = 'continue connecting (yes/no)?';
 | 
						|
    my $retry      = $req->{ppcretry};
 | 
						|
    my $timeout    = $req->{ppctimeout};
 | 
						|
    my $verbose    = $req->{verbose};
 | 
						|
    my $ssh;
 | 
						|
    my $expect_log = "/dev/null";
 | 
						|
    my $errmsg;
 | 
						|
 | 
						|
    if ($req->{command} eq 'rflash') {
 | 
						|
        $verbose = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    ##################################################
 | 
						|
    # Use timeout from site table (if defined)
 | 
						|
    ##################################################
 | 
						|
    if (!$timeout) {
 | 
						|
        $timeout = DEFAULT_TIMEOUT;
 | 
						|
    }
 | 
						|
    ##################################################
 | 
						|
    # Shell prompt regexp based on HW Type
 | 
						|
    ##################################################
 | 
						|
    my %prompt = (
 | 
						|
        hmc => "~>\\s*\$",
 | 
						|
        ivm => "\\\$ \$"
 | 
						|
    );
 | 
						|
    ##################################################
 | 
						|
    # Get userid/password
 | 
						|
    ##################################################
 | 
						|
    my $cred       = $req->{$server}{cred};
 | 
						|
    my $parameters = "@$cred[0]\@$server";
 | 
						|
 | 
						|
    ##################################################
 | 
						|
    # Redirect STDERR to variable
 | 
						|
    ##################################################
 | 
						|
    if ($verbose) {
 | 
						|
        close STDERR;
 | 
						|
        if (!open(STDERR, '>', $expect_log)) {
 | 
						|
            return ("Unable to redirect STDERR: $!");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    ##################################################
 | 
						|
    # Redirect STDOUT to variable
 | 
						|
    ##################################################
 | 
						|
    if ($verbose) {
 | 
						|
        close STDOUT;
 | 
						|
        if (!open(STDOUT, '>', $expect_log)) {
 | 
						|
            return ("Unable to redirect STDOUT: $!");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    ######################################################
 | 
						|
    # -re $continue
 | 
						|
    #  "The authenticity of host can't be established
 | 
						|
    #   RSA key fingerprint is ....
 | 
						|
    #   Are you sure you want to continue connecting (yes/no)?"
 | 
						|
    #
 | 
						|
    # -re pwd_prompt
 | 
						|
    #   If the keys have already been transferred, we
 | 
						|
    #   may already be at the command prompt without
 | 
						|
    #   sending the password.
 | 
						|
    #
 | 
						|
    ######################################################
 | 
						|
    while ($retry--) {
 | 
						|
        my $success  = 0;
 | 
						|
        my $pwd_sent = 0;
 | 
						|
        $expect_log = undef;
 | 
						|
 | 
						|
        $ssh = new Expect;
 | 
						|
 | 
						|
        ##################################################
 | 
						|
        # 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.
 | 
						|
        ##################################################
 | 
						|
        #$ssh->raw_pty(1);
 | 
						|
        $ssh->slave->stty(qw(sane -echo));
 | 
						|
 | 
						|
        ##################################################
 | 
						|
        # exp_internal(1) sets exp_internal debugging
 | 
						|
        # to STDERR.
 | 
						|
        ##################################################
 | 
						|
        $ssh->exp_internal($verbose);
 | 
						|
 | 
						|
        ##################################################
 | 
						|
        # log_stdout(0) disables logging to STDOUT.
 | 
						|
        # This corresponds to the Tcl log_user variable.
 | 
						|
        ##################################################
 | 
						|
        $ssh->log_stdout($verbose);
 | 
						|
 | 
						|
        unless ($ssh->spawn("ssh", $parameters)) {
 | 
						|
            return ($expect_log . "Unable to spawn ssh connection to server");
 | 
						|
        }
 | 
						|
        my @result = $ssh->expect($timeout,
 | 
						|
            [ $continue,
 | 
						|
                sub {
 | 
						|
                    $ssh->send("yes\r");
 | 
						|
                    $ssh->clear_accum();
 | 
						|
                    $ssh->exp_continue();
 | 
						|
                  } ],
 | 
						|
            [ $pwd_prompt,
 | 
						|
                sub {
 | 
						|
                    if (++$pwd_sent) {
 | 
						|
                        $ssh->send("@$cred[1]\r");
 | 
						|
                        $ssh->exp_continue();
 | 
						|
                    }
 | 
						|
                  } ],
 | 
						|
            [ $prompt{$hwtype},
 | 
						|
                sub {
 | 
						|
                    $success = 1;
 | 
						|
                  } ]
 | 
						|
        );
 | 
						|
        ##########################################
 | 
						|
        # Expect error - retry
 | 
						|
        ##########################################
 | 
						|
        if (defined($result[1])) {
 | 
						|
            $errmsg = $expect_log . expect_error(@result);
 | 
						|
            sleep(1);
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        ##########################################
 | 
						|
        # Successful logon....
 | 
						|
        # Return:
 | 
						|
        #    Expect
 | 
						|
        #    HW Shell Prompt regexp
 | 
						|
        #    HW Type (hmc/ivm)
 | 
						|
        #    Server hostname
 | 
						|
        #    UserId
 | 
						|
        #    Password
 | 
						|
        #    Redirected STDERR/STDOUT
 | 
						|
        #    Connect/Command timeout
 | 
						|
        ##########################################
 | 
						|
        if ($success) {
 | 
						|
            return ($ssh,
 | 
						|
                $prompt{$hwtype},
 | 
						|
                $hwtype,
 | 
						|
                $server,
 | 
						|
                @$cred[0],
 | 
						|
                @$cred[1],
 | 
						|
                \$expect_log,
 | 
						|
                $timeout);
 | 
						|
        }
 | 
						|
        ##########################################
 | 
						|
        # Failed logon - kill ssh process
 | 
						|
        ##########################################
 | 
						|
        $ssh->hard_close();
 | 
						|
        return ($expect_log . "Invalid userid/password");
 | 
						|
    }
 | 
						|
    $ssh->hard_close();
 | 
						|
    return ($errmsg);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Logoff to remote server
 | 
						|
##########################################################################
 | 
						|
sub disconnect {
 | 
						|
 | 
						|
    my $exp = shift;
 | 
						|
    my $ssh = @$exp[0];
 | 
						|
 | 
						|
    if (defined($ssh)) {
 | 
						|
        $ssh->send("exit\r");
 | 
						|
        $ssh->hard_close();
 | 
						|
        @$exp[0] = undef;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# List attributes for resources (lpars, managed system, etc)
 | 
						|
##########################################################################
 | 
						|
sub lssyscfg {
 | 
						|
 | 
						|
    my $exp = shift;
 | 
						|
    my $res = shift;
 | 
						|
    my $d1  = shift;
 | 
						|
    my $d2  = shift;
 | 
						|
    my $d3  = shift;
 | 
						|
 | 
						|
    ###################################
 | 
						|
    # Select command
 | 
						|
    ###################################
 | 
						|
    my $cmd = sprintf($lssyscfg{$res}, $d1, $d2, $d3);
 | 
						|
 | 
						|
    ###################################
 | 
						|
    # Send command
 | 
						|
    ###################################
 | 
						|
    my $result = send_cmd($exp, $cmd);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Changes a logical partition configuration data
 | 
						|
##########################################################################
 | 
						|
sub chsyscfg {
 | 
						|
 | 
						|
    my $exp     = shift;
 | 
						|
    my $res     = shift;
 | 
						|
    my $d       = shift;
 | 
						|
    my $cfgdata = shift;
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Select command
 | 
						|
    #####################################
 | 
						|
    my $cmd = sprintf($chsyscfg{$res}, @$d[2], $cfgdata);
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Send command
 | 
						|
    #####################################
 | 
						|
    my $result = send_cmd($exp, $cmd);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# List reference codes for resources (lpars, managed system, etc)
 | 
						|
##########################################################################
 | 
						|
sub lsrefcode {
 | 
						|
 | 
						|
    my $exp    = shift;
 | 
						|
    my $res    = shift;
 | 
						|
    my $d1     = shift;
 | 
						|
    my $d2     = shift;
 | 
						|
    my $cmd    = undef;
 | 
						|
    my @cmds   = undef;
 | 
						|
    my $result = undef;
 | 
						|
    my @values;
 | 
						|
 | 
						|
    ###################################
 | 
						|
    # Select command
 | 
						|
    ###################################
 | 
						|
    if ($res =~ /^(fsp|cec)$/) {
 | 
						|
        $cmds[0] = sprintf($lsrefcode{$res}{pri}, $d1);
 | 
						|
        $cmds[1] = sprintf($lsrefcode{$res}{sec}, $d1);
 | 
						|
    } elsif ($res eq 'lpar') {
 | 
						|
        $cmds[0] = sprintf($lsrefcode{$res}, $d1, $d2);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        return [ [ 0, 'Not available' ] ];
 | 
						|
    }
 | 
						|
 | 
						|
    ###################################
 | 
						|
    # Send command
 | 
						|
    ###################################
 | 
						|
    foreach $cmd (@cmds) {
 | 
						|
        $result = send_cmd($exp, $cmd);
 | 
						|
        push @values, $result;
 | 
						|
    }
 | 
						|
    return \@values;
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Creates a logical partition on the managed system
 | 
						|
##########################################################################
 | 
						|
sub mksyscfg {
 | 
						|
 | 
						|
    my $exp     = shift;
 | 
						|
    my $res     = shift;
 | 
						|
    my $d       = shift;
 | 
						|
    my $cfgdata = shift;
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Command only support on LPARs
 | 
						|
    #####################################
 | 
						|
    if (@$d[4] ne "lpar") {
 | 
						|
        return ([ RC_ERROR, "Command not supported on '@$d[4]'" ]);
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Format command based on CEC name
 | 
						|
    #####################################
 | 
						|
    my $cmd = "mksyscfg -r $res -m @$d[2] -i \"$cfgdata\"";
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Send command
 | 
						|
    #####################################
 | 
						|
    my $result = send_cmd($exp, $cmd);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Removes a logical partition on the managed system
 | 
						|
##########################################################################
 | 
						|
sub rmsyscfg {
 | 
						|
 | 
						|
    my $exp = shift;
 | 
						|
    my $d   = shift;
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Command only supported on LPARs
 | 
						|
    #####################################
 | 
						|
    if (@$d[4] ne "lpar") {
 | 
						|
        return ([ RC_ERROR, "Command not supported on '@$d[4]'" ]);
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Format command based on CEC name
 | 
						|
    #####################################
 | 
						|
    my $cmd = "rmsyscfg -r lpar -m @$d[2] --id @$d[0]";
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Send command
 | 
						|
    #####################################
 | 
						|
    my $result = send_cmd($exp, $cmd);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Lists environmental information
 | 
						|
##########################################################################
 | 
						|
sub lshwinfo {
 | 
						|
 | 
						|
    my $exp    = shift;
 | 
						|
    my $res    = shift;
 | 
						|
    my $frame  = shift;
 | 
						|
    my $filter = shift;
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Format command based on CEC name
 | 
						|
    #####################################
 | 
						|
    my $cmd = "lshwinfo -r $res -e $frame -F $filter";
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Send command
 | 
						|
    #####################################
 | 
						|
    my $result = send_cmd($exp, $cmd);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Changes the state of a partition or managed system
 | 
						|
##########################################################################
 | 
						|
sub chsysstate {
 | 
						|
 | 
						|
    my $exp = shift;
 | 
						|
    my $op  = shift;
 | 
						|
    my $d   = shift;
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Format command based on CEC name
 | 
						|
    #####################################
 | 
						|
    my $cmd = power_cmd($op, $d);
 | 
						|
    if (!defined($cmd)) {
 | 
						|
        return ([ RC_ERROR, "'$op' command not supported" ]);
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Special case - return immediately
 | 
						|
    #####################################
 | 
						|
    if ($cmd =~ /^reboot$/) {
 | 
						|
        my $ssh = @$exp[0];
 | 
						|
 | 
						|
        $ssh->send("$cmd\r");
 | 
						|
        return ([ SUCCESS, "Success" ]);
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Send command
 | 
						|
    #####################################
 | 
						|
    my $result = send_cmd($exp, $cmd);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Opens a virtual terminal session
 | 
						|
##########################################################################
 | 
						|
sub mkvterm {
 | 
						|
 | 
						|
    my $exp     = shift;
 | 
						|
    my $type    = shift;
 | 
						|
    my $lparid  = shift;
 | 
						|
    my $mtms    = shift;
 | 
						|
    my $ssh     = @$exp[0];
 | 
						|
    my $hwtype  = @$exp[2];
 | 
						|
    my $failed  = 0;
 | 
						|
    my $timeout = 3;
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Format command based on HW Type
 | 
						|
    ##########################################
 | 
						|
    my %mkvt = (
 | 
						|
        hmc => "mkvterm --id %s -m %s",
 | 
						|
        ivm => "mkvt -id %s"
 | 
						|
    );
 | 
						|
    ##########################################
 | 
						|
    # HMC returns:
 | 
						|
    #  "A terminal session is already open
 | 
						|
    #   for this partition. Only one open
 | 
						|
    #   session is allowed for a partition.
 | 
						|
    #   Exiting...."
 | 
						|
    #
 | 
						|
    # HMCs may also return:
 | 
						|
    #  "The open failed.
 | 
						|
    #  "-The session may already be open on
 | 
						|
    #  another management console"
 | 
						|
    #
 | 
						|
    # But Expect (for some reason) sees each
 | 
						|
    # character preceeded with \000 (blank??)
 | 
						|
    #
 | 
						|
    ##########################################
 | 
						|
    my $fail_msg = "HSCL";
 | 
						|
    my $ivm_open = "Virtual terminal is already connected";
 | 
						|
    my $hmc_open = "\000o\000p\000e\000n\000 \000f\000a\000i\000l\000e\000d";
 | 
						|
    my $hmc_open2 =
 | 
						|
      "\000a\000l\000r\000e\000a\000d\000y\000 \000o\000p\000e\000n";
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Set command based on HW type
 | 
						|
    #   mkvterm -id lparid -m cecmtms
 | 
						|
    ##########################################
 | 
						|
    my $cmd = sprintf($mkvt{$hwtype}, $lparid, $mtms);
 | 
						|
    if ($type ne "lpar") {
 | 
						|
        return ([ RC_ERROR, "Command not supported on '$type'" ]);
 | 
						|
    }
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Close the old sessions
 | 
						|
    ##########################################
 | 
						|
    if ($hwtype eq "ivm") {
 | 
						|
        rmvterm($exp, $lparid, $mtms);
 | 
						|
        sleep 1;
 | 
						|
    } else {
 | 
						|
        rmvterm_noforce($exp, $lparid, $mtms);
 | 
						|
        sleep 1;
 | 
						|
    }
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Send command
 | 
						|
    ##########################################
 | 
						|
    $ssh->clear_accum();
 | 
						|
    $ssh->send("$cmd\r");
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Expect result
 | 
						|
    ##########################################
 | 
						|
    my @result = $ssh->expect($timeout,
 | 
						|
        [ "$hmc_open|$hmc_open2|$ivm_open|$fail_msg",
 | 
						|
            sub {
 | 
						|
                $failed = 1;
 | 
						|
              } ]
 | 
						|
    );
 | 
						|
 | 
						|
    if ($failed) {
 | 
						|
        $ssh->hard_close();
 | 
						|
        if (grep(/$fail_msg/, @result)) {
 | 
						|
            return ([ RC_ERROR, "mkvterm returns the unsuccessful value, please check your entry and retry the command." ]);
 | 
						|
        } else {
 | 
						|
            return ([ RC_ERROR, "Virtual terminal is already connected" ]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Success...
 | 
						|
    # Give control to the user and intercept
 | 
						|
    # the Ctrl-X (\030).
 | 
						|
    ##########################################
 | 
						|
    my $escape = "\030";
 | 
						|
    $ssh->send("\r");
 | 
						|
    $ssh->interact(\*STDIN, $escape);
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Close session
 | 
						|
    ##########################################
 | 
						|
    rmvterm($exp, $lparid, $mtms);
 | 
						|
    $ssh->hard_close();
 | 
						|
 | 
						|
    return ([ SUCCESS, "Success" ]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Force close a virtual terminal session
 | 
						|
##########################################################################
 | 
						|
sub rmvterm {
 | 
						|
 | 
						|
    my $exp    = shift;
 | 
						|
    my $lparid = shift;
 | 
						|
    my $mtms   = shift;
 | 
						|
    my $ssh    = @$exp[0];
 | 
						|
    my $hwtype = @$exp[2];
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Format command based on HW Type
 | 
						|
    #####################################
 | 
						|
    my %rmvt = (
 | 
						|
        hmc => "rmvterm --id %s -m %s",
 | 
						|
        ivm => "rmvt -id %s"
 | 
						|
    );
 | 
						|
    #####################################
 | 
						|
    # Set command based on HW type
 | 
						|
    #   rmvt(erm) -id lparid -m cecmtms
 | 
						|
    #####################################
 | 
						|
    my $cmd = sprintf($rmvt{$hwtype}, $lparid, $mtms);
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Send command
 | 
						|
    #####################################
 | 
						|
    $ssh->clear_accum();
 | 
						|
    $ssh->send("$cmd\r");
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Force close a virtual terminal session
 | 
						|
##########################################################################
 | 
						|
sub rmvterm_noforce {
 | 
						|
 | 
						|
    my $exp    = shift;
 | 
						|
    my $lparid = shift;
 | 
						|
    my $mtms   = shift;
 | 
						|
    my $ssh    = @$exp[0];
 | 
						|
    my $hwtype = @$exp[2];
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Format command based on HW Type
 | 
						|
    #####################################
 | 
						|
    my %rmvt = (
 | 
						|
        hmc => "rmvterm --id %s -m %s",
 | 
						|
        ivm => "rmvt -id %s"
 | 
						|
    );
 | 
						|
    #####################################
 | 
						|
    # Set command based on HW type
 | 
						|
    #   rmvt(erm) -id lparid -m cecmtms
 | 
						|
    #####################################
 | 
						|
    my $cmd = sprintf($rmvt{$hwtype}, $lparid, $mtms);
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Send command
 | 
						|
    #####################################
 | 
						|
    send_cmd($exp, $cmd);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Lists the hardware resources of a managed system
 | 
						|
##########################################################################
 | 
						|
sub lshwres {
 | 
						|
 | 
						|
    my $exp      = shift;
 | 
						|
    my $d        = shift;
 | 
						|
    my $mtms     = shift;
 | 
						|
    my $cmd      = "lshwres -r @$d[1] -m $mtms";
 | 
						|
    my $level    = @$d[0];
 | 
						|
    my $Filter   = @$d[2];
 | 
						|
    my $rsubtype = @$d[3];
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Specify Filters
 | 
						|
    #####################################
 | 
						|
    if ($Filter) {
 | 
						|
        $cmd .= " -F $Filter";
 | 
						|
    }
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # level may be "sys" or "lpar"
 | 
						|
    #####################################
 | 
						|
    if (defined($level)) {
 | 
						|
        $cmd .= " --level $level";
 | 
						|
    }
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Specify subtype
 | 
						|
    #####################################
 | 
						|
    if ($rsubtype) {
 | 
						|
        $cmd .= " --rsubtype $rsubtype"
 | 
						|
    }
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Send command
 | 
						|
    #####################################
 | 
						|
    my $result = send_cmd($exp, $cmd);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Retrieve MAC-address from network adapter or network boots an LPAR
 | 
						|
##########################################################################
 | 
						|
sub lpar_netboot {
 | 
						|
 | 
						|
    my $exp     = shift;
 | 
						|
    my $verbose = shift;
 | 
						|
    my $name    = shift;
 | 
						|
    my $d       = shift;
 | 
						|
    my $opt     = shift;
 | 
						|
    my $timeout = my $t = @$exp[7] * 10;
 | 
						|
    my $cmd     = "lpar_netboot -t ent -f";
 | 
						|
    my $gateway = $opt->{G};
 | 
						|
    my $node    = @$d[6];
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Power6 HMCs (V7) do not support
 | 
						|
    # 0.0.0.0 gateway.
 | 
						|
    #####################################
 | 
						|
    if ($gateway =~ /^0.0.0.0$/) {
 | 
						|
        my $fw = lshmc($exp, "RM");
 | 
						|
        my $Rc = shift(@$fw);
 | 
						|
 | 
						|
        if ($Rc == SUCCESS) {
 | 
						|
            if (@$fw[0] =~ /^V(\d+)/) {
 | 
						|
                #########################
 | 
						|
                # Power4 not supported
 | 
						|
                #########################
 | 
						|
                if ($1 < 6) {
 | 
						|
                    return ([ RC_ERROR, "Command not supported on V$1 HMC" ]);
 | 
						|
                }
 | 
						|
                #########################
 | 
						|
                # Use server for gateway
 | 
						|
                #########################
 | 
						|
                elsif ($1 >= 7) {
 | 
						|
                    $opt->{G} = $opt->{S};
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Verbose output
 | 
						|
    #####################################
 | 
						|
    if ($verbose) {
 | 
						|
        $cmd .= " -x -v";
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Force LPAR shutdown if -f specified
 | 
						|
    #####################################
 | 
						|
    if (exists($opt->{f})) {
 | 
						|
        $cmd .= " -i";
 | 
						|
    } else {
 | 
						|
        #################################
 | 
						|
        # Force LPAR shutdown if LPAR is
 | 
						|
        # running Linux
 | 
						|
        #################################
 | 
						|
        my $table         = "nodetype";
 | 
						|
        my $intable       = 0;
 | 
						|
        my @TableRowArray = xCAT::DBobjUtils->getDBtable($table);
 | 
						|
        if (@TableRowArray) {
 | 
						|
            foreach (@TableRowArray) {
 | 
						|
                my @nodelist = split(',', $_->{'node'});
 | 
						|
                my @oslist   = split(',', $_->{'os'});
 | 
						|
                my $osname   = "AIX";
 | 
						|
                if (grep(/^$node$/, @nodelist)) {
 | 
						|
                    if (!grep(/^$osname$/, @oslist)) {
 | 
						|
                        $cmd .= " -i";
 | 
						|
                    }
 | 
						|
                    $intable = 1;
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        #################################
 | 
						|
        # Force LPAR shutdown if LPAR OS
 | 
						|
        # type is not assigned in table
 | 
						|
        # but mnt node is running Linux
 | 
						|
        #################################
 | 
						|
        if (xCAT::Utils->isLinux() && $intable == 0) {
 | 
						|
            $cmd .= " -i";
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Get MAC-address or network boot
 | 
						|
    #####################################
 | 
						|
    my $mac = $opt->{m};
 | 
						|
    $cmd .= (defined($mac)) ? " -m $mac" : " -M -A -n";
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Command only supported on LPARs
 | 
						|
    #####################################
 | 
						|
    if (@$d[4] ne "lpar") {
 | 
						|
        return ([ RC_ERROR, "Command not supported on '@$d[4]'" ]);
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Network specified (-D ping test)
 | 
						|
    #####################################
 | 
						|
    if (exists($opt->{S})) {
 | 
						|
        my %nethash = xCAT::DBobjUtils->getNetwkInfo([$node]);
 | 
						|
        #####################################
 | 
						|
        # Network attributes undefined
 | 
						|
        #####################################
 | 
						|
        if (!%nethash) {
 | 
						|
            return ([ RC_ERROR, "Cannot get network information for $node" ]);
 | 
						|
        }
 | 
						|
        my $netmask = $nethash{$node}{mask};
 | 
						|
        $cmd .= (!defined($mac)) ? " -D" : "";
 | 
						|
        $cmd .= " -s auto -d auto -S $opt->{S} -G $opt->{G} -C $opt->{C} -K $netmask";
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Add lpar name, profile, CEC name
 | 
						|
    #####################################
 | 
						|
    $cmd .= " \"$name\" \"@$d[1]\" \"@$d[2]\"";
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Send command
 | 
						|
    #####################################
 | 
						|
 | 
						|
    my $result = send_cmd($exp, $cmd, $timeout);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# List Hardware Management Console configuration information
 | 
						|
##########################################################################
 | 
						|
sub lshmc {
 | 
						|
 | 
						|
    my $exp    = shift;
 | 
						|
    my $attr   = shift;
 | 
						|
    my $hwtype = @$exp[2];
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Format command based on HW Type
 | 
						|
    #####################################
 | 
						|
    my %cmd = (
 | 
						|
        hmc => "lshmc -v",
 | 
						|
        ivm => "lsivm"
 | 
						|
    );
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Send command
 | 
						|
    #####################################
 | 
						|
    my $result = send_cmd($exp, $cmd{$hwtype});
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Return error
 | 
						|
    #####################################
 | 
						|
    if (@$result[0] != SUCCESS) {
 | 
						|
        return ($result);
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Only return attribute requested
 | 
						|
    #####################################
 | 
						|
    if (defined($attr)) {
 | 
						|
        if (my ($vpd) = grep(/^\*$attr\s/, @$result)) {
 | 
						|
            $vpd =~ s/\*$attr\s+//;
 | 
						|
            return ([ SUCCESS, $vpd ]);
 | 
						|
        }
 | 
						|
        return ([ RC_ERROR, "'$attr' not found" ]);
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # IVM returns:
 | 
						|
    #   9133-55A,10B7D1G,1
 | 
						|
    #
 | 
						|
    # HMC returns:
 | 
						|
    #   "vpd=*FC ????????
 | 
						|
    #   *VC 20.0
 | 
						|
    #   *N2 Mon Sep 24 13:54:00 GMT 2007
 | 
						|
    #   *FC ????????
 | 
						|
    #   *DS Hardware Management Console
 | 
						|
    #   *TM 7310-CR4
 | 
						|
    #   *SE 1017E6B
 | 
						|
    #   *MN IBM
 | 
						|
    #   *PN Unknown
 | 
						|
    #   *SZ 1058721792
 | 
						|
    #   *OS Embedded Operating Systems
 | 
						|
    #   *NA 9.114.222.111
 | 
						|
    #   *FC ????????
 | 
						|
    #   *DS Platform Firmware
 | 
						|
    #   *RM V7R3.1.0.1
 | 
						|
    #####################################
 | 
						|
    if ($hwtype eq "ivm") {
 | 
						|
        my ($model, $serial, $lparid) = split /,/, @$result[1];
 | 
						|
        return ([ SUCCESS, "$model,$serial" ]);
 | 
						|
    }
 | 
						|
    my @values;
 | 
						|
    my $vpd = join(",", @$result);
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Power4 (and below) HMCs unsupported
 | 
						|
    #####################################
 | 
						|
    if ($vpd =~ /\*RM V(\d+)/) {
 | 
						|
        if ($1 <= 5) {
 | 
						|
            return ([ RC_ERROR, "Command not supported on V$1 HMC" ]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Type-Model may be in the formats:
 | 
						|
    #  "eserver xSeries 336 -[7310CR3]-"
 | 
						|
    #  "7310-CR4"
 | 
						|
    #####################################
 | 
						|
    if ($vpd =~ /\*TM ([^,]+)/) {
 | 
						|
        my $temp = $1;
 | 
						|
        my $model = ($temp =~ /\[(.*)\]/) ? $1 : $temp;
 | 
						|
        push @values, $model;
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Serial number
 | 
						|
    #####################################
 | 
						|
    if ($vpd =~ /\*SE ([^,]+)/) {
 | 
						|
        push @values, $1;
 | 
						|
    }
 | 
						|
    return ([ SUCCESS, join(",", @values) ]);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Updates authorized_keys2 file on the HMC/IVM
 | 
						|
##########################################################################
 | 
						|
sub mkauthkeys {
 | 
						|
 | 
						|
    my $exp    = shift;
 | 
						|
    my $option = shift;
 | 
						|
    my $logon  = shift;
 | 
						|
    my $sshkey = shift;
 | 
						|
    my $ssh    = @$exp[0];
 | 
						|
    my $hwtype = @$exp[2];
 | 
						|
    my $userid = @$exp[4];
 | 
						|
 | 
						|
    #########################################
 | 
						|
    # On IVM-based systems, the mkauthkeys
 | 
						|
    # command does not exist, so we have to
 | 
						|
    # include the generated key at
 | 
						|
    # /home/<userid>/.ssh/authorized_keys2
 | 
						|
    # manually.
 | 
						|
    #########################################
 | 
						|
    if ($hwtype =~ /^ivm$/) {
 | 
						|
        my @authkey;
 | 
						|
        my $auth   = "/home/$userid/.ssh/authorized_keys2";
 | 
						|
        my $result = send_cmd($exp, "cat $auth");
 | 
						|
        my $Rc     = shift(@$result);
 | 
						|
 | 
						|
        #####################################
 | 
						|
        # Return error
 | 
						|
        #####################################
 | 
						|
        if ($Rc != SUCCESS) {
 | 
						|
            return ($result);
 | 
						|
        }
 | 
						|
        #####################################
 | 
						|
        # When adding, remove old keys first
 | 
						|
        #####################################
 | 
						|
        foreach (@$result) {
 | 
						|
            unless (/$logon$/) {
 | 
						|
                push @authkey, $_;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        #####################################
 | 
						|
        # Add new key
 | 
						|
        #####################################
 | 
						|
        if ($option =~ /^enable$/i) {
 | 
						|
            push @authkey, $sshkey;
 | 
						|
        }
 | 
						|
        #####################################
 | 
						|
        # Rewrite the key file
 | 
						|
        #####################################
 | 
						|
        my $keys = join("\n", @authkey);
 | 
						|
        $result = send_cmd($exp, "echo \"$keys\" | tee $auth");
 | 
						|
        return ($result);
 | 
						|
    }
 | 
						|
    #########################################
 | 
						|
    # When adding, remove old keys first
 | 
						|
    #########################################
 | 
						|
    my $result = send_cmd($exp, "mkauthkeys --remove '$logon'");
 | 
						|
 | 
						|
    if ($option =~ /^enable$/i) {
 | 
						|
        $result = send_cmd($exp, "mkauthkeys --add '$sshkey'");
 | 
						|
    }
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# List Licensed Internal Code levels on HMC for FSP/BPAs
 | 
						|
##########################################################################
 | 
						|
sub lslic {
 | 
						|
 | 
						|
    my $exp     = shift;
 | 
						|
    my $d       = shift;
 | 
						|
    my $timeout = shift;
 | 
						|
    my $cmd     = "lslic ";
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Use timeout from site table (if defined)
 | 
						|
    ##########################################
 | 
						|
    if (!defined($timeout) || $timeout == 0) {
 | 
						|
        $timeout = @$exp[7] * 3;
 | 
						|
    }
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Command only support on CEC/BPAs
 | 
						|
    #####################################
 | 
						|
    if (@$d[4] !~ /^(fsp|bpa)$/) {
 | 
						|
        return ([ RC_ERROR, "Command not supported on '@$d[4]'" ]);
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # Format command based on name
 | 
						|
    #####################################
 | 
						|
    $cmd .= (@$d[4] =~ /^fsp$/) ? "-t sys -m " : "-t power -e ";
 | 
						|
    $cmd .= @$d[2];
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Send command
 | 
						|
    #####################################
 | 
						|
    my $result = send_cmd($exp, $cmd, $timeout);
 | 
						|
    return ($result);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Sends command and waits for response
 | 
						|
##########################################################################
 | 
						|
sub send_cmd {
 | 
						|
 | 
						|
    my $exp     = shift;
 | 
						|
    my $cmd     = shift;
 | 
						|
    my $timeout = shift;
 | 
						|
    my $ssh     = @$exp[0];
 | 
						|
    my $prompt  = @$exp[1];
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Use timeout from site table (if defined)
 | 
						|
    ##########################################
 | 
						|
    if (!defined($timeout)) {
 | 
						|
        $timeout = @$exp[7];
 | 
						|
    }
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Send command
 | 
						|
    ##########################################
 | 
						|
    $ssh->clear_accum();
 | 
						|
    $ssh->send("$cmd; echo Rc=\$\?\r");
 | 
						|
    ##########################################
 | 
						|
    # The first element is the number of the
 | 
						|
    # pattern or string that matched, the
 | 
						|
    # same as its return value in scalar
 | 
						|
    # context. The second argument is a
 | 
						|
    # string indicating why expect returned.
 | 
						|
    # If there were no error, the second
 | 
						|
    # argument will be undef. Possible errors
 | 
						|
    # are 1:TIMEOUT, 2:EOF, 3:spawn id(...)died,
 | 
						|
    # and "4:..." (see Expect (3) manpage for
 | 
						|
    # the precise meaning of these messages)
 | 
						|
    # The third argument of expects return list
 | 
						|
    # is the string matched. The fourth argument
 | 
						|
    # is text before the match, and the fifth
 | 
						|
    # argument is text after the match.
 | 
						|
    ##########################################
 | 
						|
    my @result = $ssh->expect($timeout, "-re", "(.*$prompt)");
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Expect error
 | 
						|
    ##########################################
 | 
						|
    if (defined($result[1])) {
 | 
						|
        return ([ EXPECT_ERROR, expect_error(@result) ]);
 | 
						|
    }
 | 
						|
    ##########################################
 | 
						|
    # Extract error code
 | 
						|
    ##########################################
 | 
						|
    if ($result[3] =~ s/Rc=([0-9])+\r\n//) {
 | 
						|
        if ($1 != 0) {
 | 
						|
            if ($cmd =~ "lssyscfg -r frame -F") {
 | 
						|
                # On HMC V10 the "lssyscfg -r frame -F" command returns error,
 | 
						|
                # ON HMC V9 the same command returns "No results were found"
 | 
						|
                # Try to catch that command here and return 
 | 
						|
                # "No results were found" like we would on V9
 | 
						|
                return ([ NR_ERROR, "No results were found" ]);
 | 
						|
            } else {
 | 
						|
                return ([ RC_ERROR, $result[3] ]);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    ##########################################
 | 
						|
    # No data found - return error
 | 
						|
    ##########################################
 | 
						|
    if ($result[3] =~ /No results were found/) {
 | 
						|
        return ([ NR_ERROR, "No results were found" ]);
 | 
						|
    }
 | 
						|
    ##########################################
 | 
						|
    # If no command output, return "Success"
 | 
						|
    ##########################################
 | 
						|
    if (length($result[3]) == 0) {
 | 
						|
        $result[3] = "Success";
 | 
						|
    }
 | 
						|
    ##########################################
 | 
						|
    # Success
 | 
						|
    ##########################################
 | 
						|
    my @values = (SUCCESS);
 | 
						|
    push @values, split /\r\n/, $result[3];
 | 
						|
    return (\@values);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Return Expect error
 | 
						|
##########################################################################
 | 
						|
sub expect_error {
 | 
						|
 | 
						|
    my @error = @_;
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # The first element is the number of the
 | 
						|
    # pattern or string that matched, the
 | 
						|
    # same as its return value in scalar
 | 
						|
    # context. The second argument is a
 | 
						|
    # string indicating why expect returned.
 | 
						|
    # If there were no error, the second
 | 
						|
    # argument will be undef. Possible errors
 | 
						|
    # are 1:TIMEOUT, 2:EOF, 3:spawn id(...)died,
 | 
						|
    # and "4:..." (see Expect (3) manpage for
 | 
						|
    # the precise meaning of these messages)
 | 
						|
    # The third argument of expects return list
 | 
						|
    # is the string matched. The fourth argument
 | 
						|
    # is text before the match, and the fifth
 | 
						|
    # argument is text after the match.
 | 
						|
    ##########################################
 | 
						|
    if ($error[1] eq "1:TIMEOUT") {
 | 
						|
        return ("Timeout waiting for prompt");
 | 
						|
    }
 | 
						|
    if ($error[1] eq "2:EOF") {
 | 
						|
        if ($error[3]) {
 | 
						|
            return ($error[3]);
 | 
						|
        }
 | 
						|
        return ("ssh connection terminated unexpectedly");
 | 
						|
    }
 | 
						|
    return ("Logon failed");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Returns built command based on CEC/LPAR action
 | 
						|
##########################################################################
 | 
						|
sub power_cmd {
 | 
						|
 | 
						|
    my $op = shift;
 | 
						|
    my $d  = shift;
 | 
						|
 | 
						|
    #my $type = (@$d[4] eq "fsp") ? "sys" : @$d[4];
 | 
						|
    my $type = (@$d[4] =~ /^(fsp|cec)$/) ? "sys" : @$d[4];
 | 
						|
 | 
						|
    ##############################
 | 
						|
    # Build command
 | 
						|
    ##############################
 | 
						|
    my $cmd = $powercmd{$type}{$op};
 | 
						|
 | 
						|
    if (defined($cmd)) {
 | 
						|
        return (sprintf($cmd, $type, @$d[2], @$d[0], @$d[1]));
 | 
						|
    }
 | 
						|
    ##############################
 | 
						|
    # Command not supported
 | 
						|
    ##############################
 | 
						|
    return undef;
 | 
						|
}
 | 
						|
 | 
						|
#####################################
 | 
						|
# Reset HMC network (hostname & IP)
 | 
						|
#####################################
 | 
						|
sub network_reset {
 | 
						|
 | 
						|
    my $exp         = shift;
 | 
						|
    my $current_ip  = shift;
 | 
						|
    my $hostname_ip = shift;
 | 
						|
    my $hwtype      = @$exp[2];
 | 
						|
 | 
						|
    my ($ip, $hostname) = split /,/, $hostname_ip;
 | 
						|
    if (!$hostname || !$ip)
 | 
						|
    {
 | 
						|
        return ([ RC_ERROR, "No valid hostname or IP find. This could be a internal bug of xCAT." ]);
 | 
						|
    }
 | 
						|
#####################################
 | 
						|
    # Format command based on HW Type
 | 
						|
#####################################
 | 
						|
    my %cmd = (
 | 
						|
        hmc => "lshmc -n -F hostname:ipaddr",
 | 
						|
        ivm => "lsivm"                          #just for future consideration
 | 
						|
    );
 | 
						|
 | 
						|
#####################################
 | 
						|
    # Get current hostname and IP
 | 
						|
#####################################
 | 
						|
    my $result = send_cmd($exp, $cmd{$hwtype});
 | 
						|
    if (@$result[0] != SUCCESS) {
 | 
						|
        return ($result);
 | 
						|
    }
 | 
						|
    my ($current_hostname, $current_all_ip) = split /:/, @$result[1];
 | 
						|
 | 
						|
#####################################
 | 
						|
    # Find the correct interface
 | 
						|
#####################################
 | 
						|
    my @eth_ip = split /,/, $current_all_ip;
 | 
						|
    my $i;
 | 
						|
    my $matched = 0;
 | 
						|
    for ($i = 0 ; $i < scalar(@eth_ip) ; $i++)
 | 
						|
    {
 | 
						|
        if ($eth_ip[$i] eq $current_ip)
 | 
						|
        {
 | 
						|
            $matched = 1;
 | 
						|
            last;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (!$matched)
 | 
						|
    {
 | 
						|
        # What's happen?
 | 
						|
        return ([ RC_ERROR, "No appropriate IP addresses to be updated. This could be a internal bug of xCAT." ]);
 | 
						|
    }
 | 
						|
 | 
						|
    %cmd = (
 | 
						|
 | 
						|
        # probably need update netmask also
 | 
						|
        hmc => "chhmc -c network  -s modify -h $hostname -i eth$i -a $ip",
 | 
						|
        ivm => "nothing"
 | 
						|
    );
 | 
						|
    $result = send_cmd($exp, $cmd{$hwtype});
 | 
						|
#####################################
 | 
						|
    # Return error
 | 
						|
#####################################
 | 
						|
    return ($result);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# List connection for CEC/BPA
 | 
						|
##########################################################################
 | 
						|
sub lssysconn
 | 
						|
{
 | 
						|
    my $exp    = shift;
 | 
						|
    my $res    = shift;
 | 
						|
    my $filter = shift;
 | 
						|
    my $cmd    = sprintf($lssysconn{$res}, $filter);
 | 
						|
    my $result = send_cmd($exp, $cmd);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Create connection for CEC/BPA
 | 
						|
##########################################################################
 | 
						|
sub mksysconn
 | 
						|
{
 | 
						|
    my $exp    = shift;
 | 
						|
    my $ip     = shift;
 | 
						|
    my $type   = shift;
 | 
						|
    my $passwd = shift;
 | 
						|
 | 
						|
    my $cmd = sprintf($mksysconn{$type}, $ip, $passwd);
 | 
						|
    my $result = send_cmd($exp, $cmd);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Change IP address for managed systems or frames
 | 
						|
##########################################################################
 | 
						|
sub chsyspwd
 | 
						|
{
 | 
						|
    my $exp    = shift;
 | 
						|
    my $user   = shift;
 | 
						|
    my $type   = shift;
 | 
						|
    my $mtms   = shift;
 | 
						|
    my $passwd = shift;
 | 
						|
    my $newpwd = shift;
 | 
						|
 | 
						|
    my $cmd = sprintf($chsyspwd{$type}, $user, $mtms, $passwd, $newpwd);
 | 
						|
    my $result = send_cmd($exp, $cmd);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Remove connection for CEC/BPA
 | 
						|
##########################################################################
 | 
						|
sub rmsysconn
 | 
						|
{
 | 
						|
    my $exp  = shift;
 | 
						|
    my $type = shift;
 | 
						|
    my $name = shift;
 | 
						|
 | 
						|
    my $cmd = sprintf($rmsysconn{$type}, $name);
 | 
						|
    my $result = send_cmd($exp, $cmd);
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
##########################################################################
 | 
						|
# Get FSP/BPA IP address for the redundancy FSP/BPA from HMC
 | 
						|
##########################################################################
 | 
						|
sub getHMCcontrolIP
 | 
						|
{
 | 
						|
    my $node = shift;
 | 
						|
 | 
						|
    if (($node) && ($node =~ /xCAT::/))
 | 
						|
    {
 | 
						|
        $node = shift;
 | 
						|
    }
 | 
						|
    my $exp = shift;
 | 
						|
 | 
						|
    #get node type first
 | 
						|
    my $type = xCAT::DBobjUtils::getnodetype($node, "ppc");
 | 
						|
    unless ($type)
 | 
						|
    {
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    #get node ip from hmc
 | 
						|
    my $tab = xCAT::Table->new("vpd");
 | 
						|
    my $ent;
 | 
						|
    if ($tab) {
 | 
						|
        $ent = $tab->getNodeAttribs($node, [ 'serial', 'mtm' ]);
 | 
						|
    }
 | 
						|
    my $serial = $ent->{'serial'};
 | 
						|
    my $mtm    = $ent->{'mtm'};
 | 
						|
 | 
						|
    #my $mtms = $mtm . '*' . $serial;
 | 
						|
    #my $nodes_found = lssyscfg( $exp, "$type", "$mtms");
 | 
						|
    my $nodes_found = lssysconn($exp, "all");
 | 
						|
    my @ips;
 | 
						|
    my $ip_result;
 | 
						|
    if (@$nodes_found[0] eq SUCCESS) {
 | 
						|
        my $Rc = shift(@$nodes_found);
 | 
						|
 | 
						|
        #my @newnodes = split(/,/, $nodes_found->[0]);
 | 
						|
        #$Rc = shift(@newnodes);
 | 
						|
        #for my $entry (@newnodes) {
 | 
						|
        #    if(xCAT::NetworkUtils->isIpaddr($entry)) {
 | 
						|
        #        push @ips,$entry;
 | 
						|
        #    }
 | 
						|
        #    $ip_result = join( ",", @ips );
 | 
						|
        #}
 | 
						|
        foreach my $entry (@$nodes_found) {
 | 
						|
            if ($entry =~ /$mtm\*$serial/) {
 | 
						|
                $entry =~ /ipaddr=(\d+\.\d+\.\d+\.\d+),/;
 | 
						|
                push @ips, $1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $ip_result = join(",", @ips);
 | 
						|
    }
 | 
						|
    return $ip_result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
1;
 | 
						|
 |