diff --git a/perl-xCAT/xCAT/RemoteShellExp.pm b/perl-xCAT/xCAT/RemoteShellExp.pm index 4d9b3d34d..925465dc0 100755 --- a/perl-xCAT/xCAT/RemoteShellExp.pm +++ b/perl-xCAT/xCAT/RemoteShellExp.pm @@ -495,6 +495,7 @@ sub sendnodeskeys # in $HOME/.ssh/tmp/authorized_keys # copy to the node to the temp directory # scp $HOME/.ssh/tmp/authorized_keys to_userid@:/tmp/$to_userid/.ssh + # scp $HOME/.ssh/id_rsa.pub to_userid@:/tmp/$to_userid/.ssh # If you are going to enable ssh to ssh between nodes, then # scp $HOME/.ssh/id_rsa to that temp directory on the node # copy the script $HOME/.ssh/copy.sh to the node, it will do the @@ -607,11 +608,11 @@ sub sendnodeskeys my $spawncopyfiles; if ($ENV{'DSH_ENABLE_SSH'}) { # we will enable node to node ssh $spawncopyfiles= - "$remotecopy $home/.ssh/id_rsa $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; + "$remotecopy $home/.ssh/id_rsa $home/.ssh/id_rsa.pub $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; } else { # no node to node ssh ( don't send private key) $spawncopyfiles= - "$remotecopy $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; + "$remotecopy $home/.ssh/id_rsa.pub $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; } # send copy command unless ($sendkeys->spawn($spawncopyfiles)) diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index e588ec9f5..6850e50f2 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -1052,7 +1052,8 @@ site => { " Set to NOGROUPS,if you do not wish to enabled any group of compute nodes.\n". " Service Nodes are not affected by this attribute\n". " they are always setup with\n". - " passwordless root access to nodes and other SN.\n\n". + " passwordless root access to nodes and other SN.\n". + " If using the zone table, this attribute in not used.\n\n". " -----------------\n". "SERVICES ATTRIBUTES\n". " -----------------\n". @@ -1191,12 +1192,13 @@ performance => { }, }, zone => { - cols => [qw(zonename sshkeydir defaultzone comments disable)], + cols => [qw(zonename sshkeydir sshbetweennodes defaultzone comments disable)], keys => [qw(zonename)], table_desc => 'Defines a cluster zone for nodes that share root ssh key access to each other.', descriptions => { zonename => 'The name of the zone.', sshkeydir => 'Directory containing the shared root ssh RSA keys.', + sshbetweennodes => 'Indicates whether passwordless ssh will be setup between the nodes of this zone. Values are yes/1 or no/0. Default is yes. ', defaultzone => 'If nodes are not assigned to any other zone, they will default to this zone. If value is set to yes or 1.', comments => 'Any user-provided notes.', disable => "Set to 'yes' or '1' to comment out this row.", @@ -3083,6 +3085,10 @@ push(@{$defspec{node}->{'attrs'}}, @nodeattrs); tabentry => 'zone.sshkeydir', access_tabentry => 'zone.zonename=attr:zonename', }, + {attr_name => 'sshbetweennodes', + tabentry => 'zone.sshbetweennodes', + access_tabentry => 'zone.zonename=attr:zonename', + }, {attr_name => 'defaultzone', tabentry => 'zone.defaultzone', access_tabentry => 'zone.zonename=attr:zonename', diff --git a/perl-xCAT/xCAT/TableUtils.pm b/perl-xCAT/xCAT/TableUtils.pm index 9e3b452ad..b44cb6f27 100644 --- a/perl-xCAT/xCAT/TableUtils.pm +++ b/perl-xCAT/xCAT/TableUtils.pm @@ -19,6 +19,7 @@ if ($^O =~ /^aix/i) { use lib "$::XCATROOT/lib/perl"; use strict; require xCAT::Table; +require xCAT::Zone; use File::Path; #----------------------------------------------------------------------- @@ -271,7 +272,7 @@ sub bldnonrootSSHFiles Error: 0=good, 1=error Example: - xCAT::TableUtils->setupSSH(@target_nodes); + xCAT::TableUtils->setupSSH(@target_nodes,$expecttimeout); Comments: Does not setup known_hosts. Assumes automatically setup by SSH ( ssh config option StrictHostKeyChecking no should @@ -335,21 +336,21 @@ sub setupSSH $::REMOTE_SHELL = "/usr/bin/ssh"; my $rsp = {}; + # Get the home directory my $home = xCAT::Utils->getHomeDir($from_userid); $ENV{'DSH_FROM_USERID_HOME'} = $home; - if ($from_userid eq "root") { - # make the directory to hold keys to transfer to the nodes if (!-d $SSHdir) { mkpath("$SSHdir", { mode => 0755 }); } - # generates new keys for root, if they do not already exist + # generates new keys for root, if they do not already exist ~/.ssh + # nodes not used on this option but in there to preserve the interface my $rc= xCAT::RemoteShellExp->remoteshellexp("k",$::CALLBACK,$::REMOTE_SHELL,$n_str,$expecttimeout); @@ -374,7 +375,9 @@ else fi mkdir -p \$dest_dir cat /tmp/$to_userid/.ssh/authorized_keys >> \$home/.ssh/authorized_keys 2>&1 +cat /tmp/$to_userid/.ssh/id_rsa.pub >> \$home/.ssh/authorized_keys 2>&1 cp /tmp/$to_userid/.ssh/id_rsa \$home/.ssh/id_rsa 2>&1 +cp /tmp/$to_userid/.ssh/id_rsa.pub \$home/.ssh/id_rsa.pub 2>&1 chmod 0600 \$home/.ssh/id_* 2>&1 rm -f /tmp/$to_userid/.ssh/* 2>&1 rmdir \"/tmp/$to_userid/.ssh\" @@ -386,6 +389,7 @@ rmdir \"/tmp/$to_userid\" \n"; my $auth_key2=0; if ($from_userid eq "root") { + # this will put the root/.ssh/id_rsa.pub key in the authorized keys file to put on the node my $rc = xCAT::TableUtils->cpSSHFiles($SSHdir); if ($rc != 0) { # error @@ -418,13 +422,43 @@ rmdir \"/tmp/$to_userid\" \n"; xCAT::TableUtils->bldnonrootSSHFiles($from_userid); } - # send the keys to the nodes for root or some other id - # - # This environment variable determines whether to setup - # node to node ssh - # The nodes must be checked against the site.sshbetweennodes attribute # For root user and not to devices only to nodes if (($from_userid eq "root") && (!($ENV{'DEVICETYPE'}))) { + # Need to check if nodes are in a zone. + # If in a zone, then root ssh keys for the node will be taken from the zones ssh keys not ~/.ssh + # zones are only supported on nodes that are not a service node. + # Also for the call to RemoteShellExp, we must group the nodes that are in the same zone + + my $tab = xCAT::Table->new("zone"); + if ($tab) + { + # if we have zones, need to send the zone keys to each node in the zone + my @zones = $tab->getAllAttribs('zonename'); + $tab->close(); + if (@zones) { # we have zones defined + my $rc = xCAT::TableUtils->sendkeystozones($ref_nodes,$expecttimeout); + if ($rc != 0) + { + $rsp->{data}->[0] = "Error sending ssh keys to the zones.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + + } + return 0; + } + } else { + $rsp->{data}->[0] = "Could not open zone table.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + } + + + # if no zone table defined, do it the old way + # send the keys to the nodes for root or some other id + # + # The nodes must be checked against the site.sshbetweennodes attribute + # This site attribute determines whether to setup + # node to node ssh my $enablenodes; my $disablenodes; my @nodelist= split(",", $n_str); @@ -440,10 +474,10 @@ rmdir \"/tmp/$to_userid\" \n"; } } - my $cmd; if ($enablenodes) { # node on list to setup nodetonodessh chop $enablenodes; # remove last comma $ENV{'DSH_ENABLE_SSH'} = "YES"; + # send the keys to the nodes my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$enablenodes,$expecttimeout); if ($rc != 0) { @@ -452,8 +486,9 @@ rmdir \"/tmp/$to_userid\" \n"; } } - if ($disablenodes) { # node on list to setup nodetonodessh + if ($disablenodes) { # node on list to disable nodetonodessh chop $disablenodes; # remove last comma + # send the keys to the nodes my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$disablenodes,$expecttimeout); if ($rc != 0) { @@ -462,6 +497,7 @@ rmdir \"/tmp/$to_userid\" \n"; } } + } else { # from user is not root or it is a device , always send private key $ENV{'DSH_ENABLE_SSH'} = "YES"; my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$n_str,$expecttimeout); @@ -503,6 +539,60 @@ rmdir \"/tmp/$to_userid\" \n"; #-------------------------------------------------------------------------------- +=head3 sendkeystozones + + Transfers the ssh keys + for the root id on the nodes using the zone table. + + + Arguments: + Array of nodes + Timeout for expect call (optional) + 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: + 0=good, 1=error + Example: + xCAT::TableUtils->setupSSH(@target_nodes,$expecttimeout); + Comments: + Does not setup known_hosts. Assumes automatically + setup by SSH ( ssh config option StrictHostKeyChecking no should + be set in the ssh config file). + +=cut + +#-------------------------------------------------------------------------------- +sub sendkeystozones +{ + my ($class, $ref_nodes,$expecttimeout) = @_; + my @nodes=$ref_nodes; + my %zonehash =xCAT::Zone->getNodeZones(@nodes); + # for each zone in the zonehash + # if sshbetweennodes is yes + # $ENV{'DSH_ENABLE_SSH'} = "YES"; + # else + # unset $ENV{'DSH_ENABLE_SSH'} + # send the keys to the nodes + # my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$nodelist,$expecttimeout); + # if ($rc != 0) + # { + # $rsp->{data}->[0] = "remoteshellexp failed sending keys to $zonename."; + # xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + # + # } + # } # endforeach + return 0; +} +#-------------------------------------------------------------------------------- + =head3 cpSSHFiles Builds authorized_keyfiles for root diff --git a/perl-xCAT/xCAT/Zone.pm b/perl-xCAT/xCAT/Zone.pm index bf62b7635..e974a366d 100644 --- a/perl-xCAT/xCAT/Zone.pm +++ b/perl-xCAT/xCAT/Zone.pm @@ -199,7 +199,7 @@ sub getdefaultzone foreach my $zone (@zones) { # Look for the defaultzone=yes/1 entry if ((defined($zone->{defaultzone})) && - (($zone->{defaultzone} =~ "yes") || ($zone->{defaultzone} = "1"))) { + (($zone->{defaultzone} =~ "yes") || ($zone->{defaultzone} eq "1"))) { $defaultzone = $zone->{zonename}; } $tab->close(); @@ -249,28 +249,29 @@ sub iszonedefined -> {sshkeydir} -> directory containing ssh RSA keys -> {defaultzone} -> is it the default zone Example: - my %zonehash =xCAT::Zone->getNodeZones($nodelist); + my %zonehash =xCAT::Zone->getNodeZones(@nodearray); Rules: If the nodes nodelist.zonename attribute is a zonename, it is assigned to that zone If the nodes nodelist.zonename attribute is undefined: If there is a defaultzone in the zone table, the node is assigned to that zone If there is no defaultzone in the zone table, the node is assigned to the ~.ssh keydir + $::GETZONEINFO_RC + 0 = good return + 1 = error occured =cut #-------------------------------------------------------------------------------- sub getzoneinfo { my ($class, $callback,$nodes) = @_; - - # make the list into an array -# $nodelist=~ s/\s*//g; # remove blanks -# my @nodes = split ',', $nodelist; + $::GETZONEINFO_RC=0; my $zonehash; my $defaultzone; # read all the zone table my $zonetab = xCAT::Table->new("zone"); + my @zones; if ($zonetab){ - my @zones = $zonetab->getAllAttribs('zonename','sshkeydir','defaultzone'); + @zones = $zonetab->getAllAttribs('zonename','sshkeydir','sshbetweennodes','defaultzone'); $zonetab->close(); if (@zones) { foreach my $zone (@zones) { @@ -279,7 +280,7 @@ sub getzoneinfo $zonehash->{$zonename}->{defaultzone}= $zone->{defaultzone}; # find the defaultzone if ((defined($zone->{defaultzone})) && - (($zone->{defaultzone} =~ "yes") || ($zone->{defaultzone} = "1"))) { + (($zone->{defaultzone} =~ "yes") || ($zone->{defaultzone} eq "1"))) { $defaultzone = $zone->{zonename}; } } @@ -289,6 +290,7 @@ sub getzoneinfo $rsp->{error}->[0] = "Error reading the zone table. "; xCAT::MsgUtils->message("E", $rsp, $callback); + $::GETZONEINFO_RC =1; return; } @@ -314,6 +316,15 @@ sub getzoneinfo $zonename=$nodehash->{$node}->[0]->{zonename}; } if (defined($zonename)) { # zonename explicitly defined in nodelist.zonename + # check to see if defined in the zone table + if (!(grep(/^$zonename$/, @zones))) { + my $rsp = {}; + $rsp->{error}->[0] = + "$node has a zonenane: $zonename that is not define in the zone table. Remove the zonename from the node, or create the zone using mkzone."; + xCAT::MsgUtils->message("E", $rsp, $callback); + $::GETZONEINFO_RC =1; + return; + } push @{$zonehash->{$zonename}->{nodes}},$node; } else { # no explict zonename if (defined ($defaultzone)) { # there is a default zone in the zone table, use it diff --git a/xCAT-client/pods/man1/updatenode.1.pod b/xCAT-client/pods/man1/updatenode.1.pod index 24ad11b11..441870d53 100644 --- a/xCAT-client/pods/man1/updatenode.1.pod +++ b/xCAT-client/pods/man1/updatenode.1.pod @@ -8,6 +8,8 @@ B B [B<-V>|B<--verbose>] [B<-F>|B<--sync>] [B<-f>|B<--sns B B [B<-k>|B<--security>] [B<-t timeout>] +B B [B<-g>|B<--genmypost>] + B B [B<-V>|B<--verbose>] [B<-t timeout>] [B] B B [B<-V>|B<--verbose>] [B<-f>|B<--snsync>] @@ -327,6 +329,11 @@ For statelite installations to sync files, you should use the read-only option for files/directories listed in litefile table with source location specified in the litetree table. +=item B<-g|--genmypost + +Will generate a new mypostscript file for the +nodes in the noderange, if site precreatemypostscripts is 1 or YES. + =item B<-h|--help> diff --git a/xCAT-server/lib/xcat/plugins/zone.pm b/xCAT-server/lib/xcat/plugins/zone.pm index 19efa20c7..91398d3a8 100644 --- a/xCAT-server/lib/xcat/plugins/zone.pm +++ b/xCAT-server/lib/xcat/plugins/zone.pm @@ -108,6 +108,7 @@ sub process_request 'h|help' => \$options{'help'}, 'k|sshkeypath=s' => \$options{'sshkeypath'}, 'K|genkeys' => \$options{'gensshkeys'}, + 's|sshbetweennodes=s' => \$options{'sshbetweennodes'}, 'v|version' => \$options{'version'}, 'V|Verbose' => \$options{'verbose'}, ) @@ -244,6 +245,7 @@ sub mkzone # Create path to generated ssh keys $keydir .= $request->{zonename}; + # update the zone table $rc=updatezonetable($request, $callback,$options,$keydir); @@ -337,11 +339,11 @@ sub usage my $usagemsg2=""; if ($command eq "mkzone") { $usagemsg1 = " mkzone -h \n mkzone -v \n"; - $usagemsg2 = " mkzone [-V] [--defaultzone] [-k ] [-g] [-f]"; + $usagemsg2 = " mkzone [-V] [--defaultzone] [-k ] [-g] [-f] [-s ]"; } else { if ($command eq "chzone") { $usagemsg1 = " chzone -h \n chzone -v \n"; - $usagemsg2 = " chzone [-V] [--defaultzone] [-k ] [-r ] [-g] "; + $usagemsg2 = " chzone [-V] [--defaultzone] [-k ] [-r ] [-g] [-s ]"; } else { if ($command eq "rmzone") { $usagemsg1 = " rmzone -h \n rmzone -v \n"; @@ -424,6 +426,18 @@ sub updatezonetable my $tab = xCAT::Table->new("zone"); if ($tab) { + # read a record from the zone table, if it is empty then add + # the xcatdefault entry + my @zones = $tab->getAllAttribs('zonename'); + if (!(@zones)) { # table empty + my %xcatdefaultzone; + $xcatdefaultzone{defaultzone} ="yes"; + $xcatdefaultzone{sshbetweennodes} ="yes"; + $xcatdefaultzone{sshkeydir} ="~/.ssh"; + $tab->setAttribs({zonename => "xcatdefault"}, \%xcatdefaultzone); + } + + # now add the users zone my %tb_cols; $tb_cols{sshkeydir} = $keydir; my $zonename=$request->{zonename};