# 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; 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; } 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($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 "],errorcode=>[1]}); } } } 1; # vim: set ts=2 sts=2 sw=2 et ai: