mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 11:22:27 +00:00 
			
		
		
		
	git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@7001 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			385 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			385 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env perl
 | |
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | |
| BEGIN
 | |
| {
 | |
|     $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | |
| }
 | |
| use lib "$::XCATROOT/lib/perl";
 | |
| use strict;
 | |
| use Getopt::Long;
 | |
| use xCAT::Table;
 | |
| use xCAT::PPCdb;
 | |
| use Expect;
 | |
| use xCAT::DBobjUtils;
 | |
| use Data::Dumper;
 | |
| use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR);
 | |
| use xCAT::FSPUtils;
 | |
| 
 | |
| ##############################################
 | |
| # Globals
 | |
| ##############################################
 | |
| my $verbose = 0;
 | |
| my $node;
 | |
| 
 | |
| ##########################################
 | |
| # Database errors
 | |
| ##########################################
 | |
| my %errmsg = (
 | |
|   NODE_UNDEF =>"Node not defined in '%s' database",
 | |
|   NO_ATTR    =>"'%s' not defined in '%s' database",
 | |
|   DB_UNDEF   =>"'%s' database not defined"
 | |
| );
 | |
| 
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Parse the command line for options and operands
 | |
| ##########################################################################
 | |
| sub parse_args {
 | |
| 
 | |
|     my %opt = ();
 | |
|     my @VERSION = qw( 2.0 );
 | |
| 
 | |
|     #############################################
 | |
|     # Responds with usage statement
 | |
|     #############################################
 | |
|     local *usage = sub {
 | |
| 
 | |
|         my $cmd = __FILE__;
 | |
|         $cmd =~ s/.*([\w]{3}$)/$1/;
 | |
| 
 | |
|         if ( defined( $_[0] )) {
 | |
|             print STDERR "$_[0]\n";
 | |
|         }
 | |
|         my @msg = ( 
 | |
|             "$cmd -h|--help\n",
 | |
|             "$cmd -v|--version\n",
 | |
|             "$cmd singlenode [-V|-Verbose]\n" );
 | |
|         print STDERR @msg;
 | |
|     };
 | |
|     #############################################
 | |
|     # Process command-line arguments
 | |
|     #############################################
 | |
|     if ( !defined( @ARGV )) {
 | |
|         usage( "No node specified" );
 | |
|         return(1);
 | |
|     }
 | |
|     #############################################
 | |
|     # Checks case in GetOptions, allows opts
 | |
|     # to be grouped (e.g. -vx), and terminates
 | |
|     # at the first unrecognized option.
 | |
|     #############################################
 | |
|     $Getopt::Long::ignorecase = 0;
 | |
|     Getopt::Long::Configure( "bundling" );
 | |
| 
 | |
|     if ( !GetOptions( \%opt, qw(h|help V|Verbose v|version) )) {
 | |
|         usage();
 | |
|         return(1);
 | |
|     }
 | |
|     #######################################
 | |
|     # Option -h for Help
 | |
|     #######################################
 | |
|     if ( exists( $opt{h} )) {
 | |
|         usage();
 | |
|         return(1);
 | |
|     }
 | |
|     #######################################
 | |
|     # Option -v for version
 | |
|     #######################################
 | |
|     if ( exists( $opt{v} )) {
 | |
|         print STDERR \@VERSION;
 | |
|         return(1);
 | |
|     }
 | |
|     #######################################
 | |
|     # Option -V for verbose output
 | |
|     #######################################
 | |
|     if ( exists( $opt{V} )) {
 | |
|         $verbose = 1;
 | |
|     }
 | |
|     #######################################
 | |
|     # Check for "-" with no option
 | |
|     #######################################
 | |
|     if ( grep(/^-$/, @ARGV )) {
 | |
|         usage( "Missing option: -" );
 | |
|         return(1);
 | |
|     }
 | |
|     #######################################
 | |
|     # Get node
 | |
|     #######################################
 | |
|     if ( !defined( $ARGV[0] )) {
 | |
|         usage( "No node specified" );
 | |
|         return(1);
 | |
|     }
 | |
|     #######################################
 | |
|     # Check for extra argument
 | |
|     #######################################
 | |
|     $node = shift @ARGV;
 | |
|     if ( defined( $ARGV[0] )) {
 | |
|         usage( "Invalid Argument: $ARGV[0]" );
 | |
|         return(1);
 | |
|     }
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| ##########################################################################
 | |
| # Open remote console thourgh fsp
 | |
| ##########################################################################
 | |
| sub invoke_fsp {
 | |
|     my $fsp_name = shift;
 | |
|     my $id       = shift;
 | |
| 
 | |
|     my $fsp_api    = ($::XCATROOT) ? "$::XCATROOT/sbin/fsp-api" : "/opt/xcat/sbin/fsp-api";
 | |
|     my $action = "console";
 | |
|     my $type = "0";
 | |
|     my $fsp_ip = ();
 | |
|     my $Rc = 0;
 | |
|    
 | |
|     if( !(-e $fsp_api) && !(-x $fsp_api) ) {
 | |
|         return "please check the $fsp_api";
 | |
|     }
 | |
|    
 | |
|     $fsp_ip = xCAT::Utils::getNodeIPaddress( $fsp_name );
 | |
|     if(!defined($fsp_ip)) {
 | |
|         return "Failed to get the $fsp_name\'s ip";
 | |
|     }
 | |
| 	
 | |
|     my $cmd = "$fsp_api -a $action -t $type:$fsp_ip:$id:$node:\r";
 | |
| #    print "cmd: $cmd\n";
 | |
|     my $running_failed_code = "Reason code: 0x1000000";
 | |
|     my $fsp_standby_msg = "Reason code: 0x1300";
 | |
|     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";
 | |
|     #$exp->spawn( $cmd ) or return("Can't spawn $cmd)";
 | |
|    
 | |
|     my @result = $exp->expect( $timeout,
 | |
| 	       [ "$running_failed_code",
 | |
| 		  sub {
 | |
| 		  	$failed = 1;
 | |
| 		      } ],
 | |
| 		[ "$fsp_standby_msg",
 | |
| 	          sub {
 | |
| 			$failed = 2;
 | |
| 			 
 | |
| 		  }],
 | |
| 		[ "Session closed, back from open_vterm",
 | |
| 	          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) {
 | |
| 	 $exp->hard_close();
 | |
|          return("Failed to open the console. Please check the related FSP's IP");
 | |
|      
 | |
|      }
 | |
|    
 | |
|      
 | |
|     my $escape = "\030";
 | |
|     $exp->send( "\r" );
 | |
|     $exp->interact( \*STDIN, $escape );
 | |
|     
 | |
|     $exp->hard_close();    
 | |
|      
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Open remote console through hmc 
 | |
| ##########################################################################
 | |
| sub invoke_hmc {
 | |
|     my $host    = shift;
 | |
|     my $lparid  = shift;
 | |
|     my $parent  = shift;
 | |
|     my @attribs = qw(id parent hcp);
 | |
|     my %tabs    = ();
 | |
| 
 | |
|     ##################################
 | |
|     # Get node power type 
 | |
|     ##################################
 | |
|     my $hwtype = "hmc";
 | |
| 
 | |
|     ##################################
 | |
|     # Open databases needed
 | |
|     ##################################
 | |
|     my $vpdtab = xCAT::Table->new('vpd');
 | |
| 
 | |
|     if ( !$vpdtab ) {
 | |
|         return( sprintf( $errmsg{DB_UNDEF},'vpd' ));
 | |
|     }
 | |
|     
 | |
|     #################################
 | |
|     # Find MTMS in vpd database
 | |
|     #################################
 | |
|     my @attrs = qw(mtm serial);
 | |
|     my ($vpd) = $vpdtab->getNodeAttribs($parent, \@attrs );
 | |
| 
 | |
|     if ( !$vpd ) {
 | |
|         return( sprintf( $errmsg{NODE_UNDEF}, "vpd" ));
 | |
|     }
 | |
|     ################################
 | |
|     # Verify both vpd attributes
 | |
|     ################################
 | |
|     foreach ( @attrs ) {
 | |
|         if ( !exists( $vpd->{$_} )) {
 | |
|             return( sprintf( $errmsg{NO_ATTR}, $_, "vpd" ));
 | |
|         }
 | |
|     }
 | |
|     my $mtms   = "$vpd->{mtm}*$vpd->{serial}";
 | |
|     my $type   = "lpar";
 | |
| 
 | |
|     my %request = (
 | |
|         ppcretry => 1,
 | |
|         verbose  => $verbose
 | |
|     );
 | |
|     #################################
 | |
|     # Get userid and password 
 | |
|     #################################
 | |
|     my @cred = xCAT::PPCdb::credentials( $host, $hwtype );
 | |
|     $request{$host}{cred} = \@cred;
 | |
| 
 | |
|     #################################
 | |
|     # Connect to the remote server
 | |
|     #################################
 | |
|     my @exp = xCAT::PPCcli::connect( \%request, $hwtype, $host );
 | |
|     if ( ref($exp[0]) ne "Expect" ) {
 | |
|         return( $exp[0] );
 | |
|     }
 | |
|     #################################
 | |
|     # Open console connection 
 | |
|     #################################
 | |
|     my $result = xCAT::PPCcli::mkvterm( \@exp, $type, $lparid, $mtms );
 | |
|     my $Rc = shift(@$result);
 | |
| 
 | |
|     if ( $Rc != SUCCESS ) {
 | |
|         return( @$result[0] );
 | |
|     }
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| ##########################################################################
 | |
| # Open remote console 
 | |
| ##########################################################################
 | |
| sub invoke_cmd {
 | |
| 
 | |
|     my @attribs = qw(id parent hcp);
 | |
|     my %tabs    = ();
 | |
| 
 | |
|     ##################################
 | |
|     # Open databases needed
 | |
|     ##################################
 | |
|     foreach ( qw(ppc nodetype) ) {
 | |
|         $tabs{$_} = xCAT::Table->new($_);
 | |
| 
 | |
|         if ( !exists( $tabs{$_} )) {
 | |
|             return( sprintf( $errmsg{DB_UNDEF}, $_ ));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #################################
 | |
|     # Get node type
 | |
|     #################################
 | |
|     my ($ent) = $tabs{nodetype}->getNodeAttribs($node, ["nodetype"] );
 | |
|     if ( !defined( $ent )) {
 | |
|         return( sprintf( $errmsg{NODE_UNDEF}, "nodetype" ));
 | |
|     }
 | |
|     #################################
 | |
|     # Check for type
 | |
|     #################################
 | |
|     if ( !exists( $ent->{nodetype} )) {
 | |
|         return( sprintf( $errmsg{NO_ATTR}, $ent->{nodetype},"nodetype" ));
 | |
|     }
 | |
|     #################################
 | |
|     # Check for valid "type"
 | |
|     #################################
 | |
|     my @types = split /,/, $ent->{nodetype};
 | |
|     my ($type) = grep( /^(lpar|osi)$/, @types );
 | |
| 
 | |
|     if ( !defined( $type )) {
 | |
|         return( "Invalid node type: $ent->{nodetype}" );
 | |
|     }
 | |
| 
 | |
|     #################################
 | |
|     # Get attributes
 | |
|     #################################
 | |
|     my ($att) = $tabs{ppc}->getAttribs({'node'=>$node}, @attribs );
 | |
| 
 | |
|     if ( !defined( $att )) {
 | |
|         return( sprintf( $errmsg{NODE_UNDEF}, "ppc" ));
 | |
|     }
 | |
|     #################################
 | |
|     # Verify required attributes
 | |
|     #################################
 | |
|     foreach my $at ( @attribs ) {
 | |
|         if ( !exists( $att->{$at} )) {
 | |
|             return( sprintf( $errmsg{NO_ATTR}, $at, "ppc" ));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     my $id       = $att->{id};
 | |
|     my $parent   = $att->{parent};
 | |
|     my $hcps     = $att->{hcp};
 | |
|     my @hcp_list = split(",", $hcps);
 | |
|     my $cmd = ();
 | |
|     my $res;
 | |
|     my $Rc;
 | |
|     my $c = @hcp_list; 
 | |
|     foreach my $thishcp ( @hcp_list ) {
 | |
|         my $thishcp_type = xCAT::FSPUtils->getTypeOfNode($thishcp);
 | |
| 	if(!defined($thishcp_type)) {
 | |
|             next;
 | |
| 	}
 | |
|         if($thishcp_type =~ /^(fsp)$/) {
 | |
| 		$res = invoke_fsp($thishcp, $id);  
 | |
| 	} elsif ($thishcp_type =~ /^(hmc)$/) {
 | |
| 		$res = invoke_hmc($thishcp, $id, $parent);  
 | |
| 	} else {
 | |
|    	    return "Couldn't open the console. Please check this node's hcp. "; 
 | |
| 	}
 | |
| 
 | |
| 	if($res eq 0) {
 | |
| 	    return 0;	
 | |
| 	}
 | |
| 
 | |
|         ##############
 | |
| 	#Once once every hcp is tried, if the $res!=0, it will return -1;
 | |
| 	###############	
 | |
| 	$c--;
 | |
| 	if($c == 0) {
 | |
| 	    return -1;
 | |
| 	}
 | |
|     }
 | |
|     
 | |
| }
 | |
| 
 | |
| 
 | |
| ##############################################
 | |
| # Start main body of code                                                 
 | |
| ##############################################
 | |
| if ( parse_args() ) {
 | |
|     exit(1);
 | |
| }
 | |
| my $result = invoke_cmd();
 | |
| if ( $result ne "0" ) {
 | |
|     print STDERR "$node: $result\n";
 | |
|     exit(1);
 | |
| }
 | |
| exit(0);
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |