From bae1e1110a3e12ee4595541b813ccbbbe72347e9 Mon Sep 17 00:00:00 2001 From: lissav Date: Wed, 4 Feb 2009 17:18:44 +0000 Subject: [PATCH] add code to support xdsh -K for non-root ids and not to use xcatbypass git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@2701 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- perl-xCAT/xCAT/DSHCLI.pm | 232 ++++--- perl-xCAT/xCAT/Utils.pm | 930 ++++++++++++++++------------ xCAT-client/bin/xdsh | 62 +- xCAT-server/sbin/remoteshell.expect | 250 ++++---- 4 files changed, 851 insertions(+), 623 deletions(-) diff --git a/perl-xCAT/xCAT/DSHCLI.pm b/perl-xCAT/xCAT/DSHCLI.pm index 1c30dda0e..2457ae466 100644 --- a/perl-xCAT/xCAT/DSHCLI.pm +++ b/perl-xCAT/xCAT/DSHCLI.pm @@ -40,7 +40,7 @@ our @dsh_valid_env = ( 'DSH_NODE_OPTS', 'DSH_NODE_RCP', 'DSH_NODE_RSH', 'DSH_OUTPUT', 'DSH_PATH', 'DSH_SYNTAX', - 'DSH_TIMEOUT', + 'DSH_TIMEOUT', 'DSH_REMOTE_PASSWORD', ); select(STDERR); $| = 1; @@ -2127,20 +2127,23 @@ sub config_dsh && xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); # Check devicetype attr and try to load device configuration - $$options{'devicetype'} = - $$options{'devicetype'} || $ENV{'DEVICETYPE'} || undef; - if ( $$options{'devicetype'} ) + $$options{'devicetype'} = $$options{'devicetype'} + || $ENV{'DEVICETYPE'} + || undef; + if ($$options{'devicetype'}) { $ENV{'DEVICETYPE'} = $$options{'devicetype'}; my $devicepath = $$options{'devicetype'}; $devicepath =~ s/::/\//g; - $devicepath = "/var/opt/xcat/" . $devicepath. "/config"; + $devicepath = "/var/opt/xcat/" . $devicepath . "/config"; + # Get configuration from $::XCATDEVCFGDIR - if ( -e $devicepath) + if (-e $devicepath) { my $deviceconf = get_config($devicepath); + # Get all dsh section configuration - foreach my $entry (keys %{ $$deviceconf{'xdsh'} } ) + foreach my $entry (keys %{$$deviceconf{'xdsh'}}) { my $value = $$deviceconf{'xdsh'}{$entry}; if ($value) @@ -2259,6 +2262,7 @@ sub config_dsh # Check if $$options{'pre-command'} has been overwritten if (!$$options{'pre-command'}) { + # Set a default PATH $$options{'pre-command'} = $path_set; @@ -2294,7 +2298,7 @@ sub config_dsh { push @settings, "PERL_BADLANG${env_assign}0"; } - + my $locale_settings = join ' ', @settings; !($$options{'syntax'} eq 'csh') && ($locale_settings .= ' ; '); @@ -2307,7 +2311,7 @@ sub config_dsh } # Check if $$options{'post-command'} has been overwritten. - if (! $$options{'post-command'} ) + if (!$$options{'post-command'}) { if ($$options{'syntax'} eq 'csh') { @@ -2327,19 +2331,22 @@ sub config_dsh } else { + # post-command is overwritten by user , set env $::USER_POST_CMD $::USER_POST_CMD = 1; - if ($$options{'post-command'} =~ /NULL/ ) + 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); + && ($::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"; } @@ -3540,9 +3547,10 @@ sub usage_dsh ## usage message my $usagemsg1 = " xdsh -h \n xdsh -q \n xdsh -v \n xdsh [noderange] [group]\n"; - my $usagemsg2 = + my $usagemsg1a = " xdsh [noderange] -K [-w touserid]\n"; + my $usagemsg2 = " [-B bypass ] [-C context] [-c] [-e] [-E environment_file] [--devicetype type_of_device] [-f fanout]\n"; - my $usagemsg3 = " [-l user_ID] [-L] [-K ssh setup] "; + my $usagemsg3 = " [-l user_ID] [-L] "; my $usagemsg4 = "[-m] [-o options][-q] [-Q] [-r remote_shell] [-i image path]\n"; my $usagemsg5 = @@ -3550,8 +3558,8 @@ sub usage_dsh my $usagemsg6 = " [command_list]\n"; my $usagemsg7 = "Note:Context always defaults to XCAT unless -C flag is set."; - my $usagemsg .= $usagemsg1 .= $usagemsg2 .= $usagemsg3 .= $usagemsg4 .= - $usagemsg5 .= $usagemsg6 .= $usagemsg7; + my $usagemsg .= $usagemsg1 .= $usagemsg1a .= $usagemsg2 .= $usagemsg3 .= + $usagemsg4 .= $usagemsg5 .= $usagemsg6 .= $usagemsg7; ### end usage mesage if ($::CALLBACK) { @@ -3599,11 +3607,12 @@ sub parse_and_run_dsh my ($class, $nodes, $args, $callback, $command, $noderange) = @_; $::CALLBACK = $callback; - if (!($args)) { + if (!($args)) + { usage_dsh; exit 1; } - @ARGV = @{$args}; # get arguments + @ARGV = @{$args}; # get arguments if ($ENV{'XCATROOT'}) { $::XCATROOT = $ENV{'XCATROOT'}; # setup xcatroot home directory @@ -3633,20 +3642,20 @@ sub parse_and_run_dsh if ( !GetOptions( - 'e|execute' => \$options{'execute'}, - 'f|fanout=i' => \$options{'fanout'}, - 'h|help' => \$options{'help'}, - 'l|user=s' => \$options{'user'}, - 'm|monitor' => \$options{'monitor'}, - 'o|node-options=s' => \$options{'node-options'}, - 'q|show-config' => \$options{'show-config'}, - 'r|node-rsh=s' => \$options{'node-rsh'}, - 'i|rootimg=s' => \$options{'rootimg'}, - 's|stream' => \$options{'streaming'}, - 't|timeout=i' => \$options{'timeout'}, - 'v|verify' => \$options{'verify'}, - 'z|exit-status' => \$options{'exit-status'}, - + 'e|execute' => \$options{'execute'}, + 'f|fanout=i' => \$options{'fanout'}, + 'h|help' => \$options{'help'}, + 'l|user=s' => \$options{'user'}, + 'm|monitor' => \$options{'monitor'}, + 'o|node-options=s' => \$options{'node-options'}, + 'q|show-config' => \$options{'show-config'}, + 'r|node-rsh=s' => \$options{'node-rsh'}, + 'i|rootimg=s' => \$options{'rootimg'}, + 's|stream' => \$options{'streaming'}, + 't|timeout=i' => \$options{'timeout'}, + 'v|verify' => \$options{'verify'}, + 'w|touserid=s' => \$options{'touserid'}, + 'z|exit-status' => \$options{'exit-status'}, 'B|bypass' => \$options{'bypass'}, 'C|context=s' => \$options{'context'}, 'E|environment=s' => \$options{'environment'}, @@ -3658,7 +3667,7 @@ sub parse_and_run_dsh 'T|trace' => \$options{'trace'}, 'V|version' => \$options{'version'}, - 'devicetype|devicetype=s' => \$options{'devicetype'}, + 'devicetype|devicetype=s' => \$options{'devicetype'}, 'command-name|commandName=s' => \$options{'command-name'}, 'command-description|commandDescription=s' => \$options{'command-description'}, @@ -3718,8 +3727,9 @@ sub parse_and_run_dsh # we will use the create the nostname from the directory # for the hostname in the output my $path = $options{'rootimg'}; - $imagename= xCAT::Utils->get_image_name($path); - if (@$nodes[0] eq "NO_NODE_RANGE") { # from sinv, discard this name + $imagename = xCAT::Utils->get_image_name($path); + if (@$nodes[0] eq "NO_NODE_RANGE") + { # from sinv, discard this name undef @$nodes; } if (defined(@$nodes)) @@ -3727,7 +3737,7 @@ sub parse_and_run_dsh my $rsp = (); $rsp->{data}->[0] = "Input noderange:@$nodes and any other xdsh flags or environment variables are not valid with -i flag."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK,1); + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); return; } @@ -3755,25 +3765,89 @@ sub parse_and_run_dsh return; } - else + + # Rules: if (current userid running command) not eq touserid, + # the current running userid must be root + # + # if not set then the touserid will be defaulted to + # the current running userid. + # DSH_REMOTE_PASSWORD env variable must be set to the correct + # password for the key update. This was setup in xdsh client + # frontend. remoteshell.expect depends on this + + if (!($ENV{'DSH_REMOTE_PASSWORD'})) { - 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); + my $rsp = (); + $rsp->{data}->[0] = + "User password for ssh key exchange has not been supplied./n Cannot complete the -K command./n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return; + } + + if (!($ENV{'DSH_CURRENT_USERID'})) + { + my $rsp = (); + $rsp->{data}->[0] = + "Current Userid has not been supplied./n Cannot complete the -K command./n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return; + + } + + my $current_userid = $ENV{'DSH_CURRENT_USERID'}; + + # if touser id defined + if (defined $options{'touserid'}) + { + + # if current_userid ne touserid then current_userid + # must be root + if ( ($current_userid ne $options{'touserid'}) + && ($current_userid ne "root")) + { + my $rsp = (); + $rsp->{data}->[0] = + "When touserid:$options{'touserid'} is not the same as the current user:$current_userid. The the command must be run by root id."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return; + } + + # passed security checks so, if set + $ENV{'DSH_FROM_USERID'} = $current_userid; + $ENV{'DSH_TO_USERID'} = $options{'touserid'}; + } + else + { # not defined, so default to current userid + $ENV{'DSH_FROM_USERID'} = $current_userid; + $ENV{'DSH_TO_USERID'} = $current_userid; + } + + # setting up IB switch ssh, different interface that ssh for + # userid on node. Must build special ssh command to be sent + # to the IB switch to setup ssh + 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'}; + } + } + + # + # setup ssh keys on the nodes or ib switch + # + my $rc = xCAT::Utils->setupSSH(@nodelist); + my @results = "return code = $rc"; + return (@results); } if (!(@ARGV)) { # no args , an error @@ -3892,11 +3966,12 @@ sub parse_and_run_dcp { my ($class, $nodes, $args, $callback, $command, $noderange) = @_; $::CALLBACK = $callback; - if (!($args)) { + if (!($args)) + { usage_dcp; exit 1; } - @ARGV = @{$args}; # get arguments + @ARGV = @{$args}; # get arguments if ($ENV{'XCATROOT'}) { $::XCATROOT = $ENV{'XCATROOT'}; # setup xcatroot home directory @@ -4031,20 +4106,24 @@ sub parse_and_run_dcp # # build list of nodes my @nodelist; - if (defined(@$nodes)) { # there are nodes - @nodelist = @$nodes; - $options{'nodes'} = join(',', @nodelist); - } else { - my $rsp={}; + if (defined(@$nodes)) + { # there are nodes + @nodelist = @$nodes; + $options{'nodes'} = join(',', @nodelist); + } + else + { + my $rsp = {}; $rsp->{data}->[0] = "Noderange missing in command input."; xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); return; } + # Execute the dcp api my @results = xCAT::DSHCLI->runDcp_api(\%options, 0); if ($::RUNCMD_RC) { # error from dcp - my $rsp={}; + my $rsp = {}; $rsp->{data}->[0] = "Error from xdsh. Return Code = $::RUNCMD_RC"; xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); @@ -4383,7 +4462,7 @@ sub runDcp_api if (!$DSHCLI::NO_MESSAGES) { xCAT::MsgUtils->message("E", - "dcp command failed, Return code=$::RUNCMD_RC."); + "dcp command failed, Return code=$::RUNCMD_RC."); } } @@ -4490,8 +4569,8 @@ duke.edu/pub/yum-repository/redhat/$releasever/$basearch/' #------------------------------------------------------------------------------- sub get_config { - my $configfile = shift; - my @content = readFile($configfile); + my $configfile = shift; + my @content = readFile($configfile); my $current_section = "DEFAULT"; my %config; my $xcat_use; @@ -4500,27 +4579,34 @@ sub get_config { my ($entry, $value); chomp $line; - if ( $line =~ /\QDO NOT ERASE THIS SECTION\E/ ) + if ($line =~ /\QDO NOT ERASE THIS SECTION\E/) { - # reverse flag - $xcat_use = ! $xcat_use; + + # reverse flag + $xcat_use = !$xcat_use; } if ($xcat_use) { - # Remove leading "#". This line is used by xCAT - $line =~ s/^#//g; + + # Remove leading "#". This line is used by xCAT + $line =~ s/^#//g; } else { - # Remove comment line - $line =~ s/#.*$//g; + + # Remove comment line + $line =~ s/#.*$//g; } $line =~ s/^\s+//g; $line =~ s/\s+$//g; next unless $line; - if ( $line =~ /^\s*\[([\w+-\.]+)\]\s*$/ ) { + if ($line =~ /^\s*\[([\w+-\.]+)\]\s*$/) + { $current_section = $1; - } else { + } + else + { + # Ignore line doesn't key/value pair. if ($line !~ /=/) { @@ -4530,6 +4616,7 @@ sub get_config $entry = $1; $value = $2; $entry =~ s/^#*//g; + # Remove leading and trailing spaces $entry =~ s/^\s+//g; $entry =~ s/\s+$//g; @@ -4573,5 +4660,4 @@ sub readFile return @contents; } - 1; diff --git a/perl-xCAT/xCAT/Utils.pm b/perl-xCAT/xCAT/Utils.pm index ab8d5e76e..9fa3323a6 100644 --- a/perl-xCAT/xCAT/Utils.pm +++ b/perl-xCAT/xCAT/Utils.pm @@ -1,9 +1,10 @@ #!/usr/bin/env perl # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html package xCAT::Utils; + BEGIN { - $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; } use lib "$::XCATROOT/lib/perl"; require xCAT::Table; @@ -15,7 +16,6 @@ require Data::Dumper; require xCAT::NodeRange; require DBI; - our @ISA = qw(Exporter); our @EXPORT_OK = qw(genpassword); @@ -30,6 +30,7 @@ This program module file, is a set of utilities used by xCAT commands. =cut #------------------------------------------------------------- + =head3 genUUID Returns an RFC 4122 compliant UUIDv4 Arguments: @@ -39,23 +40,28 @@ This program module file, is a set of utilities used by xCAT commands. for example: f16196d1-7534-41c1-a0ae-a9633b030583 =cut + #------------------------------------------------------- -sub genUUID { +sub genUUID +{ + #UUIDv4 has 6 fixed bits and 122 random bits #Though a UUID of this form is not guaranteed to be unique absolutely, - #the chances of a cluster the size of the entire internet generating - #two identical UUIDs is 4 in 10 octillion. - srand(); #Many note this as bad practice, however, forks are going on.. + #the chances of a cluster the size of the entire internet generating + #two identical UUIDs is 4 in 10 octillion. + srand(); #Many note this as bad practice, however, forks are going on.. my $uuid; - $uuid=sprintf("%08x-%04x-4%03x-",int(rand(4294967295)),int(rand(65535)),int(rand(4095))); - my $num=32768; + $uuid = + sprintf("%08x-%04x-4%03x-", + int(rand(4294967295)), + int(rand(65535)), int(rand(4095))); + my $num = 32768; $num = $num | int(rand(16383)); - $uuid.=sprintf("%04x-%04x%08x",$num,int(rand(65535)),int(rand(4294967295))); + $uuid .= + sprintf("%04x-%04x%08x", $num, int(rand(65535)), int(rand(4294967295))); return $uuid; } - - #-------------------------------------------------------------------------------- =head3 genpassword @@ -257,15 +263,18 @@ sub isLinux #------------------------------------------------------------------------------- sub Version { -#The following tag tells the build script where to append build info - my $version=shift; - if ($version eq 'short') { - $version = '' #XCATVERSIONSUBHERE ; - } else { - $version = 'Version ' #XCATVERSIONSUBHERE #XCATSVNBUILDSUBHERE ; + + #The following tag tells the build script where to append build info + my $version = shift; + if ($version eq 'short') + { + $version = '' #XCATVERSIONSUBHERE ; } - ; - return $version; + else + { + $version = 'Version ' #XCATVERSIONSUBHERE #XCATSVNBUILDSUBHERE ; + } + return $version; } #------------------------------------------------------------------------------- @@ -497,7 +506,7 @@ sub list_all_node_groups sub list_nodes_in_nodegroups { my ($class, $group) = @_; - my $req={}; + my $req = {}; $req->{noderange}->[0] = $group; my @nodes = xCAT::NodeRange::noderange($req->{noderange}->[0]); return @nodes; @@ -740,7 +749,7 @@ sub runcmd } # if exitcode not specified, use cmd exit code if ($displayerror) { - my $rsp={}; + my $rsp = {}; my $errmsg = ''; if (xCAT::Utils->isLinux() && $::RUNCMD_RC == 139) { @@ -786,7 +795,6 @@ sub runcmd } - #------------------------------------------------------------------------------- =head3 runxcmd @@ -849,39 +857,48 @@ sub runxcmd { - my $save_CALLBACK = $::CALLBACK; + my $save_CALLBACK = $::CALLBACK; my ($class, $cmd, $subreq, $exitcode, $refoutput) = @_; $::RUNCMD_RC = 0; if ($::VERBOSE) { - if (ref($cmd) eq "HASH") { - xCAT::MsgUtils->message("I", "Running internal xCAT command: $cmd->{command}->[0] ... \n"); - } else { - xCAT::MsgUtils->message("I", "Running Command: $cmd\n"); + if (ref($cmd) eq "HASH") + { + xCAT::MsgUtils->message("I", + "Running internal xCAT command: $cmd->{command}->[0] ... \n"); + } + else + { + xCAT::MsgUtils->message("I", "Running Command: $cmd\n"); } } $::xcmd_outref = []; - my $req; - if (ref($cmd) eq "HASH") { - $req = $cmd; - } else { # assume scalar, build request hash the way we do in xcatclient - my @cmdargs=split(/\s+/,$cmd); - my $cmdname = shift(@cmdargs); - $req->{command}=[$cmdname]; - my $arg=shift(@cmdargs); - while ($arg =~ /^-/) { - push (@{$req->{arg}}, $arg); - $arg=shift(@cmdargs); - } - if ($arg ne "NO_NODE_RANGE") { - my @nodes = split(",",$arg); - $req->{node}=\@nodes; - } - push (@{$req->{arg}}, @cmdargs); - } - $subreq->($req,\&runxcmd_output); - $::CALLBACK = $save_CALLBACK; # in case the subreq call changed it - my $outref=$::xcmd_outref; + my $req; + if (ref($cmd) eq "HASH") + { + $req = $cmd; + } + else + { # assume scalar, build request hash the way we do in xcatclient + my @cmdargs = split(/\s+/, $cmd); + my $cmdname = shift(@cmdargs); + $req->{command} = [$cmdname]; + my $arg = shift(@cmdargs); + while ($arg =~ /^-/) + { + push(@{$req->{arg}}, $arg); + $arg = shift(@cmdargs); + } + if ($arg ne "NO_NODE_RANGE") + { + my @nodes = split(",", $arg); + $req->{node} = \@nodes; + } + push(@{$req->{arg}}, @cmdargs); + } + $subreq->($req, \&runxcmd_output); + $::CALLBACK = $save_CALLBACK; # in case the subreq call changed it + my $outref = $::xcmd_outref; if ($::RUNCMD_RC) { my $displayerror = 1; @@ -891,10 +908,10 @@ sub runxcmd if ($exitcode > 0) { $rc = $exitcode; - } # if not zero, exit with specified code + } # if not zero, exit with specified code elsif ($exitcode <= 0) { - $rc = ''; # if zero or negative, do not exit + $rc = ''; # if zero or negative, do not exit if ($exitcode < 0) { $displayerror = 0; } } } @@ -904,13 +921,14 @@ sub runxcmd } # if exitcode not specified, use cmd exit code if ($displayerror) { - my $rsp={}; + my $rsp = {}; my $errmsg = join('', @$outref); chomp $errmsg; - my $displaycmd=$cmd; - if (ref($cmd) eq "HASH") { - $displaycmd=$cmd->{command}->[0]; - } + my $displaycmd = $cmd; + if (ref($cmd) eq "HASH") + { + $displaycmd = $cmd->{command}->[0]; + } if ($::CALLBACK) { $rsp->{data}->[0] = @@ -920,7 +938,7 @@ sub runxcmd else { xCAT::MsgUtils->message("E", - "Command failed: $displaycmd. Error message: $errmsg.\n"); + "Command failed: $displaycmd. Error message: $errmsg.\n"); } $xCAT::Utils::errno = 29; } @@ -942,64 +960,81 @@ sub runxcmd return $line; } } + # runxcmd_output -- Internal subroutine for runxcmd to capture the output # from the xCAT daemon subrequest call # Note - only basic info, data, and error responses returned # For more complex node or other return structures, you will need # to write your own wrapper to subreq instead of using runxcmd. -sub runxcmd_output { - my $resp = shift; - if (defined($resp->{info})) { - push @$::xcmd_outref,@{$resp->{info}}; - } - if (defined($resp->{sinfo})) { - push @$::xcmd_outref,@{$resp->{sinfo}}; - } - if (defined($resp->{data})) { - push @$::xcmd_outref,@{$resp->{data}}; - } - if (defined($resp->{node})) { - my $node=$resp->{node}->[0]; - my $desc=$node->{name}->[0]; - if (defined($node->{data})) { - if (ref(\($node->{data}->[0])) eq 'SCALAR') { - $desc=$desc.": ".$node->{data}->[0]; - } else { - if (defined($node->{data}->[0]->{desc})) { - $desc=$desc.": ".$node->{data}->[0]->{desc}->[0]; - } - if (defined($node->{data}->[0]->{contents})) { - $desc="$desc: ".$node->{data}->[0]->{contents}->[0]; - } - } - } - push @$::xcmd_outref,$desc; +sub runxcmd_output +{ + my $resp = shift; + if (defined($resp->{info})) + { + push @$::xcmd_outref, @{$resp->{info}}; } - if (defined($resp->{error})) { - push @$::xcmd_outref,@{$resp->{error}}; - $::RUNCMD_RC=1; - } - if (defined($resp->{errorcode})) { - if (ref($resp->{errorcode}) eq 'ARRAY') { - foreach my $ecode (@{$resp->{errorcode}}) { - $::RUNCMD_RC |= $ecode; - } - } else { - # assume it is a non-reference scalar - $::RUNCMD_RC |= $resp->{errorcode}; - } - } + if (defined($resp->{sinfo})) + { + push @$::xcmd_outref, @{$resp->{sinfo}}; + } + if (defined($resp->{data})) + { + push @$::xcmd_outref, @{$resp->{data}}; + } + if (defined($resp->{node})) + { + my $node = $resp->{node}->[0]; + my $desc = $node->{name}->[0]; + if (defined($node->{data})) + { + if (ref(\($node->{data}->[0])) eq 'SCALAR') + { + $desc = $desc . ": " . $node->{data}->[0]; + } + else + { + if (defined($node->{data}->[0]->{desc})) + { + $desc = $desc . ": " . $node->{data}->[0]->{desc}->[0]; + } + if (defined($node->{data}->[0]->{contents})) + { + $desc = "$desc: " . $node->{data}->[0]->{contents}->[0]; + } + } + } + push @$::xcmd_outref, $desc; + } + if (defined($resp->{error})) + { + push @$::xcmd_outref, @{$resp->{error}}; + $::RUNCMD_RC = 1; + } + if (defined($resp->{errorcode})) + { + if (ref($resp->{errorcode}) eq 'ARRAY') + { + foreach my $ecode (@{$resp->{errorcode}}) + { + $::RUNCMD_RC |= $ecode; + } + } + else + { + # assume it is a non-reference scalar + $::RUNCMD_RC |= $resp->{errorcode}; + } + } -# my $i=0; -# foreach my $line ($resp->{info}->[$i]) { -# push (@dshresult, $line); -# $i++; -# } - return 0; + # my $i=0; + # foreach my $line ($resp->{info}->[$i]) { + # push (@dshresult, $line); + # $i++; + # } + return 0; } - #-------------------------------------------------------------------------------- =head3 getHomeDir @@ -1035,12 +1070,19 @@ sub getHomeDir =head3 setupSSH - Transfers the ssh keys to setup ssh to the input nodes. + Generates if needed and Transfers the ssh keys + fOr a userid to setup ssh to the input nodes. Arguments: Array of nodes Returns: + Env Variables: $DSH_FROM_USERID, $DSH_TO_USERID, $DSH_REMOTE_PASSWORD + the ssh keys are transferred from the $DSH_FROM_USERID to the $DSH_TO_USERID + on the node(s). The DSH_REMOTE_PASSWORD and the DSH_FROM_USERID + must be obtained by + the calling script or from the xdsh client + Globals: $::XCATROOT , $::CALLBACK Error: @@ -1062,6 +1104,46 @@ sub setupSSH my @badnodes = (); my $n_str = join ',', @nodes; my $SSHdir = "/install/postscripts/.ssh"; + if (!($ENV{'DSH_REMOTE_PASSWORD'})) + { + my $rsp = (); + $rsp->{data}->[0] = + "User password for the ssh key exchange has not been input. xdsh -K cannot complete.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return; + + } + + # setup who the keys are coming from and who they are going to + my $from_userid; + my $to_userid; + if (!($ENV{'DSH_FROM_USERID'})) + { + my $rsp = (); + $rsp->{data}->[0] = + "DSH From Userid has not been input. xdsh -K cannot complete.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return; + + } + else + { + $from_userid = $ENV{'DSH_FROM_USERID'}; + } + if (!($ENV{'DSH_TO_USERID'})) + { + my $rsp = (); + $rsp->{data}->[0] = + "DSH to Userid has not been input. xdsh -K cannot complete.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return; + + } + else + { + $to_userid = $ENV{'DSH_TO_USERID'}; + } + if ($::XCATROOT) { $::REMOTESHELL_EXPECT = "$::XCATROOT/sbin/remoteshell.expect"; @@ -1081,36 +1163,26 @@ sub setupSSH } # Generate the keys, if they do not already exist - my $rsp={}; - my $home = xCAT::Utils->getHomeDir("root"); - if ( !(-e "$home/.ssh/id_rsa.pub") - || !(-e "$home/.ssh/id_dsa.pub")) - { - xCAT::Utils->runcmd("$::REMOTESHELL_EXPECT -k", 0); - if ($::RUNCMD_RC != 0) - { # error - $rsp->{data}->[0] = "remoteshell.expect failed generating keys."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + my $rsp = {}; - } - } + # Get the home directory + my $home = xCAT::Utils->getHomeDir($from_userid); + $ENV{'DSH_FROM_USERID_HOME'} = $home; - # Copy the keys to the directory - my $rc = xCAT::Utils->cpSSHFiles($SSHdir); - if ($rc != 0) + # generates new keys, if they do not already exist + xCAT::Utils->runcmd("$::REMOTESHELL_EXPECT -k", 0); + if ($::RUNCMD_RC != 0) { # error - $rsp->{data}->[0] = "Error running cpSSHFiles.\n"; + $rsp->{data}->[0] = "remoteshell.expect failed generating keys."; xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - return 1; } - open(FILE, ">$SSHdir/copy.perl") - or die "cannot open file $SSHdir/copy.perl\n"; - - # build the perl copy script in $SSHdir/copy.perl + # build the perl copy script in $HOME/.ssh/copy.perl + open(FILE, ">$home/.ssh/copy.perl") + or die "cannot open file $home/.ssh/copy.perl\n"; print FILE "#!/usr/bin/perl -my (\$name,\$passwd,\$uid,\$gid,\$quota,\$comment,\$gcos,\$dir,\$shell,\$expire) = getpwnam(\"root\"); +my (\$name,\$passwd,\$uid,\$gid,\$quota,\$comment,\$gcos,\$dir,\$shell,\$expire) = getpwnam($to_userid); my \$home = \$dir; umask(0077); \$dest_dir = \"\$home/.ssh/\"; @@ -1120,25 +1192,51 @@ if (! -d \"\$dest_dir\" ) { system(\"\$cmd\"); chmod 0700, \$dest_dir; } -`cat /tmp/.ssh/authorized_keys >> \$home/.ssh/authorized_keys 2>&1`; -`cat /tmp/.ssh/authorized_keys2 >> \$home/.ssh/authorized_keys2 2>&1`; -`rm -f /tmp/.ssh/authorized_keys 2>&1`; -`rm -f /tmp/.ssh/authorized_keys2 2>&1`; -`rm -f /tmp/.ssh/copy.perl 2>&1`; -rmdir(\"/tmp/.ssh\");"; +`cat /tmp/$to_userid/.ssh/authorized_keys >> \$home/.ssh/authorized_keys 2>&1`; +`cat /tmp/$to_userid/.ssh/authorized_keys2 >> \$home/.ssh/authorized_keys2 2>&1`; +`rm -f /tmp/$to_userid/.ssh/* 2>&1`; +rmdir(\"/tmp/$to_userid/.ssh\"); +rmdir(\"/tmp/$to_userid\");"; close FILE; - chmod 0744, "$SSHdir/copy.perl"; + chmod 0744, "$home/.ssh/copy.perl"; - # end build Perl code + # TODO build the shell copy script in $HOME/.ssh/copy.sh + #open(FILE, ">$home/.ssh/copy.sh") + # or die "cannot open file $home/.ssh/copy.sh\n"; + #print FILE "#!/bin/sh"; + #close FILE; + #chmod 0744, "$home/.ssh/copy.sh"; - #set an ENV var if more than 10 nodes for remoteshell.expect - my $num_nodes = scalar(@nodes); - if ($num_nodes > 10) + if ($from_userid eq "root") { - $ENV{'XCAT_UPD_MULTNODES'} = 1; + my $rc = xCAT::Utils->cpSSHFiles($SSHdir); + if ($rc != 0) + { # error + $rsp->{data}->[0] = "Error running cpSSHFiles.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + + } + + # copy the copy install file to the install directory, if from and + # to userid are root + if ($to_userid eq "root") + { + + my $cmd = " cp $home/.ssh/copy.perl $SSHdir/copy.perl"; + xCAT::Utils->runcmd($cmd, 0); + my $rsp = {}; + if ($::RUNCMD_RC != 0) + { + $rsp->{data}->[0] = "$cmd failed.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return (1); + + } + } } - # send the keys to the nodes + # send the keys to the nodes for root or some other id # my $cmd = "$::REMOTESHELL_EXPECT -s $n_str"; my $rc = system("$cmd") >> 8; @@ -1162,9 +1260,6 @@ rmdir(\"/tmp/.ssh\");"; } } - xCAT::Utils->runcmd("/bin/stty echo", 0); - delete $ENV{'XCAT_UPD_MULTNODES'}; - if (@badnodes) { my $nstring = join ',', @badnodes; @@ -1186,7 +1281,8 @@ rmdir(\"/tmp/.ssh\");"; =head3 cpSSHFiles Copies the ssh keyfiles and the copy perl script into - /install/postscripts/.ssh. + /install/postscripts/.ssh. and the $HOME/.ssh directory of + userid Arguments: directory path @@ -1210,7 +1306,7 @@ sub cpSSHFiles { my ($class, $SSHdir) = @_; my ($cmd, $rc); - my $rsp={}; + my $rsp = {}; if ($::VERBOSE) { $rsp->{data}->[0] = "Copying SSH Keys"; @@ -1228,7 +1324,7 @@ sub cpSSHFiles } $cmd = " cp $home/.ssh/identity.pub $authorized_keys"; xCAT::Utils->runcmd($cmd, 0); - my $rsp={}; + my $rsp = {}; if ($::RUNCMD_RC != 0) { $rsp->{data}->[0] = "$cmd failed.\n"; @@ -1244,6 +1340,25 @@ sub cpSSHFiles xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); } } + $cmd = " cp $home/.ssh/identity.pub $home/.ssh/authorized_keys"; + xCAT::Utils->runcmd($cmd, 0); + my $rsp = {}; + if ($::RUNCMD_RC != 0) + { + $rsp->{data}->[0] = "$cmd failed.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return (1); + + } + else + { + chmod 0600, "$home/.ssh/authorized_keys"; + if ($::VERBOSE) + { + $rsp->{data}->[0] = "$cmd succeeded.\n"; + xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + } + } $cmd = "cp $home/.ssh/id_rsa.pub $authorized_keys2"; xCAT::Utils->runcmd($cmd, 0); @@ -1262,8 +1377,26 @@ sub cpSSHFiles xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); } } + $cmd = "cp $home/.ssh/id_rsa.pub $home/.ssh/authorized_keys2"; + xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) + { + $rsp->{data}->[0] = "$cmd failed.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return (1); - my $rsp={}; + } + else + { + chmod 0600, "$home/.ssh/authorized_keys2"; + if ($::VERBOSE) + { + $rsp->{data}->[0] = "$cmd succeeded.\n"; + xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + } + } + + my $rsp = {}; $cmd = "cat $home/.ssh/id_dsa.pub >> $authorized_keys2"; xCAT::Utils->runcmd($cmd, 0); if ($::RUNCMD_RC != 0) @@ -1637,22 +1770,23 @@ sub thishostisnot my @ips = split /\n/, `/sbin/ip addr`; my $comp = inet_aton($comparison); - if ($comp) { - foreach (@ips) - { - if (/^\s*inet/) + if ($comp) + { + foreach (@ips) { - my @ents = split(/\s+/); - my $ip = $ents[2]; - $ip =~ s/\/.*//; - if (inet_aton($ip) eq $comp) + if (/^\s*inet/) { - return 0; - } + my @ents = split(/\s+/); + my $ip = $ents[2]; + $ip =~ s/\/.*//; + if (inet_aton($ip) eq $comp) + { + return 0; + } - #print Dumper(inet_aton($ip)); + #print Dumper(inet_aton($ip)); + } } - } } return 1; } @@ -1828,11 +1962,12 @@ sub readSNInfo } $et = xCAT::Utils->GetNodeOSARCH($nodename); - if ($et == 1) { + if ($et == 1) + { xCAT::MsgUtils->message('S', "Could not get OS/ARCH for node $nodename\n"); return 1; - } + } if (!($et->{'os'} || $et->{'arch'})) { xCAT::MsgUtils->message('S', @@ -2361,6 +2496,7 @@ sub get_ServiceNode #----------------------------------------------------------------------------- sub toIP { + # does not support IPV6 IPV6TODO if ($_[0] =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/) { @@ -2551,7 +2687,7 @@ sub getSNList # reads all nodes from the service node table my @servicenodes; - my $servicenodetab = xCAT::Table->new('servicenode',-create=>1); + my $servicenodetab = xCAT::Table->new('servicenode', -create => 1); unless ($servicenodetab) # no servicenode table { xCAT::MsgUtils->message('I', "Unable to open servicenode table.\n"); @@ -2620,6 +2756,7 @@ sub isMounted } return 0; } + #------------------------------------------------------------------------------- =head3 runxcatd @@ -2640,57 +2777,60 @@ sub isMounted =cut #------------------------------------------------------------------------------- -sub runxcatd +sub runxcatd { - my ($class, $cmd) = @_; - if ( ! (xCAT::Utils->isAIX())) { # only runs on AIX - xCAT::MsgUtils->message("E", "This command should only be run on AIX.\n"); - return 1; - } + my ($class, $cmd) = @_; + if (!(xCAT::Utils->isAIX())) + { # only runs on AIX + xCAT::MsgUtils->message("E", + "This command should only be run on AIX.\n"); + return 1; + } - # - # if xcatd already running - # Get the xcatd processes and stop them - # - my @xpids = xCAT::Utils->runcmd("ps -ef\|grep \"xcatd\"", 0); - if ($#xpids >= 1) - { # will have at least "0" for the grep - xCAT::MsgUtils->message('I', "Stopping xcatd processes....\n"); - foreach my $ps (@xpids) - { - - $ps =~ s/^\s+//; # strip any leading spaces - my ($uid, $pid, $ppid, $desc) = split /\s+/, $ps; - - # if $ps contains "grep" then it's not one of the daemon processes - if ($ps !~ /grep/) + # + # if xcatd already running + # Get the xcatd processes and stop them + # + my @xpids = xCAT::Utils->runcmd("ps -ef\|grep \"xcatd\"", 0); + if ($#xpids >= 1) + { # will have at least "0" for the grep + xCAT::MsgUtils->message('I', "Stopping xcatd processes....\n"); + foreach my $ps (@xpids) { - # print "pid=$pid\n"; - #my $cmd = "/bin/kill -9 $pid"; - my $cmd = "/bin/kill $pid"; - xCAT::Utils->runcmd($cmd, 0); - if ($::RUNCMD_RC != 0) + $ps =~ s/^\s+//; # strip any leading spaces + my ($uid, $pid, $ppid, $desc) = split /\s+/, $ps; + + # if $ps contains "grep" then it's not one of the daemon processes + if ($ps !~ /grep/) { - xCAT::MsgUtils->message('E', - "Could not stop xcatd process $pid.\n"); - return 1; + + # print "pid=$pid\n"; + #my $cmd = "/bin/kill -9 $pid"; + my $cmd = "/bin/kill $pid"; + xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) + { + xCAT::MsgUtils->message('E', + "Could not stop xcatd process $pid.\n"); + return 1; + } } } } - } - - if ($cmd eq "xcatstart") { # start xcatd - xCAT::MsgUtils->message('I', "Starting xcatd.....\n"); - my $xcmd = "$::XCATROOT/sbin/xcatd &"; - my $outref = xCAT::Utils->runcmd("$xcmd", 0); - if ($::RUNCMD_RC != 0) { - xCAT::MsgUtils->message('E', "Could not start xcatd process.\n"); - return 1; + if ($cmd eq "xcatstart") + { # start xcatd + xCAT::MsgUtils->message('I', "Starting xcatd.....\n"); + my $xcmd = "$::XCATROOT/sbin/xcatd &"; + my $outref = xCAT::Utils->runcmd("$xcmd", 0); + if ($::RUNCMD_RC != 0) + { + xCAT::MsgUtils->message('E', "Could not start xcatd process.\n"); + return 1; + } } - } - return 0; + return 0; } #------------------------------------------------------------------------------- @@ -2706,73 +2846,92 @@ sub runxcatd =cut #------------------------------------------------------------------------------- -sub getNodesetStates{ - my $noderef=shift; - if ($noderef =~ /xCAT::Utils/) { - $noderef=shift; - } - my @nodes=@$noderef; - my $hashref=shift; - - if (@nodes>0) { - my $tab = xCAT::Table->new('noderes'); - if (! $tab) { return (1, "Unable to open noderes table.");} - - #initialize all nodes - foreach (@nodes) { $hashref->{$_}="undefined";} - - my @aixnodes=(); - my @pxenodes=(); - my @yabootnodes=(); - my $tabdata=$tab->getNodesAttribs(\@nodes,['node', 'netboot']); - foreach my $node (@nodes) { - my $nb="aixinstall"; - my $tmp1=$tabdata->{$node}->[0]; - if (($tmp1) && ($tmp1->{netboot})) { $nb=$tmp1->{netboot};} - if ($nb eq "yaboot") { - push(@yabootnodes,$node); - } elsif ($nb eq "pxe") { - push(@pxenodes,$node); - } elsif ($nb eq "aixinstall") { - push(@aixnodes,$node); - } +sub getNodesetStates +{ + my $noderef = shift; + if ($noderef =~ /xCAT::Utils/) + { + $noderef = shift; } + my @nodes = @$noderef; + my $hashref = shift; - my @retarray; - my $retcode=0; - my $errormsg; - # print "ya=@yabootnodes, pxe=@pxenodes, aix=@aixnodes\n"; - if (@yabootnodes > 0) { - require xCAT_plugin::yaboot; - @retarray=xCAT_plugin::yaboot::getNodesetStates(\@yabootnodes, $hashref); - if ($retarray[0]) { - $retcode=$retarray[0]; - $errormsg .= $retarray[1]; - xCAT::MsgUtils->message('E',$retarray[1]);} - } - if (@pxenodes > 0) { - require xCAT_plugin::pxe; - @retarray=xCAT_plugin::pxe::getNodesetStates(\@pxenodes, $hashref); - if ($retarray[0]) { - $retcode=$retarray[0]; - $errormsg .= $retarray[1]; - xCAT::MsgUtils->message('E',$retarray[1]); - } - } - if (@aixnodes > 0) { - require xCAT_plugin::aixinstall; - @retarray=xCAT_plugin::aixinstall::getNodesetStates(\@aixnodes, $hashref); - if ($retarray[0]) { - $retcode=$retarray[0]; - $errormsg .= $retarray[1]; - xCAT::MsgUtils->message('E',$retarray[1]); - } + if (@nodes > 0) + { + my $tab = xCAT::Table->new('noderes'); + if (!$tab) { return (1, "Unable to open noderes table."); } + + #initialize all nodes + foreach (@nodes) { $hashref->{$_} = "undefined"; } + + my @aixnodes = (); + my @pxenodes = (); + my @yabootnodes = (); + my $tabdata = $tab->getNodesAttribs(\@nodes, ['node', 'netboot']); + foreach my $node (@nodes) + { + my $nb = "aixinstall"; + my $tmp1 = $tabdata->{$node}->[0]; + if (($tmp1) && ($tmp1->{netboot})) { $nb = $tmp1->{netboot}; } + if ($nb eq "yaboot") + { + push(@yabootnodes, $node); + } + elsif ($nb eq "pxe") + { + push(@pxenodes, $node); + } + elsif ($nb eq "aixinstall") + { + push(@aixnodes, $node); + } + } + + my @retarray; + my $retcode = 0; + my $errormsg; + + # print "ya=@yabootnodes, pxe=@pxenodes, aix=@aixnodes\n"; + if (@yabootnodes > 0) + { + require xCAT_plugin::yaboot; + @retarray = + xCAT_plugin::yaboot::getNodesetStates(\@yabootnodes, $hashref); + if ($retarray[0]) + { + $retcode = $retarray[0]; + $errormsg .= $retarray[1]; + xCAT::MsgUtils->message('E', $retarray[1]); + } + } + if (@pxenodes > 0) + { + require xCAT_plugin::pxe; + @retarray = + xCAT_plugin::pxe::getNodesetStates(\@pxenodes, $hashref); + if ($retarray[0]) + { + $retcode = $retarray[0]; + $errormsg .= $retarray[1]; + xCAT::MsgUtils->message('E', $retarray[1]); + } + } + if (@aixnodes > 0) + { + require xCAT_plugin::aixinstall; + @retarray = + xCAT_plugin::aixinstall::getNodesetStates(\@aixnodes, $hashref); + if ($retarray[0]) + { + $retcode = $retarray[0]; + $errormsg .= $retarray[1]; + xCAT::MsgUtils->message('E', $retarray[1]); + } + } } - } - return (0, ""); + return (0, ""); } - #------------------------------------------------------------------------------- =head3 get_nodeset_state @@ -2785,54 +2944,62 @@ sub getNodesetStates{ =cut #------------------------------------------------------------------------------- -sub get_nodeset_state { - my $node=shift; - if ($node =~ /xCAT::Utils/) { - $node=shift; - } - - my $state="undefined"; - - #get boot type (pxe, yaboot or aixinstall) for the node - my $noderestab=xCAT::Table->new('noderes',-create=>0); - my $ent=$noderestab->getNodeAttribs($node,[qw(netboot)]); - if ($ent && $ent->{netboot}) { - my $boottype=$ent->{netboot}; - #get nodeset state from corresponding files - if ($boottype eq "pxe") { - require xCAT_plugin::pxe; - my $tmp=xCAT_plugin::pxe::getstate($node); - my @a=split(' ', $tmp); - $state = $a[0]; - +sub get_nodeset_state +{ + my $node = shift; + if ($node =~ /xCAT::Utils/) + { + $node = shift; } - elsif ($boottype eq "yaboot") { - require xCAT_plugin::yaboot; - my $tmp=xCAT_plugin::yaboot::getstate($node); - my @a=split(' ', $tmp); - $state = $a[0]; - } - elsif ($boottype eq "aixinstall") { - require xCAT_plugin::aixinstall; - $state=xCAT_plugin::aixinstall::getNodesetState($node); - } - } - else { #default to AIX because AIX does not set noderes.netboot value - require xCAT_plugin::aixinstall; - $state=xCAT_plugin::aixinstall::getNodesetState($node); - } - #get the nodeset state from the chain table as a backup. - if ($state eq "undefined") { - my $chaintab = xCAT::Table->new('chain'); - my $stref = $chaintab->getNodeAttribs($node,['currstate']); - if ($stref and $stref->{currstate}) { $state=$stref->{currstate}; } - } + my $state = "undefined"; - return $state; + #get boot type (pxe, yaboot or aixinstall) for the node + my $noderestab = xCAT::Table->new('noderes', -create => 0); + my $ent = $noderestab->getNodeAttribs($node, [qw(netboot)]); + if ($ent && $ent->{netboot}) + { + my $boottype = $ent->{netboot}; + + #get nodeset state from corresponding files + if ($boottype eq "pxe") + { + require xCAT_plugin::pxe; + my $tmp = xCAT_plugin::pxe::getstate($node); + my @a = split(' ', $tmp); + $state = $a[0]; + + } + elsif ($boottype eq "yaboot") + { + require xCAT_plugin::yaboot; + my $tmp = xCAT_plugin::yaboot::getstate($node); + my @a = split(' ', $tmp); + $state = $a[0]; + } + elsif ($boottype eq "aixinstall") + { + require xCAT_plugin::aixinstall; + $state = xCAT_plugin::aixinstall::getNodesetState($node); + } + } + else + { #default to AIX because AIX does not set noderes.netboot value + require xCAT_plugin::aixinstall; + $state = xCAT_plugin::aixinstall::getNodesetState($node); + } + + #get the nodeset state from the chain table as a backup. + if ($state eq "undefined") + { + my $chaintab = xCAT::Table->new('chain'); + my $stref = $chaintab->getNodeAttribs($node, ['currstate']); + if ($stref and $stref->{currstate}) { $state = $stref->{currstate}; } + } + + return $state; } - #------------------------------------------------------------------------------- =head3 get_image_name @@ -2846,29 +3013,29 @@ sub get_nodeset_state { =cut #------------------------------------------------------------------------------- -sub get_image_name { - my ($class, $imagepath) = @_; - my $imagename; - if (xCAT::Utils->isLinux()) - { - my @fields = split('/', $imagepath); - $imagename .= $fields[5]; - $imagename .= "-"; - $imagename .= $fields[3]; - $imagename .= "-"; - $imagename .= $fields[4]; - } - else - { # AIX - my @fields = split('/', $imagepath); - my $name = pop @fields; - $imagename = $name; - } +sub get_image_name +{ + my ($class, $imagepath) = @_; + my $imagename; + if (xCAT::Utils->isLinux()) + { + my @fields = split('/', $imagepath); + $imagename .= $fields[5]; + $imagename .= "-"; + $imagename .= $fields[3]; + $imagename .= "-"; + $imagename .= $fields[4]; + } + else + { # AIX + my @fields = split('/', $imagepath); + my $name = pop @fields; + $imagename = $name; + } - return $imagename; + return $imagename; } - #------------------------------------------------------------------------------- =head3 logEventsToDatabase @@ -2912,78 +3079,49 @@ sub get_image_name { =cut #------------------------------------------------------------------------------- -sub logEventsToDatabase{ - my $pEvents=shift; - if (($pEvents) && ($pEvents =~ /xCAT::Utils/)) { - $pEvents=shift; +sub logEventsToDatabase +{ + my $pEvents = shift; + if (($pEvents) && ($pEvents =~ /xCAT::Utils/)) + { + $pEvents = shift; } - - if (($pEvents) && (@$pEvents > 0)) { - my $currtime; - my $tab = xCAT::Table->new("eventlog",-create => 1,-autocommit => 0); - if (!$tab) { - return (1, "The evnetlog table cannot be opened."); - } - foreach my $event (@$pEvents) { - #create event time if it does not exist - if (!exists($event->{eventtime})) { - if (!$currtime) { - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time); - $currtime=sprintf("%02d-%02d-%04d %02d:%02d:%02d", $mon+1,$mday,$year+1900,$hour,$min,$sec); - } - $event->{eventtime}=$currtime; - } - my @ret=$tab->setAttribs(undef, $event); + if (($pEvents) && (@$pEvents > 0)) + { + my $currtime; + my $tab = xCAT::Table->new("eventlog", -create => 1, -autocommit => 0); + if (!$tab) + { + return (1, "The evnetlog table cannot be opened."); + } + + foreach my $event (@$pEvents) + { + + #create event time if it does not exist + if (!exists($event->{eventtime})) + { + if (!$currtime) + { + my ( + $sec, $min, $hour, $mday, $mon, + $year, $wday, $yday, $isdst + ) + = localtime(time); + $currtime = sprintf("%02d-%02d-%04d %02d:%02d:%02d", + $mon + 1, $mday, $year + 1900, + $hour, $min, $sec); + } + $event->{eventtime} = $currtime; + } + my @ret = $tab->setAttribs(undef, $event); if (@ret > 1) { return (1, $ret[1]); } - } - $tab->commit; - } - + } + $tab->commit; + } + return (0, ""); } - -#------------------------------------------------------------------------------- - -=head3 CheckVersion - Checks the two versions numbers to see which one is greater. - Arguments: - ver_a the version number in format of d.d.d.d... - ver_b the version number in format of d.d.d.d... - Returns: - 1 if ver_a is greater than ver_b - 0 if ver_a is eaqual to ver_b - -1 if ver_a is smaller than ver_b - -=cut - -#------------------------------------------------------------------------------- -sub CheckVersion { - my $ver_a=shift; - if ($ver_a =~ /xCAT::Utils/) { - $ver_a=shift; - } - my $ver_b=shift; - - my @a=split(/\./,$ver_a); - my @b=split(/\./,$ver_b); - my $len_a=@a; - my $len_b=@b; - - my $index=0; - my $max_index=($len_a>$len_b) ? $len_a : $len_b; - - for ($index=0; $index <= $max_index; $index++) { - my $val_a=($len_a < $index) ? 0 : $a[$index]; - my $val_b=($len_b < $index) ? 0 : $b[$index]; - if ($val_a > $val_b) { return 1;} - if ($val_a < $val_b) { return -1;} - } - - return 0; -} - - - 1; diff --git a/xCAT-client/bin/xdsh b/xCAT-client/bin/xdsh index 976a921bd..feb902908 100644 --- a/xCAT-client/bin/xdsh +++ b/xCAT-client/bin/xdsh @@ -151,6 +151,14 @@ if (!($::CONTEXT_SET)) push(@{$cmdref->{env}}, "DSH_CONTEXT=$ENV{'DSH_CONTEXT'}"); } } +if ($ENV{'DSH_REMOTE_PASSWORD'}) +{ + push(@{$cmdref->{env}}, "DSH_REMOTE_PASSWORD=$ENV{'DSH_REMOTE_PASSWORD'}"); +} +if ($ENV{'DSH_CURRENT_USERID'}) +{ + push(@{$cmdref->{env}}, "DSH_CURRENT_USERID=$ENV{'DSH_CURRENT_USERID'}"); +} xCAT::Client::submit_request($cmdref, \&xCAT::Client::handle_response); exit $xCAT::Client::EXITCODE; @@ -176,20 +184,20 @@ sub parse_args_xdsh my %options = (); if ( !GetOptions( - 'e|execute' => \$options{'execute'}, - 'f|fanout=i' => \$options{'fanout'}, - 'h|help' => \$options{'help'}, - 'l|user=s' => \$options{'user'}, - 'm|monitor' => \$options{'monitor'}, - 'o|node-options=s' => \$options{'node-options'}, - 'q|show-config' => \$options{'show-config'}, - 'r|node-rsh=s' => \$options{'node-rsh'}, - 'i|rootimg=s' => \$options{'rootimg'}, - 's|stream' => \$options{'streaming'}, - 't|timeout=i' => \$options{'timeout'}, - 'v|verify' => \$options{'verify'}, - 'z|exit-status' => \$options{'exit-status'}, - + 'e|execute' => \$options{'execute'}, + 'f|fanout=i' => \$options{'fanout'}, + 'h|help' => \$options{'help'}, + 'l|user=s' => \$options{'user'}, + 'm|monitor' => \$options{'monitor'}, + 'o|node-options=s' => \$options{'node-options'}, + 'q|show-config' => \$options{'show-config'}, + 'r|node-rsh=s' => \$options{'node-rsh'}, + 'i|rootimg=s' => \$options{'rootimg'}, + 's|stream' => \$options{'streaming'}, + 't|timeout=i' => \$options{'timeout'}, + 'v|verify' => \$options{'verify'}, + 'w|touserid=s' => \$options{'touserid'}, + 'z|exit-status' => \$options{'exit-status'}, 'B|bypass' => \$options{'bypass'}, 'C|context=s' => \$options{'context'}, 'E|environment=s' => \$options{'environment'}, @@ -201,7 +209,7 @@ sub parse_args_xdsh 'T|trace' => \$options{'trace'}, 'V|version' => \$options{'version'}, - 'devicetype=s' => \$options{'devicetype'}, + 'devicetype=s' => \$options{'devicetype'}, 'command-name|commandName=s' => \$options{'command-name'}, 'command-description|commandDescription=s' => \$options{'command-description'}, @@ -225,7 +233,29 @@ sub parse_args_xdsh } if ($options{'ssh-setup'}) { - $ENV{XCATBYPASS} = "yes"; # bypass xcatd + + # prompt for the password for the current userid on the node + my $current_userid = getlogin(); + $ENV{DSH_CURRENT_USERID} = $current_userid; + my $userpw; + my $msg = + "Enter the password for the userid on the node where the ssh keys \nwill be updated:\n"; + xCAT::MsgUtils->message("I", $msg); + system("stty -echo"); # turn off keyboard + chop($userpw = ); + system("stty echo"); # turn on keyboard + + if ($userpw eq "") + { # did not enter a password + $msg = "Did not enter a password must abort the key exchange"; + xCAT::MsgUtils->message("E", $msg); + exit 2; + } + else + { # password entered pass to the server + $ENV{DSH_REMOTE_PASSWORD} = $userpw; + + } } if ($options{'version'}) { diff --git a/xCAT-server/sbin/remoteshell.expect b/xCAT-server/sbin/remoteshell.expect index 77a904372..49bc9fc72 100644 --- a/xCAT-server/sbin/remoteshell.expect +++ b/xCAT-server/sbin/remoteshell.expect @@ -1,17 +1,34 @@ #!/usr/bin/expect -- # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html # +# # sets up ssh on the input node list # called from by xdsh -K command +# Environment Variables: # -# DSH_REMOTE_CMD set to path to remote shell (ssh) +# DSH_REMOTE_CMD set to path to remote shell (ssh) # root password must agree on all the nodes # +# XCAT_ROOT set to root of xCAT install +# +# DSH_REMOTE_PASSWORD - user password for -s option +# +# SSH_SETUP_COMMAND - Command to be sent to the IB switch to setup SSH. +# +# DSH_FROM_USERID_HOME - The home directory of the userid from +# where the ssh keys will be obtained +# to send +# +# DSH_FROM_USERID - The userid from where the ssh keys will be obtained +# to send +# to the node, or generated and then obtained to send to the +# node. +# DSH_TO_USERID - The userid on the node where the ssh keys will be updated. +# # Usage: remoteshell.expect # [-t remote_shell hostname] test the remoteshell on the host # [-k] Generates the ssh keys needed -# [-n hostname] - gather ssh keys for the hostname -# [-s node_list] +# [-s node_list] copies the ssh keys to the nodes # [-h ] usage # # exit 0 - good @@ -21,6 +38,9 @@ # ################################################################################ +# +################################################################################ + set timeout 80 log_user 0 @@ -39,17 +59,34 @@ if { [info exists env(XCATROOT)] } { } else { set xcatroot "/opt/xcat" } -if { [info exists env(XCAT_UPD_MULTNODES)] } { - set manynodes $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 "" } +# User on the Management node that has the ssh keys +if { [info exists env(DSH_FROM_USERID)] } { + set from_userid $env(DSH_FROM_USERID) +} else { + set from_userid "root" +} + +# User on the node where we will send the ssh keys +if { [info exists env(DSH_TO_USERID)] } { + set to_userid $env(DSH_TO_USERID) +} else { + set to_userid "root" +} + +# get the from userid and its home directory to get the ssh keys + +#set home [exec /usr/bin/perl -e {$user = $ENV{'DSH_FROM_USERID'} ? $ENV{'DSH_FROM_USERID'} : "root"; @info = getpwnam($user); print $info[7] . "\n";}] + +#if { [string compare $home $empty] ==0 } { +#set home $env(HOME) +#} +set home $env(DSH_FROM_USERID_HOME) # # check input arguments @@ -60,7 +97,6 @@ if { [llength $argv] != 0 } { puts "Usage: remoteshell.expect" puts " -t remote_shell hostname - test the remoteshell on the host" puts " -k Generates the ssh keys needed" - puts " -n hostname - gather ssh keys for the hostname" puts " -s node_list - copies keys to the nodes" puts " -h usage" exit 0 @@ -68,13 +104,8 @@ 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" - 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 ] + set pid [ spawn [lindex $argv 1] [lindex $argv 2] -l $to_userid echo test.success ] expect { timeout { exit 1 } "Are you sure you want to continue connecting (yes/no)?" { @@ -94,11 +125,7 @@ if { [llength $argv] != 0 } { } exit 1 } elseif { [string compare "-k" [lindex $argv 0]] ==0 } { - # -k means copy the keys to the nodes - set home [exec /usr/bin/perl -e {$user = $ENV{'USER'} ? $ENV{'USER'} : "root"; @info = getpwnam($user); print $info[7] . "\n";}] - if { [string compare $home $empty] ==0 } { - set home $env(HOME) - } + # -k means generate the keys to the nodes # check to see if ssh rsa1 keys exists, if not generate it if {![file exists "$home/.ssh/identity"]} { # key does not exist set env(LC_ALL) "C" @@ -179,39 +206,8 @@ if { [llength $argv] != 0 } { send "\r" expect eof } - } elseif { [string compare "-n" [lindex $argv 0]] ==0 } { - #gather ssh host keys - set hostname [lindex $argv 1] - set hlist [split $hostname '.'] - set name "" - set nlist "" - set j [llength $hlist] - for { set i 0 } { $i<$j} {incr i } { - set element [lindex $hlist $i] - if { $i == 0 } { - set name $element - } else { - - set name "$name.$element" - } - lappend nlist $name - } - - foreach hn $nlist { - set env(LC_ALL) "C" - set pid [ spawn $remoteshell $hn -l root echo test.success ] - expect { - "Are you sure you want to continue connecting (yes/no)?" { - send "yes\r" - exp_continue - } - "*ssword*" { - exec /bin/kill $pid - } - "test.success" { continue } - } - } } elseif { [string compare "-s" [lindex $argv 0]] ==0 } { + # copy the keys to the nodes set nodes [lindex $argv 1] set empty "" if { [string compare $nodes $empty] ==0 } { @@ -222,27 +218,29 @@ if { [llength $argv] != 0 } { set nodelist2 $nodelist 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 directory "$home/.ssh" + set fh_auth_keys2 [ open "$home/.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) + if { [info exists env(DSH_REMOTE_PASSWORD)] } { + set word $env(DSH_REMOTE_PASSWORD) } else { - exec /bin/stty -echo - set timeout 360 - puts "Enter the password for the userid (usually root) used to access the following target nodes: $printlist" - expect_user "*\n" - set timeout 80 - exec /bin/stty echo - set word $expect_out(buffer) - set expect_out(buffer) "" - send_user "\n" + exec /bin/stty -echo + set timeout 360 + puts "Enter the password for the userid:$to_userid to access the following target nodes: $printlist" + expect_user "*\n" + set timeout 80 + exec /bin/stty echo + set word $expect_out(buffer) + set expect_out(buffer) "" + send_user "\n" } + foreach node $nodelist { + puts $node if { [string compare $ssh_setup_cmd $empty] ==0 } { set env(LC_ALL) "C" - set pid [ spawn $scp -r -p $directory root\@$node:/tmp ] + set pid [ spawn $remoteshell $node -l $to_userid /bin/mkdir -p /tmp/$to_userid/.ssh ] expect { "Are you sure you want to continue connecting (yes/no)?" { send "yes\r" @@ -256,7 +254,49 @@ if { [llength $argv] != 0 } { exec /bin/kill $pid } } - set pid [ spawn $remoteshell $node -l root /tmp/.ssh/copy.perl ] + set pid [ spawn $scp $directory/authorized_keys2 $to_userid\@$node:/tmp/$to_userid/.ssh ] + 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 + } + } + set pid [ spawn $scp $directory/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh ] + 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 + } + } + set pid [ spawn $scp $directory/copy.perl $to_userid\@$node:/tmp/$to_userid/.ssh ] + 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 + } + } + set pid [ spawn $remoteshell $node -l $to_userid /tmp/$to_userid/.ssh/copy.perl ] expect { "Are you sure you want to continue connecting (yes/no)?" { send "yes\r" @@ -285,7 +325,7 @@ if { [llength $argv] != 0 } { } # 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 ] + set pid [ spawn $remoteshell $node -l $to_userid $ssh_setup_string ] expect { "Are you sure you want to continue connecting (yes/no)?" { send "yes\r" @@ -320,12 +360,7 @@ if { [llength $argv] != 0 } { } foreach hn $nlist { set env(LC_ALL) "C" - 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 ] + set pid [ spawn $remoteshell $hn -l $to_userid echo test.success ] expect { "Are you sure you want to continue connecting (yes/no)?" { send "yes\r" @@ -356,80 +391,19 @@ if { [llength $argv] != 0 } { } else { exit 0 } - } elseif { [string compare "-d" [lindex $argv 0]] ==0 } { - # check xdsh ping to verify - set env(DSH_PING_VERIFY) "1" - set env(DSH_LIST) [lindex $argv 1] - log_user 1 - set timeout 360 - set env(LC_ALL) "C" - if { [info exists env(XCAT_PING)] } { - set pid [ spawn "$xcatroot/bin/xdsh" -B -v -t 80 /bin/echo test.success ] - } else { - set pid [ spawn "$xcatroot/bin/xdsh" -B -t 80 /bin/echo test.success ] - } - expect { - timeout { - exec /bin/kill $pid - set failed "1" - } - } - log_user 0 - set timeout 80 - } elseif { [string compare "-dn" [lindex $argv 0]] ==0 } { - # check xdsh ping nodes - set env(DSH_PING_VERIFY) "1" - #set env(DSH_LIST) [lindex $argv 1] - set node [lindex $argv 1] - log_user 1 - set timeout 360 - set env(LC_ALL) "C" - if { [info exists env(XCAT_PING)] } { - set pid [ spawn "$xcatroot/bin/xdsh" $node -B -v -t 80 /bin/echo test.success ] - } else { # no verify - set pid [ spawn "$xcatroot/bin/xdsh" $node -B -t 80 /bin/echo test.success ] - } - expect { - timeout { - exec /bin/kill $pid - set failed "1" - } - } - log_user 0 - set timeout 80 - } elseif { [string compare "-ds" [lindex $argv 0]] ==0 } { - # check dsh, ssh with options - set env(DSH_PING_VERIFY) "1" - set env(DSH_LIST) [lindex $argv 1] - log_user 1 - set timeout 360 - set env(LC_ALL) "C" - if { [info exists env(XCAT_PING)] } { - set pid [ spawn $xcatroot/bin/xdsh -B -v -o "-o BatchMode=yes" -t 80 /bin/echo test.success ] - } else { # no verify - set pid [ spawn $xcatroot/bin/xdsh -B -o "-o BatchMode=yes" -t 80 /bin/echo test.success ] - } - expect { - timeout { - exec /bin/kill $pid - set failed "1" - } - } - log_user 0 - set timeout 80 - } else { # usage error + } else { # usage error + puts "flag entered is not valid" puts "Usage: remoteshell.expect" puts " -t remote_shell hostname - test the remoteshell on the host" puts " -k Generates the ssh keys needed" - puts " -n hostname - gather ssh keys for the hostname" puts " -s node_list - copies keys to the nodes" exit 2 } } else { # usage error + puts "Command requires a flag" puts "Usage: remoteshell.expect" puts " -t remote_shell hostname - test the remoteshell on the host" puts " -k Generates the ssh keys needed" - puts " -n hostname - gather ssh keys for the hostname" puts " -s node_list - copies keys to the nodes" exit 2 }