mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-03 21:02:34 +00:00 
			
		
		
		
	git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/branches/2.8@16820 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			201 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			5.3 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 $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;
 | 
						|
 | 
						|
  $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,
 | 
						|
    '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;
 | 
						|
  }
 | 
						|
  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;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    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)
 | 
						|
    {
 | 
						|
        push @{$newreq->{arg}},("-p",$path);
 | 
						|
    }
 | 
						|
 | 
						|
    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:
 |