mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-03 21:02:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			311 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			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;
 |