mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 03:12:30 +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;
 |