git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@11570 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			403 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			403 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| =head1
 | |
|   xCAT plugin package to handle makeknownhosts 
 | |
| 
 | |
|    Supported command:
 | |
|          makenownhosts-> makeknownhosts 
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| package xCAT_plugin::makeknownhosts;
 | |
| use strict;
 | |
| require xCAT::Table;
 | |
| 
 | |
| require xCAT::Utils;
 | |
| 
 | |
| require xCAT::MsgUtils;
 | |
| use Getopt::Long;
 | |
| use Socket;
 | |
| require xCAT::DSHCLI;
 | |
| require xCAT::NetworkUtils;
 | |
| 1;
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| =head3  handled_commands
 | |
| 
 | |
| Return list of commands handled by this plugin
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| sub handled_commands
 | |
| {
 | |
|     return {makeknownhosts => "makeknownhosts"};
 | |
| }
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| =head3  process_request
 | |
| 
 | |
|   Process the command
 | |
|   Get list of nodes and for each node, find all possible 
 | |
|   names and ipaddresses and add an entry into the users
 | |
|   /.ssh knownhost file.
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| sub process_request
 | |
| {
 | |
| 
 | |
|     Getopt::Long::Configure("bundling");
 | |
|     $Getopt::Long::ignorecase = 0;
 | |
|     Getopt::Long::Configure("no_pass_through");
 | |
|     my $request  = shift;
 | |
|     my $callback = shift;
 | |
|     my $nodes    = $request->{node};
 | |
|     my $rc       = 0;
 | |
| 
 | |
|     # parse the input
 | |
|     if ($request && $request->{arg}) { @ARGV = @{$request->{arg}}; }
 | |
|     else { @ARGV = (); }
 | |
| 
 | |
|     my $usage = "Usage: makeknownhosts <noderange> [-r] [-V]\n       makeknownhosts -h";
 | |
| 
 | |
|     # print "argv=@ARGV\n";
 | |
|     if (!GetOptions(
 | |
|                      'h|help'    => \$::opt_h,
 | |
|                      'V|verbose' => \$::opt_V,
 | |
|                      'r|remove'  => \$::opt_r
 | |
|                    )) 
 | |
|     {
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = $usage;
 | |
|         xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     # display the usage if -h
 | |
|     if ($::opt_h)
 | |
|     {
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = $usage;
 | |
|         xCAT::MsgUtils->message("I", $rsp, $callback, 1);
 | |
|         return 0;
 | |
|     }
 | |
|     if ($nodes eq "")
 | |
|     {    # no noderange
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "The Noderange is missing.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | |
|         return 1;
 | |
|     }
 | |
|     my $hostkey = "/etc/xcat/hostkeys/ssh_host_rsa_key.pub";
 | |
|     if (!(-e $hostkey))
 | |
|     {    # the key is missing, cannot create known_hosts
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] =
 | |
|           "The keyfile:$hostkey is missing. Cannot create the known_hosts file.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     # Backup the existing known_hosts file to known_hosts.backup
 | |
|     $rc = backup_known_hosts_file($callback);
 | |
|     if ($rc != 0)
 | |
|     {
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "Error backing up known_hosts file.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | |
|         return 1;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     # Remove the nodes from knownhosts file
 | |
|     $rc = remove_nodes_from_knownhosts($callback, $nodes);
 | |
|     if ($rc != 0)
 | |
|     {
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "Error backing up known_hosts file.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | |
|         return 1;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     # if -r flag is not specified, adding the nodes back to known_hosts file
 | |
|     if (!$::opt_r)
 | |
|     {
 | |
|         my @nodelist = @$nodes;
 | |
|         foreach my $node (@nodelist)
 | |
|         {
 | |
|             $rc = add_known_host($node, $callback);
 | |
|             if ($rc != 0)
 | |
|             {
 | |
|                 my $rsp = {};
 | |
|                 $rsp->{data}->[0] = "Error building known_hosts file.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | |
|                 return 1;
 | |
|             }
 | |
|         }
 | |
|      }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| =head3  backup_known_hosts file 
 | |
| 
 | |
|   Backs up the old known_hosts file in roots  .ssh directory,
 | |
|   if it exists. 
 | |
| 
 | |
| 
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| sub backup_known_hosts_file
 | |
| {
 | |
| 
 | |
|     my ($callback) = @_;
 | |
| 
 | |
|     # Get the home directory
 | |
|     my $home = xCAT::Utils->getHomeDir("root");
 | |
|     if (!-d "$home/.ssh")
 | |
|     {    # ssh has not been setup
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] =
 | |
|           "ssh has not been setup on this machine. .ssh directory does not existfor root id";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | |
|         return 1;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         my $cmd;
 | |
|         my $file = "$home/.ssh/known_hosts";
 | |
|         if (-e $file)
 | |
|         {
 | |
|             my $newfile = $file;
 | |
|             $newfile .= ".backup";
 | |
|             $cmd = "cat $file > $newfile";
 | |
|             xCAT::Utils->runcmd($cmd, -1);
 | |
|             if ($::RUNCMD_RC != 0)
 | |
|             {
 | |
|                 my $rsp = {};
 | |
|                 $rsp->{data}->[0] = "$cmd failed";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | |
|                 return 1;
 | |
|             }
 | |
| 
 | |
|         }
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| =head3  add_known_host 
 | |
| 
 | |
|   Adds entires to $ROOTHOME/.ssh/known_hosts file 
 | |
| 
 | |
| 
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| sub add_known_host
 | |
| {
 | |
|     my ($node, $callback) = @_;
 | |
|     my $cmd;
 | |
|     my $line;
 | |
|     my @ip_address;
 | |
|     my $home        = xCAT::Utils->getHomeDir("root");
 | |
|     my $known_hosts = "$home/.ssh/known_hosts";
 | |
| 
 | |
|     my $hostkey = "/etc/xcat/hostkeys/ssh_host_rsa_key.pub";
 | |
|     my $hostname;
 | |
|     my $aliases;
 | |
|     my $addrtype;
 | |
|     my $length;
 | |
|     my @addrs;
 | |
| 
 | |
|     # get the key
 | |
|     $cmd = "cat $hostkey";
 | |
|     if ($::opt_V)
 | |
|     {
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "Running command: $cmd";
 | |
|         xCAT::MsgUtils->message("I", $rsp, $callback);
 | |
|     }
 | |
|     my @output = xCAT::Utils->runcmd($cmd, 0);
 | |
|     if ($::RUNCMD_RC != 0)
 | |
|     {
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "$cmd failed, cannot build known_hosts file";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | |
|         return 1;
 | |
|     }
 | |
|     chop($output[0]);
 | |
|     my ($hostname,$ip_address) = xCAT::NetworkUtils->gethostnameandip($node);
 | |
|     if (!$hostname || !$ip_address)
 | |
|     {
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "Can not resolve $node";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | |
|         return 1;
 | |
|     }
 | |
|     chomp($ip_address);
 | |
| 
 | |
|     if (defined $hostname)
 | |
|     {
 | |
|         my $sitedomain;
 | |
|         my @domain = xCAT::Utils->get_site_attribute("domain");
 | |
|         if ($domain[0])
 | |
|         {
 | |
|             $sitedomain = $domain[0];
 | |
|         }
 | |
|         $line = "\"";
 | |
|         $line .= "$hostname,";
 | |
|         if ($sitedomain)
 | |
|         {
 | |
|             $line .= "$hostname.$sitedomain,";
 | |
|         }
 | |
|         $line .= "$ip_address";
 | |
|         $line .= " ";
 | |
|         $line .= $output[0];
 | |
|         $line .= "\"";
 | |
|         $cmd = "echo  $line >> $known_hosts";
 | |
|         if ($::opt_V)
 | |
|         {
 | |
|             my $rsp = {};
 | |
|             $rsp->{data}->[0] = "Running command: $cmd";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $callback);
 | |
|         }
 | |
|         xCAT::Utils->runcmd($cmd, 0);
 | |
| 
 | |
|         if ($::RUNCMD_RC != 0)
 | |
|         {
 | |
|             my $rsp = {};
 | |
|             $rsp->{data}->[0] = "$cmd failed, cannot create known_hosts";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #--------------------------------------------------------------------------------
 | |
| 
 | |
| =head3    remove_nodes_from_knownhosts
 | |
| 
 | |
|         Removes the nodes from SSH known hosts
 | |
| 
 | |
|         Arguments:
 | |
|                 \@node_hostnames
 | |
| 
 | |
|         Returns:
 | |
|                 1 - error
 | |
|                 0 - success
 | |
|         Globals:
 | |
|                 none
 | |
|         Example:
 | |
|                 remove_nodes_from_knownhosts(\@nodes);
 | |
|         Comments:
 | |
|                 none
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #--------------------------------------------------------------------------------
 | |
| 
 | |
| sub remove_nodes_from_knownhosts
 | |
| {
 | |
|     my ($callback, $ref_nodes) = @_;
 | |
|     my @node_hostnames = @$ref_nodes;
 | |
|     my $home           = xCAT::Utils->getHomeDir("root");
 | |
|     
 | |
|     my @all_names;
 | |
|     
 | |
|     my ($hostname, $ipaddr);
 | |
|     
 | |
|     # Put all the possible knownhosts entries 
 | |
|     # for the nodes into @all_names
 | |
|     foreach my $node (@node_hostnames)
 | |
|     {
 | |
|         if (!grep(/^$node$/, @all_names))
 | |
|         { 
 | |
|             push @all_names, $node;
 | |
|         }
 | |
|         ($hostname, $ipaddr) = xCAT::NetworkUtils->gethostnameandip($node);
 | |
|         if (!$hostname || !$ipaddr)
 | |
|         {
 | |
|             return 0;
 | |
|         }
 | |
|         if (!grep(/^$hostname$/, @all_names))
 | |
|         {
 | |
|             push @all_names, $hostname;
 | |
|         }
 | |
|         if (!grep(/^$ipaddr$/, @all_names))
 | |
|         {
 | |
|             push @all_names, $ipaddr;
 | |
|         }
 | |
|         
 | |
|     }
 | |
| 
 | |
|     #create the sed command
 | |
|     my $sed = "/bin/sed -e ";
 | |
|     $sed .= "\"";
 | |
|     foreach my $n (@all_names)
 | |
|     {
 | |
|         $sed .= "/^$n\[,| ]/d; ";
 | |
|     }
 | |
|     chop $sed;    #get rid of last space
 | |
|     $sed .= "\"";
 | |
|     my $file = "/tmp/$$";
 | |
|     while (-e $file)
 | |
|     {
 | |
|         $file = xCAT::Utils->CreateRandomName($file);
 | |
|     }
 | |
|     if (-e "$home/.ssh/known_hosts")
 | |
|     {
 | |
|         $sed .= " $home/.ssh/known_hosts";
 | |
|         $sed .= " > $file";
 | |
|         my $printsed = $sed;
 | |
|         $printsed =~ s/"//g;    #"
 | |
|         if ($::opt_V)
 | |
|         {
 | |
|             my $rsp = {};
 | |
|             $rsp->{data}->[0] = "Running command: $printsed";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $callback);
 | |
|         }
 | |
|         xCAT::Utils->runcmd($sed, -1);
 | |
|         if ($::RUNCMD_RC != 0)
 | |
|         {
 | |
|             my $rsp = {};
 | |
|             $rsp->{data}->[0] = "Command \"$printsed\" failed.";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $callback, 1);
 | |
|             return 1;
 | |
|         }
 | |
| 
 | |
|         my $cp = "cat $file > $home/.ssh/known_hosts";
 | |
|         if ($::opt_V)
 | |
|         {
 | |
|             my $rsp = {};
 | |
|             $rsp->{data}->[0] = "Running command: $cp";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $callback);
 | |
|         }
 | |
| 
 | |
|         xCAT::Utils->runcmd($cp, -1);
 | |
|         if ($::RUNCMD_RC != 0)
 | |
|         {
 | |
|             my $rsp = {};
 | |
|             $rsp->{data}->[0] = "Command \"$cp\" failed.";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $callback, 1);
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
|     xCAT::Utils->runcmd("rm -f $file", -1);
 | |
|     return 0;
 | |
| }
 |