2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-05-22 11:42:05 +00:00

311 lines
9.2 KiB
Perl

#!/usr/bin/env perl
## IBM(c) 20013 EPL license http://www.eclipse.org/legal/epl-v10.html
#
# This plugin is used to handle the command requests for cumulus OS support
#
package xCAT_plugin::onie;
BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use lib "$::XCATROOT/lib/perl";
use strict;
use Getopt::Long;
use File::Path;
use File::Basename;
use xCAT::Utils;
use xCAT::MsgUtils;
use xCAT::TableUtils;
use xCAT::SvrUtils;
use xCAT::Table;
my $xcatdebugmode = 0;
$::VERBOSE = 0;
sub handled_commands {
return {
nodeset => 'nodehm:mgt=switch',
copydata => 'onie',
}
}
my $CALLBACK; # used to hanel the output from xdsh
sub preprocess_request {
my $request = shift;
my $callback = shift;
if ($request->{command}->[0] eq 'copydata')
{
return [$request];
}
# if already preprocessed, go straight to request
if ((defined($request->{_xcatpreprocessed}->[0]))
&& ($request->{_xcatpreprocessed}->[0] == 1)) {
return [$request];
}
my $nodes = $request->{node};
my $command = $request->{command}->[0];
my $extraargs = $request->{arg};
if ($extraargs) {
@ARGV = @{$extraargs};
my ($verbose, $help, $ver);
GetOptions("V" => \$verbose, 'h|help' => \$help, 'v|version' => \$ver);
if ($help) {
my $usage_string = xCAT::Usage->getUsage($command);
my $rsp;
push @{ $rsp->{data} }, $usage_string;
xCAT::MsgUtils->message("I", $rsp, $callback);
return ();
}
if ($ver) {
my $ver_string = xCAT::Usage->getVersion($command);
my $rsp;
push @{ $rsp->{data} }, $ver_string;
xCAT::MsgUtils->message("I", $rsp, $callback);
return ();
}
if ($verbose) {
$::VERBOSE = 1;
}
}
return [$request];
}
sub process_request {
my $request = shift;
my $callback = shift;
my $subreq = shift;
my $nodes = $request->{node};
my $command = $request->{command}->[0];
my $args = $request->{arg};
if ($::XCATSITEVALS{xcatdebugmode} != 0) { $::VERBOSE = 1}
if ($command eq "copydata") {
copydata($request, $callback);
} elsif ($command eq "nodeset") {
nodeset($request, $callback, $subreq);
}
}
# build cumulus OS image
sub copydata {
my $request = shift;
my $callback = shift;
my $file;
my $inspection = undef;
my $noosimage = undef;
my $nooverwrite = undef;
# get arguments
my $args = $request->{arg};
if ($args) {
@ARGV = @{$args};
GetOptions(
'w' => \$nooverwrite,
'o' => \$noosimage,
'i' => \$inspection,
'f=s' => \$file
);
}
if (!(-x $file)) {
xCAT::MsgUtils->message("E", { error => ["$file is not executable, will not process"], errorcode => ["1"] }, $callback);
return;
}
#get install dir
my $installroot = "/install";
my $sitetab = xCAT::Table->new('site');
my @ents = xCAT::TableUtils->get_site_attribute("installdir");
my $site_ent = $ents[0];
if (defined($site_ent))
{
$installroot = $site_ent;
}
my $arch;
my $desc;
my $release;
my $osname;
my $filename = basename($file);
my $output = `$file`;
if ($inspection) {
$callback->({ data => "file output: $output" });
return;
}
foreach my $line (split /[\r\n]+/, $output) {
if ($line =~ /^Architecture/) {
($desc, $arch) = split /: /, $line ;
chomp $arch;
}
if ($line =~ /^Release/) {
($desc, $release) = split /: /, $line ;
chomp $release;
}
if ($line =~ /cumulus/) {
$osname = "cumulus" ;
}
}
unless ($osname) {
$osname="image";
}
my $distname = $osname . $release;
my $imagename = $distname . "-" . $arch;
my $defaultpath = "$installroot/$distname/$arch";
#check if file exists
if ( (-e "$defaultpath/$filename") && ($nooverwrite)){
$callback->({ data => "$defaultpath/$filename is already exists, will not overwrite" });
} else {
$callback->({ data => "Copying media to $defaultpath" });
mkpath ("$defaultpath");
system("cp $file $defaultpath");
$callback->({ data => "Media copy operation successful" });
}
if ($noosimage) {
$callback->({ data => "Option noosimage is specified, will not create osimage definition" });
return;
}
# generate the image objects
my $oitab = xCAT::Table->new('osimage');
unless ($oitab) {
xCAT::MsgUtils->message("E", { error => ["Error: Cannot open table osimage."], errorcode => ["1"] }, $callback);
return 1;
}
my $litab = xCAT::Table->new('linuximage');
unless ($litab) {
xCAT::MsgUtils->message("E", { error => ["Error: Cannot open table linuximage."], errorcode => ["1"] }, $callback);
return 1;
}
my $pkgdir = "$defaultpath/$filename";
my $imgdir = $litab->getAttribs({ 'imagename' => $imagename }, 'pkgdir');
if ($::VERBOSE) {
$callback->({ data => "creating image $imagename with osarch=$arch, osvers=$distname" });
}
my %values;
$values{'imagetype'} = "linux";
$values{'provmethod'} = "install";
$values{'description'} = "Cumulus Linux";
$values{'osname'} = "$osname";
$values{'osvers'} = "$distname";
$values{'osarch'} = "$arch";
$oitab->setAttribs({ 'imagename' => $imagename }, \%values);
# set a default package list
$litab->setAttribs({ 'imagename' => $imagename }, { 'pkgdir' => $pkgdir });
if ($::VERBOSE) {
$callback->({ data => "setting pkgdir=$pkgdir for image $imagename" });
}
#Need to update osdistro table?
my @ret = xCAT::SvrUtils->update_osdistro_table($distname, $arch, $defaultpath, $imagename);
if ($ret[0] != 0) {
xCAT::MsgUtils->message("E", { error => ["Error when updating the osdistro tables."], errorcode => ["1"] }, $callback);
}
xCAT::MsgUtils->message("I", { data => ["The image $imagename is created."] }, $callback);
}
# run the nodeset to updatenode provmethod
sub nodeset {
my $request = shift;
my $callback = shift;
my $subreq = shift;
my $switches = $request->{'node'};
my $args = $request->{arg};
my $provmethod;
my $image_pkgdir;
my $setosimg;
foreach (@$args) {
if (/osimage=(.*)/) {
$setosimg = $1;
}
}
my $switchestab = xCAT::Table->new('switches');
my $switcheshash = $switchestab->getNodesAttribs($switches, ['switchtype']);
my $nodetab = xCAT::Table->new('nodetype');
my $nodehash = $nodetab->getNodesAttribs($switches, [ 'provmethod' ]);
foreach my $switch (@$switches) {
if ($switcheshash->{$switch}->[0]->{switchtype} ne "onie") {
xCAT::MsgUtils->message("E", { error => ["nodeset command is not processed for $switch, only supports switchtype=onie"], errorcode => ["1"] }, $callback);
next;
}
if ($setosimg) {
$provmethod = $setosimg;
} else {
$provmethod = $nodehash->{$switch}->[0]->{provmethod};
}
if ($::VERBOSE) {
xCAT::MsgUtils->message("I", { data => ["$switch has provmethod=$provmethod"] }, $callback);
}
#get pkgdir from osimage
my $linuximagetab = xCAT::Table->new('linuximage');
my $osimagetab = xCAT::Table->new('osimage');
my $imagetab = $linuximagetab->getAttribs({ imagename => $provmethod },'pkgdir');
my $osimghash = $osimagetab->getAttribs({ imagename => $provmethod },'osvers','osarch');
unless($imagetab and $osimghash){
xCAT::MsgUtils->message("E", { error => ["cannot find osimage \"$provmethod\" for $switch, please make sure the osimage specified in command line or node.provmethod exists!"], errorcode => ["1"] }, $callback);
next;
}
my %attribs=('provmethod' => $provmethod,'os'=>$osimghash->{'osvers'},'arch'=>$osimghash->{'osarch'} );
$nodetab->setAttribs({ 'node' => $switch }, \%attribs);
$image_pkgdir = $imagetab->{'pkgdir'};
#validate the image pkgdir
my $flag=0;
if (-r $image_pkgdir) {
my @filestat = `file $image_pkgdir`;
if (grep /$image_pkgdir: data/, @filestat) {
$flag=1;
}
}
unless ($flag) {
xCAT::MsgUtils->message("E", { error => ["The image '$image_pkgdir' is invalid"], errorcode => ["1"] }, $callback);
next;
}
if ($::VERBOSE) {
xCAT::MsgUtils->message("I", { data => ["osimage=$provmethod, pkgdir=$image_pkgdir"] }, $callback);
}
#updateing DHCP entries
my $ret = xCAT::Utils->runxcmd({ command => ["makedhcp"], node => [$switch] }, $subreq, 0, 1);
if ($::RUNCMD_RC) {
xCAT::MsgUtils->message("E", { error => ["Failed to run 'makedhcp' command"], errorcode => ["$::RUNCMD_RC"] }, $callback);
}
xCAT::MsgUtils->message("I", { data => ["$switch: install $provmethod"] }, $callback);
}
return;
}
1;