mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-03 21:02:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			965 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			965 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head1
 | 
						|
  xCAT plugin package to handle mkzone,chzone,Input rmzone commands 
 | 
						|
 | 
						|
   Supported command:
 | 
						|
         mkzone,chzone,rmzone - manage xcat cluster zones 
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
package xCAT_plugin::zone;
 | 
						|
BEGIN
 | 
						|
{
 | 
						|
  $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr';
 | 
						|
}
 | 
						|
 | 
						|
use strict;
 | 
						|
require xCAT::Utils;
 | 
						|
require xCAT::Zone;
 | 
						|
require xCAT::MsgUtils;
 | 
						|
require xCAT::Table;
 | 
						|
use xCAT::NodeRange;
 | 
						|
use xCAT::NodeRange qw/noderange abbreviate_noderange/;
 | 
						|
 | 
						|
use Getopt::Long;
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3  handled_commands
 | 
						|
 | 
						|
Return list of commands handled by this plugin
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
sub handled_commands
 | 
						|
{
 | 
						|
    return {mkzone => "zone",
 | 
						|
            chzone => "zone",
 | 
						|
            rmzone => "zone",
 | 
						|
            };
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3  process_request
 | 
						|
 | 
						|
  Process the command, this only runs on the management node
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub process_request
 | 
						|
{
 | 
						|
 | 
						|
    my $request  = shift;
 | 
						|
    my $callback = shift;
 | 
						|
    my $sub_req = shift;
 | 
						|
    $::CALLBACK = $callback;
 | 
						|
    my $command = $request->{command}->[0];
 | 
						|
    my $rc=0;
 | 
						|
    # the directory which will contain the zone keys
 | 
						|
    my $keydir="/etc/xcat/sshkeys/";
 | 
						|
    
 | 
						|
    # check if Management Node, if not error
 | 
						|
    unless (xCAT::Utils->isMN()) 
 | 
						|
    {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{error}->[0] = "The $command may only be run on the Management Node.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            return 1; 
 | 
						|
 | 
						|
    }
 | 
						|
    # you may not run on AIX
 | 
						|
    if (xCAT::Utils->isAIX()) {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{error}->[0] = "The $command may only be run on a Linux Cluster.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            return 1; 
 | 
						|
    }
 | 
						|
    # test to see if any parms 
 | 
						|
    if (scalar($request->{arg} == 0)) {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{error}->[0] =
 | 
						|
          "No parameters input to the $command command,  see man page for syntax.";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
        exit 1;
 | 
						|
    }
 | 
						|
 | 
						|
    my $args = $request->{arg};
 | 
						|
    @ARGV = @{$args};    # get arguments
 | 
						|
    # Get the zonename if it is in the input 
 | 
						|
    my @SaveARGV = @ARGV;
 | 
						|
    my $zonename;
 | 
						|
    my $arg= @SaveARGV[0];
 | 
						|
    if (!($arg =~ /-h/) && (!($arg =~ /-v/)))  {   # if not -h -v,then it must be a zone name 
 | 
						|
     $zonename = @SaveARGV[0];  # here is the zonename, if there is one
 | 
						|
     if ($zonename) {   #  take zonename off the argument list so it will parse correctly
 | 
						|
        my $tmp = shift(@SaveARGV);
 | 
						|
        @ARGV = @SaveARGV;       
 | 
						|
     }
 | 
						|
    }
 | 
						|
    Getopt::Long::Configure("posix_default");
 | 
						|
    Getopt::Long::Configure("no_gnu_compat");
 | 
						|
    Getopt::Long::Configure("bundling");
 | 
						|
    my %options = ();
 | 
						|
 | 
						|
    if (
 | 
						|
        !GetOptions(
 | 
						|
                    'a|noderange=s'   => \$options{'addnoderange'},
 | 
						|
                    'r|noderange=s'   => \$options{'rmnoderange'},
 | 
						|
                    'defaultzone|defaultzone'   => \$options{'defaultzone'}, 
 | 
						|
                    'g|assigngrp'     => \$options{'assigngroup'},
 | 
						|
                    'f|force'        => \$options{'force'},
 | 
						|
                    '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'},
 | 
						|
        )
 | 
						|
      )
 | 
						|
    {
 | 
						|
 | 
						|
        &usage($callback,$command);
 | 
						|
        exit 1;
 | 
						|
    }
 | 
						|
    # if the ARGS still have data we have invalid input
 | 
						|
    if (@ARGV) {
 | 
						|
            my $args=join(',', @ARGV);
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{error}->[0] =
 | 
						|
              "The input to the command: $command contained invalid arguments: $args.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            exit 1; 
 | 
						|
    }
 | 
						|
 
 | 
						|
    if ($options{'help'})
 | 
						|
    {
 | 
						|
        &usage($callback,$command);
 | 
						|
        exit 0;
 | 
						|
    }
 | 
						|
    if ($options{'version'})
 | 
						|
    {
 | 
						|
        my $version = xCAT::Utils->Version();
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{data}->[0] = $version;
 | 
						|
        xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
        exit 0;
 | 
						|
    }
 | 
						|
    # test to see if the zonename was input
 | 
						|
    if (!$zonename) {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{error}->[0] =
 | 
						|
          "zonename not specified, it is required for this command.";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
        exit 1;
 | 
						|
    } else {
 | 
						|
       $request->{zonename} = $zonename;
 | 
						|
    }
 | 
						|
    # if -s entered must be yes/1 or no/0
 | 
						|
    if ($options{'sshbetweennodes'}) {
 | 
						|
      if ($options{'sshbetweennodes'}=~ /^yes$/i || $options{'sshbetweennodes'} eq "1") {
 | 
						|
           $options{'sshbetweennodes'}= "yes";
 | 
						|
      } else {
 | 
						|
        if ($options{'sshbetweennodes'}=~ /^no$/i || $options{'sshbetweennodes'} eq "0") {
 | 
						|
           $options{'sshbetweennodes'}= "no";
 | 
						|
        } else {
 | 
						|
             my $rsp = {};
 | 
						|
             $rsp->{error}->[0] =
 | 
						|
              "The input on the -s flag $options{'sshbetweennodes'} is not valid.";
 | 
						|
             xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
             exit 1;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    # cannot enter -K and -k
 | 
						|
    if (($options{'sshkeypath'}) && ($options{'gensshkeys'})) {
 | 
						|
      my $rsp = {};
 | 
						|
      $rsp->{error}->[0] =
 | 
						|
      "The input of -k and -K is not valid on the command : $command.";
 | 
						|
      xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
      exit 1;
 | 
						|
    }
 | 
						|
 | 
						|
    # check for site.sshbetweennodes attribute, put out a warning it will not be used as long
 | 
						|
    # as zones are defined in the zone table.
 | 
						|
    my @entries =  xCAT::TableUtils->get_site_attribute("sshbetweennodes");    
 | 
						|
    if ($entries[0]) {
 | 
						|
         my $rsp = {};
 | 
						|
         $rsp->{info}->[0] =
 | 
						|
              "The site table sshbetweennodes attribute is set to $entries[0].  It is not used when zones are defined.  To get rid of this warning, remove the site table sshbetweennodes attribute.";
 | 
						|
             xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
    }
 | 
						|
    #  -a and -r flags cannot be used together
 | 
						|
    if (($options{'addnoderange'})  && ($options{'rmnoderange'})) {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{error}->[0] =
 | 
						|
              "You may not use the -a flag to add nodes and the -r flag to remove nodes on one command.";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
        exit 1;
 | 
						|
           
 | 
						|
    }
 | 
						|
    # save input noderange  to add nodes
 | 
						|
    if ($options{'addnoderange'}) {
 | 
						|
       
 | 
						|
       # check to see if Management Node is in the noderange, if so error
 | 
						|
       $request->{noderange}->[0] = $options{'addnoderange'};
 | 
						|
       my @nodes = xCAT::NodeRange::noderange($request->{noderange}->[0]);
 | 
						|
       my @mname = xCAT::Utils->noderangecontainsMn(@nodes); 
 | 
						|
       if (@mname)
 | 
						|
        {    # MN in the nodelist
 | 
						|
            my $nodes=join(',', @mname);
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{error}->[0] =
 | 
						|
              "You must not run $command and include the  management node: $nodes.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            exit 1; 
 | 
						|
        }
 | 
						|
 
 | 
						|
 
 | 
						|
    }
 | 
						|
    # save input noderange  to remove nodes
 | 
						|
    if ($options{'rmnoderange'}) {
 | 
						|
       
 | 
						|
       # check to see if Management Node is in the noderange, if so error
 | 
						|
       $request->{noderange}->[0] = $options{'rmnoderange'};
 | 
						|
       my @nodes = xCAT::NodeRange::noderange($request->{noderange}->[0]);
 | 
						|
       my @mname = xCAT::Utils->noderangecontainsMn(@nodes); 
 | 
						|
       if (@mname)
 | 
						|
        {    # MN in the nodelist
 | 
						|
            my $nodes=join(',', @mname);
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{error}->[0] =
 | 
						|
              "You must not run $command and include the  management node: $nodes.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            exit 1; 
 | 
						|
        }
 | 
						|
 
 | 
						|
 
 | 
						|
    }
 | 
						|
    if ($options{'verbose'})
 | 
						|
    {
 | 
						|
        $::VERBOSE = "yes";
 | 
						|
    }
 | 
						|
 | 
						|
    if ($command eq "mkzone")
 | 
						|
    {
 | 
						|
      $rc=mkzone($request, $callback,\%options,$keydir);
 | 
						|
    }
 | 
						|
    if ($command eq "chzone")
 | 
						|
    {
 | 
						|
        $rc=chzone($request, $callback,\%options,$keydir);
 | 
						|
    }
 | 
						|
    if ($command eq "rmzone")
 | 
						|
    {
 | 
						|
         $rc=rmzone($request, $callback,\%options);
 | 
						|
    }
 | 
						|
    my $rsp = {};
 | 
						|
    if ($rc ==0) {
 | 
						|
      $rsp->{info}->[0] = "The $command ran successfully.";
 | 
						|
      xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
    } else {
 | 
						|
      $rsp->{error}->[0] = "The $command had errors.";
 | 
						|
      xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
    }
 | 
						|
    return $rc; 
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   
 | 
						|
 | 
						|
   Parses and runs  mkzone 
 | 
						|
   Input 
 | 
						|
     request
 | 
						|
     callback
 | 
						|
     Input  arguments from the GetOpts
 | 
						|
     zone ssh key dir
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub mkzone 
 | 
						|
{
 | 
						|
    my ($request, $callback,$options,$keydir) = @_;
 | 
						|
    my $rc=0;
 | 
						|
    # already checked but lets do it again,  need a zonename, it is the only required parm
 | 
						|
    if (!($request->{zonename})) {
 | 
						|
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{error}->[0] =
 | 
						|
          "zonename not specified The zonename is required.";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    # test for -g, if no noderange this is an error 
 | 
						|
    if (( ! defined($$options{'addnoderange'})) && ($$options{'assigngroup'})) {
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " The -g flag requires a noderange ( -a).";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    }  
 | 
						|
    # test for -r,  not valid 
 | 
						|
    if ($$options{'rmnoderange'}) {
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " The -r flag Is not valid for mkzone. Use chzone.";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    }  
 | 
						|
    # check to see if the input zone already exists
 | 
						|
    if (xCAT::Zone->iszonedefined($request->{zonename})) {
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " zonename: $request->{zonename} already defined, use chzone or rmzone to change or remove it.";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Create path to generated ssh keys
 | 
						|
    # keydir comes in set to /etc/xcat/sshkeys
 | 
						|
    $keydir .= $request->{zonename}; 
 | 
						|
    $keydir .= "/.ssh"; 
 | 
						|
    
 | 
						|
 | 
						|
    # add new zones to the zone table 
 | 
						|
    $rc=addtozonetable($request, $callback,$options,$keydir);
 | 
						|
    if ($rc == 0) {  # zone table setup is ok
 | 
						|
      # test for a noderange, if(-a) not supplied nothing to do
 | 
						|
      if (defined($$options{'addnoderange'})) {
 | 
						|
        $rc=addnodestozone($request, $callback,$options,$keydir);
 | 
						|
      }  
 | 
						|
      if ($rc == 0) {  # zone table setup is ok
 | 
						|
        # generate root ssh keys
 | 
						|
        $rc=gensshkeys($request, $callback,$options,$keydir);
 | 
						|
        if ($rc != 0) {
 | 
						|
          return 1;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    return $rc;
 | 
						|
 | 
						|
}
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   
 | 
						|
 | 
						|
   Parses and runs chzone 
 | 
						|
   Input 
 | 
						|
     request
 | 
						|
     callback
 | 
						|
     Input  arguments from the GetOpts
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub chzone 
 | 
						|
{
 | 
						|
    my ($request, $callback,$options,$keydir) = @_;
 | 
						|
    my $rc=0;
 | 
						|
    # Create default  path to generated ssh keys
 | 
						|
    # keydir comes in set to /etc/xcat/sshkeys
 | 
						|
    $keydir .= $request->{zonename}; 
 | 
						|
    $keydir .= "/.ssh"; 
 | 
						|
    my $zonename=$request->{zonename};
 | 
						|
    # already checked but lets do it again,  need a zonename
 | 
						|
    if (!($request->{zonename})) {
 | 
						|
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{error}->[0] =
 | 
						|
          "zonename not specified The zonename is required.";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    # see if they asked to do anything
 | 
						|
    if ((!($$options{'sshkeypath'})) && (!($$options{'gensshkeys'})) && 
 | 
						|
       (!( $$options{'addnoderange'})) && (!( $$options{'rmnoderange'})) &&
 | 
						|
       (!( $$options{'defaultzone'})) &&
 | 
						|
        (!($$options{'assigngroup'} )) && (!($$options{'sshbetweennodes'}))) {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{info}->[0] =
 | 
						|
          "chzone was run but nothing to do.";
 | 
						|
        xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
    # test for -g, if no noderange (-r or -a) this is an error 
 | 
						|
    if ((( ! defined($$options{'addnoderange'}))&& ( ! defined($$options{'rmnoderange'}))) && ($$options{'assigngroup'})) {
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " The -g flag requires a noderange using the -a or -r option.";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    #  if -r remove nodes from zone, check to see that they are a member of the zone
 | 
						|
    #  if not a member of the zone,  error out and do nothing
 | 
						|
    if ($$options{'rmnoderange'}){
 | 
						|
      my @nodes = xCAT::NodeRange::noderange($request->{noderange}->[0]);
 | 
						|
     
 | 
						|
      foreach my $node (@nodes) {
 | 
						|
        my $nodezonename=xCAT::Zone->getmyzonename($node);
 | 
						|
        if ($nodezonename ne $zonename) {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{error}->[0] =
 | 
						|
             " $node does not belong to the zone:$zonename. Rerun the chzone -r  command with only nodes in the noderange that are currently assigned to the zone.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
            return 1;
 | 
						|
        }  
 | 
						|
       
 | 
						|
      }  
 | 
						|
    }  
 | 
						|
    # get the zone ssh key directory. We don't have a good zone without it.
 | 
						|
    my $sshrootkeydir = xCAT::Zone->getzonekeydir($zonename);
 | 
						|
    if ($sshrootkeydir == 1) { # error return
 | 
						|
       #if we have been requested to regenerated the ssh keys continue
 | 
						|
       if (($$options{'sshkeypath'}) || ($$options{'gensshkeys'})) { 
 | 
						|
           my $rsp = {};
 | 
						|
           $rsp->{info}->[0] =
 | 
						|
           " sshkeydir attribute not defined for $zonename. The zone sshkeydir will be regenerated.";
 | 
						|
           xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
       } else {  # sshkeydir is missing  and they did not request to regenerate,   that is an error
 | 
						|
           my $rsp = {};
 | 
						|
           $rsp->{error}->[0] =
 | 
						|
           " sshkeydir attribute not defined for $zonename. The zone sshkeydir must be regenerated. Rerun this command with -k or -K options";
 | 
						|
           xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
        return 1;
 | 
						|
       }
 | 
						|
    } else {  # we got a sshkeydir from the database, use it
 | 
						|
        $keydir=$sshrootkeydir;
 | 
						|
    }
 | 
						|
    # do we regenerate keys (-k or -K)
 | 
						|
    if (($$options{'sshkeypath'}) || ($$options{'gensshkeys'})) {
 | 
						|
       $rc=gensshkeys($request, $callback,$options,$keydir);
 | 
						|
       if ($rc != 0) {
 | 
						|
         return 1;
 | 
						|
       }
 | 
						|
    }
 | 
						|
    
 | 
						|
    # update the zone table 
 | 
						|
    $rc=updatezonetable($request, $callback,$options,$keydir);
 | 
						|
    if ($rc == 0) {  # zone table setup is ok
 | 
						|
      # update the nodelist table
 | 
						|
      if (defined($$options{'addnoderange'})) {
 | 
						|
        $rc=addnodestozone($request, $callback,$options,$keydir);
 | 
						|
      } else {  # note -a and -r are not allowed on one chzone
 | 
						|
          if (defined($$options{'rmnoderange'})) {
 | 
						|
            $rc=rmnodesfromzone($request, $callback,$options,$keydir);
 | 
						|
          }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    return $rc;
 | 
						|
}
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   
 | 
						|
 | 
						|
   Parses and runs rmzone 
 | 
						|
   Input 
 | 
						|
     request
 | 
						|
     callback
 | 
						|
     Input  arguments from the GetOpts
 | 
						|
      
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub rmzone 
 | 
						|
{
 | 
						|
    my ($request, $callback,$options) = @_;
 | 
						|
    
 | 
						|
    # already checked but lets do it again,  need a zonename, it is the only required parm
 | 
						|
    if (!($request->{zonename})) {
 | 
						|
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{error}->[0] =
 | 
						|
          "zonename not specified The zonename is required.";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    # see if they input invalid flags 
 | 
						|
    if (($$options{'sshkeypath'}) || ($$options{'gensshkeys'}) || 
 | 
						|
       ( $$options{'addnoderange'}) || ( $$options{'rmnoderange'}) ||
 | 
						|
       ( $$options{'defaultzone'}) || 
 | 
						|
       ($$options{'sshbetweennodes'})) {
 | 
						|
        
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{error}->[0] =
 | 
						|
          "The following flags are not valid input for the rmzone command: -k,-K,-a,-r,-f,-s  ";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    # check to see if the input zone already exists
 | 
						|
    # cannot remove it if it is not defined
 | 
						|
    my $zonename=$request->{zonename};
 | 
						|
    if (!(xCAT::Zone->iszonedefined($zonename))) {
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " zonename: $zonename is not defined. You cannot remove it.";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    }
 | 
						|
    # is this zone is the default zone you must force the delete
 | 
						|
    my $defaultzone =xCAT::Zone->getdefaultzone($callback);
 | 
						|
    if (($defaultzone eq $zonename) && (!($$options{'force'}))) {
 | 
						|
       my $rsp = {};     
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " You are removing the default zone: $zonename.  You must define another default zone before deleting or use the -f flag to force the removal.";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    # get the zone ssh key directory
 | 
						|
    my $sshrootkeydir = xCAT::Zone->getzonekeydir($zonename);
 | 
						|
    if ($sshrootkeydir == 1) { # error return
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{info}->[0] =
 | 
						|
        " sshkeydir attribute not defined for $zonename. Cannot remove it.";
 | 
						|
       xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
    } else {  # remove the keys  unless it is /root/.ssh
 | 
						|
       my $roothome = xCAT::Utils->getHomeDir("root");
 | 
						|
       $roothome .="\/.ssh";
 | 
						|
       if ($sshrootkeydir eq $roothome) {  # will not delete /root/.ssh
 | 
						|
           my $rsp = {};
 | 
						|
           $rsp->{info}->[0] =
 | 
						|
             "  $zonename sshkeydir is $roothome. This will not be deleted.";
 | 
						|
             xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
       } else {  # not roothome/.ssh
 | 
						|
         # check to see if id_rsa.pub is there. I don't want to remove the
 | 
						|
         # wrong directory
 | 
						|
         # if id_rsa.pub exists remove the files
 | 
						|
         # then remove the directory
 | 
						|
         if ( -e "$sshrootkeydir/id_rsa.pub") {
 | 
						|
           my $cmd= "rm -rf $sshrootkeydir";    
 | 
						|
           xCAT::Utils->runcmd($cmd,0);
 | 
						|
           if ($::RUNCMD_RC != 0)
 | 
						|
           {
 | 
						|
              my $rsp = {};
 | 
						|
              $rsp->{error}->[0] = "Command: $cmd failed";
 | 
						|
              xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
           }
 | 
						|
           my ($zonedir,$ssh)= split(/\.ssh/, $sshrootkeydir);
 | 
						|
           $cmd= "rmdir $zonedir";    
 | 
						|
           xCAT::Utils->runcmd($cmd,0);
 | 
						|
           if ($::RUNCMD_RC != 0)
 | 
						|
           {
 | 
						|
              my $rsp = {};
 | 
						|
              $rsp->{error}->[0] = "Command: $cmd failed";
 | 
						|
              xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
           }
 | 
						|
          } else {  #  no id_rsa.pub key will not remove the files
 | 
						|
              my $rsp = {};
 | 
						|
              $rsp->{info}->[0] = "$sshrootkeydir did not contain an id_rsa.pub key, will not remove files";
 | 
						|
              xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
          }
 | 
						|
       }
 | 
						|
    
 | 
						|
    }
 | 
						|
 | 
						|
    # open zone table and remove this entry
 | 
						|
    my $tab = xCAT::Table->new("zone");
 | 
						|
    if (!defined($tab)) {  
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " Failure opening the zone table.";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    }
 | 
						|
    # remove the table entry
 | 
						|
    $tab->delEntries({zonename=>$zonename});
 | 
						|
 | 
						|
    # remove zonename and possibly group name (-g flag) from  any nodes defined in this zone
 | 
						|
    my $rc=rmnodesfromzone($request, $callback,$options,"ALL");
 | 
						|
 | 
						|
    return $rc;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
}
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3
 | 
						|
      usage
 | 
						|
 | 
						|
        puts out zone command usage message
 | 
						|
 | 
						|
        Arguments:
 | 
						|
          None
 | 
						|
 | 
						|
        Returns:
 | 
						|
 | 
						|
        Globals:
 | 
						|
 | 
						|
 | 
						|
        Error:
 | 
						|
                None
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
sub usage
 | 
						|
{
 | 
						|
    my ($callback, $command) = @_;
 | 
						|
    my $usagemsg1="";
 | 
						|
    my $usagemsg2="";
 | 
						|
    if ($command eq "mkzone") {
 | 
						|
       $usagemsg1  = " mkzone -h \n mkzone -v \n";
 | 
						|
       $usagemsg2  = " mkzone <zonename> [-V] [--defaultzone] [-k <full path to the ssh RSA private key>] \n        [-a <noderange>] [-g] [-f] [-s <yes/no>]";
 | 
						|
    } else {
 | 
						|
       if ($command eq "chzone") {
 | 
						|
           $usagemsg1  = " chzone -h \n chzone -v \n";
 | 
						|
           $usagemsg2  = " chzone <zonename> [-V] [--defaultzone] [-k <full path to the ssh RSA private key>] \n      [-K] [-a <noderange>] [-r <noderange>] [-g] [-s <yes/no>]";
 | 
						|
       } else {
 | 
						|
            if ($command eq "rmzone") {
 | 
						|
               $usagemsg1  = " rmzone -h \n rmzone -v \n";
 | 
						|
               $usagemsg2  = " rmzone <zonename> [-g]";
 | 
						|
            }
 | 
						|
       }
 | 
						|
    }
 | 
						|
    my $usagemsg .= $usagemsg1 .=  $usagemsg2 ;
 | 
						|
    if ($callback)
 | 
						|
    {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{data}->[0] = $usagemsg;
 | 
						|
        xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        xCAT::MsgUtils->message("I", $usagemsg);
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   
 | 
						|
 | 
						|
   generate the ssh keys and store them in /etc/xcat/sshkeys/<zonename>/.ssh 
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub gensshkeys 
 | 
						|
{
 | 
						|
    my ($request, $callback,$options,$keydir) = @_;
 | 
						|
    my $rc=0;
 | 
						|
    # generate root ssh keys
 | 
						|
    # Did they input a path to existing RSA keys
 | 
						|
    my $rsakey;
 | 
						|
    my $zonename=$request->{zonename};
 | 
						|
    if ($$options{'sshkeypath'}) {
 | 
						|
        # check to see if RSA keys exists
 | 
						|
        $rsakey= $$options{'sshkeypath'} .= "/id_rsa";
 | 
						|
        if (!(-e $rsakey)){   # if it does not exist error out
 | 
						|
           my $rsp = {};
 | 
						|
           $rsp->{error}->[0] =
 | 
						|
             "Input $rsakey does not exist.  Cannot generate the ssh root keys for the zone.";
 | 
						|
           xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
           return 1;
 | 
						|
        }
 | 
						|
    } 
 | 
						|
    
 | 
						|
    $rc =xCAT::Zone->genSSHRootKeys($callback,$keydir, $zonename,$rsakey);
 | 
						|
    if ($rc !=0) {
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " Failure generating the ssh root keys for the zone.";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return  $rc;
 | 
						|
 | 
						|
}
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   
 | 
						|
    addtozonetable
 | 
						|
    Add the new zone to the zone table, check if already there and 
 | 
						|
    error - use either chzone or -f to override default 
 | 
						|
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub addtozonetable 
 | 
						|
{
 | 
						|
    my ($request, $callback,$options,$keydir) = @_;
 | 
						|
    my $rc=0;
 | 
						|
    my $zoneentry;
 | 
						|
    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";
 | 
						|
       my $roothome = xCAT::Utils->getHomeDir("root");
 | 
						|
       $roothome .="\/.ssh";
 | 
						|
       $xcatdefaultzone{sshkeydir} =$roothome;
 | 
						|
       $tab->setAttribs({zonename => "xcatdefault"}, \%xcatdefaultzone);
 | 
						|
     }
 | 
						|
 | 
						|
     # now add the users zone
 | 
						|
     my %tb_cols;
 | 
						|
     $tb_cols{sshkeydir} = $keydir;  # key directory
 | 
						|
     # set sshbetweennodes attribute from -s flag or default to yes
 | 
						|
     if ( $$options{'sshbetweennodes'}) {
 | 
						|
        $tb_cols{sshbetweennodes} = $$options{'sshbetweennodes'};         
 | 
						|
     } else {
 | 
						|
        $tb_cols{sshbetweennodes} = "yes";         
 | 
						|
     }
 | 
						|
     my $zonename=$request->{zonename};
 | 
						|
     if ( $$options{'defaultzone'}) {  # set the default
 | 
						|
       # check to see if a default already defined
 | 
						|
       my $curdefaultzone = xCAT::Zone->getdefaultzone($callback);
 | 
						|
       if (!(defined ($curdefaultzone))) {  # no default defined
 | 
						|
           $tb_cols{defaultzone} ="yes";
 | 
						|
           $tab->setAttribs({zonename => $zonename}, \%tb_cols);
 | 
						|
           $tab->commit();
 | 
						|
           $tab->close();
 | 
						|
       } else { # already a default
 | 
						|
          if ($$options{'force'}) {  # force the default
 | 
						|
            $tb_cols{defaultzone} ="yes";
 | 
						|
            $tab->setAttribs({zonename => $zonename}, \%tb_cols);
 | 
						|
            # now change the old default zone to not be the default
 | 
						|
            my %tb1_cols;
 | 
						|
            $tb1_cols{defaultzone} ="no";
 | 
						|
            $tab->setAttribs({zonename => $curdefaultzone}, \%tb1_cols);
 | 
						|
            $tab->commit();
 | 
						|
            $tab->close();
 | 
						|
          } else {  # no force this is an error
 | 
						|
             my $rsp = {};
 | 
						|
             $rsp->{error}->[0] =
 | 
						|
             " Failure setting default zone. The defaultzone $curdefaultzone already exists. Use the -f flag if you want to override the current default zone.";
 | 
						|
             xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
             return 1;
 | 
						|
          }
 | 
						|
       }
 | 
						|
     } else { # not a default zone
 | 
						|
       $tb_cols{defaultzone} ="no";
 | 
						|
       $tab->setAttribs({zonename => $zonename}, \%tb_cols);
 | 
						|
       $tab->commit();
 | 
						|
       $tab->close();
 | 
						|
     }
 | 
						|
    } else {
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " Failure opening the zone table.";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    }
 | 
						|
 | 
						|
     
 | 
						|
    return  $rc;
 | 
						|
 | 
						|
}
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   
 | 
						|
    updatezonetable
 | 
						|
    change either the sshbetweennodes or defaultzone  attribute
 | 
						|
    or generate new keys ( -k -K)
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub updatezonetable 
 | 
						|
{
 | 
						|
    my ($request, $callback,$options,$keydir) = @_;
 | 
						|
    my $zoneentry; 
 | 
						|
    my $zonename=$request->{zonename};
 | 
						|
    # check for changes
 | 
						|
    if (($$options{'sshbetweennodes'}) || ( $$options{'defaultzone'}) ||
 | 
						|
       ($$options{'sshkeypath'}) || ($$options{'gensshkeys'})) { 
 | 
						|
 | 
						|
      my $tab = xCAT::Table->new("zone");
 | 
						|
      if($tab) {
 | 
						|
 | 
						|
       # now add the users changes 
 | 
						|
       my %tb_cols;
 | 
						|
       # generated keys ( -k or -K)
 | 
						|
       if (($$options{'sshkeypath'}) || ($$options{'gensshkeys'})) {
 | 
						|
         $tb_cols{sshkeydir} = $keydir;  # key directory
 | 
						|
       }
 | 
						|
       # set sshbetweennodes attribute from -s flag 
 | 
						|
       if ( $$options{'sshbetweennodes'}) {
 | 
						|
        $tb_cols{sshbetweennodes} = $$options{'sshbetweennodes'};         
 | 
						|
       }
 | 
						|
       # if --defaultzone
 | 
						|
       if ( $$options{'defaultzone'}) {  # set the default
 | 
						|
         # check to see if a default already defined
 | 
						|
         my $curdefaultzone = xCAT::Zone->getdefaultzone($callback);
 | 
						|
         if (!(defined ($curdefaultzone))) {  # no default defined
 | 
						|
           $tb_cols{defaultzone} ="yes";
 | 
						|
           $tab->setAttribs({zonename => $zonename}, \%tb_cols);
 | 
						|
           $tab->commit();
 | 
						|
           $tab->close();
 | 
						|
         } else { # already a default
 | 
						|
            if ($$options{'force'}) {  # force the default
 | 
						|
              $tb_cols{defaultzone} ="yes";
 | 
						|
              $tab->setAttribs({zonename => $zonename}, \%tb_cols);
 | 
						|
              # now change the old default zone to not be the default
 | 
						|
              my %tb1_cols;
 | 
						|
              $tb1_cols{defaultzone} ="no";
 | 
						|
              $tab->setAttribs({zonename => $curdefaultzone}, \%tb1_cols);
 | 
						|
              $tab->commit();
 | 
						|
              $tab->close();
 | 
						|
            } else {  # no force this is an error
 | 
						|
               my $rsp = {};
 | 
						|
               $rsp->{error}->[0] =
 | 
						|
               " Failure setting default zone. The defaultzone $curdefaultzone already exists. Use the -f flag if you want to override the current default zone.";
 | 
						|
               xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
               return 1;
 | 
						|
            }
 | 
						|
         }
 | 
						|
       } else { # not a default zone change, just commit the other changes
 | 
						|
         $tab->setAttribs({zonename => $zonename}, \%tb_cols);
 | 
						|
         $tab->commit();
 | 
						|
         $tab->close();
 | 
						|
       }
 | 
						|
      } else {
 | 
						|
         my $rsp = {};
 | 
						|
         $rsp->{error}->[0] =
 | 
						|
        " Failure opening the zone table.";
 | 
						|
         xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
         return 1;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
     
 | 
						|
  return  0;
 | 
						|
 | 
						|
}
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   
 | 
						|
    addnodestozone 
 | 
						|
    Add the new zonename attribute to any nodes in the noderange ( if a noderange specified) 
 | 
						|
    Add zonename group to nodes in the noderange if -g flag. 
 | 
						|
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub addnodestozone 
 | 
						|
{
 | 
						|
    my ($request, $callback,$options,$keydir) = @_;
 | 
						|
    my $rc=0;
 | 
						|
    my $zonename=$request->{zonename};
 | 
						|
    # if -g add zonename group also
 | 
						|
    my @nodes = xCAT::NodeRange::noderange($request->{noderange}->[0]);
 | 
						|
    # check to see if noderange expanded
 | 
						|
    if (!(scalar @nodes)) {
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " The noderange $request->{noderange}->[0] is not valid. The nodes are not defined.";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    } 
 | 
						|
    my $tab = xCAT::Table->new("nodelist");
 | 
						|
    if ($tab)
 | 
						|
    {
 | 
						|
      # if -g then add the zonename to the group attribute on each node
 | 
						|
      if ($$options{'assigngroup'}){
 | 
						|
         foreach my $node (@nodes) {
 | 
						|
             xCAT::TableUtils->updatenodegroups($node,$tab,$zonename);
 | 
						|
         }
 | 
						|
      }
 | 
						|
      # set the nodelist zonename attribute to the zonename for all nodes in the range
 | 
						|
      $tab-> setNodesAttribs(\@nodes, { zonename => $zonename });
 | 
						|
      $tab->commit();
 | 
						|
      $tab->close();
 | 
						|
    } else {
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " Failure opening the nodelist table.";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    }
 | 
						|
    return  $rc;
 | 
						|
 | 
						|
}
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   
 | 
						|
    rmnodesfromzone 
 | 
						|
    removes the zonename from all nodes with their zonename the input zone or
 | 
						|
    the noderange supplied on the -r flag
 | 
						|
    if -g, removes zonename group from all nodes defined with their zonename the input zone. 
 | 
						|
    Note if $ALL is input it removes all nodes from the zone, 
 | 
						|
     otherwise  $request->{noderange} points to the noderange
 | 
						|
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub rmnodesfromzone 
 | 
						|
{
 | 
						|
    my ($request, $callback,$options,$ALL) = @_;
 | 
						|
    my $zonename=$request->{zonename};
 | 
						|
    my $tab = xCAT::Table->new("nodelist");
 | 
						|
    if ($tab)
 | 
						|
    {
 | 
						|
      # read all the nodes with zonename
 | 
						|
      my @nodes;
 | 
						|
      if ($ALL) {  # do all nodes
 | 
						|
        @nodes = xCAT::Zone->getnodesinzone($callback,$zonename);
 | 
						|
      } else {  # the nodes in the noderange ( -r )
 | 
						|
        @nodes = xCAT::NodeRange::noderange($request->{noderange}->[0]);
 | 
						|
        # check to see if noderange expanded
 | 
						|
        if (!(scalar @nodes)) {
 | 
						|
           my $rsp = {};
 | 
						|
           $rsp->{error}->[0] =
 | 
						|
           " The noderange $request->{noderange}->[0] is not valid. The nodes are not defined.";
 | 
						|
           xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
           return 1;
 | 
						|
        } 
 | 
						|
      }
 | 
						|
      # if -g then remove the zonename  group attribute on each node
 | 
						|
      if ($$options{'assigngroup'}){
 | 
						|
         foreach my $node (@nodes) {
 | 
						|
             xCAT::TableUtils->rmnodegroups($node,$tab,$zonename);
 | 
						|
         }
 | 
						|
      }
 | 
						|
      # set the nodelist zonename to nothing
 | 
						|
      my $nozonename=""; 
 | 
						|
      $tab-> setNodesAttribs(\@nodes, { zonename => $nozonename  });
 | 
						|
      $tab->commit();
 | 
						|
      $tab->close();
 | 
						|
    } else {
 | 
						|
       my $rsp = {};
 | 
						|
       $rsp->{error}->[0] =
 | 
						|
        " Failure opening the nodelist table.";
 | 
						|
       xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
       return 1;
 | 
						|
    }
 | 
						|
    return  0;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
1;
 |