diff --git a/xCAT-server/lib/xcat/plugins/rinstall.pm b/xCAT-server/lib/xcat/plugins/rinstall.pm new file mode 100644 index 000000000..62fd73c48 --- /dev/null +++ b/xCAT-server/lib/xcat/plugins/rinstall.pm @@ -0,0 +1,481 @@ +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +#------------------------------------------------------- + +=head1 + xCAT plugin package to handle rinstall and winstall + + Supported command: + rinstall - runs nodeset, rsetboot,rpower commands + winstall - also opens the console + +=cut + +#------------------------------------------------------- +package xCAT_plugin::rinstall; +use strict; + +require xCAT::Utils; +require xCAT::MsgUtils; +use xCAT::NodeRange; +use xCAT::Table; + +use Data::Dumper; +use Getopt::Long; + +#------------------------------------------------------- + +=head3 handled_commands + +Return list of commands handled by this plugin + +=cut + +#------------------------------------------------------- + +sub handled_commands +{ + return { + rinstall => "rinstall", + winstall => "rinstall", + }; +} + +#------------------------------------------------------- + +=head3 Process the command + +=cut + +#------------------------------------------------------- +sub process_request +{ + + my $request = shift; + my $callback = shift; + my $subreq = shift; + + rinstall($request, $callback, $subreq); +} + +#------------------------------------------------------- + +=head3 rinstall + + Wrapper around nodeset, rsetboot, rpower for the admin convenience + + +=cut + +#------------------------------------------------------- +sub rinstall +{ + my ($req, $callback, $subreq) = @_; + $::CALLBACK=$callback; + my $OSVER; + my $PROFILE; + my $ARCH; + my $CONSOLE; + my $OSIMAGE; + my $HELP; + my $VERSION; + my $command = $req->{command}->[0]; # could be rinstall on winstall + my $args; + if (defined($req->{arg}) ) { # there are arguments + $args=$req->{arg}; # argument + @ARGV = @{$args}; + } + my $nodes; + my @nodes; + if (defined ($req->{node})) { # there are nodes + $nodes = $req->{node}; + @nodes=@$nodes; + } + # no arguments, no nodes then input wrong + if ((scalar(@nodes) == 0) && (scalar(@ARGV) == 0)){ + &usage($command,$callback); + return 1; + } + #print Dumper($req); + Getopt::Long::Configure("bundling"); + + unless ( + GetOptions( + 'o|osver=s' => \$OSVER, + 'p|profile=s' => \$PROFILE, + 'a|arch=s' => \$ARCH, + 'O|osimage=s' => \$OSIMAGE, + 'h|help' => \$HELP, + 'v|version' => \$VERSION, + 'c|console' => \$CONSOLE + ) + ) + { + &usage($command,$callback); + return 1; + } + if ($HELP) + { + &usage($command,$callback); + return 0; + } + if ($VERSION) + { + my $version = xCAT::Utils->Version(); + my $rsp = {}; + $rsp->{data}->[0] = "$version"; + xCAT::MsgUtils->message("I", $rsp, $callback); + return (0); + } + + if (scalar @$nodes eq 0) + { + my $rsp = {}; + $rsp->{error}->[0] ="noderange not supplied"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + + my $rc = 0; + my %pnhash; + + + if ($OSIMAGE) + { + + # -O|--osimage is specified, ignore any -a,-p,-o options, + # call "nodeset ... osimage= ..." to set the boot state of the noderange to the specified osimage, + # "nodeset" will handle the updating of node attributes such as os,arch,profile,provmethod + # verify input + &checkoption("[-O|--osimage] $OSIMAGE",$OSVER,$PROFILE,$ARCH,$callback); + + # run nodeset $noderange osimage=$OSIMAGE + my @osimageargs; + push @osimageargs,"osimage=$OSIMAGE" ; + my $res = + xCAT::Utils->runxcmd( + { + command => ["nodeset"], + node => \@nodes, + arg => \@osimageargs + }, + $subreq, -1, 1); + + my $rsp = {}; + if ($::RUNCMD_RC ==0 ) { + foreach my $line (@$res) { + $rsp->{data} ->[0] = $line; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + } else { + foreach my $line (@$res) { + $rsp->{error} ->[0] = $line; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + return 1; + } + } + else + { + + # no osimage specified, update the node attributes specified by -a,-p,-o options thru "nodech", + # then set the boot state of each node based on the nodetype.provmethod: + # 1) if nodetype.provmethod = , ignore any -p,-o,-a option, + # then call "nodeset ... osimage" + # 2) if nodetype.provmethod = [install/netboot/statelite], + # update the node attributes specified by -a,-p,-o options thru "nodech", + # call "nodeset ... [install/netboot/statelite]" + # 3) if nodetype.provmethod is not set, use 'install' as the default value + + # group the nodes according to the nodetype.provmethod + + foreach (@$nodes) + { + my $tab = xCAT::Table->new("nodetype"); + my $nthash = $tab->getNodeAttribs($_, ['provmethod']); + $tab->close(); + if (defined($nthash) and defined($nthash->{'provmethod'})) + { + push(@{$pnhash{$nthash->{'provmethod'}}}, $_); + } + else + { + + #if nodetype.provmethod is not specified, + push(@{$pnhash{'install'}}, $_); + } + } + # Now for each group based on provmethod + foreach my $key (keys %pnhash) + { + $::RUNCMD_RC =0; + my $nodes = join(',', @{$pnhash{$key}}); + if ($key =~ /^(install|netboot|statelite)$/) + { + + # nodetype.provmethod = [install|netboot|statelite] + my @nodechline; + if ($OSVER) + { + push @nodechline, "nodetype.os=$OSVER"; + } + if ($PROFILE) + { + push @nodechline, "nodetype.profile=$PROFILE"; + } + if ($ARCH) + { + push @nodechline, "nodetype.arch=$ARCH"; + } + if (@nodechline) + { + # run nodech $nodes $nodechline + my $res = + xCAT::Utils->runxcmd( + { + command => ["nodech"], + node => \@nodes, + arg => \@nodechline + }, + $subreq, -1, 1); + + my $rsp = {}; + $rc=$::RUNCMD_RC; + if ($rc == 0 ) { + foreach my $line (@$res) { + $rsp->{data} ->[0] = $line; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + } else { # error + $rsp->{error} ->[0] = "nodech error"; + xCAT::MsgUtils->message("E", $rsp, $callback); + foreach my $line (@$res) { + $rsp->{error} ->[0] = $line; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + } + } # end nodechline + + if ($rc == 0) # if no error from nodech then run nodeset + { + # run nodeset $nodes $key ( where key is install/netboot/statelite) + my @nodesetarg; + push @nodesetarg, "$key"; + my $res = + xCAT::Utils->runxcmd( + { + command => ["nodeset"], + node => \@nodes, + arg => \@nodesetarg + }, + $subreq, -1, 1); + + my $rsp = {}; + $rc=$::RUNCMD_RC; + if ($rc ==0 ) { + foreach my $line (@$res) { + $rsp->{data} ->[0] = $line; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + } else { # error + foreach my $line (@$res) { + $rsp->{error} ->[0] = $line; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + } + } + } + else # if not install/netboot/statelite + { + + # nodetype.provmethod = + &checkoption("nodetype.provmethod=$key",$OSVER,$PROFILE,$ARCH,$callback); + # run nodeset $nodes osimage + my @nodesetarg; + push @nodesetarg, "osimage"; + my $res = + xCAT::Utils->runxcmd( + { + command => ["nodeset"], + node => \@nodes, + arg => \@nodesetarg + }, + $subreq, -1, 1); + + my $rsp = {}; + $rc=$::RUNCMD_RC; + if ($rc ==0 ) { + foreach my $line (@$res) { + $rsp->{data} ->[0] = $line; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + } else { # error + foreach my $line (@$res) { + $rsp->{error} ->[0] = $line; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + } + } + + } + } # end nodech/nodeset for each group + + if ($rc != 0) # we got an error with the nodeset + { + my $rsp = {}; + $rsp->{error}->[0] = "nodeset failure will not continue "; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + + # call "rsetboot" to set the boot order of the nodehm.mgt=ipmi nodes,for others, + # assume user has set the correct boot order before "rinstall" + + # run rsetboot $noderange net + + my @rsetbootarg; + push @rsetbootarg, "net"; + my $res = + xCAT::Utils->runxcmd( + { + command => ["rsetboot"], + node => \@nodes, + arg => \@rsetbootarg + }, + $subreq, -1, 1); + # fix output it is a hash and you must get error out of the hash. + my $rsp = {}; + $rc=$::RUNCMD_RC; + if ($rc ==0 ) { + foreach my $line (@$res) { + $rsp->{data} ->[0] = $line; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + } else { # error + foreach my $line (@$res) { + $rsp->{error} ->[0] = $line; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + } + if ($rc != 0) # we got an error with the rsetboot + { + my $rsp = {}; + $rsp->{error}->[0] = "rsetboot failure will not continue "; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + + # call "rpower" to start the node provision process + + #run rpower $noderange boot + my @rpowerarg; + push @rpowerarg, "boot"; + my $res = + xCAT::Utils->runxcmd( + { + command => ["rpower"], + node => \@nodes, + arg => \@rpowerarg + }, + $subreq, -1, 1); + + my $rsp = {}; + $rc=$::RUNCMD_RC; + if ($rc ==0 ) { + foreach my $line (@$res) { + $rsp->{data} ->[0] = $line; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + } else { # error + foreach my $line (@$res) { + $rsp->{error} ->[0] = $line; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + } + # Check if they asked to bring up a console ( -c) from rinstall always for winstall + $req->{startconsole}->[0] =0; + if ($command =~ /rinstall/) + { + + # for rinstall, the -c|--console option can provide the remote console for only 1 node + if ($CONSOLE) + { + if (scalar @$nodes ne 1) + { + my $rsp = {}; + $rsp->{error}->[0] = "rinstall -c only accepts one node in the noderange. See winstall for support for support of consoles on multiple nodes."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } else { # tell rinstall client ok to start rcons + $req->{startconsole}->[0] =1; + } + + } + } + elsif ($command =~ /winstall/) + { + + # winstall can start a wcons command to multiple nodes for monitoring the provision cycle + $req->{startconsole}->[0] =1; + + } + + return 0; +} + +#------------------------------------------------------- + +=head3 Usage + + +=cut + +#------------------------------------------------------- + +sub usage +{ + my $command = shift; + my $callback = shift; + my $rsp = {}; + $rsp->{data}->[0] = "$command usage:"; + if ($command =~ /rinstall/) { + $rsp->{data}->[1] = " [-o|--osver] [-p|--profile] [-a|--arch] [-c|--console] "; + } else { # winstall + $rsp->{data}->[1] = " [-o|--osver] [-p|--profile] [-a|--arch] "; + } + if ($command =~ /rinstall/) { + $rsp->{data}->[2] = " [-O|--osimage] [-c|--console] "; + } else { # wininstall + $rsp->{data}->[2] = " [-O|--osimage] "; + } + + $rsp->{data}->[3] = " [-h|--help]"; + $rsp->{data}->[4] = " [-v|--version]"; + xCAT::MsgUtils->message("I", $rsp, $callback); +} + +# check and complain about the invalid combination of the options, +# ignore -o,-p and -a options and prompt a warning message when provmethod=osimagename +sub checkoption{ + my $optstring=shift; + my $OSVER=shift; + my $PROFILE=shift; + my $ARCH=shift; + my $callback=shift; + my $rsp = {}; + if($OSVER) { + $rsp->{data}->[0] = "-o option not valid with $optstring. It is ignored."; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + if($PROFILE) { + $rsp->{data}->[0] = "-p option not valid with $optstring. It is ignored."; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + if($ARCH) { + $rsp->{data}->[0] = "-a option not valid with $optstring. It is ignored."; + xCAT::MsgUtils->message("I", $rsp, $callback); + } +} + + + +1;