IB Switch Support in xCAT. With this change, xdsh gets the capability to connect to IB switch as a compute node.

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@2581 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
wanghuaz 2009-01-08 12:57:02 +00:00
parent 9a9ef9d94c
commit 11befcd181
5 changed files with 412 additions and 66 deletions

View File

@ -2126,6 +2126,37 @@ sub config_dsh
$dsh_trace
&& xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
# Check devicetype attr and try to load device configuration
$$options{'devicetype'} = $$options{'devicetype'} || $ENV{'DEVICETYPE'} || u
ndef;
if ( $$options{'devicetype'} )
{
$ENV{'DEVICETYPE'} = $$options{'devicetype'};
my $devicepath = $$options{'devicetype'};
$devicepath =~ s/::/\//g;
$devicepath = "/var/opt/xcat/" . $devicepath. "/config";
# Get configuration from $::XCATDEVCFGDIR
if ( -e $devicepath)
{
my $deviceconf = get_config($devicepath);
# Get all dsh section configuration
foreach my $entry (keys %{ $$deviceconf{'xdsh'} } )
{
my $value = $$deviceconf{'xdsh'}{$entry};
if ($value)
{
$$options{$entry} = $value;
}
}
}
else
{
$rsp->{data}->[0] = "EMsgMISSING_DEV_CFG";
xCAT::MsgUtils->message('E', $rsp, $::CALLBACK);
}
}
!$$options{'node-rsh'}
&& ( $$options{'node-rsh'} = $ENV{'DSH_NODE_RSH'}
|| $ENV{'DSH_REMOTE_CMD'}
@ -2225,64 +2256,95 @@ sub config_dsh
$dsh_trace
&& xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
# Set a default PATH
$$options{'pre-command'} = $path_set;
if (!$$options{'no-locale'})
# Check if $$options{'pre-command'} has been overwritten
if (!$$options{'pre-command'})
{
my @output = `/usr/bin/locale`;
chomp(@output);
# Set a default PATH
$$options{'pre-command'} = $path_set;
my @settings = ();
!($$options{'syntax'} eq 'csh') && (push @settings, $env_set);
foreach my $line (@output)
if (!$$options{'no-locale'})
{
$line =~ s/=/$env_assign/;
my @output = `/usr/bin/locale`;
chomp(@output);
my @settings = ();
!($$options{'syntax'} eq 'csh') && (push @settings, $env_set);
foreach my $line (@output)
{
$line =~ s/=/$env_assign/;
if ($$options{'syntax'} eq 'csh')
{
push @settings, "$env_set $line;";
}
else
{
push @settings, $line;
}
}
if ($$options{'syntax'} eq 'csh')
{
push @settings, "$env_set $line;";
push @settings, "$env_set PERL_BADLANG${env_assign}0;";
}
else
{
push @settings, $line;
push @settings, "PERL_BADLANG${env_assign}0";
}
}
my $locale_settings = join ' ', @settings;
!($$options{'syntax'} eq 'csh') && ($locale_settings .= ' ; ');
$$options{'pre-command'} .= $locale_settings;
}
}
else
{
$$options{'pre-command'} = '';
}
# Check if $$options{'post-command'} has been overwritten.
if (! $$options{'post-command'} )
{
if ($$options{'syntax'} eq 'csh')
{
push @settings, "$env_set PERL_BADLANG${env_assign}0;";
$$options{'post-command'} =
"; $env_set DSH_TARGET_RC$env_assign\$status; echo \":DSH_TARGET_RC=\${DSH_TARGET_RC}:\"";
}
else
{
push @settings, "PERL_BADLANG${env_assign}0";
$$options{'post-command'} =
"; $env_set DSH_TARGET_RC$env_assign\$?; echo \":DSH_TARGET_RC=\${DSH_TARGET_RC}:\"";
}
my $locale_settings = join ' ', @settings;
!($$options{'syntax'} eq 'csh') && ($locale_settings .= ' ; ');
$$options{'pre-command'} .= $locale_settings;
$$options{'exit-status'}
&& ($$options{'post-command'} .=
' ; echo "Remote_command_rc = $DSH_TARGET_RC"');
}
if ($$options{'syntax'} eq 'csh')
{
$$options{'post-command'} =
"; $env_set DSH_TARGET_RC$env_assign\$status; echo \":DSH_TARGET_RC=\${DSH_TARGET_RC}:\"";
}
else
{
$$options{'post-command'} =
"; $env_set DSH_TARGET_RC$env_assign\$?; echo \":DSH_TARGET_RC=\${DSH_TARGET_RC}:\"";
# post-command is overwritten by user , set env $::USER_POST_CMD
$::USER_POST_CMD = 1;
if ($$options{'post-command'} =~ /NULL/ )
{
$$options{'post-command'} = '';
}
else
{
# $::DSH_EXIT_STATUS ony can be used in DSHCore::pipe_handler_buffer
# and DSHCore::pipe_handler
$$options{'exit-status'}
&& ($::DSH_EXIT_STATUS = 1);
$$options{'post-command'} = ";$$options{'post-command'}";
# Append "DSH_RC" keyword to mark output
$$options{'post-command'} = "$$options{'post-command'};echo DSH_RC";
}
}
$$options{'exit-status'}
&& ($$options{'post-command'} .=
' ; echo "Remote_command_rc = $DSH_TARGET_RC"');
if (
!$$options{'nodes'}
&& ( $ENV{'DSH_NODE_LIST'}
@ -3476,7 +3538,6 @@ sub isFdNumExceed
sub usage_dsh
{
## usage message
my $usagemsg1 =
" xdsh -h \n xdsh -q \n xdsh -v \n xdsh [noderange] [group]\n";
my $usagemsg2 =
@ -3485,7 +3546,7 @@ sub usage_dsh
my $usagemsg4 =
"[-m] [-o options][-q] [-Q] [-r remote_shell] [-i image path]\n";
my $usagemsg5 =
" [-s] [-S ksh | csh] [-t timeout] [-T] [-X environment variables] [-v] [-z]\n";
" [-s] [-S ksh | csh] [-t timeout] [-T] [-X environment variables] [--devicetype type_of_device] [-v] [-z]\n";
my $usagemsg6 = " [command_list]\n";
my $usagemsg7 =
"Note:Context always defaults to XCAT unless -C flag is set.";
@ -3597,6 +3658,7 @@ sub parse_and_run_dsh
'T|trace' => \$options{'trace'},
'V|version' => \$options{'version'},
'devicetype|devicetype=s' => \$options{'devicetype'},
'command-name|commandName=s' => \$options{'command-name'},
'command-description|commandDescription=s' =>
\$options{'command-description'},
@ -3695,7 +3757,19 @@ sub parse_and_run_dsh
}
else
{
if (defined $options{'devicetype'})
{
$ENV{'DEVICETYPE'} = $options{'devicetype'};
my $devicepath = $options{'devicetype'};
$devicepath =~ s/::/\//g;
$devicepath = "/var/opt/xcat/" . $devicepath. "/config";
if ( -e $devicepath)
{
my $deviceconf = get_config($devicepath);
# Get ssh-setup-command attribute from configuration
$ENV{'SSH_SETUP_COMMAND'} = $$deviceconf{'main'}{'ssh-setup-command'};
}
}
my $rc = xCAT::Utils->setupSSH(@nodelist);
my @results = "return code = $rc";
return (@results);
@ -3864,6 +3938,7 @@ sub parse_and_run_dcp
'R|recursive' => \$options{'recursive'},
'T|trace' => \$options{'trace'},
'V|version' => \$options{'version'},
'devicetype=s' => \$options{'devicetype'},
'X:s' => \$options{'ignore_env'}
)
)
@ -4377,4 +4452,126 @@ sub show_dsh_config
}
}
#-------------------------------------------------------------------------------
=head3 get_config
Substitute specific keywords in hash
e.g. config file:
[main]
cachedir=/var/cache/yum
keepcache=1
[base]
name=Red Hat Linux $releasever - $basearch - Base
baseurl=http://mirror.dulug.duke.edu/pub/yum-repository/redhat/$releasev
er/$basearch/
%config = {
main => {
'cachedir' => '/var/cache/yum',
'keepcache' => '1'
},
bash => {
'name' => 'Red Hat Linux $relea
sever - $basearch - Base',
'baseurl' => 'http://mirror.dulug.
duke.edu/pub/yum-repository/redhat/$releasever/$basearch/'
}
}
Arguments:
$configfile - config file
Returns:
$config_ref - reference to config hash
Comments:
=cut
#-------------------------------------------------------------------------------
sub get_config
{
my $configfile = shift;
my @content = readFile($configfile);
my $current_section = "DEFAULT";
my %config;
my $xcat_use;
$xcat_use = 0;
foreach my $line (@content)
{
my ($entry, $value);
chomp $line;
if ( $line =~ /\QDO NOT ERASE THIS SECTION\E/ )
{
# reverse flag
$xcat_use = ! $xcat_use;
}
if ($xcat_use)
{
# Remove leading "#". This line is used by xCAT
$line =~ s/^#//g;
}
else
{
# Remove comment line
$line =~ s/#.*$//g;
}
$line =~ s/^\s+//g;
$line =~ s/\s+$//g;
next unless $line;
if ( $line =~ /^\s*\[([\w+-\.]+)\]\s*$/ ) {
$current_section = $1;
} else {
# Ignore line doesn't key/value pair.
if ($line !~ /=/)
{
next;
}
$line =~ /^\s*([^=]*)\s*=\s*(.*)\s*$/;
$entry = $1;
$value = $2;
$entry =~ s/^#*//g;
# Remove leading and trailing spaces
$entry =~ s/^\s+//g;
$entry =~ s/\s+$//g;
$value =~ s/^\s+//g;
$value =~ s/\s+$//g;
$config{$current_section}{"$entry"} = $value;
}
}
return \%config;
}
#-------------------------------------------------------------------------------
=head3 readFile
Read a file and return its content.
Arguments:
filename
Returns:
file contents or undef
Globals:
none
Error:
undef
Example:
my $blah = readFile('/etc/redhat-release');
Comments:
none
=cut
#-------------------------------------------------------------------------------
sub readFile
{
my $filename = shift;
open(FILE, "<$filename");
my @contents = <FILE>;
close(FILE);
return @contents;
}
1;

View File

@ -248,7 +248,8 @@ sub ifconfig_inet
=cut
#---------------------------------------------------------------------------
# NOTE: global environment $::__DSH_LAST_LINE only can be used in DSHCore::pipe_handler and DSHCore::pipe_handler_buffer
$::__DSH_LAST_LINE = undef;
sub pipe_handler
{
my ($class, $options, $target_properties, $read_fh, $buffer_size, $label,
@ -258,6 +259,21 @@ sub pipe_handler
my $line;
my $target_hostname;
my $eof_reached = undef;
my $cust_rc_deal =0;
if ($::USER_POST_CMD)
{
# If user provide post-command to display return code,
# the keyword 'DSH_RC' will be searched,
# the return code is gotten in another way as shown like below:
# ...
# <output>
# <return_code>
# DSH_RC
#
# The last two lines are needed to be moved out from output
$cust_rc_deal = 1;
}
while (sysread($read_fh, $line, $buffer_size) != 0
|| ($eof_reached = 1))
@ -288,6 +304,22 @@ sub pipe_handler
if (@lines)
{
if ($cust_rc_deal)
{
# Dump the last line at the beginning of current buffer
if ($::__DSH_LAST_LINE)
{
unshift @lines, "$::__DSH_LAST_LINE" ;
}
# Pop current buffer to $::__DSH_LAST_LINE
$::__DSH_LAST_LINE = $lines[scalar @lines - 1];
pop @lines;
# Skip this loop if array @lines is empty.
if (scalar @lines == 0)
{
next;
}
}
$line = join "\n", @lines;
$line .= "\n";
@ -302,6 +334,21 @@ sub pipe_handler
$line =~ s/:DSH_TARGET_RC=$target_rc:\n//g;
$$target_properties{'target-rc'} = $target_rc;
}
if ( $::__DSH_LAST_LINE =~ /DSH_RC/ && $cust_rc_deal) {
my $target_rc = undef;
# Get the number in the last line
$line =~ /[\D]*([0-9]+)\s*$/ ;
$target_rc = $1;
$$target_properties{'target-rc'} = $target_rc;
# Remove the last line
$line =~ s/$target_rc\s*\n$//g;
#$line = $line . "## ret=$target_rc";
# Clean up $::__DSH_LAST_LINE
undef $::__DSH_LAST_LINE ;
# when '-z' is specified, display return code
$::DSH_EXIT_STATUS &&
($line .="Remote_command_rc = $target_rc");
}
if ($line ne '')
{
@ -395,6 +442,7 @@ sub pipe_handler
=cut
#---------------------------------------------------------------------------
# NOTE: global environment $::__DSH_LAST_LINE only can be used in DSHCore::pipe_handler and DSHCore::pipe_handler_buffer
sub pipe_handler_buffer
{
@ -405,11 +453,25 @@ sub pipe_handler_buffer
my $line;
my $eof_reached = undef;
my $cust_rc_deal =0;
if ($::USER_POST_CMD)
{
# If user provide post-command to display return code,
# the keyword 'DSH_RC' will be searched,
# the return code is gotten in another way as shown like below:
# ...
# <output>
# <return_code>
# DSH_RC
#
# The last two lines are needed to be moved out from output
$cust_rc_deal = 1;
}
while ( (sysread($read_fh, $line, $buffer_size) != 0)
|| ($eof_reached = 1))
{
last if ($eof_reached);
if ($line =~ /^\n$/)
{
@ -434,6 +496,22 @@ sub pipe_handler_buffer
if (@lines)
{
if ($cust_rc_deal)
{
# Dump the last line at the beginning of current buffer
if ($::__DSH_LAST_LINE)
{
unshift @lines, "$::__DSH_LAST_LINE" ;
}
# Pop current buffer to $::__DSH_LAST_LINE
$::__DSH_LAST_LINE = $lines[scalar @lines - 1];
pop @lines;
# Skip this loop if array @lines is empty.
if (scalar @lines == 0)
{
next;
}
}
$line = join "\n", @lines;
$line .= "\n";
@ -448,6 +526,21 @@ sub pipe_handler_buffer
$line =~ s/:DSH_TARGET_RC=$target_rc:\n//g;
$$target_properties{'target-rc'} = $target_rc;
}
if ( $::__DSH_LAST_LINE =~ /DSH_RC/ && $cust_rc_deal) {
my $target_rc = undef;
# Get the number in the last line
$line =~ /[\D]*([0-9]+)\s*$/ ;
$target_rc = $1;
$$target_properties{'target-rc'} = $target_rc;
# Remove the last line
$line =~ s/$target_rc\s*\n$//g;
#$line = $line . "## ret=$target_rc";
# Clean up $::__DSH_LAST_LINE
undef $::__DSH_LAST_LINE ;
# when '-z' is specified, display return code
$::DSH_EXIT_STATUS &&
($line .="Remote_command_rc = $target_rc");
}
if ($line ne '')
{
@ -469,7 +562,6 @@ sub pipe_handler_buffer
last if ($fh_count == 0);
}
}
return $eof_reached;
}

View File

@ -201,6 +201,7 @@ sub parse_args_xdsh
'T|trace' => \$options{'trace'},
'V|version' => \$options{'version'},
'devicetype=s' => \$options{'devicetype'},
'command-name|commandName=s' => \$options{'command-name'},
'command-description|commandDescription=s' =>
\$options{'command-description'},

View File

@ -7,7 +7,7 @@ B<xdsh> - Concurrently runs commands on multiple nodes.
B<xdsh> I<noderange> [B<-B> I<bypass>] [B<-C> I<context>] [B<-e>] [B<-E> I<environment_file>] [B<-f> I<fanout>]
[B<-K>] [B<-L>] [B<-l> I<userID>] [B<-m>] [B<-o>
I<node_options>] [B<-Q>] [B<-r> I<node_remote_shell>] [B<-s>] [B<-S> B<csh>|B<ksh>] [B<-t> I<timeout>]
[B<-T>] [B<-v>] [B<-X> I<env_list>] [B<-z>] I<command_list>
[B<-T>] [B<-v>] [B<-X> I<env_list>] [B<--devicetype> I<type of device>] [B<-z>] I<command_list>
B<xdsh> [B<-i> I<image path>] I<command_list>
@ -344,6 +344,10 @@ This option is useful when running B<xdsh> from within other
scripts when you don't want the user's environment affecting
the behavior of xdsh.
=item B<--devicetype> I<type of device>
Specify a user-defined device type that references the location of relevant device configuration file. The devicetype value must correspond to a valid device configuration file under the /var/opt/csm/ directory. For example, the /var/opt/csm/IBSwitch/Qlogic/config file is the location if devicetype is specified ¡°IBSwitch::Qlogic¡±
=item B<-z>|B<--exit-status>
Displays the exit status for the last remotely executed

View File

@ -44,6 +44,13 @@ if { [info exists env(XCAT_UPD_MULTNODES)] } {
} else {
set manynodes ""
}
if { [info exists env(SSH_SETUP_COMMAND)] } {
set ssh_setup_cmd $env(SSH_SETUP_COMMAND)
} else {
set ssh_setup_cmd ""
}
#
# check input arguments
#
@ -61,7 +68,13 @@ if { [llength $argv] != 0 } {
# -t means test to see if the shell is already setup
if { [string compare "-t" [lindex $argv 0]] ==0 } {
set env(LC_ALL) "C"
set pid [ spawn [lindex $argv 1] [lindex $argv 2] -l root echo test.success ]
if { [string compare $ssh_setup_cmd $empty] !=0 } {
set userid "admin"
} else {
set userid "root"
}
set pid [ spawn [lindex $argv 1] [lindex $argv 2] -l $userid echo test.success ]
expect {
timeout { exit 1 }
"Are you sure you want to continue connecting (yes/no)?" {
@ -210,6 +223,9 @@ if { [llength $argv] != 0 } {
set printlist [ join $nodelist ", " ]
set scp "/usr/bin/scp"
set directory "/install/postscripts/.ssh"
set fh_auth_keys2 [ open "/install/postscripts/.ssh/authorized_keys2" "r"]
set auth_keys2 [read $fh_auth_keys2]
close $fh_auth_keys2
if { [info exists env(XCAT_REMOTE_PASSWORD)] } {
set word $env(XCAT_REMOTE_PASSWORD)
} else {
@ -224,33 +240,64 @@ if { [llength $argv] != 0 } {
send_user "\n"
}
foreach node $nodelist {
set env(LC_ALL) "C"
set pid [ spawn $scp -r -p $directory root\@$node:/tmp ]
expect {
"Are you sure you want to continue connecting (yes/no)?" {
send "yes\r"
exp_continue
if { [string compare $ssh_setup_cmd $empty] ==0 } {
set env(LC_ALL) "C"
set pid [ spawn $scp -r -p $directory root\@$node:/tmp ]
expect {
"Are you sure you want to continue connecting (yes/no)?" {
send "yes\r"
exp_continue
}
"*ssword*" {
send "$word\r"
exp_continue
}
"Permission denied*" {
exec /bin/kill $pid
}
}
"*ssword*" {
send "$word\r"
exp_continue
set pid [ spawn $remoteshell $node -l root /tmp/.ssh/copy.perl ]
expect {
"Are you sure you want to continue connecting (yes/no)?" {
send "yes\r"
exp_continue
}
"*ssword*" {
send "$word\r"
exp_continue
}
"Permission denied*" {
exec /bin/kill $pid
}
}
"Permission denied*" {
exec /bin/kill $pid
} else {
# Loop all keys in $auth_keys2 and generate ssh setup command one by one
# Remove '\n'
set auth_keys2 [string range $auth_keys2 0 end-1]
set all_keys [split $auth_keys2 "\n"]
set ssh_setup_string ""
foreach each_key $all_keys {
# Skip blank line
if { [string compare each_key $empty] == 0 } {
continue;
}
set ssh_setup_string "$ssh_setup_string;$ssh_setup_cmd \"$each_key\""
}
}
set pid [ spawn $remoteshell $node -l root /tmp/.ssh/copy.perl ]
expect {
"Are you sure you want to continue connecting (yes/no)?" {
send "yes\r"
exp_continue
}
"*ssword*" {
send "$word\r"
exp_continue
}
"Permission denied*" {
exec /bin/kill $pid
# Trim semicolon at the tail
set ssh_setup_string [string range $ssh_setup_string 1 end]
set pid [ spawn $remoteshell $node -l admin $ssh_setup_string ]
expect {
"Are you sure you want to continue connecting (yes/no)?" {
send "yes\r"
exp_continue
}
"*ssword*" {
send "$word\r"
exp_continue
}
"Permission denied*" {
exec /bin/kill $pid
}
}
}
}
@ -273,7 +320,12 @@ if { [llength $argv] != 0 } {
}
foreach hn $nlist {
set env(LC_ALL) "C"
set pid [ spawn $remoteshell $hn -l root echo test.success ]
if { [string compare $ssh_setup_cmd $empty] !=0 } {
set userid "admin"
} else {
set userid "root"
}
set pid [ spawn $remoteshell $hn -l $userid echo test.success ]
expect {
"Are you sure you want to continue connecting (yes/no)?" {
send "yes\r"