mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 03:12:30 +00:00 
			
		
		
		
	* Support copycds command to create cumulus osimage * Add Error handler * fix a typo * Add VERBOSE * Modify a error message * modify per yangSong's comment * Add '-i' and '-o' flag * remove nooverwrite when checking pkgdir
		
			
				
	
	
		
			244 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | |
| package xCAT_plugin::copycds;
 | |
| use strict;
 | |
| use warnings;
 | |
| use Storable qw(dclone);
 | |
| use xCAT::Table;
 | |
| use Thread qw(yield);
 | |
| use Data::Dumper;
 | |
| use Getopt::Long;
 | |
| use File::Basename;
 | |
| use File::Spec;
 | |
| use Digest::MD5 qw(md5_hex);
 | |
| use Cwd;
 | |
| Getopt::Long::Configure("bundling");
 | |
| Getopt::Long::Configure("pass_through");
 | |
| 
 | |
| my $xcatdebugmode = 0;
 | |
| my $processed = 0;
 | |
| my $callback;
 | |
| 
 | |
| sub handled_commands {
 | |
|     return {
 | |
|         copycds => "copycds",
 | |
|       }
 | |
| }
 | |
| 
 | |
| my $identified;
 | |
| 
 | |
| sub take_answer {
 | |
| 
 | |
|     #TODO: Intelligently filter and decide things
 | |
|     my $resp = shift;
 | |
|     $callback->($resp);
 | |
|     $identified = 1;
 | |
| }
 | |
| 
 | |
| sub process_request {
 | |
|     my $request = shift;
 | |
|     $callback = shift;
 | |
|     my $doreq        = shift;
 | |
|     my $distname     = undef;
 | |
|     my $arch         = undef;
 | |
|     my $help         = undef;
 | |
|     my $inspection   = undef;
 | |
|     my $path         = undef;
 | |
|     my $noosimage    = undef;
 | |
|     my $nonoverwrite = undef;
 | |
|     my $specific     = undef;
 | |
| 
 | |
|     $identified    = 0;
 | |
|     $::CDMOUNTPATH = "/var/run/xcat/mountpoint";
 | |
|     my $existdir = getcwd;
 | |
| 
 | |
|     if ($request->{arg}) {
 | |
|         @ARGV = @{ $request->{arg} };
 | |
|     }
 | |
|     GetOptions(
 | |
|         'n|name|osver=s' => \$distname,
 | |
|         'a|arch=s'       => \$arch,
 | |
|         'h|help'         => \$help,
 | |
|         'i|inspection'   => \$inspection,
 | |
|         'p|path=s'       => \$path,
 | |
|         'o|noosimage'    => \$noosimage,
 | |
|         's|specific'     => \$specific,
 | |
|         'w|nonoverwrite' => \$nonoverwrite,
 | |
|     );
 | |
|     if ($help) {
 | |
|         $callback->({ info => "copycds [{-p|--path}=path] [{-n|--name|--osver}=distroname] [{-a|--arch}=architecture] [-i|--inspection] [{-o|--noosimage}] [{-w|--nonoverwrite}] 1st.iso [2nd.iso ...]." });
 | |
|         return;
 | |
|     }
 | |
|     if ($arch and $arch =~ /i.86/) {
 | |
|         $arch = 'x86';
 | |
|     }
 | |
|     my @args = @ARGV;    #copy ARGV
 | |
|     unless ($#args >= 0) {
 | |
|         $callback->({ error => "copycds needs at least one full path to ISO currently.", errorcode => [1] });
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if ($::XCATSITEVALS{xcatdebugmode}) { $xcatdebugmode = $::XCATSITEVALS{xcatdebugmode} }
 | |
| 
 | |
|     my $file;
 | |
|     foreach (@args) {
 | |
|         $identified = 0;
 | |
| 
 | |
|         unless (/^\//) { #If not an absolute path, concatenate with client specified cwd
 | |
|             s/^/$request->{cwd}->[0]\//;
 | |
|         }
 | |
| 
 | |
|         # /dev/cdrom is a symlink on some systems. We need to be able to determine
 | |
|         # if the arg points to a block device.
 | |
|         if (-l $_) {
 | |
|             my $link = readlink($_);
 | |
| 
 | |
|             # Symlinks can be relative, i.e., "../../foo"
 | |
|             if ($link =~ m{^/})
 | |
|             { $file = $link; }
 | |
|             else
 | |
|             { $file = dirname($_) . "/" . $link; } # Unix can handle "/foo/../bar"
 | |
|         }
 | |
|         else { $file = $_; }
 | |
| 
 | |
|         # handle the copycds for tar file
 | |
|         # if the source file is tar format, call the 'copytar' command to handle it.
 | |
|         # currently it's used for Xeon Phi (mic) support
 | |
|         if (-r $file) {
 | |
|             my @filestat = `file $file`;
 | |
|             if (grep /tar archive/, @filestat) {
 | |
| 
 | |
|                 # this is a tar file, call the 'copytar' to generate the image
 | |
|                 my $newreq = dclone($request);
 | |
|                 $newreq->{command} = ['copytar']; #Note the singular, it's different
 | |
|                 $newreq->{arg} = [ "-f", $file, "-n", $distname ];
 | |
|                 $doreq->($newreq, $callback);
 | |
| 
 | |
|                 return;
 | |
|             }
 | |
|             if (grep /$file: data/, @filestat) {
 | |
|                 if ($xcatdebugmode) {
 | |
|                     $callback->({ info => "run copydata for data file = $file" });
 | |
|                 }
 | |
|                 my $newreq = dclone($request);
 | |
|                 $newreq->{command} = ['copydata']; #Note the singular, it's different
 | |
|                 $newreq->{arg} = [ "-f", $file ];
 | |
|                 if ($inspection)
 | |
|                 {
 | |
|                     push @{ $newreq->{arg} }, ("-i");
 | |
|                 }
 | |
|                 if ($nonoverwrite)
 | |
|                 {
 | |
|                     push @{ $newreq->{arg} }, ("-w");
 | |
|                 }
 | |
|                 if ($noosimage)
 | |
|                 {
 | |
|                     push @{ $newreq->{arg} }, ("-o");
 | |
|                 }
 | |
| 
 | |
|                 $doreq->($newreq, $callback);
 | |
|                 return;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         my $mntopts = "-t udf,iso9660"; #Prefer udf formate to iso when media supports both, like MS media
 | |
|         if (-r $file and -b $file)      # Block device?
 | |
|         { $mntopts .= " -o ro"; }
 | |
|         elsif (-r $file and -f $file)    # Assume ISO file
 | |
|         { $mntopts .= " -o ro,loop"; }
 | |
|         else {
 | |
|             $callback->({ error => "The management server was unable to find/read $file. Ensure that file exists on the server at the specified location.", errorcode => [1] });
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         #let the MD5 Digest of isofullpath as the default mount point of the iso
 | |
|         my $isofullpath = File::Spec->rel2abs($file);
 | |
|         my $mntpath = File::Spec->catpath("", $::CDMOUNTPATH, md5_hex($isofullpath));
 | |
| 
 | |
|         system("mkdir -p $mntpath");
 | |
|         system("umount $mntpath >/dev/null 2>&1");
 | |
| 
 | |
| 
 | |
| 
 | |
|         if (system("mount $mntopts '$file' $mntpath")) {
 | |
|             eval { $callback->({ error => "copycds was unable to mount $file to $mntpath.", errorcode => [1] }) };
 | |
|             chdir("/");
 | |
|             system("umount  $mntpath");
 | |
|             return;
 | |
|         }
 | |
|         eval {
 | |
|             my $newreq = dclone($request);
 | |
|             $newreq->{command} = ['copycd'];  #Note the singular, it's different
 | |
|             $newreq->{arg} = [ "-m", $mntpath ];
 | |
| 
 | |
|             if ($path)
 | |
|             {
 | |
|                 
 | |
|                 if(-e $path) {
 | |
|                     $path=Cwd::realpath($path);
 | |
|                 }
 | |
|                 unless((substr($path,0,length("/install/")) eq "/install/") or ($path eq "/install")){
 | |
|                     $callback->({ warning => "copycds: the specified path \"$path\" is not a subdirectory under /install. Make sure this path is configured for httpd/apache, otherwise, the provisioning with this iso will fail!" }); 
 | |
|                 }
 | |
|                 push @{ $newreq->{arg} }, ("-p", $path);
 | |
|             }
 | |
|             if ($specific)
 | |
|             {
 | |
|                 push @{ $newreq->{arg} }, ("-s");
 | |
|             }
 | |
| 
 | |
|             if ($inspection)
 | |
|             {
 | |
|                 push @{ $newreq->{arg} }, ("-i");
 | |
|                 $callback->({ info => "OS Image:" . $_ });
 | |
|             }
 | |
| 
 | |
|             if ($distname) {
 | |
|                 if ($inspection) {
 | |
|                     $callback->({ warning => "copycds: option --inspection specified, argument specified with option --name is ignored" });
 | |
|                 }
 | |
|                 else {
 | |
|                     push @{ $newreq->{arg} }, ("-n", $distname);
 | |
|                 }
 | |
|             }
 | |
|             if ($arch) {
 | |
|                 if ($inspection) {
 | |
|                     $callback->({ warning => "copycds: option --inspection specified, argument specified with option --arch is ignored" });
 | |
|                 }
 | |
|                 else {
 | |
|                     push @{ $newreq->{arg} }, ("-a", $arch);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (!-l $file) {
 | |
|                 push @{ $newreq->{arg} }, ("-f", $file);
 | |
|             }
 | |
| 
 | |
| 
 | |
|             if ($noosimage) {
 | |
|                 push @{ $newreq->{arg} }, ("-o");
 | |
|             }
 | |
| 
 | |
|             if ($nonoverwrite) {
 | |
|                 push @{ $newreq->{arg} }, ("-w");
 | |
|             }
 | |
| 
 | |
|             $doreq->($newreq, \&take_answer);
 | |
| 
 | |
|             #$::CDMOUNTPATH="";
 | |
| 
 | |
|             chdir($existdir);
 | |
|             while (wait() > 0) { yield(); } #Make sure all children exit before trying umount
 | |
|         };
 | |
|         chdir("/");
 | |
|         system("umount  $mntpath");
 | |
|         system("rm -rf $mntpath");
 | |
|         unless ($identified) {
 | |
|             $callback->({ error => ["copycds could not identify the ISO supplied, you may wish to try -n <osver>"], errorcode => [1] });
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 1;
 | |
| 
 | |
| # vim: set ts=2 sts=2 sw=2 et ai:
 |