xdsh -K support (still need to do hierarchy)

This commit is contained in:
lissav 2014-02-24 11:48:09 -05:00
parent 539f37f391
commit d5695f5727
3 changed files with 151 additions and 91 deletions

View File

@ -35,7 +35,7 @@ package xCAT::RemoteShellExp;
node.
DSH_TO_USERID - The userid on the node where the ssh keys will be updated.
DSH_ENABLE_SSH - Node to node root passwordless ssh will be setup.
DSH_ZONE_SSHKEYS - directory containing the zones root .ssh keys
Usage: remoteshellexp
[-t node list] test ssh connection to the node
@ -144,7 +144,7 @@ sub remoteshellexp
} else {
$from_userid="root";
}
# set User on the node where we will send the keys
# set User on the node where we will send the keys
# this id can be a local id as well as root
if ($ENV{'DSH_TO_USERID'}) {
$to_userid=$ENV{'DSH_TO_USERID'};
@ -154,18 +154,19 @@ sub remoteshellexp
# set User home directory to find the ssh public key to send
# For non-root ids information may not be in /etc/passwd
# but elsewhere like LDAP
if ($ENV{'DSH_FROM_USERID_HOME'}) {
$home=$ENV{'DSH_FROM_USERID_HOME'};
$home=$ENV{'DSH_FROM_USERID_HOME'};
} else {
$home=xCAT::Utils->getHomeDir($from_userid);
$home=xCAT::Utils->getHomeDir($from_userid);
}
# This indicates we will generate new ssh keys for the user,
# if they are not already there
my $key="$home/.ssh/id_rsa";
my $key2="$home/.ssh/id_rsa.pub";
# Check to see if empty
if (-z $key) {
# unless using zones
my $key="$home/.ssh/id_rsa";
my $key2="$home/.ssh/id_rsa.pub";
# Check to see if empty
if (-z $key) {
my $rsp = {};
$rsp->{error}->[0] =
"The $key file is empty. Remove it and rerun the command.";
@ -183,8 +184,7 @@ sub remoteshellexp
}
if (($flag eq "k") && (!(-e $key)))
{
# if the file size of the id_rsa key is 0, tell them to remove it
# and run the command again
# updating keys and the key file does not exist
$rc=xCAT::RemoteShellExp->gensshkeys($expecttimeout);
}
# send ssh keys to the nodes/devices, to setup passwordless ssh
@ -200,6 +200,9 @@ sub remoteshellexp
if ($ssh_setup_cmd) { # setup ssh on devices
$rc=xCAT::RemoteShellExp->senddeviceskeys($remoteshell,$remotecopy,$to_userid,$to_user_password,$home,$ssh_setup_cmd,$nodes, $expecttimeout);
} else { #setup ssh on nodes
if ($ENV{'DSH_ZONE_SSHKEYS'}) { # if using zones the override the location of the keys
$home= $ENV{'DSH_ZONE_SSHKEYS'};
}
$rc=xCAT::RemoteShellExp->sendnodeskeys($remoteshell,$remotecopy,$to_userid,$to_user_password,$home,$nodes, $expecttimeout);
}
}
@ -496,11 +499,14 @@ sub sendnodeskeys
# copy to the node to the temp directory
# scp $HOME/.ssh/tmp/authorized_keys to_userid@<node>:/tmp/$to_userid/.ssh
# scp $HOME/.ssh/id_rsa.pub to_userid@<node>:/tmp/$to_userid/.ssh
# Note if using zones, the keys do not come from ~/.ssh but from the
# zone table, sshkeydir attribute. For zones the userid is always root
# 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
# the work of setting up the user's ssh keys and clean up
# ssh (run) copy.sh on the node
my @nodelist=split(/,/,$nodes);
foreach my $node (@nodelist) {
$sendkeys = new Expect;

View File

@ -427,23 +427,28 @@ rmdir \"/tmp/$to_userid\" \n";
if (($from_userid eq "root") && (!($ENV{'DEVICETYPE'}))) {
# Need to check if nodes are in a zone.
my @zones;
my $tab = xCAT::Table->new("zone");
my $tab = xCAT::Table->new("zone");
my @zones;
if ($tab)
{
# if we have zones, need to send the zone keys to each node in the zone
my @zones = $tab->getAllAttribs('zonename');
my @attribs = ("zonename");
@zones = $tab->getAllAttribs(@attribs);
$tab->close();
} else {
$rsp->{data}->[0] = "Could not open zone table.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
# check for zones, key send is different if zones defined or not
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);
exit 1;
}
} else { # no zones
@ -614,26 +619,117 @@ sub sendkeysNOzones
#--------------------------------------------------------------------------------
sub sendkeysTOzones
{
my ($class, $ref_nodes,$expecttimeout) = @_;
my ($class, $ref_nodes,$expecttimeout) = @_;
my @nodes=$ref_nodes;
my $n_str = $nodes[0];
my @nodelist= split(",", $n_str);
my %zonehash =xCAT::Zone->getNodeZones(@nodelist);
# 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;
my @nodes= split(",", $n_str);
my $rsp = ();
my $cmd;
my $roothome = xCAT::Utils->getHomeDir("root");
my $zonehash =xCAT::Zone->getzoneinfo($::CALLBACK,\@nodes);
foreach my $zonename (keys %$zonehash) {
# build list of nodes
my $zonenodelist="";
foreach my $node (@{$zonehash->{$zonename}->{nodes}}) {
$zonenodelist .= $node;
$zonenodelist .= ",";
}
$zonenodelist =~ s/,$//; # remove last comma
# if any nodes defined for the zone
if ($zonenodelist) {
# check to see if we enable passwordless ssh between the nodes
if (!(defined($zonehash->{$zonename}->{sshbetweennodes}))||
(($zonehash->{$zonename}->{sshbetweennodes} =~ /^yes$/i )
|| ($zonehash->{$zonename}->{sshbetweennodes} eq "1"))) {
$ENV{'DSH_ENABLE_SSH'} = "YES";
} else {
delete $ENV{'DSH_ENABLE_SSH'}; # do not enable passwordless ssh
}
# point to the ssh keys to send for this zone
my $keydir = $zonehash->{$zonename}->{sshkeydir} ;
# check to see if the id_rsa and id_rsa.pub key is in the directory
my $key="$keydir/id_rsa";
my $key2="$keydir/id_rsa.pub";
# Check to see if empty
if (!(-e $key)) {
my $rsp = {};
$rsp->{error}->[0] =
"The $key file does not exist for $zonename. Need to use chzone to regenerate the keys.";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1);
return 1;
}
if (!(-e $key2)) {
my $rsp = {};
$rsp->{error}->[0] =
"The $key2 file does not exist for $zonename. Need to use chzone to regenerate the keys.";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1);
return 1;
}
# now put copy.sh in the zone directory from ~/.ssh
my $rootkeydir="$roothome/.ssh";
if ($rootkeydir ne $keydir) { # the zone keydir is not the same as ~/.ssh.
$cmd="cp $rootkeydir/copy.sh $keydir";
xCAT::Utils->runcmd($cmd, 0);
if ($::RUNCMD_RC != 0)
{
my $rsp = {};
$rsp->{error}->[0] =
"Could not copy copy.sh to the zone key dir";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
}
# Also create $keydir/tmp and put root's id_rsa.pub (in authorized_keys) for the transfer
$cmd="mkdir -p $keydir/tmp";
xCAT::Utils->runcmd($cmd, 0);
if ($::RUNCMD_RC != 0)
{
my $rsp = {};
$rsp->{error}->[0] =
"Could not mkdir the zone $keydir/tmp";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
# create authorized_keys file
if (xCAT::Utils->isMN()) { # if on Management Node
$cmd = " cp $roothome/.ssh/id_rsa.pub $keydir/tmp/authorized_keys";
} else { # SN
$cmd = " cp $roothome/.ssh/authorized_keys $keydir/tmp/authorized_keys";
}
xCAT::Utils->runcmd($cmd, 0);
if ($::RUNCMD_RC != 0)
{
$rsp->{data}->[0] = "$cmd failed.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return (1);
}
else
{
chmod 0600, "$keydir/.ssh/tmp/authorized_keys";
}
# strip off .ssh
my ($newkeydir,$ssh) = (split(/\.ssh/, $keydir));
$ENV{'DSH_ZONE_SSHKEYS'} =$newkeydir ;
# send the keys to the nodes
my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",
$zonenodelist,$expecttimeout);
if ($rc != 0)
{
$rsp = {};
$rsp->{data}->[0] = "remoteshellexp failed sending keys to $zonename.";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
}
} # end nodes in the zone
} # end for each zone
return (0);
}
#--------------------------------------------------------------------------------

View File

@ -49,7 +49,7 @@ This program module file, is a set of Zone utilities used by xCAT *zone commands
=cut
#--------------------------------------------------------------------------------
sub genSSHRootKeys
sub genSSHRootKeys
{
my ($class, $callback, $keydir,$zonename,$rsakey) = @_;
@ -71,22 +71,6 @@ sub genSSHRootKeys
}
}
#
# create /install/postscripts/_ssh/zonename if needed
#
my $installdir = xCAT::TableUtils->getInstallDir(); # get installdir
if (!-d "$installdir/postscripts/_ssh/$zonename")
{
my $cmd = "/bin/mkdir -m 755 -p $installdir/postscripts/_ssh/$zonename";
my $output = xCAT::Utils->runcmd("$cmd", 0);
if ($::RUNCMD_RC != 0)
{
my $rsp = {};
$rsp->{error}->[0] = "Could not create $installdir/postscripts/_ssh/$zonename directory.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return 1;
}
}
#need to gen a new rsa key for root for the zone
my $pubfile = "$keydir/id_rsa.pub";
@ -152,29 +136,6 @@ sub genSSHRootKeys
xCAT::MsgUtils->message("E", $rsp, $callback);
return 1;
}
# copy authorized_keys for install on node
if (-r $pubfile)
{
my $cmd =
"/bin/cp -p $pubfile $installdir/postscripts/_ssh/$zonename ";
my $output = xCAT::Utils->runcmd("$cmd", 0);
if ($::RUNCMD_RC != 0)
{
my $rsp = {};
$rsp->{error}->[0] =
"Could not copy $pubfile to $installdir/postscripts/_ssh/$zonename";
xCAT::MsgUtils->message("E", $rsp, $callback);
return 1;
}
}
else
{
my $rsp = {};
$rsp->{error}->[0] =
"Could not copy $pubfile to $installdir/postscripts/_ssh/$zonename, because $pubfile does not exist.";
xCAT::MsgUtils->message("E", $rsp, $callback);
}
}
#--------------------------------------------------------------------------------
@ -188,7 +149,7 @@ sub genSSHRootKeys
=cut
#--------------------------------------------------------------------------------
sub getdefaultzone
sub getdefaultzone
{
my ($class, $callback) = @_;
my $defaultzone;
@ -262,7 +223,7 @@ sub iszonedefined
=cut
#--------------------------------------------------------------------------------
sub getzoneinfo
sub getzoneinfo
{
my ($class, $callback,$nodes) = @_;
$::GETZONEINFO_RC=0;
@ -279,6 +240,7 @@ sub getzoneinfo
my $zonename=$zone->{zonename};
$zonehash->{$zonename}->{sshkeydir}= $zone->{sshkeydir};
$zonehash->{$zonename}->{defaultzone}= $zone->{defaultzone};
$zonehash->{$zonename}->{sshbetweennodes}= $zone->{sshbetweennodes};
# find the defaultzone
if ((defined($zone->{defaultzone})) &&
(($zone->{defaultzone} =~ /^yes$/i )
@ -299,44 +261,40 @@ sub getzoneinfo
my $nodelisttab = xCAT::Table->new("nodelist");
my $nodehash = $nodelisttab->getNodesAttribs(\@$nodes, ['zonename']);
# for each of the nodes, look up it's zone name and assign to the zonehash
# if the node is a service node, it is assigned to the __xcatzone which gets its keys from
# the ~/.ssh dir no matter what in the database for the zonename.
# 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
# If there is no defaultzone error out
my @allSN=xCAT::ServiceNodeUtils->getAllSN("ALL"); # read all the servicenodes define
my $xcatzone = "__xcatzone"; # if node is in no zones or a service node, use this one
$zonehash->{$xcatzone}->{sshkeydir}= "~/.ssh";
foreach my $node (@$nodes) {
my $zonename;
if (grep(/^$node$/, @allSN)) { # this is a servicenode, treat special
$zonename=$xcatzone; # always use ~/.ssh directory
} else { # use the nodelist.zonename attribute
$zonename=$nodehash->{$node}->[0]->{zonename};
}
$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))) {
# check to see if defined in the zone table
unless ( xCAT::Zone->iszonedefined($zonename)) {
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;
}
push @{$zonehash->{$zonename}->{nodes}},$node;
} else { # no explict zonename
if (defined ($defaultzone)) { # there is a default zone in the zone table, use it
push @{$zonehash->{$defaultzone}->{nodes}},$node;
} else { # if no default then use the ~/.ssh keys as the default, put them in the __xcatzone
push @{$zonehash->{$xcatzone}->{nodes}},$node;
} else { # if no default, this is an error
my $rsp = {};
$rsp->{error}->[0] =
"There is no default zone defined in the zone table. There must be exactly one default zone. ";
xCAT::MsgUtils->message("E", $rsp, $callback);
$::GETZONEINFO_RC =1;
return;
}
}
}
return;
return $zonehash;
}
1;