40e144b4cc
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@13467 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
1831 lines
47 KiB
Perl
1831 lines
47 KiB
Perl
#!/usr/bin/env perl -w
|
|
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
|
#####################################################
|
|
#
|
|
# xCAT plugin package to handle the xcat2nim command.
|
|
#
|
|
#####################################################
|
|
|
|
package xCAT_plugin::xcat2nim;
|
|
BEGIN
|
|
{
|
|
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
|
}
|
|
use lib "$::XCATROOT/lib/perl";
|
|
use Sys::Hostname;
|
|
use xCAT::NodeRange;
|
|
use xCAT::Schema;
|
|
use xCAT::Utils;
|
|
use xCAT::TableUtils;
|
|
use xCAT::ServiceNodeUtils;
|
|
use xCAT::NetworkUtils;
|
|
use xCAT::DBobjUtils;
|
|
use Data::Dumper;
|
|
use Getopt::Long;
|
|
use xCAT::MsgUtils;
|
|
use Socket;
|
|
|
|
# options can be bundled up like -vV
|
|
Getopt::Long::Configure("bundling");
|
|
$Getopt::Long::ignorecase = 0;
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
=head1 xcat2nim
|
|
|
|
This program module file supports the xcat2nim command.
|
|
|
|
|
|
=cut
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
=head2 xCAT xcat2nim command
|
|
|
|
=cut
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head3 handled_commands
|
|
|
|
Return a list of commands handled by this plugin
|
|
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
sub handled_commands
|
|
{
|
|
return {
|
|
xcat2nim => "xcat2nim"
|
|
};
|
|
}
|
|
|
|
#-------------------------------------------------------
|
|
|
|
=head3 preprocess_request
|
|
|
|
Check and setup for hierarchy
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------
|
|
sub preprocess_request
|
|
{
|
|
my $req = shift;
|
|
my $cb = shift;
|
|
my %sn;
|
|
|
|
# need for runcmd output
|
|
$::CALLBACK=$cb;
|
|
|
|
#exit if preprocessed
|
|
if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; }
|
|
|
|
my $nodes = $req->{node}; # this may not be the list of nodes we need!
|
|
my $command = $req->{command}->[0];
|
|
$::args = $req->{arg};
|
|
my $service = "xcat";
|
|
my @requests;
|
|
|
|
if ($command =~ /xcat2nim/) {
|
|
|
|
# handle -h etc.
|
|
# list of nodes could be derived multiple ways!!
|
|
my ($ret, $mynodes, $servnodes, $type) = &prexcat2nim($cb);
|
|
if ( $ret ) { # either error or -h was processed etc.
|
|
my $rsp;
|
|
if ($ret eq "1") {
|
|
$rsp->{errorcode}->[0] = $ret;
|
|
push @{$rsp->{data}}, "Return=$ret.";
|
|
xCAT::MsgUtils->message("E", $rsp, $cb, $ret);
|
|
}
|
|
return undef;
|
|
} elsif (scalar(@{$mynodes})) {
|
|
|
|
# set up the requests to go to the service nodes
|
|
# - for the nodes that were provided
|
|
# - to handle node and group objects
|
|
my $sn;
|
|
$sn = xCAT::ServiceNodeUtils->getSNformattedhash($mynodes, $service, "MN", $type);
|
|
foreach my $snkey (keys %$sn) {
|
|
my $reqcopy = {%$req};
|
|
$reqcopy->{node} = $sn->{$snkey};
|
|
$reqcopy->{'_xcatdest'} = $snkey;
|
|
$reqcopy->{_xcatpreprocessed}->[0] = 1;
|
|
push @requests, $reqcopy;
|
|
}
|
|
|
|
return \@requests;
|
|
|
|
} elsif (scalar(@{$servnodes} )) {
|
|
# set up the requests to go to the service nodes
|
|
# for network objects
|
|
foreach my $sn (@{$servnodes}) {
|
|
my $reqcopy = {%$req};
|
|
$reqcopy->{'_xcatdest'} = $sn;
|
|
$reqcopy->{_xcatpreprocessed}->[0] = 1;
|
|
push @requests, $reqcopy;
|
|
}
|
|
|
|
return \@requests;
|
|
}
|
|
}
|
|
|
|
return undef;
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head3 process_request
|
|
|
|
Check for xCAT command and call the appropriate subroutine.
|
|
|
|
Returns:
|
|
0 - OK
|
|
1 - error
|
|
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
sub process_request
|
|
{
|
|
|
|
$::request = shift;
|
|
my $callback = shift;
|
|
|
|
# need for runcmd output
|
|
$::CALLBACK=$callback;
|
|
|
|
my $ret;
|
|
my $msg;
|
|
my $rsp;
|
|
|
|
# globals used by all subroutines.
|
|
$::args = $::request->{arg};
|
|
|
|
($ret, $msg) = &x2n($callback);
|
|
if ($ret > 0) {
|
|
my $rsp;
|
|
$rsp->{errorcode}->[0] = $ret;
|
|
push @{$rsp->{data}}, "Return=$ret.";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback, $ret);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head3 prexcat2nim
|
|
|
|
Preprocessing for the xcat2nim command.
|
|
|
|
Arguments:
|
|
Returns:
|
|
0 - OK - needs further processing
|
|
1 - error - done processing this cmd
|
|
2 - help or version - done processing this cmd
|
|
Comments:
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
sub prexcat2nim
|
|
{
|
|
my $callback = shift;
|
|
|
|
my @nodelist=(); # pass back list of nodes - if applicable
|
|
my @servicenodes=(); # pass back list of service nodes - if applicable
|
|
|
|
if (defined(@{$::args})) {
|
|
@ARGV = @{$::args};
|
|
} else {
|
|
&xcat2nim_usage($callback);
|
|
return 1;
|
|
}
|
|
|
|
Getopt::Long::Configure("no_pass_through");
|
|
if (
|
|
!GetOptions(
|
|
'all|a' => \$::opt_a,
|
|
'b|backupSN' => \$::BACKUP,
|
|
'f|force' => \$::FORCE,
|
|
'help|h|?' => \$::opt_h,
|
|
'list|l' => \$::opt_l,
|
|
'update|u' => \$::opt_u,
|
|
'remove|r' => \$::opt_r,
|
|
'managementnode|M' => \$::MN,
|
|
'o=s' => \$::opt_o,
|
|
'p|primarySN' => \$::PRIMARY,
|
|
't=s' => \$::opt_t,
|
|
's=s' => \$::SERVERS,
|
|
'verbose|V' => \$::opt_V,
|
|
'version|v' => \$::opt_v,
|
|
)
|
|
)
|
|
{
|
|
&xcat2nim_usage($callback);
|
|
return 1;
|
|
}
|
|
|
|
# Option -h for Help
|
|
if ($::opt_h )
|
|
{
|
|
&xcat2nim_usage($callback);
|
|
return 2;
|
|
}
|
|
|
|
# Option -v for version
|
|
if ($::opt_v)
|
|
{
|
|
my $rsp;
|
|
my $version=xCAT::Utils->Version();
|
|
$rsp->{data}->[0] = "xcat2nim - $version";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
return 2; # - just exit
|
|
}
|
|
|
|
# process the command line
|
|
my $rc = &processArgs($callback);
|
|
|
|
my $type;
|
|
if ($::PRIMARY && $::BACKUP) {
|
|
# setting both is the same as all
|
|
$type="all";
|
|
} elsif ($::PRIMARY) {
|
|
$type="primary";
|
|
} elsif ($::BACKUP) {
|
|
$type="backup";
|
|
} else {
|
|
$type="all";
|
|
}
|
|
|
|
# figure out what nodes are involved - if any
|
|
# - so we can send the request to the correct service nodes
|
|
my %objhash = xCAT::DBobjUtils->getobjdefs(\%::objtype);
|
|
my $donet = 0;
|
|
foreach my $o (@::clobjnames) {
|
|
if ($::objtype{$o} eq 'node') {
|
|
push (@nodelist, $o);
|
|
}
|
|
if ($::objtype{$o} eq 'group') {
|
|
my $memberlist = xCAT::DBobjUtils->getGroupMembers($o, \%objhash);
|
|
my @members = split(',', $memberlist);
|
|
if (@members) {
|
|
foreach my $n (@members) {
|
|
push (@nodelist, $n);
|
|
}
|
|
}
|
|
}
|
|
if ($::objtype{$o} eq 'network') {
|
|
if ($::FORCE || $::opt_u || $::opt_r) {
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "The -f, -r and -u options are not supported for network objects.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
&xcat2nim_usage($callback);
|
|
return 2;
|
|
}
|
|
$donet = 1;
|
|
}
|
|
}
|
|
|
|
# NIM network defs need to be created on the NIM primary
|
|
my $nimprime = xCAT::InstUtils->getnimprime();
|
|
chomp $nimprime;
|
|
@servicenodes=($nimprime);
|
|
|
|
if(0) { # only do networks on the management node (NIM primary) for now
|
|
if ($donet) {
|
|
if ($::MN) {
|
|
# only do management node
|
|
@servicenodes=("$nimprime");
|
|
} elsif ($::SERVERS) {
|
|
@servicenodes=split(',', $::SERVERS);
|
|
} else {
|
|
# do MN and all servers
|
|
@servicenodes=xCAT::ServiceNodeUtils->getAllSN();
|
|
push(@servicenodes, $nimprime);
|
|
}
|
|
}
|
|
|
|
if (scalar(@nodelist) ) {
|
|
# make sure the nodes are resolvable
|
|
# - if not then exit
|
|
foreach my $n (@nodelist) {
|
|
my $packed_ip = gethostbyname($n);
|
|
if (!$packed_ip) {
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "Could not resolve node $n.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (0, \@nodelist, \@servicenodes, $type);
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head3 processArgs
|
|
|
|
Process the command line.
|
|
|
|
Also - Process any input files provided on cmd line.
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
0 - OK
|
|
1 - just print usage
|
|
2 - error
|
|
Globals:
|
|
|
|
Error:
|
|
|
|
Example:
|
|
|
|
Comments:
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
sub processArgs
|
|
{
|
|
my $callback = shift;
|
|
|
|
my $gotattrs = 0;
|
|
|
|
if (defined(@{$::args})) {
|
|
@ARGV = @{$::args};
|
|
} else {
|
|
return 3;
|
|
}
|
|
|
|
my %ObjTypeHash;
|
|
@::clobjnames = ();
|
|
@::clobjtypes = ();
|
|
|
|
# parse the options
|
|
Getopt::Long::Configure("no_pass_through");
|
|
if (
|
|
!GetOptions(
|
|
'all|a' => \$::opt_a,
|
|
'b|backupSN' => \$::BACKUP,
|
|
'f|force' => \$::FORCE,
|
|
'help|h|?' => \$::opt_h,
|
|
'list|l' => \$::opt_l,
|
|
'update|u' => \$::opt_u,
|
|
'remove|r' => \$::opt_r,
|
|
'managementnode|M' => \$::MN,
|
|
'o=s' => \$::opt_o,
|
|
'p|primarySN' => \$::PRIMARY,
|
|
's=s' => \$::SERVERS,
|
|
't=s' => \$::opt_t,
|
|
'verbose|V' => \$::opt_V,
|
|
'version|v' => \$::opt_v,
|
|
)
|
|
)
|
|
{
|
|
|
|
# return 2;
|
|
}
|
|
|
|
# can get object names in many ways - easier to keep track
|
|
$::objectsfrom_args = 0;
|
|
$::objectsfrom_opto = 0;
|
|
$::objectsfrom_optt = 0;
|
|
$::objectsfrom_opta = 0;
|
|
|
|
#
|
|
# process @ARGV
|
|
#
|
|
|
|
# - put attr=val operands in ATTRS hash
|
|
while (my $a = shift(@ARGV))
|
|
{
|
|
|
|
if (!($a =~ /=/))
|
|
{
|
|
|
|
# the first arg could be a noderange or a list of args
|
|
if (($::opt_t) && ($::opt_t ne 'node'))
|
|
{
|
|
|
|
# if we know the type isn't "node" then set the object list
|
|
@::clobjnames = split(',', $a);
|
|
$::objectsfrom_args = 1;
|
|
}
|
|
elsif (!$::opt_t || ($::opt_t eq 'node'))
|
|
{
|
|
|
|
# if the type was not provided or it is "node"
|
|
# then set noderange
|
|
@::noderange = &noderange($a, 0);
|
|
@::clobjnames = @::noderange;
|
|
$::objectsfrom_args = 1;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
# if it has an "=" sign its an attr=val - we hope
|
|
# - this will handle "attr= "
|
|
my ($attr, $value) = $a =~ /^\s*(\S+?)\s*=\s*(\S*.*)$/;
|
|
if (!defined($attr) || !defined($value))
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "Incorrect \'attr=val\' pair - $a\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 3;
|
|
}
|
|
|
|
$gotattrs = 1;
|
|
|
|
# put attr=val in hash
|
|
$::ATTRS{$attr} = $value;
|
|
|
|
}
|
|
}
|
|
|
|
# Option -V for verbose output
|
|
if (defined($::opt_V))
|
|
{
|
|
$::verbose = 1;
|
|
$::VERBOSE = 1;
|
|
}
|
|
|
|
#
|
|
# determine the object types
|
|
#
|
|
|
|
# could have comma seperated list of types
|
|
if ($::opt_t)
|
|
{
|
|
my @tmptypes;
|
|
|
|
if ($::opt_t =~ /,/)
|
|
{
|
|
|
|
# can't have mult types when using attr=val
|
|
if ($gotattrs)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] =
|
|
"Cannot combine multiple types with \'att=val\' pairs on the command line.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 3;
|
|
}
|
|
else
|
|
{
|
|
@tmptypes = split(',', $::opt_t);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
push(@tmptypes, $::opt_t);
|
|
}
|
|
|
|
# check for valid types
|
|
my @xdeftypes;
|
|
foreach my $k (keys %{xCAT::Schema::defspec})
|
|
{
|
|
push(@xdeftypes, $k);
|
|
}
|
|
|
|
foreach my $t (@tmptypes)
|
|
{
|
|
if (!grep(/$t/, @xdeftypes))
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] =
|
|
"$::msgstr Type \'$t\' is not a valid xCAT object type.\n";
|
|
$rsp->{data}->[1] = "Skipping to the next type.\n";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
else
|
|
{
|
|
chomp $t;
|
|
push(@::clobjtypes, $t);
|
|
}
|
|
}
|
|
}
|
|
|
|
# must have object type(s) - default if not provided
|
|
if (!@::clobjtypes && !$::opt_a)
|
|
{
|
|
|
|
# make the default type = 'node' if not specified
|
|
push(@::clobjtypes, 'node');
|
|
#my $rsp;
|
|
#$rsp->{data}->[0] = "Assuming an object type of \'node\'.\n";
|
|
#xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
|
|
#
|
|
# determine the object names
|
|
#
|
|
|
|
# - get object names from the -o option or the noderange
|
|
# - this assumes the noderange was not provided as an arg!!!
|
|
if ($::opt_o)
|
|
{
|
|
|
|
$::objectsfrom_opto = 1;
|
|
|
|
# make a list
|
|
if ($::opt_o =~ /,/)
|
|
{
|
|
@::clobjnames = split(',', $::opt_o);
|
|
}
|
|
else
|
|
{
|
|
push(@::clobjnames, $::opt_o);
|
|
}
|
|
|
|
if (!$::opt_t || ($::opt_t eq 'node')) {
|
|
# if the type is "node"
|
|
@::noderange = &noderange($::opt_o, 0);
|
|
@::clobjnames = @::noderange;
|
|
}
|
|
}
|
|
|
|
# if there is no opt_o & no noderange then try to find all the objects
|
|
# of the given types.
|
|
if ($::opt_t
|
|
&& !( $::opt_o
|
|
|| $::opt_a
|
|
|| @::noderange
|
|
|| @::clobjnames))
|
|
{
|
|
my @tmplist;
|
|
|
|
$::objectsfrom_optt = 1;
|
|
|
|
# could have multiple type
|
|
foreach my $t (@::clobjtypes)
|
|
{
|
|
|
|
# look up all objects of this type in the DB ???
|
|
@tmplist = xCAT::DBobjUtils->getObjectsOfType($t);
|
|
|
|
unless (@tmplist)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] =
|
|
"Could not get objects of type \'$t\'.\n";
|
|
$rsp->{data}->[1] = "Skipping to the next type.\n";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
next;
|
|
}
|
|
|
|
# add objname and type to hash and global list
|
|
foreach my $o (@tmplist)
|
|
{
|
|
push(@::clobjnames, $o);
|
|
$ObjTypeHash{$o} = $t;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
# can't have -a with other obj sources
|
|
if ($::opt_a
|
|
&& ($::opt_o || @::noderange))
|
|
{
|
|
|
|
my $rsp;
|
|
$rsp->{data}->[0] =
|
|
"Cannot use \'-a\' with \'-o\' or a noderange.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 3;
|
|
}
|
|
|
|
# if -a then get a list of all DB objects
|
|
my %AllObjTypeHash;
|
|
if ($::opt_a)
|
|
{
|
|
my @tmplist;
|
|
|
|
$::objectsfrom_opta = 1;
|
|
|
|
# for every type of data object get the list of defined objects
|
|
foreach my $t (keys %{xCAT::Schema::defspec})
|
|
{
|
|
if ( ($t eq 'node') || ($t eq 'group') || ($t eq 'network')) {
|
|
|
|
my @tmplist;
|
|
@tmplist = xCAT::DBobjUtils->getObjectsOfType($t);
|
|
|
|
# add objname and type to hash and global list
|
|
if (scalar(@tmplist) > 0)
|
|
{
|
|
foreach my $o (@tmplist)
|
|
{
|
|
push(@::clobjnames, $o);
|
|
$AllObjTypeHash{$o} = $t;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# must have object name(s) -
|
|
if (!@::clobjnames)
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
# create hash with object names and types
|
|
foreach my $o (@::clobjnames)
|
|
{
|
|
if ($::objectsfrom_opta) {
|
|
# if the object names came from the "-a" option then
|
|
%::objtype = %AllObjTypeHash;
|
|
|
|
} elsif ($::objectsfrom_optt) {
|
|
# if the names came from the opt_t option
|
|
%::objtype = %ObjTypeHash;
|
|
|
|
} elsif ($::objectsfrom_args || $::objectsfrom_opto) {
|
|
# from the opt_o or as an argument
|
|
# - there can only be one type
|
|
$::objtype{$o}=$::clobjtypes[0];
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head3 x2n
|
|
|
|
Support for the xcat2nim command.
|
|
|
|
Arguments:
|
|
Returns:
|
|
0 - OK
|
|
1 - error
|
|
Globals:
|
|
|
|
Error:
|
|
|
|
Example:
|
|
|
|
Comments:
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
sub x2n
|
|
{
|
|
my $callback = shift;
|
|
|
|
my $rc = 0;
|
|
my $error = 0;
|
|
|
|
# get this systems name as known by xCAT management node
|
|
$::Sname = xCAT::InstUtils->myxCATname();
|
|
chomp $::Sname;
|
|
|
|
$::msgstr = "$::Sname: ";
|
|
|
|
# process the command line
|
|
$rc = &processArgs($callback);
|
|
if ($rc != 0)
|
|
{
|
|
|
|
# rc: 0 - ok, 1 - return, 2 - help, 3 - error
|
|
if ($rc != 1)
|
|
{
|
|
&xcat2nim_usage($callback);
|
|
}
|
|
return ($rc - 1);
|
|
}
|
|
|
|
# get all the attrs for these definitions
|
|
%::objhash = xCAT::DBobjUtils->getobjdefs(\%::objtype);
|
|
if (!%::objhash)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "Could not get xCAT object definitions.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
my @nodes;
|
|
my @networks;
|
|
my @groups;
|
|
foreach my $obj (keys %::objhash) {
|
|
if ($::objtype{$obj} eq 'node') {
|
|
push(@nodes, $obj);
|
|
} elsif ($::objtype{$obj} eq 'network') {
|
|
if ($::objhash{$obj}{'gateway'} eq '<xcatmaster>') {
|
|
$::objhash{$obj}{'gateway'} = xCAT::NetworkUtils->my_ip_in_subnet($::objhash{$obj}{'net'}, $::objhash{$obj}{'mask'});
|
|
if(!$::objhash{$obj}{'gateway'}) {
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "Could not get gateway for network $obj, ...skipping\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
next;
|
|
}
|
|
}
|
|
push(@networks, $obj);
|
|
} elsif ($::objtype{$obj} eq 'group') {
|
|
push(@groups, $obj);
|
|
}
|
|
}
|
|
|
|
# NIM machine definitions
|
|
if (scalar(@nodes)) {
|
|
foreach my $objname (@nodes) {
|
|
|
|
if ($::opt_l || $::opt_r) {
|
|
|
|
if (&rm_or_list_nim_object($objname, $::objtype{$objname}, $callback)) {
|
|
# the routine failed
|
|
$error++;
|
|
}
|
|
} else {
|
|
if (mkclientdef($objname, $callback)) {
|
|
# could not create client definition
|
|
$error++;
|
|
}
|
|
}
|
|
next;
|
|
}
|
|
}
|
|
|
|
# NIM network definitions
|
|
if (scalar(@networks) ){
|
|
if ($::opt_l) {
|
|
# list network def
|
|
if (&listNIMnetwork($callback, \@networks, \%::objhash) ) {
|
|
# could not create client definition
|
|
$error++;
|
|
}
|
|
} elsif ($::opt_r) {
|
|
# remove network def
|
|
|
|
#if (&rmNIMnetwork($callback, \@networks) ) {
|
|
# # could not create client definition
|
|
# $error++;
|
|
#}
|
|
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr The remove option is not supported for NIM network definitions.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
$error++;
|
|
|
|
} else {
|
|
if (&mkNIMnetwork($callback, \@networks, \%::objhash)) {
|
|
# could not create client definition
|
|
$error++;
|
|
}
|
|
}
|
|
}
|
|
|
|
# NIM group definitions
|
|
if (scalar(@groups) ) {
|
|
foreach my $objname (@groups) {
|
|
|
|
# make sure grouptype is set ???
|
|
$::objhash{$objname}{'grouptype'}='static';
|
|
my $grptab = xCAT::Table->new('nodegroup');
|
|
#dynamic groups and static groups in nodegroup table
|
|
my @grplist = @{$grptab->getAllEntries()};
|
|
foreach my $grpdef_ref (@grplist) {
|
|
my %grpdef = %$grpdef_ref;
|
|
if (($grpdef{'groupname'} eq $objname) && ($grpdef{'grouptype'} eq 'dynamic')) {
|
|
$::objhash{$objname}{'grouptype'}='dynamic';
|
|
last;
|
|
}
|
|
}
|
|
$grptab->close;
|
|
|
|
if ($::opt_l || $::opt_r) {
|
|
if (&rm_or_list_nim_object($objname, $::objtype{$objname}, $callback)) {
|
|
# the routine failed
|
|
$error++;
|
|
}
|
|
} else {
|
|
if (&mkgrpdef($objname, $callback)) {
|
|
# could not create group definition
|
|
$error++;
|
|
}
|
|
}
|
|
next;
|
|
}
|
|
}
|
|
|
|
if ($error)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] =
|
|
"$::msgstr One or more errors occured.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head3 mkclientdef
|
|
|
|
Create a NIM client definition.
|
|
Arguments:
|
|
Returns:
|
|
0 - OK
|
|
1 - error
|
|
Globals:
|
|
|
|
Error:
|
|
|
|
Example:
|
|
|
|
Comments:
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
sub mkclientdef
|
|
{
|
|
my $node = shift;
|
|
my $callback = shift;
|
|
|
|
my $cabletype = undef;
|
|
my $ifattr = undef;
|
|
|
|
my %finalattrs;
|
|
my $shorthost;
|
|
my $net_name;
|
|
my $adaptertype;
|
|
my $nim_args;
|
|
my $nim_type;
|
|
|
|
# this code runs on service nodes - which are NIM masters
|
|
|
|
# check to see if the client is already defined
|
|
# - sets $::client_exists
|
|
if (&check_nim_client($node, $::Sname, $callback)) {
|
|
# the routine failed
|
|
return 1;
|
|
}
|
|
|
|
# need short host name for NIM client defs
|
|
($shorthost = $node) =~ s/\..*$//;
|
|
|
|
# NIM has a limit of 39 characters for a machine name
|
|
my $len = length($shorthost);
|
|
if ($len > 39) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not define \'$shorthost\'. A NIM machine name can be no longer then 39 characters.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
# don't update an existing def unless they say so!
|
|
if ($::client_exists && !$::opt_u) {
|
|
|
|
if ($::FORCE) {
|
|
# get rid of the old definition
|
|
my $rmcmd = "/usr/sbin/nim -Fo reset $shorthost;/usr/sbin/nim -Fo deallocate -a subclass=all $shorthost;/usr/sbin/nim -Fo remove $shorthost";
|
|
my $output = xCAT::Utils->runcmd("$rmcmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not remove the existing NIM object named \'$shorthost\'.\n";
|
|
if ($::VERBOSE) {
|
|
push @{$rsp->{data}}, "$output";
|
|
}
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
} else { # no force
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr The NIM client machine \'$shorthost\' already exists. Use the \'-f\' option to remove and recreate or the \'-u\' option to update an existing definition.\n";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
# either create or update the def
|
|
|
|
# process the args and add defaults etc.
|
|
foreach my $attr (keys %::ATTRS) {
|
|
|
|
if ( $attr =~ /^if/) {
|
|
|
|
$ifattr = "-a $attr=\'$::ATTRS{$attr}\'";
|
|
|
|
} elsif ( $attr =~ /^cable_type/) {
|
|
$cabletype="-a cable_type1=\'$::ATTRS{$attr}\'";
|
|
|
|
} else {
|
|
# add to
|
|
$finalattrs{$attr}=$::ATTRS{$attr};
|
|
}
|
|
}
|
|
|
|
# req a value for cable_type
|
|
|
|
if (!$cabletype) {
|
|
$cabletype="-a cable_type1=N/A ";
|
|
}
|
|
|
|
# req a value for "if1" interface def
|
|
if (!$ifattr) {
|
|
# then try to create the attr - required
|
|
if ($::objhash{$node}{'netname'}) {
|
|
$net_name=$::objhash{$node}{'netname'};
|
|
} else {
|
|
$net_name="find_net";
|
|
}
|
|
|
|
if (!$::objhash{$node}{'mac'})
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr Missing the MAC for node \'$node\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
} else {
|
|
$::objhash{$node}{'mac'} =~ s/://g;
|
|
}
|
|
|
|
my $mac_or_local_link_addr;
|
|
if (xCAT::NetworkUtils->getipaddr($shorthost) =~ /:/) #ipv6 node
|
|
{
|
|
$mac_or_local_link_addr = xCAT::NetworkUtils->linklocaladdr($::objhash{$node}{'mac'});
|
|
$adaptertype = "ent6";
|
|
} else {
|
|
$mac_or_local_link_addr = $::objhash{$node}{'mac'};
|
|
# only support Ethernet for management interfaces
|
|
$adaptertype = "ent";
|
|
}
|
|
|
|
$ifattr="-a if1=\'$net_name $shorthost $mac_or_local_link_addr $adaptertype\'";
|
|
}
|
|
|
|
# only support standalone for now - will get this from node def in future
|
|
$nim_type = "-t standalone";
|
|
|
|
$nim_args = "$ifattr ";
|
|
$nim_args .= "$cabletype";
|
|
|
|
# add the rest of the attr=val to the command line
|
|
foreach my $a (keys %finalattrs) {
|
|
$nim_args .= " -a $a=\'$finalattrs{$a}\'";
|
|
}
|
|
|
|
# put together the correct NIM command
|
|
my $cmd;
|
|
|
|
if ($::client_exists && $::opt_u) {
|
|
$cmd = "nim -F -o change $nim_args $shorthost";
|
|
} else {
|
|
$cmd = "nim -o define $nim_type $nim_args $shorthost";
|
|
}
|
|
|
|
my $nimcmd;
|
|
$nimcmd = qq~$cmd 2>&1~;
|
|
|
|
# run the cmd
|
|
my $output = xCAT::Utils->runcmd("$nimcmd", -1);
|
|
if ($::RUNCMD_RC != 0)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr Could not create a NIM definition for \'$node\'.\n";
|
|
if ($::verbose)
|
|
{
|
|
$rsp->{data}->[1] = "$output";
|
|
}
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head3 mkgrpdef
|
|
|
|
Create a NIM group definition.
|
|
|
|
Arguments:
|
|
Returns:
|
|
0 - OK
|
|
1 - error
|
|
Globals:
|
|
|
|
Error:
|
|
|
|
Example:
|
|
|
|
Comments:
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
sub mkgrpdef
|
|
{
|
|
my $group = shift;
|
|
my $callback = shift;
|
|
|
|
# get members of xCAT group
|
|
my $memberlist = xCAT::DBobjUtils->getGroupMembers($group, \%::objhash);
|
|
my @members = split(',', $memberlist);
|
|
|
|
# get list of nim groups defined locally
|
|
$cmd = qq~lsnim -c groups | cut -f1 -d' ' 2>/dev/null~;
|
|
my @GroupList = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr Could not get a list of NIM group definitions.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
# get list of nim machine defined locally
|
|
$mcmd = qq~lsnim -c machines | cut -f1 -d' ' 2>/dev/null~;
|
|
my @nimnodes = xCAT::Utils->runcmd("$mcmd", -1);
|
|
if ($::RUNCMD_RC != 0)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr Could not get a list of NIM group definit
|
|
ions.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
# don't update an existing def unless we're told
|
|
if ( (grep(/$group/, @GroupList)) && !$::opt_u) {
|
|
if ($::FORCE) {
|
|
# get rid of the old definition
|
|
my $rmcmd = "/usr/sbin/nim -Fo remove $group";
|
|
my $output = xCAT::Utils->runcmd("$rmcmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not remove the existing NIM group named \'$group\'.\n";
|
|
if ($::VERBOSE) {
|
|
push @{$rsp->{data}}, "$output";
|
|
}
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
} else { # no force
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr The NIM group \'$group\' already exists. Use the \'-f\' option to remove and recreate or the \'-u\' option to update an existing definition.\n";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
# either create or update the group def on this master
|
|
|
|
# any list with more than 1024 members is an error
|
|
# - NIM can't handle that
|
|
if ($#members > 1024) {
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr Cannot create a NIM group definition with more than 1024 members.";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
next;
|
|
}
|
|
|
|
#
|
|
# The list may become quite long and not fit on one cmd line
|
|
# so we do it one at a time for now - need to revisit this
|
|
# (like do blocks at a time) - TODO
|
|
#
|
|
my $justadd=0; # after the first define we just need to add
|
|
foreach my $memb (@members) {
|
|
|
|
# if this node is not defined locally then don't add it to the list
|
|
if (!grep(/$memb/, @nimnodes)) {
|
|
next;
|
|
}
|
|
|
|
my $shorthost;
|
|
($shorthost = $memb) =~ s/\..*$//;
|
|
|
|
# do we change or create
|
|
my $cmd;
|
|
if (((grep(/$group/, @GroupList)) && $::opt_u) || $justadd) {
|
|
$cmd = "nim -o change -a add_member=$shorthost $group 2>&1";
|
|
} else {
|
|
$cmd = "nim -o define -t mac_group -a add_member=$shorthost $group 2>&1";
|
|
$justadd++;
|
|
}
|
|
|
|
my $output = xCAT::Utils->runcmd("$cmd", -1);
|
|
|
|
if ($::RUNCMD_RC != 0)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr Could not create a NIM definition for \'$group\'.\n";
|
|
if ($::verbose)
|
|
{
|
|
$rsp->{data}->[1] = "$output";
|
|
}
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head3 rm_or_list_nim_object
|
|
|
|
List a NIM object definition.
|
|
|
|
Argument:
|
|
Returns:
|
|
0 - OK
|
|
1 - error
|
|
Globals:
|
|
|
|
Error:
|
|
|
|
Example:
|
|
|
|
Comments:
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
sub rm_or_list_nim_object
|
|
{
|
|
my ($object, $type, $callback) = @_;
|
|
|
|
if ($type eq 'node') {
|
|
|
|
if ($::opt_l) {
|
|
|
|
my $cmd;
|
|
$cmd = qq~lsnim -l $object 2>/dev/null~;
|
|
|
|
my $outref = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr Could not get the NIM definition for $object.\n";
|
|
if ($::verbose)
|
|
{
|
|
$rsp->{data}->[1] = "$outref";
|
|
}
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
} else {
|
|
|
|
# display to NIM output
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$outref";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
return 0;
|
|
}
|
|
|
|
} elsif ($::opt_r) {
|
|
# remove the object
|
|
my $cmd;
|
|
|
|
if ($::FORCE) {
|
|
$cmd = qq~nim -Fo reset $object;nim -Fo deallocate -a subclass=all $object;nim -Fo remove $object 2>/dev/null~;
|
|
} else {
|
|
$cmd = qq~nim -Fo remove $object 2>/dev/null~;
|
|
}
|
|
|
|
my $outref = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr Could not remove the NIM definition for \'$object\'.\n";
|
|
if ($::verbose)
|
|
{
|
|
$rsp->{data}->[1] = "$outref";
|
|
}
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($type eq 'group') {
|
|
|
|
my $cmd;
|
|
if ($::opt_l) {
|
|
$cmd = qq~lsnim -l $object 2>/dev/null~;
|
|
|
|
my $outref = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr Could not list the NIM definition for \'$object\'.\n";
|
|
if ($::verbose)
|
|
{
|
|
$rsp->{data}->[1] = "$outref";
|
|
}
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
} else {
|
|
|
|
# display NIM output
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$outref";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
return 0;
|
|
}
|
|
} elsif ($::opt_r) {
|
|
$cmd = qq~nim -Fo remove $object 2>/dev/null~;
|
|
|
|
my $outref = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr Could not remove the NIM definition for \'$object\'.\n";
|
|
if ($::verbose)
|
|
{
|
|
$rsp->{data}->[1] = "$outref";
|
|
}
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head3 getNIMmaster
|
|
|
|
Get the name of the NIM master for a node.
|
|
|
|
Arguments:
|
|
Returns:
|
|
name
|
|
undef - error
|
|
Globals:
|
|
|
|
Error:
|
|
|
|
Example:
|
|
|
|
Comments:
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
sub getNIMmaster
|
|
{
|
|
my ($node) = @_;
|
|
my $NimMaster;
|
|
my $master = undef;
|
|
|
|
# get the server name
|
|
if ($::objhash{$node}{nimmaster}) {
|
|
$NimMaster = $::objhash{$node}{nimmaster};
|
|
|
|
} elsif ($::objhash{$node}{servicenode}) {
|
|
# the servicenode attr is set for this node
|
|
$NimMaster = $::objhash{$node}{servicenode};
|
|
|
|
} elsif ($::objhash{$node}{xcatmaster}) {
|
|
$NimMaster = $::objhash{$node}{xcatmaster};
|
|
|
|
} else {
|
|
my $nimprime = xCAT::InstUtils->getnimprime();
|
|
chomp $nimprime;
|
|
$NimMaster = $nimprime;
|
|
}
|
|
|
|
# assume short hostnames for now???
|
|
if ($NimMaster) {
|
|
($master = $NimMaster) =~ s/\..*$//;
|
|
}
|
|
return $master;
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head3 check_nim_client
|
|
|
|
See if an xCAT node has already been defined as a NIM client.
|
|
|
|
Arguments:
|
|
Returns:
|
|
0 - OK
|
|
1 - error
|
|
Globals:
|
|
|
|
Error:
|
|
|
|
Example:
|
|
|
|
Comments:
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
sub check_nim_client
|
|
{
|
|
my ($node, $servnode, $callback) = @_;
|
|
my ($cmd, @ClientList);
|
|
|
|
$cmd = qq~lsnim -c machines | cut -f1 -d' ' 2>/dev/null~;
|
|
@ClientList = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0)
|
|
{
|
|
my $rsp;
|
|
$rsp->{data}->[0] = "$::msgstr Could not get a list of NIM client definitions from \'$servnode\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
$::client_exists = grep(/^$node$/,@ClientList) ? 1 : 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head3 xcat2nim_usage
|
|
|
|
Arguments:
|
|
Returns:
|
|
Globals:
|
|
|
|
Error:
|
|
|
|
Example:
|
|
|
|
Comments:
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
sub xcat2nim_usage
|
|
{
|
|
my $callback = shift;
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "\nUsage: xcat2nim - Use this command to create and manage AIX NIM definitions based on xCAT object definitions.\n";
|
|
push @{$rsp->{data}}, " xcat2nim [-h|--help ]\n";
|
|
push @{$rsp->{data}}, " xcat2nim [-V|--verbose] [-l|--list] [-r|--remove] [-u|--update]\n [-f|--force] [-t object-types] [-o object-names] [-a|--allobjects]\n [-p|--primarySN] [-b|--backupSN] [noderange] [attr=val [attr=val...]]\n";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
return 0;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 mkNIMnetwork
|
|
Create NIM network definitions corresponding to xCAT network
|
|
definitions. This routine runs on the NIMprime and AIX SNs
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
|
|
Comments:
|
|
|
|
ex. &mkNIMnetwork($callback, \@networks, \%nethash);
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub mkNIMnetwork
|
|
{
|
|
my $callback = shift;
|
|
my $xnets = shift;
|
|
my $xnhash = shift;
|
|
|
|
my @xnetworks = @{$xnets};
|
|
my %xnethash; # hash of xCAT network definitions
|
|
if ($xnhash) {
|
|
%xnethash = %{$xnhash};
|
|
}
|
|
|
|
#
|
|
# get all the nim network names and attrs defined on this server
|
|
#
|
|
my $cmd = qq~/usr/sbin/lsnim -c networks | /usr/bin/cut -f1 -d' ' 2>/dev/null~;
|
|
my @networks = xCAT::Utils->runcmd("$cmd", -1);
|
|
|
|
# for each NIM network - get the attrs
|
|
my %NIMnets;
|
|
foreach my $netwk (@networks) {
|
|
my $cmd = qq~/usr/sbin/lsnim -Z -a net_addr -a snm $netwk 2>/dev/null~;
|
|
my @result = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not run lsnim command: \'$cmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
foreach my $l (@result){
|
|
# skip comment lines
|
|
next if ($l =~ /^\s*#/);
|
|
|
|
my ($nimname, $net_addr, $snm) = split(':', $l);
|
|
$NIMnets{$netwk}{'net_addr'} = $net_addr;
|
|
$NIMnets{$netwk}{'snm'} = $snm;
|
|
}
|
|
}
|
|
|
|
#
|
|
# for each xCAT network - see if the net we need is defined
|
|
#
|
|
foreach my $net (@xnetworks) {
|
|
|
|
# see if it's already defined - or equivalent is defined
|
|
# split mask
|
|
my ($nm1, $nm2, $nm3, $nm4) = split('\.', $xnethash{$net}{mask});
|
|
|
|
# split net addr
|
|
my ($nn1, $nn2, $nn3, $nn4) = split('\.', $xnethash{$net}{net});
|
|
|
|
# foreach nim network name
|
|
foreach my $netwk (@networks) {
|
|
|
|
# split definition mask
|
|
my ($dm1, $dm2, $dm3, $dm4) = split('\.', $NIMnets{$netwk}{'snm'});
|
|
|
|
# split definition net addr
|
|
my ($dn1, $dn2, $dn3, $dn4) = split('\.', $NIMnets{$netwk}{'net_addr'});
|
|
# check for the same netmask and network address
|
|
if ( ($nn1 == $dn1) && ($nn2 ==$dn2) && ($nn3 == $dn3) && ($nn4 == $dn4) ) {
|
|
if ( ($nm1 == $dm1) && ($nm2 ==$dm2) && ($nm3 == $dm3) && ($nm4 == $dm4) ) {
|
|
$foundmatch=1;
|
|
}
|
|
}
|
|
}
|
|
|
|
# if not defined then define it!
|
|
if (!$foundmatch) {
|
|
|
|
# create new nim network def
|
|
# use the same network name as xCAT uses
|
|
my $cmd;
|
|
$cmd = qq~/usr/sbin/nim -o define -t ent -a net_addr=$xnethash{$net}{net} -a snm=$xnethash{$net}{mask} -a routing1='default $xnethash{$net}{gateway}' $net 2>/dev/null~;
|
|
|
|
my $output1 = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not run \'$cmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
# get all the possible IPs for the node I'm running on
|
|
my $ifgcmd = "ifconfig -a | grep 'inet'";
|
|
my @result = xCAT::Utils->runcmd($ifgcmd, 0);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not run \'$ifgcmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
|
|
my $samesubnet = 0;
|
|
my ($inet, $myIP, $str);
|
|
foreach my $int (@result) {
|
|
($inet, $myIP, $str) = split(" ", $int);
|
|
chomp $myIP;
|
|
$myIP =~ s/\/.*//; # ipv6 address 4000::99/64
|
|
$myIP =~ s/\%.*//; # ipv6 address ::1%1/128
|
|
|
|
# if the ip address is in the subnet
|
|
if ( xCAT::NetworkUtils->ishostinsubnet($myIP, $xnethash{$net}{mask}, $xnethash{$net}{net} )) {
|
|
# to create the nim network object within the same subnet
|
|
$samesubnet = 1;
|
|
last;
|
|
}
|
|
}
|
|
|
|
if ($samesubnet == 1)
|
|
{
|
|
#
|
|
# create an interface def (if*) for the master
|
|
#
|
|
# first get the if* and cable_type* attrs
|
|
# - the -A option gets the next avail index for this attr
|
|
my $ifcmd = qq~/usr/sbin/lsnim -A if master 2>/dev/null~;
|
|
my $ifindex = xCAT::Utils->runcmd("$ifcmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "Could not run \'$ifcmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
my $ctcmd = qq~/usr/sbin/lsnim -A cable_type master 2>/dev/null~;
|
|
my $ctindex = xCAT::Utils->runcmd("$ctcmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not run \'$ctcmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
#
|
|
# get the local adapter hostname for this network
|
|
my $adapterhostname = xCAT::NetworkUtils->gethostname($myIP);
|
|
|
|
# define the new interface
|
|
my $chcmd = qq~/usr/sbin/nim -o change -a if$ifindex='$net $adapterhostname 0' -a cable_type$ctindex=N/A master 2>/dev/null~;
|
|
|
|
my $output2 = xCAT::Utils->runcmd("$chcmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not run \'$chcmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# cross subnet
|
|
# create static routes between the networks
|
|
|
|
# get master_net - always if1
|
|
my $hncmd = qq~/usr/sbin/lsnim -a if1 -Z master 2>/dev/null~;
|
|
my @ifone = xCAT::Utils->runcmd("$hncmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not run \'$hncmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
my ($junk1, $masternet, $adapterhost);
|
|
foreach my $l (@ifone){
|
|
# skip comment lines
|
|
next if ($l =~ /^\s*#/);
|
|
($junk1, $masternet, $adapterhost) = split(':', $l);
|
|
|
|
}
|
|
|
|
# get the next index for the routing attr
|
|
my $ncmd = qq~/usr/sbin/lsnim -A routing $masternet 2>/dev/null~;
|
|
my $rtindex = xCAT::Utils->runcmd("$ncmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not run \'$ncmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
# get the gateway of master_net
|
|
my $gcmd = qq~/usr/sbin/lsnim -a routing1 -Z $masternet 2>/dev/null~;
|
|
my @gws = xCAT::Utils->runcmd("$gcmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not run \'$gcmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
my ($junk, $dft, $gw);
|
|
foreach my $l (@gws){
|
|
# skip comment lines
|
|
next if ($l =~ /^\s*#/);
|
|
($junk, $dft, $gw) = split(':', $l);
|
|
}
|
|
|
|
my $masternetgw;
|
|
if ($dft =~ /default/)
|
|
{
|
|
$masternetgw = $gw;
|
|
}
|
|
else
|
|
{
|
|
# use the master IP as default gateway
|
|
# get the ip of the nim primary interface
|
|
my $gwIP = xCAT::NetworkUtils->getipaddr($adapterhost);
|
|
chomp $gwIP;
|
|
$masternetgw = $gwIP;
|
|
}
|
|
|
|
# create static routes between the networks
|
|
my $rtgcmd = qq~/usr/sbin/nim -o change -a routing$rtindex='$net $masternetgw $xnethash{$net}{gateway}' $masternet 2>/dev/null~;
|
|
my $output3 = xCAT::Utils->runcmd("$rtgcmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not run \'$rtgcmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
} # end - define new nim network
|
|
|
|
} # end - for each network
|
|
return 0;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 listNIMnetwork
|
|
List NIM network definitions corresponding to xCAT network
|
|
definitions. This routine runs on the NIMprime and AIX SNs
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
Comments:
|
|
|
|
ex. &listNIMnetwork($callback, \@networks, \%nethash);
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub listNIMnetwork
|
|
{
|
|
my $callback = shift;
|
|
my $xnets = shift;
|
|
my $xnhash = shift;
|
|
|
|
my %xnethash; # hash of xCAT network definitions
|
|
if ($xnhash) {
|
|
%xnethash = %{$xnhash};
|
|
}
|
|
|
|
my @xcatnetworks = @{$xnets};
|
|
|
|
#
|
|
# get all the nim network names
|
|
#
|
|
my $cmd = qq~/usr/sbin/lsnim -c networks | /usr/bin/cut -f1 -d' ' 2>/dev/null~;
|
|
my @nimnetworks = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not run lsnim command: \'$cmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
# for each NIM network - get the attrs
|
|
my %NIMnets;
|
|
foreach my $netwk (@nimnetworks) {
|
|
my $cmd = qq~/usr/sbin/lsnim -Z -a net_addr -a snm $netwk 2>/dev/null~;
|
|
my @result = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "$::msgstr Could not run lsnim command: \'$cmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
foreach my $l (@result){
|
|
# skip comment lines
|
|
next if ($l =~ /^\s*#/);
|
|
|
|
my ($nimname, $net_addr, $snm) = split(':', $l);
|
|
$NIMnets{$netwk}{'net_addr'} = $net_addr;
|
|
$NIMnets{$netwk}{'snm'} = $snm;
|
|
}
|
|
}
|
|
|
|
# for each xCAT network check for an equivalent NIM network
|
|
# - if a match then display the NIM def
|
|
# - display output of "lsnim -l <netname>"
|
|
|
|
foreach my $xcatnet (@xcatnetworks) {
|
|
|
|
# split mask
|
|
my ($nm1, $nm2, $nm3, $nm4) = split('\.', $xnethash{$xcatnet}{mask});
|
|
|
|
# split net addr
|
|
my ($nn1, $nn2, $nn3, $nn4) = split('\.', $xnethash{$xcatnet}{net});
|
|
|
|
foreach my $nimnet (@nimnetworks) {
|
|
# split definition mask
|
|
my ($dm1, $dm2, $dm3, $dm4) = split('\.', $NIMnets{$nimnet}{'snm'});
|
|
|
|
# split definition net addr
|
|
my ($dn1, $dn2, $dn3, $dn4) = split('\.', $NIMnets{$nimnet}{'net_addr'});
|
|
# check for the same netmask and network address
|
|
if ( ($nn1 == $dn1) && ($nn2 ==$dn2) && ($nn3 == $dn3) && ($nn4 == $dn4) ) {
|
|
if ( ($nm1 == $dm1) && ($nm2 ==$dm2) && ($nm3 == $dm3) && ($nm4== $dm4) ) {
|
|
# found match so display NIM net def
|
|
my $cmd = qq~/usr/sbin/lsnim -l $nimnet 2>/dev/null~;
|
|
my $output = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
# my $rsp;
|
|
# push @{$rsp->{data}}, "Could not run lsnim command: \'$cmd\'.\n";
|
|
# xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
next;
|
|
} else {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "Note: The following is a match for \nxCAT network named \'$xcatnet\'\n";
|
|
push @{$rsp->{data}}, "$output\n";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
}
|
|
}
|
|
} # end for each nim net
|
|
} # end foreach xcat net
|
|
|
|
return 0;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 rmNIMnetwork
|
|
Remove NIM network definitions corresponding to xCAT network
|
|
definitions. This routine runs on the NIMprime and AIX SNs
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
|
|
Comments:
|
|
|
|
ex. &rmNIMnetwork($callback, \@networks);
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub rmNIMnetwork
|
|
{
|
|
my $callback = shift;
|
|
my $xnets = shift;
|
|
|
|
|
|
|
|
|
|
############################################
|
|
#
|
|
# This will not work - you must first remove the master if* definition
|
|
# and the route defs AND any objects that may reference the network
|
|
# - it is not worth the effort - maybe a future
|
|
# enhancement - I'll leave the code here for now.
|
|
#########################################################
|
|
|
|
my @xcatnetworks = @{$xnets};
|
|
|
|
#
|
|
# get all the nim network names
|
|
#
|
|
my $cmd = qq~/usr/sbin/lsnim -c networks | /usr/bin/cut -f1 -d' ' 2>/dev/null~;
|
|
my @nimnetworks = xCAT::Utils->runcmd("$cmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "Could not run lsnim command: \'$cmd\'.\n";
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
return 1;
|
|
}
|
|
|
|
foreach my $xcatnet (@xcatnetworks) {
|
|
chomp $xcatnet;
|
|
|
|
foreach my $nimnet (@nimnetworks) {
|
|
chomp $nimnet;
|
|
|
|
if ($xcatnet eq $nimnet) {
|
|
# get rid of the old definition
|
|
my $rmcmd = "/usr/sbin/nim -Fo remove $nimnet";
|
|
my $output = xCAT::Utils->runcmd("$rmcmd", -1);
|
|
if ($::RUNCMD_RC != 0) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "Could not remove the existing NIM network named \'$nimnet\'.\n";
|
|
if ($::VERBOSE) {
|
|
push @{$rsp->{data}}, "$output";
|
|
}
|
|
xCAT::MsgUtils->message("E", $rsp, $callback);
|
|
} else {
|
|
if ($::VERBOSE) {
|
|
my $rsp;
|
|
push @{$rsp->{data}}, "Removed the NIM network definition called \'$nimnet\'\n";
|
|
xCAT::MsgUtils->message("I", $rsp, $callback);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
1;
|
|
|