mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 03:12:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			243 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env perl
 | |
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | |
| use Fcntl qw(:DEFAULT :flock);
 | |
| 
 | |
| sub get_lock {
 | |
|     unless (flock(LOCKHANDLE, LOCK_EX | LOCK_NB)) {
 | |
|         $| = 1;
 | |
|         print "Acquiring startup lock...";
 | |
|         flock(LOCKHANDLE, LOCK_EX) or die "Error trying to secure a startup lock";
 | |
|         print "done\n";
 | |
|     }
 | |
|     truncate(LOCKHANDLE, 0);
 | |
|     print LOCKHANDLE $$ . "\n";
 | |
| }
 | |
| 
 | |
| sub release_lock {
 | |
|     truncate(LOCKHANDLE, 0);
 | |
|     flock(LOCKHANDLE, LOCK_UN);
 | |
| }
 | |
| 
 | |
| BEGIN
 | |
| {
 | |
|     use Time::HiRes qw(sleep);
 | |
|     use File::Path;
 | |
|     use Fcntl qw(:DEFAULT :flock);
 | |
|     $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | |
|     umask 0077;
 | |
|     mkpath("/tmp/xcat/");
 | |
|     unless (sysopen(LOCKHANDLE, "/tmp/xcat/consolelock", O_WRONLY | O_CREAT)) {
 | |
|         sleep 15;
 | |
|         print "Unable to open lock file";
 | |
|         exit 0;
 | |
|     }
 | |
|     get_lock();
 | |
| }
 | |
| my $sleepint = int(rand(10));
 | |
| use lib "$::XCATROOT/lib/perl";
 | |
| require xCAT::Client;
 | |
| require xCAT::Utils;
 | |
| use strict;
 | |
| use Expect;
 | |
| 
 | |
| require File::Basename;
 | |
| import File::Basename;
 | |
| my $scriptname = $0;
 | |
| 
 | |
| ##############################################
 | |
| # Globals
 | |
| ##############################################
 | |
| my $verbose = 0;
 | |
| my $node;
 | |
| my $ips;
 | |
| my $id;
 | |
| my $hwtype;
 | |
| 
 | |
| ##########################################################################
 | |
| # Open remote console
 | |
| ##########################################################################
 | |
| sub invoke_cmd {
 | |
|     my $node   = shift;
 | |
|     my $fsp_ip = shift;
 | |
|     my $id     = shift;
 | |
|     my $hwtype = shift;
 | |
|     my $machine;
 | |
|     if ($hwtype eq 'blade') {
 | |
|         $machine = "BLADE";
 | |
|     } else {
 | |
|         $machine = "CEC";
 | |
|     }
 | |
|     #use xcatd to get the attribute $fsp_name and $id of the node.
 | |
|     my $fsp_api = ($::XCATROOT) ? "$::XCATROOT/sbin/fsp-api" : "/opt/xcat/sbin/fsp-api";
 | |
|     my $action = "console";
 | |
|     my $type   = "0";
 | |
|     my $Rc = 0;
 | |
|     my $power_state_cmd = "$fsp_api -a cec_state -t $type:$fsp_ip:$id:$node: 2>&1";
 | |
|     my $res;
 | |
|     my $index     = 0;
 | |
|     my $pre_state = undef;
 | |
| 
 | |
|     my $ipl_num = 0;
 | |
|     while (1) {
 | |
|         $res = xCAT::Utils->runcmd($power_state_cmd, -1);
 | |
|         if ($res =~ /(operating|standby)$/) {
 | |
|             print "\n";
 | |
|             last;
 | |
|         } elsif ($res =~ /(power off)$/) {
 | |
|             if (!$pre_state or ($pre_state ne $1)) {
 | |
|                 $pre_state = $1;
 | |
|                 print "\nDestination $machine is in POWER OFF state, Please power it on and wait.";
 | |
|                 sleep 5;
 | |
|             } else {
 | |
|                 print ".";
 | |
|                 sleep 30;
 | |
|             }
 | |
|         } elsif (($res =~ /(power-on-transition)$/) or ($pre_state eq "power off" and $res =~ /$node :\s([.*])/)) {
 | |
|             if (!$pre_state or ($pre_state ne $1)) {
 | |
|                 $pre_state = $1;
 | |
|                 $index++;
 | |
|                 print "\nDestination $machine is POWERING ON, please wait.";
 | |
|                 sleep 5;
 | |
|             } else {
 | |
|                 print ".";
 | |
|                 sleep 30;
 | |
|             }
 | |
|         } elsif ($res =~ /(power-off-transition)$/) {
 | |
|             if (!$pre_state or ($pre_state ne $1)) {
 | |
|                 $pre_state = $1;
 | |
|                 print "\nDestination $machine is POWERING OFF.";
 | |
|                 sleep 20;
 | |
|             } else {
 | |
|                 print ".";
 | |
|                 sleep 5;
 | |
|                 next;
 | |
|             }
 | |
|         } elsif ($res =~ /(IPL-in-process)$/) {
 | |
|             if (!$pre_state) {
 | |
|                 $pre_state = $1;
 | |
|                 sleep 10;
 | |
|                 next;
 | |
|             } elsif ($pre_state and ($pre_state eq $1) and !$index) {
 | |
|                 print "\nDestination $machine is POWERING ON, please wait.";
 | |
|                 $index++;
 | |
|             } else {
 | |
| 
 | |
|                 #print "\r\n====>pre_state=$pre_state\n";
 | |
|                 $ipl_num++;
 | |
|                 $pre_state = $1;
 | |
|                 if ($ipl_num == 4) {
 | |
|                     print ".";
 | |
|                     $ipl_num = 0;
 | |
|                 }
 | |
|             }
 | |
|             sleep 5;
 | |
|         } else {
 | |
|             $pre_state = $res;
 | |
|             sleep 20;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     my $cmd = "$fsp_api -a $action -t $type:$fsp_ip:$id:$node:\r";
 | |
|     my $running_failed_code = "Reason code: 0x1000000";
 | |
|     my $fsp_standby_msg     = "Reason code: 0x1300";
 | |
|     my $fsp_lock_msg        = "Reason code: 0x1f00";
 | |
|     my $timeout             = 30;
 | |
|     my $failed              = 0;
 | |
|     my $exp                 = new Expect;
 | |
|     $exp->log_stdout(1);
 | |
|     $exp->spawn($cmd) or die "Can't spawn $cmd\r\n";
 | |
| 
 | |
|     my @result = $exp->expect($timeout,
 | |
|         [ "$running_failed_code",
 | |
|             sub {
 | |
|                 $failed = 1;
 | |
|               } ],
 | |
|         [ "$fsp_standby_msg",
 | |
|             sub {
 | |
|                 $failed = 2;
 | |
| 
 | |
|               } ],
 | |
|         [ "$fsp_lock_msg",
 | |
|             sub {
 | |
|                 $failed = 3;
 | |
|               } ]
 | |
|     );
 | |
|     if ($failed == 1) {
 | |
|         $exp->hard_close();
 | |
|         return ("Virtual terminal is already connected");
 | |
| 
 | |
|     }
 | |
|     if ($failed == 2) {
 | |
|         $exp->hard_close();
 | |
|         return ("Failed to open the console. Please check the related FSP's status");
 | |
| 
 | |
|     }
 | |
|     if ($failed == 3) {
 | |
|         my $link_cmd = "$fsp_api -a fsp_reconnect -t $type:$fsp_ip:$id:$node: 2>&1";
 | |
|         xCAT::Utils->runcmd($link_cmd, -1);
 | |
|         print "The connection is resetting, please wait.";
 | |
|         my $link_state = "";
 | |
|         my $rs_num     = 0;
 | |
|         while (!$link_state or $link_state !~ /state=LINE UP/i) {
 | |
|             sleep 2;
 | |
|             $rs_num++;
 | |
|             $link_cmd = "$fsp_api -a query_connection -t $type:$fsp_ip:$id:$node: 2>&1";
 | |
|             $link_state = xCAT::Utils->runcmd($link_cmd, -1);
 | |
|             if ($rs_num == 5) {
 | |
|                 print ".";
 | |
|                 $rs_num = 0;
 | |
|             }
 | |
|         }
 | |
|         print "\n";
 | |
|         $exp->hard_close();
 | |
|         return (0);
 | |
|     }
 | |
| 
 | |
|     my $escape = "\030";
 | |
|     $exp->send("\r");
 | |
|     $exp->interact(\*STDIN, $escape);
 | |
| 
 | |
|     $exp->hard_close();
 | |
| 
 | |
|     return (0);
 | |
| }
 | |
| 
 | |
| 
 | |
| ##############################################
 | |
| # Start main body of code
 | |
| ##############################################
 | |
| sub getans {
 | |
|     my $rsp = shift;
 | |
|     if ($rsp->{node}) {
 | |
|         $ips    = $rsp->{node}->[0]->{fsp_ip}->[0];
 | |
|         $id     = $rsp->{node}->[0]->{id}->[0];
 | |
|         $hwtype = $rsp->{node}->[0]->{type}->[0];
 | |
|     }
 | |
| }
 | |
| 
 | |
| my $cmdref = {
 | |
|     command   => ["getfspcon"],
 | |
|     arg       => ["text"],
 | |
|     noderange => [ $ARGV[0] ]
 | |
| };
 | |
| xCAT::Client::submit_request($cmdref, \&getans);
 | |
| until ($ips and $id) {
 | |
|     release_lock();    #Let other clients have a go
 | |
|     $sleepint = 10 + int(rand(20)); #Stagger to minimize lock collisions, but no big deal when it does happen
 | |
|     print "Console not ready, retrying in $sleepint seconds (Hit Ctrl-E,c,o to skip delay)\n";
 | |
|     sleep $sleepint;
 | |
|     get_lock();
 | |
|     xCAT::Client::submit_request($cmdref, \&getans);
 | |
| }
 | |
| release_lock();                     #done with xcatd, can run with near impunity
 | |
| 
 | |
| $node = $ARGV[0];
 | |
| 
 | |
| my $result = invoke_cmd($node, $ips, $id, $hwtype);
 | |
| if ($result ne "0") {
 | |
|     print STDERR "$node: $result\n";
 | |
|     exit(1);
 | |
| }
 | |
| exit(0);
 | |
| 
 |