mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 05:12:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1012 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			1012 lines
		
	
	
		
			32 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;
 |