diff --git a/xCAT-server-2.0/lib/xcat/plugins/xcat2nim.pm b/xCAT-server-2.0/lib/xcat/plugins/xcat2nim.pm new file mode 100644 index 000000000..51404fbb9 --- /dev/null +++ b/xCAT-server-2.0/lib/xcat/plugins/xcat2nim.pm @@ -0,0 +1,1226 @@ +#!/usr/bin/env perl +# 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; + +use xCAT::NodeRange; +use xCAT::Schema; +use xCAT::Utils; +use xCAT::DBobjUtils; +use Data::Dumper; +use Getopt::Long; +use xCAT::MsgUtils; + +# options can be bundled up like -vV +Getopt::Long::Configure("bundling"); +Getopt::Long::Configure("pass_through"); +$Getopt::Long::ignorecase = 0; + +# +# Globals +# + +@::noderange; # list of nodes derived from command line + +#------------------------------------------------------------------------------ + +=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 process_request + + Check for xCAT command and call the appropriate subroutine. + + Arguments: + + Returns: + 0 - OK + 1 - error + Globals: + + Error: + + Example: + + Comments: +=cut + +#----------------------------------------------------------------------------- + +sub process_request +{ + + $::request = shift; + $::callback = shift; + + my $ret; + my $msg; + + # globals used by all subroutines. + $::command = $::request->{command}->[0]; + $::args = $::request->{arg}; + $::filedata = $::request->{stdin}->[0]; + + ($ret, $msg) = &x2n; + + if ($msg) + { + my $rsp; + $rsp->{data}->[0] = $msg; + $::callback->($rsp); + } + return $ret; +} + +#---------------------------------------------------------------------------- + +=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 $gotattrs = 0; + + @ARGV = @{$::args}; + + # parse the options + if ( + !GetOptions( + 'all|a' => \$::opt_a, + 'f|force' => \$::opt_f, + 'help|h' => \$::opt_h, + 'o=s' => \$::opt_o, + '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 -h for Help + if (defined($::opt_h) ) + { + return 2; + } + + # Option -v for version - do we need this??? + if (defined($::opt_v)) + { + my $rsp; + $rsp->{data}->[0] = "$::command - version 1.0"; + xCAT::MsgUtils->message("I", $rsp, $::callback); + return 1; # - just exit + } + + # 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] = + "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 ronderange 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 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 + 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}) + { + + # just for node and group for now!!!!!!! + if ( ($t eq 'node') || ($t eq 'group') ) { + + 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) + { + my $rsp; + $rsp->{data}->[0] = + "Could not determine what object definitions to remove.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + 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 $rc = 0; + my $error = 0; + + # process the command line + $rc = &processArgs; + if ($rc != 0) + { + + # rc: 0 - ok, 1 - return, 2 - help, 3 - error + if ($rc != 1) + { + &xcat2nim_usage; + } + return ($rc - 1); + } + +#ndebug +my $rsp; +$rsp->{data}->[0] = "$::command - Not yet ready for prime time!"; +xCAT::MsgUtils->message("I", $rsp, $::callback); +return 0; + + # get the local short host name + ($::local_host = `hostname`) =~ s/\..*$//; + + # get all the attrs for these definitions + %::objhash = xCAT::DBobjUtils->getobjdefs(\%::objtype); + if (!defined(%::objhash)) + { + my $rsp; + $rsp->{data}->[0] = "Could not get xCAT object definitions.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 1; + } + + # create NIM defs for each xCAT def + foreach my $objname (keys %::objhash) + { + +#print "x2n: objname=$objname\n"; + + + # list the NIM object definition - if there is one + if ($::opt_l || $::opt_d) { + if (&rm_or_list_nim_object($objname)) { + # the routine failed + next; + } + } + +# ndebug +exit; + + # create a NIM machine definition + if ($::objtype{$objname} eq 'node') { + my $rc = mkclientdef($objname); + if ($rc = 1) { + # could not create client definition + } + next; + } + + # create a NIM group definition + if ($::objtype{$objname} eq 'group') { + my $rc = mkgrpdef($objname); + if ($rc = 1) { + # could not create group definition + } + next; + } + } + +return 0; + + + if ($error) + { + my $rsp; + $rsp->{data}->[0] = + "One or more errors occured when attempting to create or modify xCAT \nobject definitions.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 1; + } + else + { + if ($::verbose) + { + + # give results + my $rsp; + $rsp->{data}->[0] = + "The database was updated for the following objects:\n"; + xCAT::MsgUtils->message("I", $rsp, $::callback); + + my $n = 1; + foreach my $o (sort(keys %::FINALATTRS)) + { + $rsp->{data}->[$n] = "$o\n"; + $n++; + } + xCAT::MsgUtils->message("I", $rsp, $::callback); + } + else + { + my $rsp; + $rsp->{data}->[0] = + "Object definitions have been created or modified.\n"; + xCAT::MsgUtils->message("I", $rsp, $::callback); + } + return 0; + } +} + +#---------------------------------------------------------------------------- + +=head3 mkclientdef + + Create a NIM client definition. + Arguments: + Returns: + 0 - OK + 1 - error + Globals: + + Error: + + Example: + + Comments: +=cut + +#----------------------------------------------------------------------------- + +sub mkclientdef +{ + my ($node) = @_; + my $cabletype = undef; + my $ifattr = undef; + + # get the name of the nim master + # ???? assume node short hostname is unique in xCAT cluster???? + my $nim_master = &getNIMmaster($object); + if (!defined($nim_master)) { + my $rsp; + $rsp->{data}->[0] = "Could not find the NIM master for node \'$node\'.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 1; + } + + # check to see if the client is already defined + # - sets $::client_exists + if (&check_nim_client($node, $nim_master)) { + # the routine failed + return 1; + } + + # don't update an existing def unless they say so! + if ($::client_exists && !$::opt_u) { + + my $rsp; + $rsp->{data}->[0] = "The NIM client machine \'$node\' already exists. Use the \'-u\' option to update an existing definition.\n"; + xCAT::MsgUtils->message("I", $rsp, $::callback); + return 0; + + } else { + # either create or update the group 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 "; + } + + # need short host name for NIM client defs + ($shorthost = $node) =~ s/\..*$//; + + # 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"; + } + + # only support Ethernet for management interfaces + $adaptertype = "ent"; + + $ifattr="-a if1=\'$net_name $shorthost $::objhash{$node}{'mac'} $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) { + $cmd = "nim -F -o change $nim_args $shorthost"; + } else { + $cmd = "nim -o define $nim_type $nim_args $shorthost"; + } + + # may need to use dsh if it is a remote server + my $nimcmd; + if ($nim_master ne $::local_host) { + $nimcmd = qq~dsh -n $instserv "$cmd 2>&1"~; + } else { + $nimcmd = qq~$cmd 2>&1~; + } + + # run the cmd + #my $output = xCAT::Utils->runcmd("$nimcmd", -1); + if ($::RUNCMD_RC != 0) + { + my $rsp; + $rsp->{data}->[0] = "Could not create a NIM definition for \'$node\'.\n"; + 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) = @_; + my $cmd = undef; + my $servnode = undef; + my $GrpSN = undef; + + # get members and determine all the different masters + # For example, the xCAT group "all" will have nodes that are managed + # by multiple NIM masters - so we will create a local group "all" + # on each of those masters + %ServerList = &getMasterGroupLists($object); + + foreach my $servname (keys %ServerList) + { + my @members = @{$ServerList{$servname}}; + + # check to see if the group is already defined - sets $::grp_exists + if (&check_nim_group($group, $servname)) { + # the routine failed + return 1; + } + + # don't update an existing def unless we're told + if ($::grp_exists && !$::opt_u) { + my $rsp; + $rsp->{data}->[0] = "The NIM group \'$group\' already exists. Use the \'-u\' option to update an existing definition.\n"; + xCAT::MsgUtils->message("I", $rsp, $::callback); + return 0; + + } else { + # 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] = + "Cannot create a NIM group definition with more than 1024 members - on \'$servname\'."; + xCAT::MsgUtils->message("I", $rsp, $::callback); + next; + } + + foreach my $memb (@members) { + + ($shorthost = $memb) =~ s/\..*$//; + + # do we change or create + my $cmd; + if ($::grp_exists) { + $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"; + } + + # do we need dsh + my $nimcmd; + if ($servname ne $::local_host) { + $nimcmd = qq~dsh -n $servname "$cmd"~; + } else { + $nimcmd = $cmd; + } + + #my @output = xCAT::Utils->runcmd("$cmd", -1); + if ($::RUNCMD_RC != 0) + { + my $rsp; + $rsp->{data}->[0] = "Could not create a NIM definition for \'$group\'.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 1; + } + } + } + } + + return 0; +} + +#---------------------------------------------------------------------------- + +=head3 rm_or_list_nim_object + + List a NIM object definition. + + Arguments: + Returns: + 0 - OK + 1 - error + Globals: + + Error: + + Example: + + Comments: +=cut + +#----------------------------------------------------------------------------- + +sub rm_or_list_nim_object +{ + my ($object, $type) = @_; + my $nim_master = undef; + + if ($type eq 'node') { + # get name of nim master + # ???? assume node short hostname is unique in xCAT cluster???? + $nim_master = &getNIMmaster($object); + + if (!defined($nim_master)) { + my $rsp; + $rsp->{data}->[0] = "Could not find the NIM master for node \'$object\'.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 1; + } + + if ($::opt_l) { + + # if the name of the master is not the local host then use dsh + if ($nim_master ne $::local_host) { + $cmd = qq~dsh -n $nim_master "lsnim -l $object 2>/dev/null"~; + } else { + $cmd = qq~lsnim -l $object 2>/dev/null~; + } + + #$outref = xCAT::Utils->runcmd("$cmd", -1); + if ($::RUNCMD_RC != 0) + { + my $rsp; + $rsp->{data}->[0] = "Could not get the NIM definition for $object.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 1; + } else { + + # display to NIM output + my $rsp; + $rsp->{data}->[0] = "NIM master: $master"; + $rsp->{data}->[1] = "Client name: $object"; + $rsp->{data}->[2] = "$outref"; + xCAT::MsgUtils->message("I", $rsp, $::callback); + return 0; + } + + } elsif ($::opt_r) { + # remove the object + # if the name of the master is not the local host then use dsh + if ($nim_master ne $::local_host) { + $cmd = qq~$::DSH -n $nim_master "nim -o remove $object 2>/dev/null"~; + } else { + $cmd = qq~nim -o remove $object 2>/dev/null~; + } + + #$outref = xCAT::Utils->runcmd("$cmd", -1); + if ($::RUNCMD_RC != 0) + { + my $rsp; + $rsp->{data}->[0] = "Could not remove the NIM definition for \'$object\'.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 1; + } + } + } + + if ($type eq 'group') { + + # get members and determine all the different masters + %servgroups = &getMasterGroupLists($object); + + # get the group definition from each master and + # display it + foreach my $servname (keys %servgroups) + { + # make sure we have the short host name of the NIM master + if ($servname) { + ($master = $servname) =~ s/\..*$//; + } + + if ($::opt_l) { + # if the name of the master is not the local host then use dsh + if ($master ne $::local_host) { + $cmd = qq~$::DSH -n $instserv "lsnim -l $object 2>/dev/null"~; + } else { + $cmd = qq~lsnim -l $object 2>/dev/null~; + } + + #$outref = xCAT::Utils->runcmd("$cmd", -1); + if ($::RUNCMD_RC != 0) + { + my $rsp; + $rsp->{data}->[0] = "Could not list the NIM definition for \'$object\'.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 1; + } else { + + # display NIM output + my $rsp; + $rsp->{data}->[0] = "NIM master: $master"; + $rsp->{data}->[1] = "Group name: $object"; + $rsp->{data}->[2] = "$outref"; + xCAT::MsgUtils->message("I", $rsp, $::callback); + return 0; + } + } elsif ($::opt_r) { + # if the name of the master is not the local host then use dsh + if ($master ne $::local_host) { + $cmd = qq~$::DSH -n $instserv "nim -o remove $object 2>/dev/null"~; + } else { + $cmd = qq~nim -o remove $object 2>/dev/null~; + } + + #$outref = xCAT::Utils->runcmd("$cmd", -1); + if ($::RUNCMD_RC != 0) + { + my $rsp; + $rsp->{data}->[0] = "Could not remove the NIM definition for \'$object\'.\n"; + 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 { + $NimMaster = $::local_host; + } + + # assume short hostnames for now??? + if ($NimMaster) { + ($master = $NimMaster) =~ s/\..*$//; + } + return $master; +} + +#---------------------------------------------------------------------------- + +=head3 getMasterGroupLists + + Get a hash of all the masters that have a certain group defined + and a list of members for each masters definition. + + Arguments: + Returns: + server group list hash + undef - error + Globals: + + Error: + + Example: + + Comments: +=cut + +#----------------------------------------------------------------------------- + +sub getMasterGroupLists +{ + my ($group) = @_; + + my $NimMaster; + my $thismaster; + + # get the members list + my $memberlist = xCAT::DBobjUtils->getGroupMembers($group, \%::objhash); + my @members = split(',', $memberlist); + + # get the node(member) definitions + if (@members) { + foreach my $n (@members) { + $membhash{$n} = 'node'; + } + %memberhash = xCAT::DBobjUtils->getobjdefs(\%membhash); + } else { + my $rsp; + $rsp->{data}->[0] = "Could not get members of the xCAT group \'$group\'.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return undef; + } + + if ( defined(%memberhash)) { + # sort the list by server node - one list per server + foreach my $m (@members) { + + if ($memberhash{$m}{nimmaster}) { + $NimMaster = $memberhash{$m}{nimmaster}; + + } elsif ($memberhash{$m}{servicenode}) { + # the servicenode attr is set for this node + $NimMaster = $memberhash{$m}{servicenode}; + + } elsif ($memberhash{$m}{xcatmaster}) { + $NimMaster = $memberhash{$m}{xcatmaster}; + + } else { + $NimMaster = `hostname`; + } + + # assume short hostnames for now??? + ($thismaster = $NimMaster) =~ s/\..*$//; + + push(@{$ServerList{$thismaster}}, $m); + } + + } else { + # could not get node def + my $rsp; + $rsp->{data}->[0] = "Could not get xCAT node definition for all members of the xCAT group \'$group\'.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return undef; + } + + return %ServerList; +} + +#---------------------------------------------------------------------------- + +=head3 check_nim_group + + See if an xCAT group has already been defined as a NIM machine group. + + Arguments: + Returns: + 0 - OK + 1 - error + Globals: + + Error: + + Example: + + Comments: +=cut + +#----------------------------------------------------------------------------- + +sub check_nim_group +{ + my ($group, $servnode) = @_; + my ($cmd, @output); + + if ( $::NIMGroupList{$servnode}) { + @GroupList = @{$::NIMGroupList{$servnode}}; + } else { + if ($servnode ne $::local_host) { + $cmd = qq~dsh -n $servnode "lsnim -c groups | cut -f1 -d' ' 2>/dev/null"~; + } else { + $cmd = qq~lsnim -c groups | cut -f1 -d' ' 2>/dev/null~; + } + + #@GroupList = xCAT::Utils->runcmd("$cmd", -1); + if ($::RUNCMD_RC != 0) + { + my $rsp; + $rsp->{data}->[0] = "Could not get a list of NIM group definitions.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 1; + } + # save member list for each server + @{$::NIMGroupList{$servnode}} = @GroupList; + } + + + $::grp_exists = grep(/^$group$/,@GroupList) ? 1 : 0; + + return 0; +} + +#---------------------------------------------------------------------------- + +=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) = @_; + my ($cmd, @ClientList); + + if ( $::NIMclientList{$servnode}) { + @ClientList = @{$::NIMclientList{$servnode}}; + } else { + if ($servnode ne $::local_host) { + $cmd = qq~dsh -n $servnode "lsnim -c machines | cut -f1 -d' ' 2>/dev/null"~; + } else { + $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] = "Could not get a list of NIM client definitions from \'$servnode\'.\n"; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 1; + } + # save member list for each server + @{$::NIMclientList{$servnode}} = @ClientList; + } + + $::client_exists = grep(/^$node$/,@ClientList) ? 1 : 0; + + return 0; +} + +#---------------------------------------------------------------------------- + +=head3 xcat2nim_usage + + Arguments: + Returns: + Globals: + + Error: + + Example: + + Comments: +=cut + +#----------------------------------------------------------------------------- + +sub xcat2nim_usage +{ + my $rsp; + $rsp->{data}->[0] = + "\nUsage: xcat2nim - Use this command to create and manage AIX NIM definitions based on xCAT object definitions.\n"; + $rsp->{data}->[1] = " xcat2nim [-h | --help ]\n"; + $rsp->{data}->[2] = + " xcat2nim [-V | --verbose] [-a | --all] [-l | --list] [-u | --update] "; + + $rsp->{data}->[3] =" [-r | --remove] [-t object-types] [-o object-names]"; + $rsp->{data}->[4] = + " [noderange] [attr=val [attr=val...]]\n"; + xCAT::MsgUtils->message("I", $rsp, $::callback); + return 0; +} + +1; +