From 664cd8be8e2d56a3f4b1235561b5bd6fab99a269 Mon Sep 17 00:00:00 2001 From: vallard Date: Thu, 8 Apr 2010 20:14:16 +0000 Subject: [PATCH] finished imgimport and updated some fixes to imgexport git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@5721 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- xCAT-server/lib/xcat/plugins/imgport.pm | 221 ++++++++++++++++++++---- 1 file changed, 192 insertions(+), 29 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/imgport.pm b/xCAT-server/lib/xcat/plugins/imgport.pm index 4850386d7..870d9416b 100644 --- a/xCAT-server/lib/xcat/plugins/imgport.pm +++ b/xCAT-server/lib/xcat/plugins/imgport.pm @@ -6,19 +6,21 @@ package xCAT_plugin::imgport; use strict; use warnings; -use xCAT::Table; -use xCAT::Schema; +#use xCAT::Table; +#use xCAT::Schema; +#use xCAT::NodeRange qw/noderange abbreviate_noderange/; +#use xCAT::Utils; use Data::Dumper; use XML::Simple; -use xCAT::NodeRange qw/noderange abbreviate_noderange/; -use xCAT::Utils; use POSIX qw/strftime/; use Getopt::Long; use File::Temp; use File::Copy; -use File::Path; +use File::Path qw/mkpath/; +use File::Basename; use Cwd; my $requestcommand; +$::VERBOSE = 0; 1; @@ -94,6 +96,7 @@ sub ximport { GetOptions( 'h|?|help' => \$help, + 'v|verbose' => \$::VERBOSE ); if($help){ @@ -133,7 +136,8 @@ sub xexport { GetOptions( 'h|?|help' => \$help, - 'extra=s' => \@extra + 'extra=s' => \@extra, + 'v|verbose' => \$::VERBOSE ); if($help){ @@ -144,8 +148,10 @@ sub xexport { # ok, we're done with all that. Now lets actually start doing some work. my $img_name = shift @ARGV; my $dest = shift @ARGV; + my $cwd = $request->{cwd}; #getcwd; + $cwd = $cwd->[0]; - $callback->( {data => ["Exporting $img_name..."]}); + $callback->( {data => ["Exporting $img_name to $cwd..."]}); # check if all files are in place my $attrs = get_image_info($img_name, $callback, @extra); #print Dumper($attrs); @@ -155,7 +161,7 @@ sub xexport { } # make manifest and tar it up. - make_bundle($img_name, $dest, $attrs, $callback); + make_bundle($img_name, $dest, $attrs, $callback,$cwd); } @@ -402,8 +408,12 @@ sub make_bundle { # tar ball is made in local working directory. Sometimes doing this in /tmp # is bad. In the case of my development machine, the / filesystem was nearly full. # so doing it in cwd is easy and predictable. - my $dir = getcwd; + my $dir = shift; + #my $dir = getcwd; + + # we may find that cwd doesn't work, so we use the request cwd. my $ttpath = mkdtemp("$dir/imgexport.$$.XXXXXX"); + $callback->({data=>["Creating $ttpath..."]}) if $::VERBOSE; my $tpath = "$ttpath/$imagename"; mkdir("$tpath"); chmod 0755,$tpath; @@ -446,7 +456,13 @@ sub make_bundle { } $callback->( {data => ["Compressing $imagename bundle. Please be patient."]}); - my $rc = system("tar czvf $dest . "); + my $rc; + if($::VERBOSE){ + $callback->({data => ["tar czvf $dest . "]}); + $rc = system("tar czvf $dest . "); + }else{ + $rc = system("tar czf $dest . "); + } if($rc) { $callback->({error=>["Failed to compress archive! (Maybe there was no space left?)"],errorcode=>[1]}); return; @@ -461,20 +477,39 @@ sub make_bundle { sub extract_bundle { my $request = shift; + #print Dumper($request); my $callback = shift; @ARGV = @{ $request->{arg} }; my $xml; my $data; my $datas; + my $error = 0; - my $bundle = shift @ARGV; # extract the image in temp path in cwd - my $dir = getcwd; + my $dir = $request->{cwd}; #getcwd; + $dir = $dir->[0]; + #print Dumper($dir); + unless(-r $bundle){ + $bundle = "$dir/$bundle"; + } + + unless(-r $bundle){ + $callback->({error => ["Can not find $bundle"],errorcode=>[1]}); + return; + } + my $tpath = mkdtemp("$dir/imgimport.$$.XXXXXX"); - $callback->({data=>["Unbundling image..."],errorcode=>[1]}); - my $rc = system("tar zxf $bundle -C $tpath"); + $callback->({data=>["Unbundling image..."]}); + my $rc; + if($::VERBOSE){ + $callback->({data=>["tar zxvf $bundle -C $tpath"]}); + $rc = system("tar zxvf $bundle -C $tpath"); + $rc = system("tar zxvf $bundle -C $tpath"); + }else{ + $rc = system("tar zxf $bundle -C $tpath"); + } if($rc){ $callback->({error => ["Failed to extract bundle $bundle"],errorcode=>[1]}); } @@ -484,7 +519,7 @@ sub extract_bundle { # go through each image directory. Find the XML and put it into the array. If there are any # errors then the whole thing is over and we error and leave. foreach my $imgdir (@files){ - print "$imgdir \n"; + #print "$imgdir \n"; unless(-r "$imgdir/manifest.xml"){ $callback->({error=>["Failed to find manifest.xml file in image bundle"],errorcode=>[1]}); return; @@ -494,23 +529,80 @@ sub extract_bundle { # put it in an eval string so that it $data = eval { $xml->XMLin("$imgdir/manifest.xml") }; if($@){ - $callback->({error=>$@,errorcode=>[1]}); + $callback->({error=>["None valid manifest.xml file inside the bundle. Please verify the XML"],errorcode=>[1]}); + #my $foo = $@; + #$foo =~ s/\n//; + #$callback->({error=>[$foo],errorcode=>[1]}); + #foreach($@){ + # last; + #} return; } - print Dumper($data); + #print Dumper($data); #push @{$datas}, $data; # now we need to import the files... unless(verify_manifest($data, $callback)){ + $error++; next; } - #print "manifest looks good, lets import!\n"; - set_config($data, $callback); + # check media first + unless(check_media($data, $callback)){ + $error++; + next; + } + + #import manifest.xml into xCAT database + unless(set_config($data, $callback)){ + $error++; + next; + } # now place files in appropriate directories. - make_files($data, $callback); + unless(make_files($data, $imgdir, $callback)){ + $error++; + next; + } + + my $osimage = $data->{imagename}; + $callback->({data=>["Successfully imported $osimage"]}); + } + + # remove temp file only if there were no problems. + unless($error){ + $rc = system("rm -rf $tpath"); + if ($rc) { + $callback->({error=>["Failed to clean up temp space $tpath"],errorcode=>[1]}); + return; + } + } + +} + +# return 1 for true 0 for false. +# need to make sure media is copied before importing image. +sub check_media { + my $data = shift; + my $callback = shift; + my $rc = 0; + unless( $data->{'media'}) { + $rc = 1; + }elsif($data->{media} eq 'required'){ + my $os = $data->{osvers}; + my $arch = $data->{osarch}; + my $installroot = xCAT::Utils->getInstallDir(); + unless($installroot){ + $installroot = '/install'; + } + unless(-d "$installroot/$os/$arch"){ + $callback->({error=>["This image requires that you first copy media for $os-$arch"],errorcode=>[1]}); + }else{ + $rc = 1; + } + } + return $rc; } @@ -521,7 +613,7 @@ sub set_config { my %keyhash; my $osimage = $data->{imagename}; - $callback->({data=>["Adding $osimage"],errorcode=>[1]}); + $callback->({data=>["Adding $osimage"]}) if $::VERBOSE; # now we make a quick hash of what we want to put into this $keyhash{provmethod} = $data->{provmethod}; @@ -530,6 +622,7 @@ sub set_config { $keyhash{osarch} = $data->{osarch}; $ostab->setAttribs({imagename => $osimage }, \%keyhash ); $ostab->commit; + return 1; } @@ -603,26 +696,96 @@ sub verify_manifest { sub make_files { my $data = shift; + my $imgdir = shift; my $callback = shift; my $os = $data->{osvers}; my $arch = $data->{osarch}; my $profile = $data->{profile}; + my $installroot = xCAT::Utils->getInstallDir(); + unless($installroot){ + $installroot = '/install'; + } if($data->{provmethod} =~ /install/){ - my $template = $data->{template}; - print "mkdir -p /install/custom/$os/$arch/$profile\n"; - print "cp $template /install/netboot/$os/$arch/$profile\n"; + # you'll get a hash like this: + #$VAR1 = { + # 'provmethod' => 'install', + # 'profile' => 'all', + # 'template' => '/opt/xcat/share/xcat/install/centos/all.tmpl', + # 'imagename' => 'Default_Stateful', + # 'osarch' => 'x86_64', + # 'media' => 'required', + # 'osvers' => 'centos5.4' + # }; + my $template = basename($data->{template}); + my $instdir = "$installroot/custom/$os/$arch"; + #mkpath("$instdir", { verbose => 1, mode => 0755, error => \my $err }); + mkpath("$instdir", { verbose => 1, mode => 0755 }); + + # it could be that the old one already exists, in this case back it up. + if(-r "$instdir/$template"){ + $callback->( {data => ["$instdir/$template already exists. Moving to $instdir/$template.ORIG..."]}); + move("$instdir/$template", "$instdir/$template.ORIG"); + } + move("$imgdir/$template", $instdir); }elsif($data->{provmethod} =~/netboot|statelite/){ - print "mkdir -p /install/netboot/$os/$arch/$profile\n"; - print "cp kernel /install/netboot/$os/$arch/$profile\n"; - print "cp initrd.gz /install/netboot/$os/$arch/$profile\n"; - print "cp rootimg.gz /install/netboot/$os/$arch/$profile\n"; + + # data will look something like this: + #$VAR1 = { + # 'provmethod' => 'netboot', + # 'profile' => 'compute', + # 'ramdisk' => '/install/netboot/centos5.4/x86_64/compute/initrd.gz', + # 'kernel' => '/install/netboot/centos5.4/x86_64/compute/kernel', + # 'imagename' => 'Default_Stateless_1265981465', + # 'osarch' => 'x86_64', + # 'extra' => [ + # { + # 'dest' => '/install/custom/netboot/centos', + # 'src' => '/opt/xcat/share/xcat/netboot/centos/compute.centos5.4.pkglist' + # }, + # { + # 'dest' => '/install/custom/netboot/centos', + # 'src' => '/opt/xcat/share/xcat/netboot/centos/compute.exlist' + # } + # ], + # 'osvers' => 'centos5.4', + # 'rootimg' => '/install/netboot/centos5.4/x86_64/compute/rootimg.gz' + # }; + my $kernel = basename($data->{kernel}); + my $ramdisk = basename($data->{ramdisk}); + my $rootimg = basename($data->{rootimg}); + + my $netdir = "$installroot/netboot/$os/$arch/$profile"; + mkpath("$netdir", {verbose => 1, mode => 0755 }); + + # save the old one off + foreach my $f ($kernel, $ramdisk, $rootimg){ + if(-r "$netdir/$kernel"){ + $callback->( {data => ["Moving old $netdir/$f to $netdir/$f.ORIG..."]}) if $::VERBOSE; + move("$netdir/$f", "$netdir/$f.ORIG"); + } + copy("$imgdir/$f", $netdir); + } + # TODO: for statelite we should expand the rootimg and get the table values in place. } if($data->{extra}){ # have to copy extras - print "copying extras...\n"; + print "copying extras...\n" if $::VERBOSE; + foreach(@{ $data->{extra} }) { + my $f = basename($_->{src}); + my $dest = $_->{dest}; + print "cp $imgdir/extra/$f $dest\n" if $::VERBOSE; + if(-r "$dest/$f"){ + $callback->( {data => ["Moving old $dest/$f to $dest/$f.ORIG..."]}) if $::VERBOSE; + move("$dest/$f", "$dest/$f.ORIG"); + } + copy("$imgdir/extra/$f", $dest); + } } + + # return 1 meant everything was successful! + return 1; }