2008-02-07 18:54:58 +00:00
package xCAT_plugin::packimage ;
use xCAT::Table ;
use Getopt::Long ;
use File::Path ;
2008-04-23 20:03:51 +00:00
use File::Copy ;
2008-02-07 18:54:58 +00:00
use Cwd ;
use File::Temp ;
2008-05-07 14:51:12 +00:00
use xCAT::Utils qw( genpassword ) ;
2008-02-07 18:54:58 +00:00
Getopt::Long:: Configure ( "bundling" ) ;
Getopt::Long:: Configure ( "pass_through" ) ;
sub handled_commands {
return {
packimage = > "packimage" ,
}
}
sub process_request {
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
my $ request = shift ;
my $ callback = shift ;
my $ doreq = shift ;
my $ ent = $ sitetab - > getAttribs ( { key = > 'installdir' } , [ 'value' ] ) ;
my $ installroot = "/install" ;
if ( $ ent and $ ent - > { value } ) {
$ installroot = $ ent - > { value } ;
}
@ ARGV = @ { $ request - > { arg } } ;
2009-04-14 15:51:20 +00:00
my $ argc = scalar @ ARGV ;
if ( $ argc == 0 ) {
$ callback - > ( { info = > [ "packimage -h \npackimage -v \npackimage [-p profile] [-a architecture] [-o OS] [-m method]\n" ] } ) ;
return ;
}
2008-02-07 18:54:58 +00:00
my $ osver ;
my $ arch ;
my $ profile ;
my $ method = 'cpio' ;
GetOptions (
"profile|p=s" = > \ $ profile ,
"arch|a=s" = > \ $ arch ,
"osver|o=s" = > \ $ osver ,
2008-03-20 14:45:08 +00:00
"method|m=s" = > \ $ method ,
"help|h" = > \ $ help ,
"version|v" = > \ $ version
2008-02-07 18:54:58 +00:00
) ;
2008-03-20 14:45:08 +00:00
if ( $ version ) {
2008-07-07 18:29:55 +00:00
my $ version = xCAT::Utils - > Version ( ) ;
$ callback - > ( { info = > [ $ version ] } ) ;
2008-03-20 14:45:08 +00:00
return ;
}
2009-04-14 15:51:20 +00:00
if ( $ help ) {
2008-03-20 14:45:08 +00:00
$ callback - > ( { info = > [ "packimage -h \npackimage -v \npackimage [-p profile] [-a architecture] [-o OS] [-m method]\n" ] } ) ;
return ;
}
2008-02-07 18:54:58 +00:00
my $ distname = $ osver ;
2008-02-12 19:10:33 +00:00
until ( - r "$::XCATROOT/share/xcat/netboot/$distname/" or not $ distname ) {
chop ( $ distname ) ;
}
unless ( $ distname ) {
$ callback - > ( { error = > [ "Unable to find $::XCATROOT/share/xcat/netboot directory for $osver" ] , errorcode = > [ 1 ] } ) ;
return ;
}
2008-02-07 18:54:58 +00:00
unless ( $ installroot ) {
$ callback - > ( { error = > [ "No installdir defined in site table" ] , errorcode = > [ 1 ] } ) ;
return ;
}
my $ oldpath = cwd ( ) ;
2008-09-12 22:40:15 +00:00
my $ exlistloc = get_exlist_file_name ( "$installroot/custom/netboot/$distname" , $ profile , $ osver , $ arch ) ;
if ( ! $ exlistloc ) { $ exlistloc = get_exlist_file_name ( "$::XCATROOT/share/xcat/netboot/$distname" , $ profile , $ osver , $ arch ) ; }
2009-04-14 15:51:20 +00:00
if ( ! $ exlistloc )
{
$ callback - > ( { data = > [ "WARNING: Unable to find file exclusion list under $installroot/custom/netboot/$distname or $::XCATROOT/share/xcat/netboot/$distname/ for $profile/$arch/$osver\n" ] } ) ;
}
2009-05-19 18:56:27 +00:00
2008-02-07 18:54:58 +00:00
my $ excludestr = "find . " ;
2009-05-19 18:56:27 +00:00
my $ includestr ;
2009-04-13 14:39:55 +00:00
if ( $ exlistloc ) {
my $ exlist ;
open ( $ exlist , "<" , $ exlistloc ) ;
2009-05-19 18:56:27 +00:00
system ( "echo -n > /tmp/xcat_packimg.txt" ) ;
2009-04-13 14:39:55 +00:00
while ( <$exlist> ) {
chomp $ _ ;
s/\s*#.*// ; #-- remove comments
next if /^\s*$/ ; #-- skip empty lines
2009-05-19 18:56:27 +00:00
if ( /^\+/ ) {
s/^\+// ; #remove '+'
$ includestr . = "-path '" . $ _ . "' -o " ;
} else {
s/^\-// ; #remove '-' if any
$ excludestr . = "'!' -path '" . $ _ . "' -a " ;
}
2009-04-13 14:39:55 +00:00
}
close ( $ exlist ) ;
2009-05-19 18:56:27 +00:00
}
$ excludestr =~ s/-a $// ;
if ( $ includestr ) {
$ includestr =~ s/-o $// ;
$ includestr = "find . " . $ includestr ;
}
print "\nexcludestr=$excludestr\n\n includestr=$includestr\n\n" ;
2008-04-23 20:03:51 +00:00
2009-05-19 18:56:27 +00:00
# add the xCAT post scripts to the image
2008-05-12 19:41:17 +00:00
if ( ! - d "$installroot/netboot/$osver/$arch/$profile/rootimg" ) {
$ callback - > ( { error = > [ "$installroot/netboot/$osver/$arch/$profile/rootimg does not exist, run genimage -o $osver -p $profile on a server with matching architecture" ] } ) ;
return ;
}
2009-04-23 19:12:33 +00:00
#some rpms like atftp mount the rootimg/proc to /proc, we need to make sure rootimg/proc is free of junk
#before packaging the image
`umount $installroot/netboot/$osver/$arch/$profile/rootimg/proc` ;
2008-04-23 20:03:51 +00:00
copybootscript ( $ installroot , $ osver , $ arch , $ profile , $ callback ) ;
2008-05-07 14:51:12 +00:00
my $ passtab = xCAT::Table - > new ( 'passwd' ) ;
if ( $ passtab ) {
( my $ pent ) = $ passtab - > getAttribs ( { key = > 'system' , username = > 'root' } , 'password' ) ;
if ( $ pent and defined ( $ pent - > { password } ) ) {
my $ pass = $ pent - > { password } ;
my $ shadow ;
2008-06-26 15:41:34 +00:00
open ( $ shadow , "<" , "$installroot/netboot/$osver/$arch/$profile/rootimg/etc/shadow" ) ;
my @ shadents = <$shadow> ;
close ( $ shadow ) ;
2008-05-07 14:51:12 +00:00
open ( $ shadow , ">" , "$installroot/netboot/$osver/$arch/$profile/rootimg/etc/shadow" ) ;
unless ( $ pass =~ /^\$1\$/ ) {
$ pass = crypt ( $ pass , '$1$' . genpassword ( 8 ) ) ;
}
print $ shadow "root:$pass:13880:0:99999:7:::\n" ;
2008-06-26 15:41:34 +00:00
foreach ( @ shadents ) {
unless ( /^root:/ ) {
print $ shadow "$_" ;
}
}
2008-05-07 14:51:12 +00:00
close ( $ shadow ) ;
}
}
2008-04-23 20:03:51 +00:00
2008-04-24 12:47:21 +00:00
my $ verb = "Packing" ;
if ( $ method =~ /nfs/ ) {
2008-04-24 13:34:55 +00:00
$ verb = "Prepping" ;
2008-04-24 12:47:21 +00:00
}
if ( $ method =~ /nfs/ ) {
$ callback - > ( { data = > [ "\nNOTE: Contents of $installroot/netboot/$osver/$arch/$profile/rootimg\nMUST be available on all service and management nodes and NFS exported." ] } ) ;
}
2008-02-07 18:54:58 +00:00
my $ temppath ;
2008-05-09 15:31:09 +00:00
my $ oldumask ;
if ( ! - d "$installroot/netboot/$osver/$arch/$profile/rootimg" ) {
$ callback - > ( { error = > [ "$installroot/netboot/$osver/$arch/$profile/rootimg does not exist, run genimage -o $osver -p $profile on a server with matching architecture" ] } ) ;
return ;
}
2008-05-12 19:41:17 +00:00
$ callback - > ( { data = > [ "$verb contents of $installroot/netboot/$osver/$arch/$profile/rootimg" ] } ) ;
2008-05-09 17:25:25 +00:00
unlink ( "$installroot/netboot/$osver/$arch/$profile/rootimg.gz" ) ;
unlink ( "$installroot/netboot/$osver/$arch/$profile/rootimg.sfs" ) ;
unlink ( "$installroot/netboot/$osver/$arch/$profile/rootimg.nfs" ) ;
2008-02-07 18:54:58 +00:00
if ( $ method =~ /cpio/ ) {
2009-04-13 14:39:55 +00:00
if ( ! $ exlistloc ) {
$ excludestr = "find . |cpio -H newc -o | gzip -c - > ../rootimg.gz" ;
} else {
2009-05-19 18:56:27 +00:00
chdir ( "$installroot/netboot/$osver/$arch/$profile/rootimg" ) ;
system ( "$excludestr >> /tmp/xcat_packimg.txt" ) ;
if ( $ includestr ) {
system ( "$includestr >> /tmp/xcat_packimg.txt" ) ;
}
#$excludestr =~ s!-a \z!|cpio -H newc -o | gzip -c - > ../rootimg.gz!;
$ excludestr = "cat /tmp/xcat_packimg.txt|cpio -H newc -o | gzip -c - > ../rootimg.gz" ;
2009-04-13 14:39:55 +00:00
}
$ oldmask = umask 0077 ;
2008-02-07 18:54:58 +00:00
} elsif ( $ method =~ /squashfs/ ) {
$ temppath = mkdtemp ( "/tmp/packimage.$$.XXXXXXXX" ) ;
2008-10-09 22:51:57 +00:00
chmod 0755 , $ temppath ;
2009-05-19 18:56:27 +00:00
chdir ( "$installroot/netboot/$osver/$arch/$profile/rootimg" ) ;
system ( "$excludestr >> /tmp/xcat_packimg.txt" ) ;
if ( $ includestr ) {
system ( "$includestr >> /tmp/xcat_packimg.txt" ) ;
}
$ excludestr =~ "cat /tmp/xcat_packimg.txt|cpio -dump $temppath" ;
2008-04-24 12:47:21 +00:00
} elsif ( $ method =~ /nfs/ ) {
$ excludestr = "touch ../rootimg.nfs" ;
2008-02-21 20:09:41 +00:00
} else {
$ callback - > ( { error = > [ "Invalid method '$method' requested" ] , errorcode = > [ 1 ] } ) ;
2008-02-07 18:54:58 +00:00
}
chdir ( "$installroot/netboot/$osver/$arch/$profile/rootimg" ) ;
system ( $ excludestr ) ;
2008-05-09 15:31:09 +00:00
if ( $ method =~ /cpio/ ) {
chmod 0644 , "$installroot/netboot/$osver/$arch/$profile/rootimg.gz" ;
umask $ oldmask ;
} elsif ( $ method =~ /squashfs/ ) {
2008-02-07 18:54:58 +00:00
my $ flags ;
if ( $ arch =~ /x86/ ) {
$ flags = "-le" ;
} elsif ( $ arch =~ /ppc/ ) {
$ flags = "-be" ;
}
2008-04-24 13:31:45 +00:00
if ( ! - x "/sbin/mksquashfs" ) {
$ callback - > ( { error = > [ "mksquashfs not found, squashfs-tools rpm should be installed on the management node" ] , errorcode = > [ 1 ] } ) ;
return ;
}
2008-02-28 02:11:40 +00:00
my $ rc = system ( "mksquashfs $temppath ../rootimg.sfs $flags" ) ;
if ( $ rc ) {
$ callback - > ( { error = > [ "mksquashfs could not be run successfully" ] , errorcode = > [ 1 ] } ) ;
return ;
}
2008-05-07 19:48:09 +00:00
$ rc = system ( "rm -rf $temppath" ) ;
if ( $ rc ) {
$ callback - > ( { error = > [ "Failed to clean up temp space" ] , errorcode = > [ 1 ] } ) ;
return ;
}
2008-02-07 18:54:58 +00:00
chmod ( 0644 , "../rootimg.sfs" ) ;
}
chdir ( $ oldpath ) ;
}
2008-04-23 20:03:51 +00:00
###########################################################
#
# copybootscript - copy the xCAT diskless init scripts to the image
#
#############################################################
sub copybootscript {
my $ installroot = shift ;
my $ osver = shift ;
my $ arch = shift ;
my $ profile = shift ;
my $ callback = shift ;
2008-05-01 20:52:16 +00:00
2008-04-23 20:03:51 +00:00
if ( - f "$installroot/postscripts/xcatdsklspost" ) {
# copy the xCAT diskless post script to the image
mkpath ( "$installroot/netboot/$osver/$arch/$profile/rootimg/opt/xcat" ) ;
copy ( "$installroot/postscripts/xcatdsklspost" , "$installroot/netboot/$osver/$arch/$profile/rootimg/opt/xcat/xcatdsklspost" ) ;
chmod ( 0755 , "$installroot/netboot/$osver/$arch/$profile/rootimg/opt/xcat/xcatdsklspost" ) ;
} else {
my $ rsp ;
push @ { $ rsp - > { data } } , "Could not find the script $installroot/postscripts/xcatdsklspost.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
2008-05-01 20:52:16 +00:00
if ( - f "$installroot/postscripts/xcatdsklspost.aix" ) {
copy ( "$installroot/postscripts/xcatdsklspost.aix" , "$installroot/netboot/$osver/$arch/$profile/rootimg/opt/xcat/xcatdsklspost.aix" ) ;
chmod ( 0755 , "$installroot/netboot/$osver/$arch/$profile/rootimg/opt/xcat/xcatdsklspost.aix" ) ;
}
2008-04-23 20:03:51 +00:00
if ( - f "$installroot/postscripts/xcatpostinit" ) {
# copy the linux diskless init script to the image
# - & set the permissions
copy ( "$installroot/postscripts/xcatpostinit" , "$installroot/netboot/$osver/$arch/$profile/rootimg/etc/init.d/xcatpostinit" ) ;
chmod ( 0755 , "$installroot/netboot/$osver/$arch/$profile/rootimg/etc/init.d/xcatpostinit" ) ;
# run chkconfig
2008-05-07 19:11:13 +00:00
#my $chkcmd = "chroot $installroot/netboot/$osver/$arch/$profile/rootimg chkconfig --add xcatpostinit";
symlink "/etc/init.d/xcatpostinit" , "$installroot/netboot/$osver/$arch/$profile/rootimg/etc/rc3.d/S84xcatpostinit" ;
symlink "/etc/init.d/xcatpostinit" , "$installroot/netboot/$osver/$arch/$profile/rootimg/etc/rc4.d/S84xcatpostinit" ;
symlink "/etc/init.d/xcatpostinit" , "$installroot/netboot/$osver/$arch/$profile/rootimg/etc/rc5.d/S84xcatpostinit" ;
#my $rc = system($chkcmd);
#if ($rc) {
#my $rsp;
# push @{$rsp->{data}}, "Could not run the chkconfig command.\n";
# xCAT::MsgUtils->message("E", $rsp, $callback);
# return 1;
# }
2008-04-23 20:03:51 +00:00
} else {
my $ rsp ;
push @ { $ rsp - > { data } } , "Could not find the script $installroot/postscripts/xcatpostinit.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
return 0 ;
}
2008-09-12 22:40:15 +00:00
sub get_exlist_file_name {
my $ base = shift ;
my $ profile = shift ;
my $ osver = shift ;
my $ arch = shift ;
my $ exlistloc = "" ;
if ( - r "$base/$profile.$osver.$arch.exlist" ) {
$ exlistloc = "$base/$profile.$osver.$arch.exlist" ;
} elsif ( - r "$base/$profile.$arch.exlist" ) {
$ exlistloc = "$base/$profile.$arch.exlist" ;
} elsif ( - r "$base/$profile.$osver.exlist" ) {
$ exlistloc = "$base/$profile.$osver.exlist" ;
} elsif ( - r "$base/$profile.exlist" ) {
$ exlistloc = "$base/$profile.exlist" ;
}
return $ exlistloc ;
}