added support for xdsh to ethernet switches
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@14318 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		| @@ -2,6 +2,11 @@ | ||||
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html | ||||
|  | ||||
| package xCAT::DSHCLI; | ||||
| BEGIN | ||||
| { | ||||
|     $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; | ||||
| } | ||||
| use lib "$::XCATROOT/lib/perl"; | ||||
|  | ||||
| use File::Basename; | ||||
|  | ||||
| @@ -662,7 +667,7 @@ sub _execute_dsh | ||||
|                       if !$signal_interrupt_flag; | ||||
|                 } | ||||
|  | ||||
|                 elsif (!defined($target_rc) && !$dsh_cmd_background && ($::DSH_MELLANOX_SWITCH==0)) | ||||
|                 elsif (!defined($target_rc) && !$dsh_cmd_background && ($::DSH_MELLANOX_SWITCH==0) && ($$options{'devicetype'}!~ /EthSwitch/)) | ||||
|                 { | ||||
|                    # report error status  --nodestatus | ||||
|                   # Note the message below for node status must | ||||
| @@ -976,6 +981,32 @@ sub fork_fanout_dsh | ||||
|       ) | ||||
|       = @_; | ||||
|  | ||||
|     #get username and passeword for ether net switches (EthSwitch type) | ||||
|     if ($$options{'devicetype'} =~ /EthSwitch/) { | ||||
|         if (@$targets_waiting > 0) { | ||||
|             if ($ENV{'DSH_REMOTE_PASSWORD'}) { | ||||
|                 foreach my $t (keys(%$resolved_targets)) { | ||||
|                     $resolved_targets->{$t}->{'password'}=$ENV{'DSH_REMOTE_PASSWORD'}; | ||||
|                     $resolved_targets->{$t}->{'user'}=$$options{'user'}; | ||||
|                 } | ||||
|             } else { | ||||
|                 #get user name and password  from the switches table | ||||
|                  my $switchestab=xCAT::Table->new('switches',-create=>0); | ||||
|  | ||||
|                  my $switchents = $switchestab->getNodesAttribs($targets_waiting,[qw/switch sshusername sshpassword/]); | ||||
|                  foreach my $entry (values %$switchents) { | ||||
|                     my $switch=$entry->[0]->{switch}; | ||||
|                     if (defined($entry->[0]->{sshusername})) { | ||||
|                         $resolved_targets->{$switch}->{'user'}=$entry->[0]->{sshusername}; | ||||
|                     } | ||||
|                     if (defined($entry->[0]->{sshpassword})) { | ||||
|                         $resolved_targets->{$switch}->{'password'}=$entry->[0]->{sshpassword}; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     while (@$targets_waiting | ||||
|            && (keys(%$targets_active) < $$options{'fanout'})) | ||||
|     { | ||||
| @@ -1041,6 +1072,12 @@ sub fork_fanout_dsh | ||||
|                   || $$options{'node-rsh-defaults'}{$context}; | ||||
|                 ($remote_shell =~ /\/ssh$/) && ($rsh_extension = 'SSH'); | ||||
|  | ||||
|                 if ($$options{'devicetype'} =~ /EthSwitch/) { | ||||
|                     $remote_shell = "$::XCATROOT/sbin/rshell_api"; | ||||
|                     $rsh_extension='RShellAPI'; | ||||
|                     $rsh_config{'password'}=$$target_properties{'password'}; | ||||
|                 } | ||||
|  | ||||
|                 # will not set -n for any command,  causing problems | ||||
|                 # with running xdsh to install rpms and start xcatd on AIX | ||||
|                 # if IB switch device, do not set -n, causes no returncode | ||||
|   | ||||
							
								
								
									
										181
									
								
								xCAT-server/lib/perl/xCAT/RShellAPI.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								xCAT-server/lib/perl/xCAT/RShellAPI.pm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,181 @@ | ||||
| #!/usr/bin/perl | ||||
| # IBM(c) 2012 EPL license http://www.eclipse.org/legal/epl-v10.html | ||||
| package xCAT::RShellAPI; | ||||
|  | ||||
| BEGIN | ||||
| { | ||||
|     $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; | ||||
| } | ||||
| use lib "$::XCATROOT/lib/perl"; | ||||
| use xCAT::MsgUtils; | ||||
|  | ||||
| ####################################################### | ||||
| =head3 | ||||
|         remote_shell_command | ||||
|  | ||||
|         This routine constructs an remote shell command using the | ||||
|         given arguments | ||||
|         Arguments: | ||||
|         	$class - Calling module name (discarded) | ||||
|         	$config - Reference to remote shell command configuration hash table | ||||
|         	$exec_path - Path to ssh executable | ||||
|         Returns: | ||||
|         	A command array for the ssh command with the appropriate | ||||
|         	arguments as defined in the $config hash table | ||||
| =cut | ||||
| ##################################################### | ||||
| sub remote_shell_command { | ||||
| 	my ( $class, $config, $exec_path ) = @_; | ||||
|  | ||||
| 	my @command = (); | ||||
|  | ||||
| 	push @command, $exec_path; | ||||
|  | ||||
| 	if ( $$config{'options'} ) { | ||||
| 		my @options = split ' ', $$config{'options'}; | ||||
| 		push @command, @options; | ||||
| 	} | ||||
| 	 | ||||
|         my @tmp; | ||||
| 	if ($$config{'user'} && ($$config{'user'}  !~ /^none$/i)) { | ||||
| 	    @tmp=split(' ', "-l $$config{'user'}"); | ||||
| 	    push @command, @tmp; | ||||
| 	} | ||||
| 	if ($$config{'password'} && ($$config{'password'} !~ /^none$/i)) { | ||||
| 	    @tmp=split(' ', "-p $$config{'password'}"); | ||||
| 	    push @command, @tmp; | ||||
| 	} | ||||
| 	push @command, "$$config{'hostname'}"; | ||||
| 	push @command, $$config{'command'}; | ||||
|  | ||||
| 	return @command; | ||||
| } | ||||
|  | ||||
| sub run_remote_shell_api {  | ||||
|     require xCAT::SSHInteract; | ||||
|     my $node=shift; | ||||
|     my $user=shift; | ||||
|     my $passwd=shift; | ||||
|     my $args = join(" ", @_); | ||||
|     my $t; | ||||
|  | ||||
|     if(0) { | ||||
| 	print "start SSH session...\n"; | ||||
| 	$t = new  xCAT::SSHInteract( | ||||
| 	    -username=>$user, | ||||
| 	    -password=>$passwd, | ||||
| 	    -host=>$node, | ||||
| 	    -nokeycheck=>1, | ||||
| 	    -output_record_separator=>"\r", | ||||
| 	    Timeout=>5,  | ||||
| 	    Errmode=>'return', | ||||
| 	    Prompt=>'/.*[\>\#]$/', | ||||
| 	    ); | ||||
|     }; | ||||
|     my $errmsg=$@; | ||||
|     $errmsg =~ s/ at (.*) line (\d)+//g; | ||||
|     print "$errmsg\n";  | ||||
|  | ||||
|     my $rc=1; | ||||
|     if (not $t) {#ssh failed.. fallback to a telnet attempt | ||||
| 	print "start Telnet session...\n"; | ||||
| 	require Net::Telnet; | ||||
| 	$t = new Net::Telnet( | ||||
| 	    Timeout=>5,  | ||||
| 	    Errmode=>'return', | ||||
| 	    Prompt=>'/.*[\>\#]$/', | ||||
| 	    ); | ||||
| 	$rc = $t->open($node); | ||||
| 	if ($rc) { | ||||
|             my $pw_tried=0; | ||||
| 	    my ($prematch, $match)= $t->waitfor(Match => '/login[: ]*$/i', | ||||
| 						Match => '/username[: ]*$/i', | ||||
| 						Match => '/password[: ]*$/i', | ||||
| 						Errmode => "return"); | ||||
| 	    if (($match =~ /username[: ]*$/i) || ($match =~ /login[: ]*$/i )) { | ||||
| 		# user name | ||||
| 		if ($user) { | ||||
| 		    if (! $t->put(String => "$user\n", | ||||
| 				  Errmode => "return")) { | ||||
| 			print "login disconnected\n"; | ||||
| 			return [1, "login disconnected"]; | ||||
| 		    } | ||||
| 		} else { | ||||
| 		    print "Username is required.\n"; | ||||
| 		    return [1, "Username is required."]; | ||||
| 		} | ||||
| 	    } elsif ($match =~ /password[: ]*$/i) { | ||||
| 		if ($passwd) { | ||||
| 		    $pw_tried=1; | ||||
| 		    if (! $t->put(String => "$passwd\n", | ||||
| 				  Errmode => "return")) { | ||||
| 			print "login disconnected\n"; | ||||
| 			return [1, "login disconnected"]; | ||||
| 		    } | ||||
| 		} else { | ||||
| 		    print "password is required.\n"; | ||||
| 		    return [1, "Passwordis required."]; | ||||
| 		} | ||||
| 	    } | ||||
| 	     | ||||
| 	    ($prematch, $match)= $t->waitfor(Match => '/login[: ]*$/i', | ||||
| 					     Match => '/username[: ]*$/i', | ||||
| 					     Match => '/password[: ]*$/i', | ||||
| 					     Errmode => "return"); | ||||
| 	 | ||||
| 	    if (($match =~ /username[: ]*$/i) || ($match =~ /login[: ]*$/i )) { | ||||
| 		print "Incorrect username.\n"; | ||||
| 		return [1, "Incorrect username."]; | ||||
| 	    } elsif ($match =~ /password[: ]*$/i) { | ||||
| 		if ($pw_tried) {  | ||||
| 		    print "Incorrect password.\n"; | ||||
| 		    return [1, "Incorrect password."]; | ||||
| 		} | ||||
| 		if ($passwd) { | ||||
| 		    if (! $t->put(String => "$passwd\n", | ||||
| 				  Errmode => "return")) { | ||||
| 			print "login disconnected\n"; | ||||
| 			return [1, "login disconnected"]; | ||||
| 		    } | ||||
| 		} else { | ||||
| 		    print "password is required.\n"; | ||||
| 		    return [1, "Passwordis required."]; | ||||
| 		} | ||||
| 	    } | ||||
|  | ||||
|  | ||||
| 	    #Wait for command prompt | ||||
| 	    ($prematch, $match) = $t->waitfor(Match => '/login[: ]*$/i', | ||||
| 						 Match => '/username[: ]*$/i', | ||||
| 						 Match => '/password[: ]*$/i', | ||||
| 						 Match => '/\>/', | ||||
| 						 Errmode => "return"); | ||||
| 		 | ||||
|             #print "prematch=$prematch, match=$match\n"; | ||||
| 	    if ($match =~ /login[: ]*$/i or $match =~ /username[: ]*$/i or $match =~ /password[: ]*$/i) { | ||||
| 		print "login failed: bad login name or password\n"; | ||||
| 		return [1, "login failed: bad login name or password"]; | ||||
|    	    } | ||||
| 	} | ||||
|     } | ||||
|     if (!$rc) { | ||||
|         print "Error: " . $t->errmsg . "\n"; | ||||
| 	return([1, $t->errmsg]); | ||||
|     } | ||||
|  | ||||
|     $rc = 0; | ||||
|     my $output; | ||||
|     my @cmd_array=split(';', $args); | ||||
|     foreach my $cmd (@cmd_array) { | ||||
| 	#my @data = $t->cmd($cmd); | ||||
| 	my @data= $t->cmd(String =>$cmd); | ||||
|         $output .= "command:$cmd\n@data\n"; | ||||
|         print "command:$cmd\n@data\n"; | ||||
|     } | ||||
|     $t->close(); | ||||
|     return [0, $output]; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| 1; | ||||
| @@ -39,47 +39,48 @@ sub _startssh { | ||||
| } | ||||
|  | ||||
| sub new { | ||||
| 	my $class = shift; | ||||
| 	my %args = @_; | ||||
| 	my $pty = IO::Pty->new or die "Unable to perform ssh: $!"; | ||||
| 	$args{"-fhopen"} = $pty; | ||||
| 	$args{"-telnetmode"} = 0; | ||||
| 	$args{"-telnetmode"} = 0; | ||||
| 	$args{"-cmd_remove_mode"} = 1; | ||||
| 	my $username = $args{"-username"}; | ||||
| 	my $host = $args{"-host"}; | ||||
| 	my $password = $args{"-password"}; | ||||
| 	delete $args{"-host"}; | ||||
| 	delete $args{"-username"}; | ||||
| 	delete $args{"-password"}; | ||||
| 	my $nokeycheck = $args{"-nokeycheck"}; | ||||
| 	delete $args{"-nokeycheck"}; | ||||
| 	my $self = $class->Net::Telnet::new(%args); | ||||
| 	_startssh($self,$pty,$username,$host,"-nokeycheck"=>$nokeycheck); | ||||
| 	my $promptex = $args{Prompt}; | ||||
| 	$promptex =~ s!^/!!; | ||||
| 	$promptex =~ s!/\z!!; | ||||
|     my $class = shift; | ||||
|     my %args = @_; | ||||
|     my $pty = IO::Pty->new or die "Unable to perform ssh: $!"; | ||||
|     $args{"-fhopen"} = $pty; | ||||
|     $args{"-telnetmode"} = 0; | ||||
|     $args{"-telnetmode"} = 0; | ||||
|     $args{"-cmd_remove_mode"} = 1; | ||||
|     my $username = $args{"-username"}; | ||||
|     my $host = $args{"-host"}; | ||||
|     my $password = $args{"-password"}; | ||||
|     delete $args{"-host"}; | ||||
|     delete $args{"-username"}; | ||||
|     delete $args{"-password"}; | ||||
|     my $nokeycheck = $args{"-nokeycheck"}; | ||||
|     delete $args{"-nokeycheck"}; | ||||
|     my $self = $class->Net::Telnet::new(%args); | ||||
|     _startssh($self,$pty,$username,$host,"-nokeycheck"=>$nokeycheck); | ||||
|     my $promptex = $args{Prompt}; | ||||
|     $promptex =~ s!^/!!; | ||||
|     $promptex =~ s!/\z!!; | ||||
|     my ($prematch,$match) = $self->waitfor(Match => $args{Prompt},Match=>'/password:/i',Match=>'/REMOTE HOST IDENTIFICATION HAS CHANGED/') or die "Login Failed:", $self->lastline; | ||||
|     #print "prematch=$prematch, match=$match\n"; | ||||
|     if ($match =~ /password:/i) { | ||||
| 	    #$self->waitfor("-match" => '/password:/i', -errmode => "return") or die "Unable to reach host ",$self->lastline; | ||||
|             $self->print($password); | ||||
|             my $nextline = $self->getline(); | ||||
|             chomp($nextline); | ||||
|             while ($nextline =~ /^\s*$/) { | ||||
| 		$nextline = $self->get(); | ||||
|             	chomp($nextline); | ||||
| 	    } | ||||
| 	    if ($nextline =~ /^password:/ or $nextline =~ /Permission denied, please try again/) { | ||||
| 		    die "Incorrect Password"; | ||||
| 	    } elsif ($nextline =~ /$promptex/) { | ||||
| 		*$self->{_xcatsshinteract}->{_atprompt}=1; | ||||
| 	    } | ||||
| 	#$self->waitfor("-match" => '/password:/i', -errmode => "return") or die "Unable to reach host ",$self->lastline; | ||||
| 	$self->print($password); | ||||
| 	my $nextline = $self->getline(); | ||||
| 	chomp($nextline); | ||||
| 	while ($nextline =~ /^\s*$/) { | ||||
| 	    $nextline = $self->get(); | ||||
| 	    chomp($nextline); | ||||
| 	} | ||||
| 	if ($nextline =~ /password:/i or $nextline =~ /Permission denied, please try again/ or $nextline =~ /disconnect from/) { | ||||
| 	    die "Incorrect Password"; | ||||
| 	} elsif ($nextline =~ /$promptex/) { | ||||
| 	    *$self->{_xcatsshinteract}->{_atprompt}=1; | ||||
| 	} | ||||
|     } elsif ($match =~ /$promptex/) { | ||||
| 	*$self->{_xcatsshinteract}->{_atprompt}=1; | ||||
|     } elsif ($match =~ /REMOTE HOST IDENTIFICATION HAS CHANGED/){ | ||||
|         die "Known_hosts issue"; | ||||
| 	} | ||||
| 	return bless($self,$class); | ||||
| 	die "Known_hosts issue"; | ||||
|     } | ||||
|     return bless($self,$class); | ||||
| } | ||||
| sub atprompt { | ||||
| 	my $self=shift; | ||||
|   | ||||
							
								
								
									
										33
									
								
								xCAT-server/sbin/rshell_api
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										33
									
								
								xCAT-server/sbin/rshell_api
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| #!/usr/bin/env perl | ||||
| # IBM(c) 2012 EPL license http://www.eclipse.org/legal/epl-v10.html | ||||
|  | ||||
| BEGIN | ||||
| { | ||||
|     $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; | ||||
| } | ||||
|  | ||||
| use lib "$::XCATROOT/lib/perl"; | ||||
| use Getopt::Long; | ||||
| use xCAT::RShellAPI; | ||||
|  | ||||
| Getopt::Long::Configure("require_order"); | ||||
| Getopt::Long::Configure("no_pass_through"); | ||||
|  | ||||
| my $username; | ||||
| my $passwd; | ||||
| my $help; | ||||
|  | ||||
| if (!GetOptions( | ||||
|   'l|loginname=s' => \$username, | ||||
|   'p|password=s' => \$passwd, | ||||
|   'h|help' => \$help, | ||||
|   ) || $help || scalar(@ARGV)<2 ) { | ||||
|   print "Usage: rshell_api [-l <user>] [-p <passwrd>] <node> <command>\n"; | ||||
|   exit; | ||||
| } | ||||
|  | ||||
| my $node = $ARGV[0]; | ||||
|  | ||||
| xCAT::RShellAPI::run_remote_shell_api($node, $username, $passwd, @ARGV[1 .. $#ARGV]);  | ||||
|  | ||||
| exit 0; | ||||
							
								
								
									
										5
									
								
								xCAT-server/share/xcat/EthSwitch/config
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								xCAT-server/share/xcat/EthSwitch/config
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| [main] | ||||
| ssh-setup-command= | ||||
| [xdsh] | ||||
| pre-command=NULL | ||||
| post-command=NULL | ||||
| @@ -80,6 +80,7 @@ mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/xcat/ib/netboot/sles | ||||
| mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/xcat/ib/netboot/rh | ||||
| mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/xcat/ib/scripts/Mellanox | ||||
| mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/xcat/ib/scripts/QLogic | ||||
| mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/xcat/EthSwitch | ||||
| mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin | ||||
| mkdir -p $RPM_BUILD_ROOT/%{prefix}/xdsh/Context | ||||
| mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_monitoring/samples | ||||
| @@ -122,6 +123,8 @@ cp share/xcat/cons/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/cons | ||||
| cp -r share/xcat/ib/scripts/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/ib/scripts | ||||
| cp share/xcat/ib/netboot/sles/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/ib/netboot/sles | ||||
| cp share/xcat/ib/netboot/rh/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/ib/netboot/rh | ||||
| cp share/xcat/EthSwitch/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/EthSwitch | ||||
|  | ||||
| chmod 755 $RPM_BUILD_ROOT/%{prefix}/share/xcat/cons/* | ||||
| chmod 755 $RPM_BUILD_ROOT/%{prefix}/share/xcat/ib/scripts/* | ||||
| chmod 755 $RPM_BUILD_ROOT/%{prefix}/share/xcat/ib/netboot/sles/* | ||||
|   | ||||
		Reference in New Issue
	
	Block a user