xcat-core/xCAT-server/lib/xcat/plugins/copycds.pm
Jarrod Johnson d183a0bb9d Support 'specific' copycds mode.
ESXi releases updates without bumping version numbers.  For such cases,
the default behavior is for the new version to supersede the old.  This
makes sense for the vast majority of cases.  There are, however, corner
cases where being explicit about the release is indicated.
2014-03-21 10:57:42 -04:00

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