2010-04-03 00:07:49 +00:00
# Sumavi Inc (C) 2010
2010-09-08 18:58:39 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
2010-04-03 00:07:49 +00:00
#####################################################
# imgport will export and import xCAT stateless, statelite, and diskful templates.
# This will make it so that you can easily share your images with others.
# All your images are belong to us!
package xCAT_plugin::imgport ;
2010-09-09 19:05:29 +00:00
BEGIN
{
$ ::XCATROOT = $ ENV { 'XCATROOT' } ? $ ENV { 'XCATROOT' } : '/opt/xcat' ;
}
use lib "$::XCATROOT/lib/perl" ;
2010-04-03 00:07:49 +00:00
use strict ;
use warnings ;
2010-04-08 20:14:16 +00:00
#use xCAT::Table;
#use xCAT::Schema;
#use xCAT::NodeRange qw/noderange abbreviate_noderange/;
#use xCAT::Utils;
2010-04-03 00:07:49 +00:00
use Data::Dumper ;
use XML::Simple ;
use POSIX qw/strftime/ ;
use Getopt::Long ;
use File::Temp ;
use File::Copy ;
2010-04-08 20:14:16 +00:00
use File::Path qw/mkpath/ ;
use File::Basename ;
2010-09-09 19:05:29 +00:00
use xCAT::NodeRange ;
2010-04-03 00:07:49 +00:00
use Cwd ;
my $ requestcommand ;
2010-04-08 20:14:16 +00:00
$ ::VERBOSE = 0 ;
2010-04-03 00:07:49 +00:00
1 ;
#some quick aliases to table/value
my % shortnames = (
groups = > [ qw( nodelist groups ) ] ,
tags = > [ qw( nodelist groups ) ] ,
mgt = > [ qw( nodehm mgt ) ] ,
#switch => [qw(switch switch)],
) ;
#####################################################
# Return list of commands handled by this plugin
#####################################################
sub handled_commands
{
return {
imgexport = > "imgport" ,
imgimport = > "imgport" ,
} ;
}
#####################################################
# Process the command
#####################################################
sub process_request
{
#use Getopt::Long;
Getopt::Long:: Configure ( "bundling" ) ;
#Getopt::Long::Configure("pass_through");
Getopt::Long:: Configure ( "no_pass_through" ) ;
my $ request = shift ;
my $ callback = shift ;
$ requestcommand = shift ;
my $ command = $ request - > { command } - > [ 0 ] ;
my $ args = $ request - > { arg } ;
if ( $ command eq "imgexport" ) {
return xexport ( $ request , $ callback ) ;
} elsif ( $ command eq "imgimport" ) {
return ximport ( $ request , $ callback ) ;
} else {
print "Error: $command not found in export\n" ;
$ callback - > ( { error = > [ "Error: $command not found in this module." ] , errorcode = > [ 1 ] } ) ;
#return (1, "$command not found in sumavinode");
}
}
2010-04-08 01:40:57 +00:00
# extract the bundle, then add it to the osimage table. Basically the ying of the yang of the xexport
# function.
sub ximport {
my $ request = shift ;
my $ callback = shift ;
my % rsp ; # response
my $ help ;
2010-09-09 19:05:29 +00:00
my $ nodes ;
my $ new_profile ;
2010-04-08 01:40:57 +00:00
my $ xusage = sub {
2010-09-09 19:05:29 +00:00
my $ ec = shift ;
push @ { $ rsp { data } } , "imgimport: Takes in an xCAT image bundle and defines it to xCAT so you can use it" ;
push @ { $ rsp { data } } , "Usage: " ;
push @ { $ rsp { data } } , "\timgimport [-h|--help]" ;
push @ { $ rsp { data } } , "\timgimport <bundle_file_name> [-p|--postscripts <nodelist>] [-f|--profile <new_profile>] [-v]" ;
if ( $ ec ) { $ rsp { errorcode } = $ ec ; }
$ callback - > ( \ % rsp ) ;
2010-04-08 01:40:57 +00:00
} ;
unless ( defined ( $ request - > { arg } ) ) { $ xusage - > ( 1 ) ; return ; }
@ ARGV = @ { $ request - > { arg } } ;
if ( $# ARGV eq - 1 ) {
$ xusage - > ( 1 ) ;
return ;
}
GetOptions (
'h|?|help' = > \ $ help ,
2010-05-21 06:44:28 +00:00
'v|verbose' = > \ $ ::VERBOSE ,
2010-09-09 19:05:29 +00:00
'p|postscripts=s' = > \ $ nodes ,
'f|profile=s' = > \ $ new_profile ,
2010-04-08 01:40:57 +00:00
) ;
2010-04-03 00:07:49 +00:00
2010-04-08 01:40:57 +00:00
if ( $ help ) {
$ xusage - > ( 0 ) ;
return ;
}
# first extract the bundle
2010-09-09 19:05:29 +00:00
extract_bundle ( $ request , $ callback , $ nodes , $ new_profile ) ;
2010-04-08 01:40:57 +00:00
}
# function to export your image. The image should already be in production, work well, and have
# no bugs. Lots of places will have problems because the image may not be in osimage table
# or they may have hardcoded things, or have post install scripts.
2010-04-03 00:07:49 +00:00
sub xexport {
my $ request = shift ;
my $ callback = shift ;
my % rsp ; # response
my $ help ;
my @ extra ;
2010-09-09 19:05:29 +00:00
my $ node ;
2010-04-03 00:07:49 +00:00
my $ xusage = sub {
my $ ec = shift ;
2010-09-09 19:05:29 +00:00
push @ { $ rsp { data } } , "imgexport: Creates a tarball (bundle) of an existing xCAT image" ;
push @ { $ rsp { data } } , "Usage: " ;
push @ { $ rsp { data } } , "\timgexport [-h|--help]" ;
2011-07-20 07:30:24 +00:00
push @ { $ rsp { data } } , "\timgexport <image_name> [destination] [[-e|--extra <file:dir> ] ... ] [-p|--postscripts <node_name>] [-v]" ;
2010-04-03 00:07:49 +00:00
if ( $ ec ) { $ rsp { errorcode } = $ ec ; }
$ callback - > ( \ % rsp ) ;
} ;
unless ( defined ( $ request - > { arg } ) ) { $ xusage - > ( 1 ) ; return ; }
@ ARGV = @ { $ request - > { arg } } ;
if ( $# ARGV eq - 1 ) {
$ xusage - > ( 1 ) ;
return ;
}
GetOptions (
'h|?|help' = > \ $ help ,
2010-09-09 19:05:29 +00:00
'p|postscripts=s' = > \ $ node ,
'e|extra=s' = > \ @ extra ,
2010-04-08 20:14:16 +00:00
'v|verbose' = > \ $ ::VERBOSE
2010-04-03 00:07:49 +00:00
) ;
if ( $ help ) {
$ xusage - > ( 0 ) ;
return ;
}
# ok, we're done with all that. Now lets actually start doing some work.
my $ img_name = shift @ ARGV ;
my $ dest = shift @ ARGV ;
2010-04-08 20:14:16 +00:00
my $ cwd = $ request - > { cwd } ; #getcwd;
$ cwd = $ cwd - > [ 0 ] ;
2010-04-03 00:07:49 +00:00
2010-04-08 20:14:16 +00:00
$ callback - > ( { data = > [ "Exporting $img_name to $cwd..." ] } ) ;
2010-04-03 00:07:49 +00:00
# check if all files are in place
2010-09-09 19:05:29 +00:00
my $ attrs = get_image_info ( $ img_name , $ callback , $ node , @ extra ) ;
2010-04-03 00:07:49 +00:00
#print Dumper($attrs);
unless ( $ attrs ) {
2010-09-09 19:05:29 +00:00
return 1 ;
2010-04-03 00:07:49 +00:00
}
# make manifest and tar it up.
2010-04-08 20:14:16 +00:00
make_bundle ( $ img_name , $ dest , $ attrs , $ callback , $ cwd ) ;
2010-04-03 00:07:49 +00:00
}
2010-04-08 01:40:57 +00:00
2010-04-03 00:07:49 +00:00
# verify the image and return the values
sub get_image_info {
my $ imagename = shift ;
my $ callback = shift ;
2010-09-09 19:05:29 +00:00
my $ node = shift ;
2010-04-03 00:07:49 +00:00
my @ extra = @ _ ;
my $ errors = 0 ;
my $ ostab = new xCAT:: Table ( 'osimage' , - create = > 1 ) ;
unless ( $ ostab ) {
$ callback - > (
2010-09-08 18:58:39 +00:00
{ error = > [ "Unable to open table 'osimage'." ] , errorcode = > 1 }
2010-04-03 00:07:49 +00:00
) ;
return 0 ;
}
2010-09-08 18:58:39 +00:00
( my $ attrs ) = $ ostab - > getAttribs ( { imagename = > $ imagename } , 'profile' , 'imagetype' , 'provmethod' , 'osname' , 'osvers' , 'osdistro' , 'osarch' , 'synclists' ) ;
2010-04-03 00:07:49 +00:00
if ( ! $ attrs ) {
$ callback - > ( { error = > [ "Cannot find image \'$imagename\' from the osimage table." ] , errorcode = > [ 1 ] } ) ;
return 0 ;
}
unless ( $ attrs - > { provmethod } ) {
$ callback - > ( { error = > [ "The 'provmethod' field is not set for \'$imagename\' in the osimage table." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ attrs - > { profile } ) {
$ callback - > ( { error = > [ "The 'profile' field is not set for \'$imagename\' in the osimage table." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ attrs - > { osvers } ) {
$ callback - > ( { error = > [ "The 'osvers' field is not set for \'$imagename\' in the osimage table." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ attrs - > { osarch } ) {
$ callback - > ( { error = > [ "The 'osarch' field is not set for \'$imagename\' in the osimage table." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ attrs - > { provmethod } =~ /install|netboot|statelite/ ) {
$ callback - > ( { error = > [ "Exporting images with 'provemethod' " . $ attrs - > { provmethod } . " is not supported. Hint: install, netboot, or statelite" ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
2010-04-08 21:53:05 +00:00
$ attrs - > { imagename } = $ imagename ;
2010-04-03 00:07:49 +00:00
if ( $ errors ) {
return 0 ;
}
2010-09-08 18:58:39 +00:00
my $ linuximagetab = new xCAT:: Table ( 'linuximage' , - create = > 1 ) ;
unless ( $ linuximagetab ) {
$ callback - > (
{ error = > [ "Unable to open table 'linuximage'" ] , errorcode = > 1 }
) ;
return 0 ;
}
#from linuximage table
2010-09-17 17:51:39 +00:00
( my $ attrs1 ) = $ linuximagetab - > getAttribs ( { imagename = > $ imagename } , 'template' , 'pkglist' , 'pkgdir' , 'otherpkglist' , 'otherpkgdir' , 'exlist' , 'postinstall' , 'rootimgdir' , 'nodebootif' , 'otherifce' , 'netdrivers' , 'kernelver' , 'permission' ) ;
2010-09-08 18:58:39 +00:00
if ( ! $ attrs1 ) {
$ callback - > ( { error = > [ "Cannot find image \'$imagename\' from the linuximage table." ] , errorcode = > [ 1 ] } ) ;
return 0 ;
}
#merge attrs with attrs1
foreach ( keys %$ attrs1 ) {
$ attrs - > { $ _ } = $ attrs1 - > { $ _ } ;
}
2010-04-03 00:07:49 +00:00
$ attrs = get_files ( $ imagename , $ callback , $ attrs ) ;
if ( $# extra > - 1 ) {
my $ ex = get_extra ( $ callback , @ extra ) ;
if ( $ ex ) {
$ attrs - > { extra } = $ ex ;
}
}
2010-09-09 19:05:29 +00:00
#get postscripts
if ( $ node ) {
$ attrs = get_postscripts ( $ node , $ callback , $ attrs )
}
2010-04-03 00:07:49 +00:00
# if we get nothing back, then we couldn't find the files. How sad, return nuthin'
return $ attrs ;
}
2010-09-09 19:05:29 +00:00
sub get_postscripts {
my $ node = shift ;
my $ errors = 0 ;
my $ callback = shift ;
my $ attrs = shift ;
my @ nodes = noderange ( $ node ) ;
if ( @ nodes > 0 ) { $ node = $ nodes [ 0 ] ; }
else {
$ callback - > (
{ error = > [ "Unable to get postscripts, $node is not a valide node." ] , errorcode = > 1 }
) ;
return 0 ;
}
my $ postscripts ;
my $ postbootscripts ;
my $ ptab = new xCAT:: Table ( 'postscripts' , - create = > 1 ) ;
unless ( $ ptab ) {
$ callback - > (
{ error = > [ "Unable to open table 'postscripts'." ] , errorcode = > 1 }
) ;
return 0 ;
}
my $ ent = $ ptab - > getNodeAttribs ( $ node , [ 'postscripts' , 'postbootscripts' ] ) ;
if ( $ ent )
{
if ( $ ent - > { postscripts } ) { $ postscripts = $ ent - > { postscripts } ; }
if ( $ ent - > { postbootscripts } ) { $ postbootscripts = $ ent - > { postbootscripts } ; }
}
( my $ attrs1 ) = $ ptab - > getAttribs ( { node = > "xcatdefaults" } , 'postscripts' , 'postbootscripts' ) ;
if ( $ attrs1 ) {
if ( $ attrs1 - > { postscripts } ) {
if ( $ postscripts ) {
$ postscripts = $ attrs1 - > { postscripts } . ",$postscripts" ;
} else {
$ postscripts = $ attrs1 - > { postscripts } ;
}
}
if ( $ attrs1 - > { postbootscripts } ) {
if ( $ postbootscripts ) {
$ postbootscripts = $ attrs1 - > { postbootscripts } . ",$postbootscripts" ;
} else {
$ postbootscripts = $ attrs1 - > { postbootscripts } ;
}
}
}
if ( $ postscripts ) {
$ attrs - > { postscripts } = $ postscripts ;
}
if ( $ postbootscripts ) {
$ attrs - > { postbootscripts } = $ postbootscripts ;
}
return $ attrs ;
}
2010-04-03 00:07:49 +00:00
# returns a hash of files
# extra {
# file => dir
# file => dir
# }
sub get_extra {
2010-09-08 18:58:39 +00:00
my $ callback = shift ;
my @ extra = @ _ ;
my $ extra ;
# make sure that the extra is formatted correctly:
foreach my $ e ( @ extra ) {
my ( $ file , $ to_dir ) = split ( /:/ , $ e ) ;
unless ( - r $ file ) {
$ callback - > ( { error = > [ "Can not find Extra file $file. Argument will be ignored" ] , errorcode = > [ 1 ] } ) ;
next ;
}
#print "$file => $to_dir";
if ( ! $ to_dir ) {
if ( - d $ file ) {
$ to_dir = $ file ;
} else {
$ to_dir = dirname ( $ file ) ;
}
}
push @ { $ extra } , { 'src' = > $ file , 'dest' = > $ to_dir } ;
}
return $ extra ;
2010-04-03 00:07:49 +00:00
}
# well we check to make sure the files exist and then we return them.
sub get_files {
my $ imagename = shift ;
my $ errors = 0 ;
my $ callback = shift ;
my $ attrs = shift ; # we'll hopefully get a reference to it and modify this variable.
my @ arr ; # array of directory search paths
my $ template = '' ;
# todo is XCATROOT not going to be /opt/xcat/ in normal situations? We'll always
# assume it is for now
my $ xcatroot = "/opt/xcat" ;
# get the install root
my $ installroot = xCAT::Utils - > getInstallDir ( ) ;
unless ( $ installroot ) {
$ installroot = '/install' ;
}
my $ provmethod = $ attrs - > { provmethod } ;
2010-05-21 06:44:28 +00:00
my $ osvers = $ attrs - > { osvers } ;
2010-04-03 00:07:49 +00:00
2010-09-08 18:58:39 +00:00
2010-04-03 00:07:49 +00:00
# here's the case for the install. All we need at first is the
# template. That should do it.
if ( $ provmethod =~ /install/ ) {
2010-09-08 18:58:39 +00:00
@ arr = ( "$installroot/custom/install" , "$xcatroot/share/xcat/install" ) ;
#get .tmpl file
if ( ( ! $ attrs - > { template } ) || ( ! - r $ attrs - > { template } ) ) {
2010-04-08 21:53:05 +00:00
my $ template = look_for_file ( 'tmpl' , $ callback , $ attrs , @ arr ) ;
2010-04-03 00:07:49 +00:00
unless ( $ template ) {
$ callback - > ( { error = > [ "Couldn't find install template for $imagename" ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
} else {
$ callback - > ( { data = > [ "$template" ] } ) ;
$ attrs - > { template } = $ template ;
}
2010-09-08 18:58:39 +00:00
}
$ attrs - > { media } = "required" ;
2010-04-03 00:07:49 +00:00
}
# for stateless I need to save the
# ramdisk
# the kernel
# the rootimg.gz
2010-09-14 20:17:32 +00:00
if ( $ osvers !~ /esx/ ) {
# don't do anything because these files don't exist for ESX stateless.
if ( $ provmethod =~ /netboot/ ) {
@ arr = ( "$installroot/custom/netboot" , "$xcatroot/share/xcat/netboot" ) ;
#get .pkglist file
if ( ( ! $ attrs - > { pkglist } ) || ( ! - f $ attrs - > { pkglist } ) ) {
# we need to get the .pkglist for this one!
my $ temp = look_for_file ( 'pkglist' , $ callback , $ attrs , @ arr ) ;
unless ( $ temp ) {
2010-09-08 18:58:39 +00:00
$ callback - > ( { error = > [ "Couldn't find pkglist file for $imagename" ] , errorcode = > [ 1 ] } ) ;
2010-04-03 00:07:49 +00:00
$ errors + + ;
2010-09-14 20:17:32 +00:00
} else {
2010-09-08 18:58:39 +00:00
$ attrs - > { pkglist } = $ temp ;
2010-09-14 20:17:32 +00:00
}
}
@ arr = ( "$installroot/netboot" ) ;
# look for ramdisk
2010-09-22 13:55:48 +00:00
my $ ramdisk = look_for_file ( 'initrd-stateless.gz' , $ callback , $ attrs , @ arr ) ;
2010-09-14 20:17:32 +00:00
unless ( $ ramdisk ) {
2010-09-22 13:55:48 +00:00
$ callback - > ( { error = > [ "Couldn't find ramdisk (initrd-stateless.gz) for $imagename" ] , errorcode = > [ 1 ] } ) ;
2010-09-14 20:17:32 +00:00
$ errors + + ;
} else {
$ attrs - > { ramdisk } = $ ramdisk ;
}
# look for kernel
my $ kernel = look_for_file ( 'kernel' , $ callback , $ attrs , @ arr ) ;
unless ( $ kernel ) {
$ callback - > ( { error = > [ "Couldn't find kernel (kernel) for $imagename" ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
} else {
$ attrs - > { kernel } = $ kernel ;
}
# look for rootimg.gz
my $ rootimg = look_for_file ( 'rootimg.gz' , $ callback , $ attrs , @ arr ) ;
unless ( $ rootimg ) {
$ callback - > ( { error = > [ "Couldn't find rootimg (rootimg.gz) for $imagename" ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
} else {
$ attrs - > { rootimg } = $ rootimg ;
2010-04-03 00:07:49 +00:00
}
2010-09-14 20:17:32 +00:00
} elsif ( $ provmethod =~ /statelite/ ) {
@ arr = ( "$installroot/custom/netboot" , "$xcatroot/share/xcat/netboot" ) ;
#get .pkglist file
if ( ( ! $ attrs - > { pkglist } ) || ( ! - f $ attrs - > { pkglist } ) ) {
# we need to get the .pkglist for this one!
my $ temp = look_for_file ( 'pkglist' , $ callback , $ attrs , @ arr ) ;
unless ( $ temp ) {
$ callback - > ( { error = > [ "Couldn't find pkglist file for $imagename" ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
} else {
$ attrs - > { pkglist } = $ temp ;
}
}
2010-04-03 00:07:49 +00:00
2010-09-14 20:17:32 +00:00
@ arr = ( "$installroot/netboot" ) ;
# look for kernel
my $ kernel = look_for_file ( 'kernel' , $ callback , $ attrs , @ arr ) ;
unless ( $ kernel ) {
$ callback - > ( { error = > [ "Couldn't find kernel (kernel) for $imagename" ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
} else {
$ attrs - > { kernel } = $ kernel ;
}
# look for ramdisk
my $ ramdisk = look_for_file ( 'initrd-statelite.gz' , $ callback , $ attrs , @ arr ) ;
unless ( $ ramdisk ) {
$ callback - > ( { error = > [ "Couldn't find ramdisk (initrd-statelite.gz) for $imagename" ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
} else {
$ attrs - > { ramdisk } = $ ramdisk ;
}
}
}
2010-04-03 00:07:49 +00:00
if ( $ errors ) {
2010-09-08 18:58:39 +00:00
$ attrs = 0 ;
2010-04-03 00:07:49 +00:00
}
return $ attrs ;
}
# argument:
# type of file: This is usually the suffix of the file, or the file name.
# attributes: These are the paramaters you got from the osimage table in a hash.
# @dirs: Some search paths where we'll start looking for them.
# then we just return a string of the full path to where the file is.
# mostly because we just ooze awesomeness.
sub look_for_file {
2010-09-08 18:58:39 +00:00
my $ file = shift ;
my $ callback = shift ;
my $ attrs = shift ;
my @ dirs = @ _ ;
my $ r_file = '' ;
my $ profile = $ attrs - > { profile } ;
my $ arch = $ attrs - > { osarch } ;
my $ distname = $ attrs - > { osvers } ;
# go through the directories and look for the file. We hopefully will find it...
foreach my $ d ( @ dirs ) {
# widdle down rhel5.4, rhel5., rhel5, rhel, rhe, rh, r,
my $ dd = $ distname ; # dd is distro directory, or disco dave, whichever you prefer.
if ( $ dd =~ /win/ ) { $ dd = 'windows' } ;
until ( - r "$d/$dd" or not $ dd ) {
$ callback - > ( { data = > [ "not in $d/$dd..." ] } ) if $ ::VERBOSE ;
chop ( $ dd ) ;
}
if ( $ distname && ( ( $ file eq 'tmpl' ) || ( $ file eq 'pkglist' ) ) ) {
$ callback - > ( { data = > [ "looking in $d/$dd..." ] } ) if $ ::VERBOSE ;
# now look for the file name: foo.rhel5.x86_64.tmpl
( - r "$d/$dd/$profile.$distname.$arch.$file" ) && ( return "$d/$dd/$profile.$distname.$arch.$file" ) ;
# now look for the file name: foo.rhel5.tmpl
( - r "$d/$dd/$profile.$distname.$file" ) && ( return "$d/$dd/$profile.$distname.$file" ) ;
# now look for the file name: foo.x86_64.tmpl
( - r "$d/$dd/$profile.$arch.$file" ) && ( return "$d/$dd/$profile.$arch.$file" ) ;
# finally, look for the file name: foo.tmpl
( - r "$d/$dd/$profile.$file" ) && ( return "$d/$dd/$profile.$file" ) ;
} else {
# this may find the ramdisk: /install/netboot/
( - r "$d/$dd/$arch/$profile/$file" ) && ( return "$d/$dd/$arch/$profile/$file" ) ;
}
}
# I got nothing man. Can't find it. Sorry 'bout that.
# returning nothing:
return '' ;
2010-04-03 00:07:49 +00:00
}
# here's where we make the tarball
sub make_bundle {
2010-09-14 20:17:32 +00:00
my $ imagename = shift ;
my $ dest = shift ;
my $ attribs = shift ;
my $ callback = shift ;
# 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 = shift ;
#my $dir = getcwd;
# get rid of spaces and put in underlines.
$ imagename =~ s/\s+/_/g ;
# 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 ;
2010-04-03 00:07:49 +00:00
2010-09-14 20:17:32 +00:00
#for statelite
if ( $ attribs - > { provmethod } eq 'statelite' ) {
#copy the rootimgdir over
my $ rootimgdir = $ attribs - > { rootimgdir } ;
if ( $ rootimgdir ) {
$ callback - > ( { data = > [ "Packing root image. It will take a while" ] } ) ;
system ( "cd $rootimgdir; find rootimg |cpio -H newc -o | gzip -c - > $tpath/rootimgtree.gz" ) ;
2011-08-10 08:12:57 +00:00
$ attribs - > { 'rootimgtree' } = "$rootimgdir/rootimgtree.gz" ;
2010-09-14 20:17:32 +00:00
} else {
$ callback - > ( { error = > [ "Couldn't locate the root image directory. " ] , errorcode = > [ 1 ] } ) ;
return 0 ;
2010-04-03 00:07:49 +00:00
}
2010-09-14 20:17:32 +00:00
#get litefile table setting for the image
my $ lftab = xCAT::Table - > new ( "litefile" , - create = > 1 ) ;
if ( ! $ lftab ) {
$ callback - > ( { error = > [ "Could not open the litefile table." ] , errorcode = > [ 1 ] } ) ;
return 0 ;
2010-04-03 00:07:49 +00:00
}
2010-09-14 20:17:32 +00:00
$ callback - > ( { data = > [ "Getting litefile settings" ] } ) ;
my @ imageInfo ;
# get the directories with no names
push @ imageInfo , $ lftab - > getAttribs ( { image = > '' } , ( 'file' , 'options' ) ) ;
# get the ALL directories
push @ imageInfo , $ lftab - > getAttribs ( { image = > 'ALL' } , ( 'file' , 'options' ) ) ;
# get for the image specific directories
push @ imageInfo , $ lftab - > getAttribs ( { image = > $ imagename } , ( 'file' , 'options' ) ) ;
open ( FILE , ">$tpath/litefile.csv" ) or die "Could not open $tpath/litefile.csv" ;
foreach ( @ imageInfo ) {
my $ file = $ _ - > { file } ;
if ( ! $ file ) { next ; }
my $ o = $ _ - > { options } ;
if ( ! $ o ) {
2010-09-16 16:06:18 +00:00
$ o = "tmpfs" ;
2010-09-14 20:17:32 +00:00
}
print FILE "\"$imagename\",\"$file\",\"$o\",,\n" ;
2010-04-03 00:07:49 +00:00
}
2010-09-14 20:17:32 +00:00
close ( FILE ) ;
$ attribs - > { 'litefile' } = "$rootimgdir/litefile.csv" ;
}
# make manifest.xml file. So easy! This is why we like XML. I didn't like
# the idea at first though.
my $ xml = new XML:: Simple ( RootName = > 'xcatimage' ) ;
open ( FILE , ">$tpath/manifest.xml" ) or die "Could not open $tpath/manifest.xml" ;
print FILE $ xml - > XMLout ( $ attribs , noattr = > 1 , xmldecl = > '<?xml version="1.0"?>' ) ;
#print $xml->XMLout($attribs, noattr => 1, xmldecl => '<?xml version="1.0">');
close ( FILE ) ;
# these are the only files we copy in. (unless you have extras)
for my $ a ( "kernel" , "template" , "ramdisk" , "rootimg" , "pkglist" , "synclists" , "otherpkglist" , "postinstall" , "exlist" ) {
my $ fn = $ attribs - > { $ a } ;
if ( $ fn ) {
$ callback - > ( { data = > [ "$fn" ] } ) ;
if ( - r $ fn ) {
system ( "cp $fn $tpath" ) ;
} else {
$ callback - > ( { error = > [ "Couldn't find file $fn for $imagename. Skip." ] , errorcode = > [ 1 ] } ) ;
}
2010-04-08 20:14:16 +00:00
}
2010-09-14 20:17:32 +00:00
}
# extra files get copied in the extra directory.
if ( $ attribs - > { extra } ) {
mkdir ( "$tpath/extra" ) ;
chmod 0755 , "$tpath/extra" ;
foreach ( @ { $ attribs - > { extra } } ) {
my $ fromf = $ _ - > { src } ;
print " $fromf\n" ;
if ( - d $ fromf ) {
print "fromf is a directory" ;
mkpath ( "$tpath/extra/$fromf" ) ;
`cp -a $fromf/* $tpath/extra/$fromf/` ;
} else {
`cp $fromf $tpath/extra` ;
}
2010-04-03 00:07:49 +00:00
}
2010-09-14 20:17:32 +00:00
}
# now get right below all this stuff and tar it up.
chdir ( $ ttpath ) ;
$ callback - > ( { data = > [ "Inside $ttpath." ] } ) ;
unless ( $ dest ) {
$ dest = "$dir/$imagename.tgz" ;
}
# if no absolute path specified put it in the cwd
unless ( $ dest =~ /^\// ) {
$ dest = "$dir/$dest" ;
}
$ callback - > ( { data = > [ "Compressing $imagename bundle. Please be patient." ] } ) ;
my $ rc ;
if ( $ ::VERBOSE ) {
$ callback - > ( { data = > [ "tar czvf $dest . " ] } ) ;
$ rc = system ( "tar czvf $dest . " ) ;
} else {
$ rc = system ( "tar czf $dest . " ) ;
}
$ callback - > ( { data = > [ "Done!" ] } ) ;
if ( $ rc ) {
$ callback - > ( { error = > [ "Failed to compress archive! (Maybe there was no space left?)" ] , errorcode = > [ 1 ] } ) ;
return ;
}
chdir ( $ dir ) ;
$ rc = system ( "rm -rf $ttpath" ) ;
if ( $ rc ) {
$ callback - > ( { error = > [ "Failed to clean up temp space $ttpath" ] , errorcode = > [ 1 ] } ) ;
return ;
}
2010-04-03 00:07:49 +00:00
}
2010-04-08 01:40:57 +00:00
sub extract_bundle {
2010-09-09 19:05:29 +00:00
my $ request = shift ;
#print Dumper($request);
my $ callback = shift ;
my $ nodes = shift ;
my $ new_profile = 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 = $ 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..." ] } ) ;
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 ] } ) ;
}
2010-04-08 20:14:16 +00:00
2010-09-09 19:05:29 +00:00
# get all the files in the tpath. These should be all the image names.
my @ files = < $ tpath / * > ;
# 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 ) {
unless ( - r "$imgdir/manifest.xml" ) {
$ callback - > ( { error = > [ "Failed to find manifest.xml file in image bundle" ] , errorcode = > [ 1 ] } ) ;
return ;
}
$ xml = new XML:: Simple ;
# get the data!
# put it in an eval string so that it
$ data = eval { $ xml - > XMLin ( "$imgdir/manifest.xml" ) } ;
if ( $@ ) {
$ callback - > ( { error = > [ "invalid 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);
#push @{$datas}, $data;
# now we need to import the files...
unless ( verify_manifest ( $ data , $ callback ) ) {
$ error + + ;
next ;
2010-04-08 20:14:16 +00:00
}
2010-04-08 01:40:57 +00:00
2010-09-09 19:05:29 +00:00
# check media first
unless ( check_media ( $ data , $ callback ) ) {
$ error + + ;
next ;
2010-04-08 20:14:16 +00:00
}
2010-09-10 13:47:57 +00:00
#change profile name if needed
if ( $ new_profile ) {
$ data = change_profile ( $ data , $ callback , $ new_profile , $ imgdir ) ;
}
2010-09-09 19:05:29 +00:00
#import manifest.xml into xCAT database
unless ( set_config ( $ data , $ callback ) ) {
$ error + + ;
next ;
2010-04-08 01:40:57 +00:00
}
2010-09-09 19:05:29 +00:00
# now place files in appropriate directories.
unless ( make_files ( $ data , $ imgdir , $ callback ) ) {
$ error + + ;
next ;
2010-04-08 01:40:57 +00:00
}
2010-09-09 19:05:29 +00:00
# put postscripts in the postsctipts table
if ( $ nodes ) {
unless ( set_postscripts ( $ data , $ callback , $ nodes ) ) {
$ error + + ;
next ;
}
2010-04-08 20:14:16 +00:00
}
2010-09-09 19:05:29 +00:00
my $ osimage = $ data - > { imagename } ;
2010-09-14 20:17:32 +00:00
$ callback - > ( { data = > [ "Successfully imported the image." ] } ) ;
2010-09-09 19:05:29 +00:00
}
# 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 ;
}
}
2010-04-08 20:14:16 +00:00
}
2010-09-10 13:47:57 +00:00
sub change_profile {
my $ data = shift ;
my $ callback = shift ;
my $ new_profile = shift ;
my $ srcdir = shift ;
$ data - > { profile } = $ new_profile ;
my $ installdir = xCAT::Utils - > getInstallDir ( ) ;
unless ( $ installdir ) {
$ installdir = '/install' ;
}
if ( $ data - > { rootimgdir } ) {
$ data - > { rootimgdir } = "$installdir/netboot/" . $ data - > { osvers } . "/" . $ data - > { osarch } . "/$new_profile" ;
2010-09-14 20:17:32 +00:00
for my $ a ( "kernel" , "ramdisk" , "rootimg" , "rootimgtree" , "litefile" ) {
2010-09-10 13:47:57 +00:00
if ( $ data - > { $ a } ) {
my $ fn = basename ( $ data - > { $ a } ) ;
$ data - > { $ a } = $ data - > { rootimgdir } . "/$fn" ;
}
}
}
my $ prov = "netboot" ;
if ( $ data - > { provmethod } eq "install" ) { $ prov = "install" ; }
my $ platform ;
my $ os = $ data - > { osvers } ;
if ( $ os ) {
if ( $ os =~ /rh.*/ ) { $ platform = "rh" ; }
elsif ( $ os =~ /centos.*/ ) { $ platform = "centos" ; }
elsif ( $ os =~ /fedora.*/ ) { $ platform = "fedora" ; }
elsif ( $ os =~ /sles.*/ ) { $ platform = "sles" ; }
elsif ( $ os =~ /SL.*/ ) { $ platform = "SL" ; }
elsif ( $ os =~ /win/ ) { $ platform = "windows" ; }
}
for my $ a ( "template" , "pkglist" , "synclists" , "otherpkglist" , "postinstall" , "exlist" ) {
if ( $ data - > { $ a } ) {
my $ fn = basename ( $ data - > { $ a } ) ;
my $ oldfn = $ fn ;
$ fn =~ s/^([^\.]+)\.(.*)$/$new_profile.$2/ ;
move ( "$srcdir/$oldfn" , "$srcdir/$fn" ) ;
$ data - > { $ a } = "$installdir/custom/$prov/$platform/$fn" ;
}
}
2010-09-14 20:17:32 +00:00
#change the image name
$ data - > { imagename } = $ data - > { osvers } . "-" . $ data - > { osarch } . "-" . $ data - > { provmethod } . "-$new_profile" ;
2010-09-10 13:47:57 +00:00
return $ data ;
}
2010-04-08 20:14:16 +00:00
# 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 ;
2010-04-08 01:40:57 +00:00
}
2010-09-09 19:05:29 +00:00
sub set_postscripts {
my $ data = shift ;
my $ callback = shift ;
my $ nodes = shift ;
2010-09-14 20:17:32 +00:00
$ callback - > ( { data = > [ "Adding postscripts." ] } ) ;
2010-09-09 19:05:29 +00:00
my @ good_nodes = noderange ( $ nodes ) ;
if ( @ good_nodes > 0 ) {
my @ missed = nodesmissed ( ) ;
if ( @ missed > 0 ) {
$ callback - > (
{ warning = > [ "The following nodes will be skipped because they are not in the nodelist table.\n " . join ( ',' , @ missed ) ] , errorcode = > 1 }
) ;
}
} else {
$ callback - > (
{ error = > [ "The nodes $nodes are not defined in xCAT DB." ] , errorcode = > 1 }
) ;
return 0 ;
}
my $ ptab = xCAT::Table - > new ( 'postscripts' , - create = > 1 , - autocommit = > 0 ) ;
unless ( $ ptab ) {
$ callback - > (
{ error = > [ "Unable to open table 'postscripts'" ] , errorcode = > 1 }
) ;
return 0 ;
}
# get xcatdefaults settings
my @ a1 = ( ) ;
my @ a2 = ( ) ;
( my $ attrs1 ) = $ ptab - > getAttribs ( { node = > "xcatdefaults" } , 'postscripts' , 'postbootscripts' ) ;
if ( $ attrs1 ) {
if ( $ attrs1 - > { postscripts } ) {
@ a1 = split ( ',' , $ attrs1 - > { postscripts } ) ;
}
if ( $ attrs1 - > { postbootscripts } ) {
@ a2 = split ( ',' , $ attrs1 - > { postbootscripts } ) ;
}
}
#remove the script if it is already in xcatdefaults
my @ a3 = ( ) ;
my @ a4 = ( ) ;
my $ postscripts = $ data - > { postscripts } ;
my $ postbootscripts = $ data - > { postbootscripts } ;
if ( $ postscripts ) { @ a3 = split ( ',' , $ postscripts ) ; }
if ( $ postbootscripts ) { @ a4 = split ( ',' , $ postbootscripts ) ; }
my @ a30 ;
my @ a40 ;
if ( @ a1 > 0 && @ a3 > 0 ) {
foreach my $ tmp1 ( @ a3 ) {
if ( ! grep /^$tmp1$/ , @ a1 ) {
push ( @ a30 , $ tmp1 ) ;
}
}
$ postscripts = join ( ',' , @ a30 ) ;
}
if ( @ a2 > 0 && @ a4 > 0 ) {
foreach my $ tmp2 ( @ a4 ) {
if ( ! grep /^$tmp2$/ , @ a2 ) {
push ( @ a40 , $ tmp2 ) ;
}
}
$ postbootscripts = join ( ',' , @ a40 ) ;
}
#now save to the db
my % keyhash ;
if ( $ postscripts || $ postbootscripts ) {
$ keyhash { postscripts } = $ postscripts ;
$ keyhash { postbootscripts } = $ postbootscripts ;
$ ptab - > setNodesAttribs ( \ @ good_nodes , \ % keyhash ) ;
$ ptab - > commit ;
}
return 1 ;
}
2010-04-08 01:40:57 +00:00
sub set_config {
my $ data = shift ;
my $ callback = shift ;
my $ ostab = xCAT::Table - > new ( 'osimage' , - create = > 1 , - autocommit = > 0 ) ;
2010-09-08 18:58:39 +00:00
my $ linuxtab = xCAT::Table - > new ( 'linuximage' , - create = > 1 , - autocommit = > 0 ) ;
2010-04-08 01:40:57 +00:00
my % keyhash ;
my $ osimage = $ data - > { imagename } ;
2010-09-08 18:58:39 +00:00
unless ( $ ostab ) {
$ callback - > (
{ error = > [ "Unable to open table 'osimage'" ] , errorcode = > 1 }
) ;
return 0 ;
}
unless ( $ linuxtab ) {
$ callback - > (
{ error = > [ "Unable to open table 'linuximage'" ] , errorcode = > 1 }
) ;
return 0 ;
}
2010-04-08 20:14:16 +00:00
$ callback - > ( { data = > [ "Adding $osimage" ] } ) if $ ::VERBOSE ;
2010-04-08 01:40:57 +00:00
# now we make a quick hash of what we want to put into this
$ keyhash { provmethod } = $ data - > { provmethod } ;
$ keyhash { profile } = $ data - > { profile } ;
$ keyhash { osvers } = $ data - > { osvers } ;
$ keyhash { osarch } = $ data - > { osarch } ;
2010-09-08 18:58:39 +00:00
if ( $ data - > { imagetype } ) {
$ keyhash { imagetype } = $ data - > { imagetype } ;
} ;
if ( $ data - > { osname } ) {
$ keyhash { osname } = $ data - > { osname } ;
} ;
if ( $ data - > { osdistro } ) {
$ keyhash { osdistro } = $ data - > { osdistro } ;
} ;
if ( $ data - > { synclists } ) {
$ keyhash { synclists } = $ data - > { synclists } ;
} ;
2010-04-08 01:40:57 +00:00
$ ostab - > setAttribs ( { imagename = > $ osimage } , \ % keyhash ) ;
$ ostab - > commit ;
2010-09-08 18:58:39 +00:00
% keyhash = ( ) ;
if ( $ data - > { template } ) {
$ keyhash { template } = $ data - > { template } ;
} ;
if ( $ data - > { pkglist } ) {
$ keyhash { pkglist } = $ data - > { pkglist } ;
} ;
if ( $ data - > { pkgdir } ) {
$ keyhash { pkgdir } = $ data - > { pkgdir } ;
} ;
if ( $ data - > { otherpkglist } ) {
$ keyhash { otherpkglist } = $ data - > { otherpkglist } ;
} ;
if ( $ data - > { otherpkgdir } ) {
$ keyhash { otherpkgdir } = $ data - > { otherpkgdir } ;
} ;
if ( $ data - > { exlist } ) {
$ keyhash { exlist } = $ data - > { exlist } ;
} ;
if ( $ data - > { postinstall } ) {
$ keyhash { postinstall } = $ data - > { postinstall } ;
} ;
if ( $ data - > { rootimgdir } ) {
$ keyhash { rootimgdir } = $ data - > { rootimgdir } ;
} ;
if ( $ data - > { netdrivers } ) {
$ keyhash { netdrivers } = $ data - > { netdrivers } ;
} ;
if ( $ data - > { kernelver } ) {
$ keyhash { kernelver } = $ data - > { kernelver } ;
} ;
2010-09-17 17:51:39 +00:00
if ( $ data - > { permission } ) {
$ keyhash { permission } = $ data - > { permission } ;
} ;
2010-09-17 14:48:54 +00:00
if ( $ data - > { nodebootif } ) {
$ keyhash { nodebootif } = $ data - > { nodebootif } ;
} ;
if ( $ data - > { otherifce } ) {
$ keyhash { otherifce } = $ data - > { otherifce } ;
} ;
2010-09-08 18:58:39 +00:00
$ linuxtab - > setAttribs ( { imagename = > $ osimage } , \ % keyhash ) ;
$ linuxtab - > commit ;
2010-09-14 20:17:32 +00:00
2010-04-08 20:14:16 +00:00
return 1 ;
2010-04-08 01:40:57 +00:00
}
sub verify_manifest {
my $ data = shift ;
my $ callback = shift ;
my $ errors = 0 ;
# first make sure that the stuff is defined!
unless ( $ data - > { imagename } ) {
$ callback - > ( { error = > [ "The 'imagename' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ data - > { provmethod } ) {
$ callback - > ( { error = > [ "The 'provmethod' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ data - > { profile } ) {
$ callback - > ( { error = > [ "The 'profile' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ data - > { osvers } ) {
$ callback - > ( { error = > [ "The 'osvers' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ data - > { osarch } ) {
$ callback - > ( { error = > [ "The 'osarch' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ data - > { provmethod } =~ /install|netboot|statelite/ ) {
$ callback - > ( { error = > [ "Importing images with 'provemethod' " . $ data - > { provmethod } . " is not supported. Hint: install, netboot, or statelite" ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
# if the install method is used, then we need to have certain files in place.
if ( $ data - > { provmethod } =~ /install/ ) {
# we need to get the template for this one!
unless ( $ data - > { template } ) {
$ callback - > ( { error = > [ "The 'osarch' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
#$attrs->{media} = "required"; (need to do something to verify media!
2010-05-21 06:44:28 +00:00
} elsif ( $ data - > { osvers } =~ /esx/ ) {
$ callback - > ( { info = > [ 'this is an esx image' ] } ) ;
# do nothing for ESX
1 ;
2010-09-14 20:17:32 +00:00
} elsif ( $ data - > { provmethod } =~ /netboot/ ) {
2010-04-08 01:40:57 +00:00
unless ( $ data - > { ramdisk } ) {
$ callback - > ( { error = > [ "The 'ramdisk' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ data - > { kernel } ) {
$ callback - > ( { error = > [ "The 'kernel' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ data - > { rootimg } ) {
$ callback - > ( { error = > [ "The 'rootimg' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
2010-09-14 20:17:32 +00:00
} elsif ( $ data - > { provmethod } =~ /statelite/ ) {
unless ( $ data - > { kernel } ) {
$ callback - > ( { error = > [ "The 'kernel' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ data - > { ramdisk } ) {
$ callback - > ( { error = > [ "The 'ramdisk' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
unless ( $ data - > { 'rootimgtree' } ) {
$ callback - > ( { error = > [ "The 'rootimgtree' field is not defined in manifest.xml." ] , errorcode = > [ 1 ] } ) ;
$ errors + + ;
}
}
2010-04-08 01:40:57 +00:00
if ( $ errors ) {
# we had problems, error and exit.
return 0 ;
}
# returning 1 means everything went good!
return 1 ;
}
sub make_files {
2010-09-08 18:58:39 +00:00
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' ;
}
# you'll get a hash like this for install:
#$VAR1 = {
# 'provmethod' => 'install',
# 'profile' => 'all',
# 'template' => '/opt/xcat/share/xcat/install/centos/all.tmpl',
# 'pkglist' => '/opt/xcat/share/xcat/install/centos/all.pkglist',
# 'otherpkglist' => '/opt/xcat/share/xcat/install/centos/all.othetpkgs.pkglist',
# 'synclists' => '/opt/xcat/share/xcat/install/centos/all.othetpkgs.synclist',
# 'imagename' => 'Default_Stateful',
# 'osarch' => 'x86_64',
# 'media' => 'required',
# 'osvers' => 'centos5.4'
# };
# data will look something like this for netboot:
#$VAR1 = {
# 'provmethod' => 'netboot',
# 'profile' => 'compute',
2010-09-22 13:55:48 +00:00
# 'ramdisk' => '/install/netboot/centos5.4/x86_64/compute/initrd-stateless.gz',
2010-09-08 18:58:39 +00:00
# 'kernel' => '/install/netboot/centos5.4/x86_64/compute/kernel',
# 'imagename' => 'Default_Stateless_1265981465',
# 'osarch' => 'x86_64',
# 'pkglist' => '/opt/xcat/share/xcat/install/centos/compute.pkglist',
# 'otherpkglist' => '/opt/xcat/share/xcat/install/centos/compute.othetpkgs.pkglist',
# 'synclists' => '/opt/xcat/share/xcat/install/centos/compute.othetpkgs.synclist',
# 'exlist' => '/opt/xcat/share/xcat/install/centos/compute.exlist',
# 'postinstall' => '/opt/xcat/share/xcat/install/centos/compute.postinstall',
# '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'
# };
2010-09-14 20:17:32 +00:00
# data will look something like this for statelite:
#$VAR1 = {
# 'provmethod' => 'statelite',
# 'profile' => 'compute',
# 'ramdisk' => '/install/netboot/centos5.4/x86_64/compute/initrd-statelite.gz',
# 'kernel' => '/install/netboot/centos5.4/x86_64/compute/kernel',
# 'imagename' => 'Default_Stateless_1265981465',
# 'osarch' => 'x86_64',
# 'pkglist' => '/opt/xcat/share/xcat/install/centos/compute.pkglist',
# 'otherpkglist' => '/opt/xcat/share/xcat/install/centos/compute.othetpkgs.pkglist',
# 'synclists' => '/opt/xcat/share/xcat/install/centos/compute.othetpkgs.synclist',
# 'exlist' => '/opt/xcat/share/xcat/install/centos/compute.exlist',
# 'postinstall' => '/opt/xcat/share/xcat/install/centos/compute.postinstall',
# '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',
# 'rootimgtree' => '/install/netboot/centos5.4/x86_64/compute/rootimg/rootimgtree.gz'
# };
2010-04-08 21:53:05 +00:00
2010-09-14 20:17:32 +00:00
for my $ a ( "kernel" , "template" , "ramdisk" , "rootimg" , "rootimgtree" , "litefile" , "pkglist" , "synclists" , "otherpkglist" , "postinstall" , "exlist" ) {
2010-09-08 18:58:39 +00:00
my $ fn = $ data - > { $ a } ;
if ( $ fn ) {
$ callback - > ( { data = > [ "$fn" ] } ) ;
my $ basename = basename ( $ fn ) ;
my $ dirname = dirname ( $ fn ) ;
if ( ! - r $ dirname ) {
mkpath ( "$dirname" , { verbose = > 1 , mode = > 0755 } ) ;
}
if ( - r $ fn ) {
2010-09-14 20:17:32 +00:00
$ callback - > ( { data = > [ " Moving old $fn to $fn.ORIG." ] } ) ;
2010-09-08 18:58:39 +00:00
move ( "$fn" , "$fn.ORIG" ) ;
}
move ( "$imgdir/$basename" , $ fn ) ;
}
}
2010-09-14 20:17:32 +00:00
#unpack the rootimgtree.gz for statelite
my $ fn = $ data - > { 'rootimgtree' } ;
if ( $ fn ) {
if ( - r $ fn ) {
my $ basename = basename ( $ fn ) ;
my $ dirname = dirname ( $ fn ) ;
#print "dirname=$dirname, basename=$basename\n";
$ callback - > ( { data = > [ "Extracting rootimgtree.gz. It will take a while." ] } ) ;
system ( "mkdir -p $dirname; cd $dirname; zcat $basename |cpio -idum; rm $basename" ) ;
}
}
2010-09-08 18:58:39 +00:00
if ( $ data - > { extra } ) {
# have to copy extras
2010-09-14 20:17:32 +00:00
print "copying extras\n" if $ ::VERBOSE ;
2010-09-08 18:58:39 +00:00
#if its just a hash then there is only one entry.
if ( ref ( $ data - > { extra } ) eq 'HASH' ) {
my $ ex = $ data - > { extra } ;
#my $f = basename($ex->{src});
my $ ff = $ ex - > { src } ;
my $ dest = $ ex - > { dest } ;
unless ( moveExtra ( $ callback , $ ff , $ dest , $ imgdir ) ) {
return 0 ;
}
# if its an array go through each item.
} else {
foreach ( @ { $ data - > { extra } } ) {
#my $f = basename($_->{src});
my $ ff = $ _ - > { src } ;
my $ dest = $ _ - > { dest } ;
unless ( moveExtra ( $ callback , $ ff , $ dest , $ imgdir ) ) {
return 0 ;
2010-04-08 20:14:16 +00:00
}
2010-09-08 18:58:39 +00:00
}
2010-04-08 01:40:57 +00:00
}
2010-09-08 18:58:39 +00:00
}
2010-09-14 20:17:32 +00:00
#litefile table for statelite
if ( $ data - > { provmethod } eq 'statelite' ) {
$ callback - > ( { data = > [ "Updating the litefile table." ] } ) ;
my $ fn = $ data - > { litefile } ;
if ( ! $ fn ) {
$ callback - > ( { error = > [ "Could not find liefile.csv." ] , errorcode = > [ 1 ] } ) ;
return 1 ;
} elsif ( ! - r $ fn ) {
$ callback - > ( { error = > [ "Could not find $fn." ] , errorcode = > [ 1 ] } ) ;
return 1 ;
}
my $ lftab = xCAT::Table - > new ( "litefile" , - create = > 1 ) ;
if ( ! $ lftab ) {
$ callback - > ( { error = > [ "Could not open the litefile table." ] , errorcode = > [ 1 ] } ) ;
return 0 ;
}
open ( FILE , "$fn" ) or die "Could not open $fn." ;
foreach my $ line ( <FILE> ) {
chomp ( $ line ) ;
print "$line\n" ;
my @ tmp = split ( '"' , $ line ) ;
my % keyhash ;
my % updates ;
$ keyhash { image } = $ data - > { imagename } ;
$ keyhash { file } = $ tmp [ 3 ] ;
$ updates { options } = $ tmp [ 5 ] ;
$ lftab - > setAttribs ( \ % keyhash , \ % updates ) ;
}
close ( FILE ) ;
$ lftab - > commit ;
$ callback - > ( { data = > [ "The litetree and statelite talbes are untouched. You can update them if needed." ] } ) ;
}
2010-09-08 18:58:39 +00:00
# return 1 meant everything was successful!
return 1 ;
2010-04-08 01:40:57 +00:00
}
2010-06-16 06:23:18 +00:00
sub moveExtra {
2010-09-08 18:58:39 +00:00
my $ callback = shift ;
my $ ff = shift ;
my $ dest = shift ;
my $ imgdir = shift ;
my $ f = basename ( $ ff ) ;
if ( - d "$imgdir/extra/$ff" ) {
#print "This is a directory\n";
# this extra file is a directory, so we are moving the directory over.
$ callback - > ( { data = > [ "$dest" ] } ) ;
unless ( - d $ dest ) {
unless ( mkpath ( $ dest ) ) {
$ callback - > ( { error = > [ "Failed to create $dest" ] , errorcode = > 1 } ) ;
return 0 ;
}
}
# this could cause some problems. This is one of the reasons we may not want to
# allow copying of directories.
`cp -a -f $imgdir/extra/$ff/* $dest` ;
if ( $? ) {
$ callback - > ( { error = > [ "Failed to cp -a $imgdir/extra/$ff/* to $dest" ] , errorcode = > 1 } ) ;
return 0 ;
}
} else {
#print "This is a file\n";
# this extra file is a file and we can just copy to the destination.
$ callback - > ( { data = > [ "$dest/$f" ] } ) ;
2010-06-16 06:23:18 +00:00
if ( - r "$dest/$f" ) {
2010-09-14 20:17:32 +00:00
$ callback - > ( { data = > [ " Moving old $dest/$f to $dest/$f.ORIG." ] } ) ;
2010-09-08 18:58:39 +00:00
move ( "$dest/$f" , "$dest/$f.ORIG" ) ;
2010-06-16 06:23:18 +00:00
}
2010-09-08 18:58:39 +00:00
`cp $imgdir/extra/$f $dest` ;
if ( $? ) {
$ callback - > ( { error = > [ "Failed to copy $imgdir/extra/$f to $dest" ] , errorcode = > 1 } ) ;
return 0 ;
}
}
return 1 ;
2010-06-16 06:23:18 +00:00
}