2011-03-02 09:50:17 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
package xCAT_plugin::debian ;
BEGIN
{
$ ::XCATROOT = $ ENV { 'XCATROOT' } ? $ ENV { 'XCATROOT' } : '/opt/xcat' ;
}
use lib "$::XCATROOT/lib/perl" ;
use Storable qw( dclone ) ;
use Sys::Syslog ;
use File::Temp qw/tempdir/ ;
use xCAT::Table ;
use xCAT::Utils ;
use xCAT::SvrUtils ;
use xCAT::MsgUtils ;
use Data::Dumper ;
use Getopt::Long ;
Getopt::Long:: Configure ( "bundling" ) ;
Getopt::Long:: Configure ( "pass_through" ) ;
use File::Path ;
use File::Copy ;
use Socket ;
#use strict;
my @ cpiopid ;
##############################################################################
#
# Author:
#
# Arif Ali (OCF plc) <mail@arif-ali.co.uk>
#
# Notes:
#
# This will not work with Ubuntu Desktop Edition, as all the packages are in
# a compressed image, and not readily available for creating images. So will
# only support Server ISOs.
#
#
#
# ChangeLog:
#
# 13 Aug 2010 - Initial release
# - Implementation of only copycd
# - Tested with 9.10 desktop and server ISOs
# 06 Oct 2010 - Added copycd support for Ubuntu 10.04 Server (LTS releases)
# - Added support for mkinstall, install successfull for 10.04
# -> used function from anaconda.pm
# -> Need to cleanup so that it has no references to rhel
# 07 Oct 2010 - Added preprocess_request (direct copy from anaconda.pm)
#
##############################################################################
sub handled_commands
{
return {
copycd = > "debian" ,
mknetboot = > "nodetype:os=(ubuntu.*)|(debian.*)" ,
mkinstall = > "nodetype:os=(ubuntu.*)|(debian.*)" ,
2012-04-29 22:42:59 +00:00
mkstatelite = > "nodetype:os=(ubuntu.*)|(debian.*)" ,
2011-03-02 09:50:17 +00:00
} ;
}
sub preprocess_request
{
my $ req = shift ;
my $ callback = shift ;
return [ $ req ] ; #calls are only made from pre-farmed out scenarios
if ( $ req - > { command } - > [ 0 ] eq 'copycd' )
{ #don't farm out copycd
return [ $ req ] ;
}
my $ stab = xCAT::Table - > new ( 'site' ) ;
my $ sent ;
( $ sent ) = $ stab - > getAttribs ( { key = > 'sharedtftp' } , 'value' ) ;
unless ( $ sent
and defined ( $ sent - > { value } )
and ( $ sent - > { value } =~ /no/i or $ sent - > { value } =~ /0/ ) )
{
#unless requesting no sharedtftp, don't make hierarchical call
return [ $ req ] ;
}
my % localnodehash ;
my % dispatchhash ;
my $ nrtab = xCAT::Table - > new ( 'noderes' ) ;
my $ nrents = $ nrtab - > getNodesAttribs ( $ req - > { node } , [ qw( tftpserver servicenode ) ] ) ;
foreach my $ node ( @ { $ req - > { node } } )
{
my $ nodeserver ;
my $ tent = $ nrents - > { $ node } - > [ 0 ] ; #$nrtab->getNodeAttribs($node, ['tftpserver']);
if ( $ tent ) { $ nodeserver = $ tent - > { tftpserver } }
unless ( $ tent and $ tent - > { tftpserver } )
{
$ tent = $ nrents - > { $ node } - > [ 0 ] ; #$nrtab->getNodeAttribs($node, ['servicenode']);
if ( $ tent ) { $ nodeserver = $ tent - > { servicenode } }
}
if ( $ nodeserver )
{
$ dispatchhash { $ nodeserver } - > { $ node } = 1 ;
}
else
{
$ localnodehash { $ node } = 1 ;
}
}
my @ requests ;
my $ reqc = { %$ req } ;
$ reqc - > { node } = [ keys % localnodehash ] ;
if ( scalar ( @ { $ reqc - > { node } } ) ) { push @ requests , $ reqc }
foreach my $ dtarg ( keys % dispatchhash )
{ #iterate dispatch targets
my $ reqcopy = { %$ req } ; #deep copy
$ reqcopy - > { '_xcatdest' } = $ dtarg ;
$ reqcopy - > { node } = [ keys % { $ dispatchhash { $ dtarg } } ] ;
push @ requests , $ reqcopy ;
}
return \ @ requests ;
}
sub process_request
{
my $ request = shift ;
my $ callback = shift ;
my $ doreq = shift ;
my $ distname = undef ;
my $ arch = undef ;
my $ path = undef ;
if ( $ request - > { command } - > [ 0 ] eq 'copycd' )
{
return copycd ( $ request , $ callback , $ doreq ) ;
}
elsif ( $ request - > { command } - > [ 0 ] eq 'mkinstall' )
{
return mkinstall ( $ request , $ callback , $ doreq ) ;
}
2012-04-29 22:42:59 +00:00
elsif ( $ request - > { command } - > [ 0 ] eq 'mknetboot' or
$ request - > { command } - > [ 0 ] eq 'mkstatelite' )
2011-03-02 09:50:17 +00:00
{
return mknetboot ( $ request , $ callback , $ doreq ) ;
}
}
2012-04-29 22:42:59 +00:00
# Check whether the dracut is supported by this os
sub using_dracut
{
my $ os = shift ;
if ( $ os =~ /ubuntu(\d+)/ ) {
if ( $ 1 >= 12.04 ) {
return 1 ;
}
} elsif ( $ os =~ /debian(\d+)/ ) {
if ( $ 1 >= 6.0 ) {
return 1 ;
}
}
return 0 ;
}
2011-03-02 09:50:17 +00:00
sub copycd
{
xCAT::MsgUtils - > message ( "S" , "Doing debian copycds" ) ;
my $ request = shift ;
my $ callback = shift ;
my $ doreq = shift ;
my $ distname = "" ;
my $ detdistname = "" ;
my $ installroot ;
my $ arch ;
my $ path ;
$ installroot = "/install" ;
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
if ( $ sitetab )
{
( my $ ref ) = $ sitetab - > getAttribs ( { key = > 'installdir' } , 'value' ) ;
print Dumper ( $ ref ) ;
if ( $ ref and $ ref - > { value } )
{
$ installroot = $ ref - > { value } ;
}
}
@ ARGV = @ { $ request - > { arg } } ;
GetOptions (
'n=s' = > \ $ distname ,
'a=s' = > \ $ arch ,
2012-06-12 11:55:54 +00:00
'm=s' = > \ $ path ,
2011-03-02 09:50:17 +00:00
) ;
2012-06-12 11:55:54 +00:00
unless ( $ path )
2011-03-02 09:50:17 +00:00
{
#this plugin needs $path...
return ;
}
2012-06-12 11:55:54 +00:00
unless ( - r $ path . "/.disk/info" )
2011-03-02 09:50:17 +00:00
{
2012-08-31 06:48:08 +00:00
#xCAT::MsgUtils->message("S","The CD doesn't look like a Debian CD, exiting...");
2011-03-02 09:50:17 +00:00
return ;
}
my $ dinfo ;
2012-06-12 11:55:54 +00:00
open ( $ dinfo , $ path . "/.disk/info" ) ;
2011-03-02 09:50:17 +00:00
my $ line = <$dinfo> ;
chomp ( $ line ) ;
my @ line2 = split ( / / , $ line ) ;
close ( $ dinfo ) ;
2012-05-13 23:12:06 +00:00
my $ isnetinst = 0 ;
my $ prod = $ line2 [ 0 ] ; # The product should be the first word
my $ ver = $ line2 [ 1 ] ; # The version should be the second word
my $ darch = $ line2 [ 6 ] ; # The architecture should be the seventh word
2011-03-02 09:50:17 +00:00
# Check to see if $darch is defined
unless ( $ darch )
{
return ;
}
2012-05-13 23:12:06 +00:00
if ( $ prod eq "Debian" )
{
# Debian specific, the arch and version are in different places
$ darch = $ line2 [ 6 ] ;
$ ver = $ line2 [ 2 ] ;
2011-03-02 09:50:17 +00:00
2012-05-13 23:12:06 +00:00
# For the purpose of copying the netinst cd before the main one
# So that we have the netboot images
$ isnetinst = 1 if ( $ line2 [ 7 ] eq "NETINST" ) ;
2011-03-02 09:50:17 +00:00
2012-05-13 23:12:06 +00:00
$ distname = "debian" . $ ver ;
$ detdistname = "debian" . $ ver ;
}
elsif ( $ prod eq "Ubuntu" or $ prod eq "Ubuntu-Server" )
2011-03-02 09:50:17 +00:00
{
2012-05-13 23:12:06 +00:00
# to cover for LTS releases
$ darch = $ line2 [ 7 ] if ( $ line2 [ 2 ] eq "LTS" ) ;
2011-03-02 09:50:17 +00:00
$ distname = "ubuntu" . $ ver ;
$ detdistname = "ubuntu" . $ ver ;
}
2012-05-13 23:12:06 +00:00
else
2011-03-02 09:50:17 +00:00
{
2012-05-13 23:12:06 +00:00
return ;
2011-03-02 09:50:17 +00:00
}
# So that I can use amd64 below
my $ debarch = $ darch ;
if ( $ darch and $ darch =~ /i.86/ )
{
$ darch = "x86" ;
}
elsif ( $ darch and $ darch =~ /ppc/ )
{
$ darch = "ppc64" ;
}
elsif ( $ darch and $ darch =~ /amd64/ )
{
$ darch = "x86_64" ;
}
if ( $ darch )
{
unless ( $ arch )
{
$ arch = $ darch ;
}
if ( $ arch and $ arch ne $ darch )
{
$ callback - > (
{
error = >
[ "Requested Debian architecture $arch, but media is $darch" ] ,
errorcode = > [ 1 ]
}
) ;
return ;
}
}
% { $ request } = ( ) ; #clear request we've got it.
2012-06-12 11:55:54 +00:00
$ callback - > (
{ data = > "Copying media to $installroot/$distname/$arch" } ) ;
2011-03-02 09:50:17 +00:00
my $ omask = umask 0022 ;
2012-06-12 11:55:54 +00:00
mkpath ( "$installroot/$distname/$arch" ) ;
mkpath ( "$installroot/$distname/$arch/install/netboot" ) if ( $ isnetinst ) ;
2011-03-02 09:50:17 +00:00
umask $ omask ;
my $ rc ;
$ SIG { INT } = $ SIG { TERM } = sub {
foreach ( @ cpiopid ) {
kill 2 , $ _ ;
}
2012-10-17 08:34:33 +00:00
if ( $ path ) {
2011-03-02 09:50:17 +00:00
chdir ( "/" ) ;
2012-10-17 08:34:33 +00:00
system ( "umount $path" ) ;
2011-03-02 09:50:17 +00:00
}
} ;
my $ kid ;
2012-06-12 11:55:54 +00:00
chdir $ path ;
2011-03-02 09:50:17 +00:00
my $ numFiles = `find . -print | wc -l` ;
my $ child = open ( $ kid , "|-" ) ;
unless ( defined $ child ) {
$ callback - > ( { error = > "Media copy operation fork failure" } ) ;
return ;
}
if ( $ child ) {
push @ cpiopid , $ child ;
my @ finddata = `find .` ;
for ( @ finddata ) {
print $ kid $ _ ;
}
close ( $ kid ) ;
$ rc = $? ;
} else {
2012-06-12 11:55:54 +00:00
my $ c = "nice -n 20 cpio -vdump $installroot/$distname/$arch" ;
2011-03-02 09:50:17 +00:00
my $ k2 = open ( PIPE , "$c 2>&1 |" ) ||
$ callback - > ( { error = > "Media copy operation fork failure" } ) ;
push @ cpiopid , $ k2 ;
my $ copied = 0 ;
my ( $ percent , $ fout ) ;
while ( <PIPE> ) {
next if /^cpio:/ ;
$ percent = $ copied / $ numFiles ;
$ fout = sprintf "%0.2f%%" , $ percent * 100 ;
$ callback - > ( { sinfo = > "$fout" } ) ;
+ + $ copied ;
}
exit ;
}
# system(
# "cd $path; find . | nice -n 20 cpio -dump $installroot/$distname/$arch/"
# );
2012-06-12 11:55:54 +00:00
chmod 0755 , "$installroot/$distname/$arch" ;
2011-03-02 09:50:17 +00:00
# Need to do this otherwise there will be warning about corrupt Packages file
# when installing a system
# Grabs the distribution codename
my @ line = split ( " " , `ls -lh $installroot/$distname/$arch/dists/ | grep dr` ) ;
my $ dist = $ line [ @ line - 1 ] ;
# touches the Packages file so that deb packaging works
system ( "touch $installroot/$distname/$arch/dists/$dist/restricted/binary-$debarch/Packages" ) ;
# removes the links unstable and testing, otherwise the repository does not work for debian
system ( "rm -f $installroot/$distname/$arch/dists/unstable" ) ;
system ( "rm -f $installroot/$distname/$arch/dists/testing" ) ;
2012-05-13 23:12:06 +00:00
# copies the netboot files for debian
if ( $ isnetinst )
{
system ( "cp install.*/initrd.gz $installroot/$distname/$arch/install/netboot/." ) ;
system ( "cp install.*/vmlinuz $installroot/$distname/$arch/install/netboot/." ) ;
}
2011-03-02 09:50:17 +00:00
if ( $ rc != 0 )
{
$ callback - > ( { error = > "Media copy operation failed, status $rc" } ) ;
}
else
{
$ callback - > ( { data = > "Media copy operation successful" } ) ;
2012-06-12 11:55:54 +00:00
my @ ret = xCAT::SvrUtils - > update_tables_with_templates ( $ distname , $ arch ) ;
2011-03-02 09:50:17 +00:00
if ( $ ret [ 0 ] != 0 ) {
$ callback - > ( { data = > "Error when updating the osimage tables: " . $ ret [ 1 ] } ) ;
}
2012-06-12 11:55:54 +00:00
my @ ret = xCAT::SvrUtils - > update_tables_with_diskless_image ( $ distname , $ arch , undef , "netboot" ) ;
2011-07-21 06:26:13 +00:00
if ( $ ret [ 0 ] != 0 ) {
$ callback - > ( { data = > "Error when updating the osimage tables for stateless: " . $ ret [ 1 ] } ) ;
}
2012-06-12 11:55:54 +00:00
my @ ret = xCAT::SvrUtils - > update_tables_with_diskless_image ( $ distname , $ arch , undef , "statelite" ) ;
2011-07-21 06:26:13 +00:00
if ( $ ret [ 0 ] != 0 ) {
$ callback - > ( { data = > "Error when updating the osimage tables for statelite: " . $ ret [ 1 ] } ) ;
}
2011-03-02 09:50:17 +00:00
}
}
sub mkinstall
{
xCAT::MsgUtils - > message ( "S" , "Doing debian mkinstall" ) ;
my $ request = shift ;
my $ callback = shift ;
my $ doreq = shift ;
my @ nodes = @ { $ request - > { node } } ;
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
my $ linuximagetab ;
my $ osimagetab ;
my % img_hash = ( ) ;
my $ installroot ;
$ installroot = "/install" ;
if ( $ sitetab )
{
( my $ ref ) = $ sitetab - > getAttribs ( { key = > 'installdir' } , 'value' ) ;
if ( $ ref and $ ref - > { value } )
{
$ installroot = $ ref - > { value } ;
}
}
my $ node ;
my $ ostab = xCAT::Table - > new ( 'nodetype' ) ;
my % doneimgs ;
my $ restab = xCAT::Table - > new ( 'noderes' ) ;
my $ bptab = xCAT::Table - > new ( 'bootparams' , - create = > 1 ) ;
my $ hmtab = xCAT::Table - > new ( 'nodehm' ) ;
my % osents = % { $ ostab - > getNodesAttribs ( \ @ nodes , [ 'profile' , 'os' , 'arch' , 'provmethod' ] ) } ;
my % rents =
% { $ restab - > getNodesAttribs ( \ @ nodes ,
[ 'nfsserver' , 'primarynic' , 'installnic' ] ) } ;
my % hents =
% { $ hmtab - > getNodesAttribs ( \ @ nodes ,
[ 'serialport' , 'serialspeed' , 'serialflow' ] ) } ;
#my $addkcmdhash =
# $bptab->getNodesAttribs(\@nodes, ['addkcmdline']);
require xCAT::Template ;
foreach $ node ( @ nodes )
{
my $ os ;
my $ arch ;
2012-08-09 08:49:43 +00:00
my $ darch ;
2011-03-02 09:50:17 +00:00
my $ profile ;
my $ tmplfile ;
my $ pkgdir ;
2012-08-09 08:49:43 +00:00
my $ pkglistfile ;
my $ imagename ;
my $ platform ;
2011-03-02 09:50:17 +00:00
my $ osinst ;
my $ ent = $ osents { $ node } - > [ 0 ] ; #$ostab->getNodeAttribs($node, ['profile', 'os', 'arch']);
if ( $ ent and $ ent - > { provmethod } and ( $ ent - > { provmethod } ne 'install' ) and ( $ ent - > { provmethod } ne 'netboot' ) and ( $ ent - > { provmethod } ne 'statelite' ) ) {
2012-08-09 08:49:43 +00:00
$ imagename = $ ent - > { provmethod } ;
#print "imagename=$imagename\n";
if ( ! exists ( $ img_hash { $ imagename } ) ) {
if ( ! $ osimagetab ) {
$ osimagetab = xCAT::Table - > new ( 'osimage' , - create = > 1 ) ;
}
( my $ ref ) = $ osimagetab - > getAttribs ( { imagename = > $ imagename } , 'osvers' , 'osarch' , 'profile' , 'provmethod' ) ;
if ( $ ref ) {
$ img_hash { $ imagename } - > { osver } = $ ref - > { 'osvers' } ;
$ img_hash { $ imagename } - > { osarch } = $ ref - > { 'osarch' } ;
$ img_hash { $ imagename } - > { profile } = $ ref - > { 'profile' } ;
$ img_hash { $ imagename } - > { provmethod } = $ ref - > { 'provmethod' } ;
if ( ! $ linuximagetab ) {
$ linuximagetab = xCAT::Table - > new ( 'linuximage' , - create = > 1 ) ;
}
( my $ ref1 ) = $ linuximagetab - > getAttribs ( { imagename = > $ imagename } , 'template' , 'pkgdir' , 'pkglist' ) ;
if ( $ ref1 ) {
if ( $ ref1 - > { 'template' } ) {
$ img_hash { $ imagename } - > { template } = $ ref1 - > { 'template' } ;
}
if ( $ ref1 - > { 'pkgdir' } ) {
$ img_hash { $ imagename } - > { pkgdir } = $ ref1 - > { 'pkgdir' } ;
}
if ( $ ref1 - > { 'pkglist' } ) {
$ img_hash { $ imagename } - > { pkglist } = $ ref1 - > { 'pkglist' } ;
}
}
# if the install template wasn't found, then lets look for it in the default locations.
unless ( $ img_hash { $ imagename } - > { template } ) {
my $ pltfrm = getplatform ( $ ref - > { 'osvers' } ) ;
my $ tmplfile = xCAT::SvrUtils:: get_tmpl_file_name ( "$installroot/custom/install/$pltfrm" ,
$ ref - > { 'profile' } , $ ref - > { 'osvers' } , $ ref - > { 'osarch' } , $ ref - > { 'osvers' } ) ;
if ( ! $ tmplfile ) {
$ tmplfile = xCAT::SvrUtils:: get_tmpl_file_name ( "$::XCATROOT/share/xcat/install/$pltfrm" ,
$ ref - > { 'profile' } , $ ref - > { 'osvers' } , $ ref - > { 'osarch' } , $ ref - > { 'osvers' } ) ;
}
# if we managed to find it, put it in the hash:
if ( $ tmplfile ) {
$ img_hash { $ imagename } - > { template } = $ tmplfile ;
}
}
2011-09-26 13:34:20 +00:00
#if the install pkglist wasn't found, then lets look for it in the default locations
2012-08-09 08:49:43 +00:00
unless ( $ img_hash { $ imagename } - > { pkglist } ) {
my $ pltfrm = getplatform ( $ ref - > { 'osvers' } ) ;
my $ pkglistfile = xCAT::SvrUtils:: get_pkglist_file_name ( "$installroot/custom/install/$pltfrm" ,
$ ref - > { 'profile' } , $ ref - > { 'osvers' } , $ ref - > { 'osarch' } , $ ref - > { 'osvers' } ) ;
if ( ! $ pkglistfile ) {
$ pkglistfile = xCAT::SvrUtils:: get_pkglist_file_name ( "$::XCATROOT/share/xcat/install/$pltfrm" ,
$ ref - > { 'profile' } , $ ref - > { 'osvers' } , $ ref - > { 'osarch' } , $ ref - > { 'osvers' } ) ;
}
# if we managed to find it, put it in the hash:
if ( $ pkglistfile ) {
$ img_hash { $ imagename } - > { pkglist } = $ pkglistfile ;
}
}
}
else {
$ callback - > (
{ error = > [ "The os image $imagename does not exists on the osimage table for $node" ] ,
errorcode = > [ 1 ] } ) ;
next ;
}
}
my $ ph = $ img_hash { $ imagename } ;
$ os = $ ph - > { osver } ;
$ arch = $ ph - > { osarch } ;
$ profile = $ ph - > { profile } ;
$ platform = xCAT_plugin::debian:: getplatform ( $ os ) ;
2011-03-02 09:50:17 +00:00
2012-08-09 08:49:43 +00:00
$ tmplfile = $ ph - > { template } ;
2011-03-02 09:50:17 +00:00
$ pkgdir = $ ph - > { pkgdir } ;
2012-08-09 08:49:43 +00:00
if ( ! $ pkgdir ) {
$ pkgdir = "$installroot/$os/$arch" ;
}
$ pkglistfile = $ ph - > { pkglist } ;
2011-03-02 09:50:17 +00:00
}
2012-08-09 08:49:43 +00:00
else {
$ os = $ ent - > { os } ;
$ arch = $ ent - > { arch } ;
$ profile = $ ent - > { profile } ;
$ platform = xCAT_plugin::debian:: getplatform ( $ os ) ;
my $ genos = $ os ;
$ genos =~ s/\..*// ;
2011-03-02 09:50:17 +00:00
2012-08-09 08:49:43 +00:00
$ tmplfile = xCAT::SvrUtils:: get_tmpl_file_name ( "$installroot/custom/install/$platform" , $ profile , $ os , $ arch , $ genos ) ;
if ( ! $ tmplfile ) {
$ tmplfile = xCAT::SvrUtils:: get_tmpl_file_name ( "$::XCATROOT/share/xcat/install/$platform" , $ profile , $ os , $ arch , $ genos ) ;
}
2011-03-02 09:50:17 +00:00
2012-08-09 08:49:43 +00:00
$ pkglistfile = xCAT::SvrUtils:: get_pkglist_file_name ( "$installroot/custom/install/$platform" , $ profile , $ os , $ arch , $ genos ) ;
if ( ! $ pkglistfile ) {
$ pkglistfile = xCAT::SvrUtils:: get_pkglist_file_name ( "$::XCATROOT/share/xcat/install/$platform" , $ profile , $ os , $ arch , $ genos ) ;
}
2011-09-26 13:34:20 +00:00
2012-08-09 08:49:43 +00:00
$ pkgdir = "$installroot/$os/$arch" ;
}
2011-03-02 09:50:17 +00:00
2011-08-16 22:27:05 +00:00
if ( $ arch eq "x86_64" ) {
2011-03-02 09:50:17 +00:00
$ darch = "amd64" ;
2012-08-09 08:49:43 +00:00
}
elsif ( $ arch eq "x86" ) {
2011-03-02 09:50:17 +00:00
$ darch = "i386" ;
2012-08-09 08:49:43 +00:00
}
else {
2011-03-02 09:50:17 +00:00
xCAT::MsgUtils - > message ( "S" , "debian.pm: Unknown arch ($arch)" ) ;
$ darch = $ arch ;
}
my @ missingparms ;
unless ( $ os ) {
2012-08-09 08:49:43 +00:00
if ( $ imagename ) {
push @ missingparms , "osimage.osvers" ;
}
else {
push @ missingparms , "nodetype.os" ;
}
2011-03-02 09:50:17 +00:00
}
2012-08-09 08:49:43 +00:00
2011-03-02 09:50:17 +00:00
unless ( $ arch ) {
2012-08-09 08:49:43 +00:00
if ( $ imagename ) {
push @ missingparms , "osimage.osarch" ;
}
else {
push @ missingparms , "nodetype.arch" ;
}
2011-03-02 09:50:17 +00:00
}
unless ( $ profile ) {
2012-08-09 08:49:43 +00:00
if ( $ imagename ) {
push @ missingparms , "osimage.profile" ;
}
else {
push @ missingparms , "nodetype.profile" ;
}
2011-03-02 09:50:17 +00:00
}
2012-08-09 08:49:43 +00:00
unless ( $ os and $ arch and $ profile ) {
$ callback - > ( { error = > [ "Missing " . join ( ',' , @ missingparms ) . " for $node" ] ,
errorcode = > [ 1 ] } ) ;
2011-03-02 09:50:17 +00:00
next ; #No profile
}
2012-08-09 08:49:43 +00:00
unless ( - r "$tmplfile" ) {
$ callback - > ( { error = > [ "No $platform preseed template exists for " . $ profile ] ,
errorcode = > [ 1 ] } ) ;
2011-03-02 09:50:17 +00:00
next ;
}
#Call the Template class to do substitution to produce a preseed file in the autoinst dir
my $ tmperr ;
my $ preerr ;
my $ posterr ;
2012-08-09 08:49:43 +00:00
if ( $ imagename ) {
$ tmperr = "Unable to find template file: $tmplfile" ;
} else {
$ tmperr = "Unable to find template in $installroot/custom/install/$platform or $::XCATROOT/share/xcat/install/$platform (for $profile/$os/$arch combination)" ;
}
if ( - r "$tmplfile" ) {
2011-03-02 09:50:17 +00:00
$ tmperr =
2012-08-09 08:49:43 +00:00
xCAT::Template - > subvars (
$ tmplfile ,
"$installroot/autoinst/" . $ node ,
$ node ,
$ pkglistfile ,
"" ,
$ platform
) ;
2011-03-02 09:50:17 +00:00
}
2012-08-09 08:49:43 +00:00
my $ prescript = "$::XCATROOT/share/xcat/install/scripts/pre.$platform" ;
my $ postscript = "$::XCATROOT/share/xcat/install/scripts/post.$platform" ;
2011-03-02 09:50:17 +00:00
2012-08-09 08:49:43 +00:00
if ( - r "$prescript" ) {
2011-03-02 09:50:17 +00:00
$ preerr =
xCAT::Template - > subvars (
2012-08-09 08:49:43 +00:00
$ prescript ,
"$installroot/autoinst/" . $ node . ".pre" ,
$ node
) ;
}
if ( - r "$postscript" ) {
2011-03-02 09:50:17 +00:00
$ posterr =
xCAT::Template - > subvars (
2012-08-09 08:49:43 +00:00
$ postscript ,
"$installroot/autoinst/" . $ node . ".post" ,
$ node
) ;
2011-03-02 09:50:17 +00:00
}
my $ errtmp ;
2012-08-09 08:49:43 +00:00
if ( $ errtmp = $ tmperr or $ errtmp = $ preerr or $ errtmp = $ posterr ) {
$ callback - > ( { node = > [ { name = > [ $ node ] , error = > [ $ errtmp ] , errorcode = > [ 1 ] } ] } ) ;
2011-03-02 09:50:17 +00:00
next ;
}
my $ tftpdir = "/tftpboot" ;
# create the node-specific post scripts
#mkpath "$installroot/postscripts/";
#xCAT::Postage->writescript($node,"$installroot/postscripts/".$node, "install", $callback);
my $ kernpath ;
my $ initrdpath ;
my $ maxmem ;
if (
(
2012-08-09 08:49:43 +00:00
$ arch =~ /x86/ and
(
( - r "$pkgdir/install/netboot/ubuntu-installer/$darch/linux"
and $ kernpath = "$pkgdir/install/netboot/ubuntu-installer/$darch/linux"
and - r "$pkgdir/install/netboot/ubuntu-installer/$darch/initrd.gz"
and $ initrdpath = "$pkgdir/install/netboot/ubuntu-installer/$darch/initrd.gz"
2011-03-02 09:50:17 +00:00
) or
2012-08-09 08:49:43 +00:00
( - r "$pkgdir/install/netboot/vmlinuz"
and $ kernpath = "$pkgdir/install/netboot/vmlinuz"
and - r "$pkgdir/install/netboot/initrd.gz"
and $ initrdpath = "$pkgdir/install/netboot/initrd.gz"
)
)
)
) {
2011-03-02 09:50:17 +00:00
#TODO: driver slipstream, targetted for network.
unless ( $ doneimgs { "$os|$arch" } )
{
mkpath ( "/tftpboot/xcat/$os/$arch" ) ;
copy ( $ kernpath , "$tftpdir/xcat/$os/$arch/vmlinuz" ) ;
copy ( $ initrdpath , "$tftpdir/xcat/$os/$arch/initrd.img" ) ;
$ doneimgs { "$os|$arch" } = 1 ;
}
#We have a shot...
my $ ent = $ rents { $ node } - > [ 0 ] ;
2012-08-09 08:49:43 +00:00
# $restab->getNodeAttribs($node,
2011-03-02 09:50:17 +00:00
# ['nfsserver', 'primarynic', 'installnic']);
my $ sent = $ hents { $ node } - > [ 0 ] ;
2012-08-09 08:49:43 +00:00
# $hmtab->getNodeAttribs(
2011-03-02 09:50:17 +00:00
# $node,
# [
# 'serialport', 'serialspeed', 'serialflow'
# ]
# );
unless ( $ ent and $ ent - > { nfsserver } )
{
2012-08-09 08:49:43 +00:00
$ callback - > ( { error = > [ "No noderes.nfsserver defined for " . $ node ] ,
errorcode = > [ 1 ] } ) ;
2011-03-02 09:50:17 +00:00
next ;
}
2012-08-09 08:49:43 +00:00
#if ($platform eq "ubuntu"){
2011-03-02 09:50:17 +00:00
# my $kcmdline =
# "nofb utf8 auto url=http://"
# . $ent->{nfsserver}
# . "$installroot/autoinst/"
# . $node;
#} else
#{
2012-08-09 08:49:43 +00:00
my $ kcmdline = "nofb utf8 auto url=http://"
2011-03-02 09:50:17 +00:00
. $ ent - > { nfsserver }
. "$installroot/autoinst/"
. $ node ;
#}
if ( $ maxmem ) {
$ kcmdline . = " mem=$maxmem" ;
}
my $ ksdev = "" ;
2012-08-09 08:49:43 +00:00
if ( $ ent - > { installnic } ) {
if ( $ ent - > { installnic } eq "mac" ) {
2011-03-02 09:50:17 +00:00
my $ mactab = xCAT::Table - > new ( "mac" ) ;
my $ macref = $ mactab - > getNodeAttribs ( $ node , [ 'mac' ] ) ;
$ ksdev = $ macref - > { mac } ;
}
2012-08-09 08:49:43 +00:00
else {
2011-03-02 09:50:17 +00:00
$ ksdev = $ ent - > { installnic } ;
}
}
2012-08-09 08:49:43 +00:00
elsif ( $ ent - > { primarynic } ) {
if ( $ ent - > { primarynic } eq "mac" ) {
2011-03-02 09:50:17 +00:00
my $ mactab = xCAT::Table - > new ( "mac" ) ;
my $ macref = $ mactab - > getNodeAttribs ( $ node , [ 'mac' ] ) ;
$ ksdev = $ macref - > { mac } ;
}
2012-08-09 08:49:43 +00:00
else {
2011-03-02 09:50:17 +00:00
$ ksdev = $ ent - > { primarynic } ;
}
}
2012-08-09 08:49:43 +00:00
else {
2011-03-02 09:50:17 +00:00
$ ksdev = "eth0" ;
}
2012-08-09 08:49:43 +00:00
if ( $ ksdev eq "" ) {
$ callback - > ( { error = > [ "No MAC address defined for " . $ node ] ,
errorcode = > [ 1 ] } ) ;
}
$ kcmdline . = " netcfg/choose_interface=" . $ ksdev ;
2011-03-02 09:50:17 +00:00
#TODO: dd=<url> for driver disks
2012-08-09 08:49:43 +00:00
if ( defined ( $ sent - > { serialport } ) ) {
unless ( $ sent - > { serialspeed } ) {
$ callback - > ( { error = > [ "serialport defined, but no serialspeed for $node in nodehm table" ] ,
errorcode = > [ 1 ] } ) ;
2011-03-02 09:50:17 +00:00
next ;
}
2012-08-09 08:49:43 +00:00
$ kcmdline . = " console=tty0 console=ttyS"
. $ sent - > { serialport } . "," . $ sent - > { serialspeed } ;
if ( $ sent - > { serialflow } =~ /(hard|cts|ctsrts)/ ) {
2011-03-02 09:50:17 +00:00
$ kcmdline . = "n8r" ;
}
}
$ kcmdline . = " noipv6" ;
# add the addkcmdline attribute to the end
# of the command, if it exists
#my $addkcmd = $addkcmdhash->{$node}->[0];
# add the extra addkcmd command info, if in the table
#if ($addkcmd->{'addkcmdline'}) {
# $kcmdline .= " ";
# $kcmdline .= $addkcmd->{'addkcmdline'};
#}
# need to add these in, otherwise aptitude will ask questions
2012-08-09 08:49:43 +00:00
$ kcmdline . = " locale=en_US console-setup/layoutcode=us" ;
#$kcmdline .= " netcfg/wireless_wep= netcfg/get_hostname= netcfg/get_domain=";
2011-03-02 09:50:17 +00:00
# default answers as much as possible, we don't want any interactiveness :)
2012-08-09 08:49:43 +00:00
$ kcmdline . = " priority=critical" ;
2011-03-02 09:50:17 +00:00
# Automatically detect all HDD
2012-08-09 08:49:43 +00:00
#$kcmdline .= " all-generic-ide irqpoll";
2011-03-02 09:50:17 +00:00
2012-08-09 08:49:43 +00:00
# by default do text based install
#$kcmdline .= " DEBIAN_FRONTEND=text";
2011-03-02 09:50:17 +00:00
2012-08-09 08:49:43 +00:00
# Maybe useful for debugging purposes
#
#$kcmdline .= " BOOT_DEBUG=3";
#$kcmdline .= " DEBCONF_DEBUG=5";
2011-03-02 09:50:17 +00:00
2012-08-09 08:49:43 +00:00
# I don't need the timeout for ubuntu, but for debian there is a problem with getting dhcp in a timely manner
$ kcmdline . = " netcfg/dhcp_timeout=120" ;
2011-03-02 09:50:17 +00:00
2012-08-09 08:49:43 +00:00
# safer way to set hostname, avoid problems with nameservers
$ kcmdline . = " hostname=" . $ node ;
2011-08-13 18:02:24 +00:00
2011-03-02 09:50:17 +00:00
$ bptab - > setNodeAttribs (
$ node ,
{
kernel = > "xcat/$os/$arch/vmlinuz" ,
initrd = > "xcat/$os/$arch/initrd.img" ,
kcmdline = > $ kcmdline
}
) ;
}
2012-08-09 08:49:43 +00:00
else {
$ callback - > ( { error = > [ "Install image not found in $installroot/$os/$arch" ] ,
errorcode = > [ 1 ] } ) ;
2011-03-02 09:50:17 +00:00
}
}
2012-08-09 04:07:40 +00:00
#my $rc = xCAT::TableUtils->create_postscripts_tar();
2011-03-02 09:50:17 +00:00
#if ($rc != 0)
#{
# xCAT::MsgUtils->message("S", "Error creating postscripts tar file.");
#}
}
sub mknetboot
{
my $ xenstyle = 0 ;
my $ req = shift ;
my $ callback = shift ;
my $ doreq = shift ;
my $ statelite = 0 ;
if ( $ req - > { command } - > [ 0 ] =~ 'mkstatelite' ) {
$ statelite = "true" ;
}
my $ tftpdir = "/tftpboot" ;
my $ nodes = @ { $ req - > { node } } ;
my @ args = @ { $ req - > { arg } } ;
my @ nodes = @ { $ req - > { node } } ;
my $ ostab = xCAT::Table - > new ( 'nodetype' ) ;
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
my $ linuximagetab ;
my $ osimagetab ;
my % img_hash = ( ) ;
my $ installroot ;
$ installroot = "/install" ;
my $ xcatdport = "3001" ;
if ( $ sitetab )
{
( my $ ref ) = $ sitetab - > getAttribs ( { key = > 'installdir' } , 'value' ) ;
if ( $ ref and $ ref - > { value } )
{
$ installroot = $ ref - > { value } ;
}
( $ ref ) = $ sitetab - > getAttribs ( { key = > 'xcatdport' } , 'value' ) ;
if ( $ ref and $ ref - > { value } )
{
$ xcatdport = $ ref - > { value } ;
}
2012-04-29 22:42:59 +00:00
( $ ref ) = $ sitetab - > getAttribs ( { key = > 'tftpdir' } , 'value' ) ;
if ( $ ref and $ ref - > { value } )
{
$ globaltftpdir = $ ref - > { value } ;
}
2011-03-02 09:50:17 +00:00
}
my % donetftp = ( ) ;
my % oents = % { $ ostab - > getNodesAttribs ( \ @ nodes , [ qw( os arch profile provmethod ) ] ) } ;
my $ restab = xCAT::Table - > new ( 'noderes' ) ;
my $ bptab = xCAT::Table - > new ( 'bootparams' , - create = > 1 ) ;
my $ hmtab = xCAT::Table - > new ( 'nodehm' ) ;
2012-04-29 22:42:59 +00:00
my $ mactab = xCAT::Table - > new ( 'mac' ) ;
my $ machash = $ mactab - > getNodesAttribs ( \ @ nodes , [ 'interface' , 'mac' ] ) ;
my $ reshash = $ restab - > getNodesAttribs ( \ @ nodes , [ 'primarynic' , 'tftpserver' , 'xcatmaster' , 'nfsserver' , 'nfsdir' , 'installnic' ] ) ;
2011-03-02 09:50:17 +00:00
my $ hmhash =
$ hmtab - > getNodesAttribs ( \ @ nodes ,
[ 'serialport' , 'serialspeed' , 'serialflow' ] ) ;
my $ statetab ;
my $ stateHash ;
if ( $ statelite ) {
$ statetab = xCAT::Table - > new ( 'statelite' , - create = > 1 ) ;
$ stateHash = $ statetab - > getNodesAttribs ( \ @ nodes , [ 'statemnt' ] ) ;
}
#my $addkcmdhash =
# $bptab->getNodesAttribs(\@nodes, ['addkcmdline']);
foreach my $ node ( @ nodes )
{
my $ osver ;
my $ arch ;
my $ profile ;
my $ platform ;
my $ rootimgdir ;
2012-04-29 22:42:59 +00:00
my $ nodebootif ; # nodebootif will be used if noderes.installnic is not set
my $ dump ; # for kdump, its format is "nfs://<nfs_server_ip>/<kdump_path>"
my $ crashkernelsize ;
my $ rootfstype ;
my $ tftpdir ;
if ( $ reshash - > { $ node } - > [ 0 ] and $ reshash - > { $ node } - > [ 0 ] - > { tftpdir } ) {
$ tftpdir = $ reshash - > { $ node } - > [ 0 ] - > { tftpdir } ;
} else {
$ tftpdir = $ globaltftpdir ;
}
2011-03-02 09:50:17 +00:00
my $ ent = $ oents { $ node } - > [ 0 ] ; #ostab->getNodeAttribs($node, ['os', 'arch', 'profile']);
if ( $ ent and $ ent - > { provmethod } and ( $ ent - > { provmethod } ne 'install' ) and ( $ ent - > { provmethod } ne 'netboot' ) and ( $ ent - > { provmethod } ne 'statelite' ) ) {
my $ imagename = $ ent - > { provmethod } ;
#print "imagename=$imagename\n";
if ( ! exists ( $ img_hash { $ imagename } ) ) {
if ( ! $ osimagetab ) {
$ osimagetab = xCAT::Table - > new ( 'osimage' , - create = > 1 ) ;
}
2012-04-29 22:42:59 +00:00
( my $ ref ) = $ osimagetab - > getAttribs ( { imagename = > $ imagename } , 'osvers' , 'osarch' , 'profile' , 'provmethod' , 'rootfstype' ) ;
2011-03-02 09:50:17 +00:00
if ( $ ref ) {
$ img_hash { $ imagename } - > { osver } = $ ref - > { 'osvers' } ;
$ img_hash { $ imagename } - > { osarch } = $ ref - > { 'osarch' } ;
$ img_hash { $ imagename } - > { profile } = $ ref - > { 'profile' } ;
$ img_hash { $ imagename } - > { provmethod } = $ ref - > { 'provmethod' } ;
2012-04-29 22:42:59 +00:00
$ img_hash { $ imagename } - > { rootfstype } = $ ref - > { 'rootfstype' } ;
2011-03-02 09:50:17 +00:00
if ( ! $ linuximagetab ) {
$ linuximagetab = xCAT::Table - > new ( 'linuximage' , - create = > 1 ) ;
}
( my $ ref1 ) = $ linuximagetab - > getAttribs ( { imagename = > $ imagename } , 'rootimgdir' ) ;
if ( ( $ ref1 ) && ( $ ref1 - > { 'rootimgdir' } ) ) {
$ img_hash { $ imagename } - > { rootimgdir } = $ ref1 - > { 'rootimgdir' } ;
}
2012-04-29 22:42:59 +00:00
if ( ( $ ref1 ) && ( $ ref1 - > { 'nodebootif' } ) ) {
$ img_hash { $ imagename } - > { nodebootif } = $ ref1 - > { 'nodebootif' } ;
}
if ( $ ref1 ) {
if ( $ ref1 - > { 'dump' } ) {
$ img_hash { $ imagename } - > { dump } = $ ref1 - > { 'dump' } ;
}
}
if ( ( $ ref1 ) && ( $ ref1 - > { 'crashkernelsize' } ) ) {
$ img_hash { $ imagename } - > { crashkernelsize } = $ ref1 - > { 'crashkernelsize' } ;
}
2011-03-02 09:50:17 +00:00
} else {
$ callback - > (
{ error = > [ "The os image $imagename does not exists on the osimage table for $node" ] ,
errorcode = > [ 1 ] } ) ;
next ;
}
}
my $ ph = $ img_hash { $ imagename } ;
$ osver = $ ph - > { osver } ;
$ arch = $ ph - > { osarch } ;
$ profile = $ ph - > { profile } ;
2012-04-29 22:42:59 +00:00
$ rootfstype = $ ph - > { rootfstype } ;
2011-03-02 09:50:17 +00:00
$ rootimgdir = $ ph - > { rootimgdir } ;
2012-04-29 22:42:59 +00:00
unless ( $ rootimgdir ) {
2011-03-02 09:50:17 +00:00
$ rootimgdir = "$installroot/netboot/$osver/$arch/$profile" ;
}
2012-04-29 22:42:59 +00:00
$ nodebootif = $ ph - > { nodebootif } ;
$ crashkernelsize = $ ph - > { crashkernelsize } ;
$ dump = $ ph - > { dump } ;
2011-03-02 09:50:17 +00:00
}
else {
$ osver = $ ent - > { os } ;
$ arch = $ ent - > { arch } ;
$ profile = $ ent - > { profile } ;
$ rootimgdir = "$installroot/netboot/$osver/$arch/$profile" ;
2012-04-29 22:42:59 +00:00
$ rootfstype = "nfs" ; # TODO: try to get it from the option or table
my $ imgname ;
if ( $ statelite ) {
$ imgname = "$osver-$arch-statelite-$profile" ;
} else {
$ imgname = "$osver-$arch-netboot-$profile" ;
}
if ( ! $ osimagetab ) {
$ osimagetab = xCAT::Table - > new ( 'osimage' ) ;
}
if ( $ osimagetab ) {
my ( $ ref1 ) = $ osimagetab - > getAttribs ( { imagename = > $ imgname } , 'rootfstype' ) ;
if ( ( $ ref1 ) && ( $ ref1 - > { 'rootfstype' } ) ) {
$ rootfstype = $ ref1 - > { 'rootfstype' } ;
}
} else {
$ callback - > (
{ error = > [ qq{ Cannot find the linux image called "$osver-$arch-$imgname-$profile", maybe you need to use the "nodeset <nr> osimage=<osimage name>" command to set the boot state } ] ,
errorcode = > [ 1 ] }
) ;
}
if ( ! $ linuximagetab ) {
$ linuximagetab = xCAT::Table - > new ( 'linuximage' ) ;
}
if ( $ linuximagetab ) {
( my $ ref1 ) = $ linuximagetab - > getAttribs ( { imagename = > $ imgname } , 'dump' , 'crashkernelsize' ) ;
if ( $ ref1 and $ ref1 - > { 'dump' } ) {
$ dump = $ ref1 - > { 'dump' } ;
}
if ( $ ref1 and $ ref1 - > { 'crashkernelsize' } ) {
$ crashkernelsize = $ ref1 - > { 'crashkernelsize' } ;
}
} else {
$ callback - > (
{ error = > [ qq{ Cannot find the linux image called "$osver-$arch-$imgname-$profile", maybe you need to use the "nodeset <nr> osimage=<your_image_name>" command to set the boot state } ] ,
errorcode = > [ 1 ] }
) ;
}
}
2011-03-02 09:50:17 +00:00
#print"osvr=$osver, arch=$arch, profile=$profile, imgdir=$rootimgdir\n";
unless ( $ osver and $ arch and $ profile )
{
$ callback - > (
{
error = > [ "Insufficient nodetype entry or osimage entry for $node" ] ,
errorcode = > [ 1 ]
}
) ;
next ;
}
$ platform = xCAT_plugin::debian:: getplatform ( $ osver ) ;
my $ suffix = 'gz' ;
2012-04-29 22:42:59 +00:00
$ suffix = 'sfs' if ( - r "$rootimgdir/rootimg.sfs" ) ;
# statelite images are not packed.
if ( $ statelite ) {
unless ( - r "$rootimgdir/kernel" ) {
$ callback - > ( {
error = > [ qq{ Did you run "genimage" before running "liteimg"? kernel cannot be found... } ] ,
errorcode = > [ 1 ]
} ) ;
next ;
}
if ( ! - r "$rootimgdir/initrd-statelite.gz" ) {
if ( ! - r "$rootimgdir/initrd.gz" ) {
$ callback - > ( {
error = > [ qq{ Did you run "genimage" before running "liteimg"? initrd.gz or initrd-statelite.gz cannot be found } ] ,
errorcode = > [ 1 ]
} ) ;
next ;
}
else {
copy ( "$rootimgdir/initrd.gz" , "$rootimgdir/initrd-statelite.gz" ) ;
}
}
if ( $ rootfstype eq "ramdisk" and ! - r "$rootimgdir/rootimg-statelite.gz" ) {
$ callback - > ( {
error = > [ qq{ No packed image for platform $osver, architecture $arch and profile $profile, please run "liteimg" to create it. } ] ,
errorcode = > [ 1 ]
} ) ;
next ;
}
} else {
unless ( - r "$rootimgdir/kernel" ) {
$ callback - > ( {
error = > [ qq{ Did you run "genimage" before running "packimage"? kernel cannot be found } ] ,
errorcode = > [ 1 ]
} ) ;
next ;
}
if ( ! - r "$rootimgdir/initrd-stateless.gz" ) {
if ( ! - r "$rootimgdir/initrd.gz" ) {
$ callback - > ( {
error = > [ qq{ Did you run "genimage" before running "packimage"? initrd.gz or initrd-stateless.gz cannot be found } ] ,
errorcode = > [ 1 ]
} ) ;
next ;
}
else {
copy ( "$rootimgdir/initrd.gz" , "$rootimgdir/initrd-stateless.gz" ) ;
}
}
unless ( - r "$rootimgdir/rootimg.gz" or - r "$rootimgdir/rootimg.sfs" ) {
$ callback - > ( {
error = > [ "No packed image for platform $osver, architecture $arch, and profile $profile, please run packimage (e.g. packimage -o $osver -p $profile -a $arch" ] ,
errorcode = > [ 1 ] } ) ;
next ;
}
2011-03-02 09:50:17 +00:00
}
# create the node-specific post scripts
#mkpath "/install/postscripts/";
#xCAT::Postage->writescript($node,"/install/postscripts/".$node, "netboot", $callback);
2012-04-29 22:42:59 +00:00
mkpath ( "$tftpdir/xcat/netboot/$osver/$arch/$profile/" ) ;
2011-03-02 09:50:17 +00:00
#TODO: only copy if newer...
unless ( $ donetftp { $ osver , $ arch , $ profile } ) {
2012-04-29 22:42:59 +00:00
if ( - f "$rootimgdir/hypervisor" ) {
2011-03-02 09:50:17 +00:00
copy ( "$rootimgdir/hypervisor" ,
2012-04-29 22:42:59 +00:00
"$tftpdir/xcat/netboot/$osver/$arch/$profile/" ) ;
2011-03-02 09:50:17 +00:00
$ xenstyle = 1 ;
2012-04-29 22:42:59 +00:00
}
copy ( "$rootimgdir/kernel" ,
"$tftpdir/xcat/netboot/$osver/$arch/$profile/" ) ;
if ( $ statelite ) {
if ( $ rootfstype eq "ramdisk" ) {
copy ( "$rootimgdir/initrd-stateless.gz" ,
"$tftpdir/xcat/netboot/$osver/$arch/$profile/" ) ;
} else {
copy ( "$rootimgdir/initrd-statelite.gz" ,
"$tftpdir/xcat/netboot/$osver/$arch/$profile/" ) ;
}
} else {
copy ( "$rootimgdir/initrd-stateless.gz" ,
"$tftpdir/xcat/netboot/$osver/$arch/$profile/" ) ;
}
2011-03-02 09:50:17 +00:00
$ donetftp { $ osver , $ arch , $ profile } = 1 ;
}
2012-04-29 22:42:59 +00:00
if ( $ statelite ) {
my $ initrdloc = "$tftpdir/xcat/netboot/$osver/$arch/$profile/" ;
if ( $ rootfstype eq "ramdisk" ) {
$ initrdloc . = "initrd-stateless.gz" ;
} else {
$ initrdloc . = "initrd-statelite.gz" ;
}
unless ( - r "$tftpdir/xcat/netboot/$osver/$arch/$profile/kernel"
and - r $ initrdloc ) {
$ callback - > ( {
error = > [ qq{ copying to $tftpdir/xcat/netboot/$osver/$arch/$profile failed } ] ,
errorcode = > [ 1 ]
} ) ;
next ;
}
} else {
unless ( - r "$tftpdir/xcat/netboot/$osver/$arch/$profile/kernel"
and - r "$tftpdir/xcat/netboot/$osver/$arch/$profile/initrd-stateless.gz" )
{
2011-03-02 09:50:17 +00:00
$ callback - > (
{
error = > [
2012-04-29 22:42:59 +00:00
"Copying to $tftpdir/xcat/netboot/$osver/$arch/$profile failed"
2011-03-02 09:50:17 +00:00
] ,
errorcode = > [ 1 ]
}
) ;
next ;
2012-04-29 22:42:59 +00:00
}
2011-03-02 09:50:17 +00:00
}
my $ ent = $ reshash - > { $ node } - > [ 0 ] ; #$restab->getNodeAttribs($node, ['primarynic']);
my $ sent = $ hmhash - > { $ node } - > [ 0 ] ;
# $hmtab->getNodeAttribs($node,
# ['serialport', 'serialspeed', 'serialflow']);
# determine image server, if tftpserver use it, else use xcatmaster
# last resort use self
my $ imgsrv ;
my $ ient ;
my $ xcatmaster ;
$ ient = $ reshash - > { $ node } - > [ 0 ] ; #$restab->getNodeAttribs($node, ['tftpserver']);
if ( $ ient and $ ient - > { xcatmaster } )
{
$ xcatmaster = $ ient - > { xcatmaster } ;
} else {
$ xcatmaster = '!myipfn!' ; #allow service nodes to dynamically nominate themselves as a good contact point, this is of limited use in the event that xcat is not the dhcp/tftp server
}
if ( $ ient and $ ient - > { tftpserver } )
{
$ imgsrv = $ ient - > { tftpserver } ;
}
else
{
$ ient = $ reshash - > { $ node } - > [ 0 ] ; #$restab->getNodeAttribs($node, ['xcatmaster']);
#if ($ient and $ient->{xcatmaster})
#{
# $imgsrv = $ient->{xcatmaster};
#}
#else
#{
# master not correct for service node pools
#$ient = $sitetab->getAttribs({key => master}, value);
#if ($ient and $ient->{value})
#{
# $imgsrv = $ient->{value};
#}
#else
#{
# $imgsrv = '!myipfn!';
#}
#}
$ imgsrv = $ xcatmaster ;
}
unless ( $ imgsrv )
{
$ callback - > (
{
error = > [
"Unable to determine or reasonably guess the image server for $node"
] ,
errorcode = > [ 1 ]
}
) ;
next ;
}
my $ kcmdline ;
2012-04-29 22:42:59 +00:00
if ( $ statelite ) {
if ( rootfstype ne "ramdisk" ) {
2011-03-02 09:50:17 +00:00
# get entry for nfs root if it exists:
# have to get nfssvr and nfsdir from noderes table
my $ nfssrv = $ imgsrv ;
my $ nfsdir = $ rootimgdir ;
if ( $ ient - > { nfsserver } ) {
$ nfssrv = $ ient - > { nfsserver } ;
}
if ( $ ient - > { nfsdir } ne '' ) {
$ nfsdir = $ ient - > { nfsdir } . "/netboot/$osver/$arch/$profile" ;
#this code sez, "if nfsdir starts with //, then
#use a absolute path, i.e. do not append xCATisms"
#this is required for some statelite envs.
#still open for debate.
if ( $ ient - > { nfsdir } =~ m !^//! ) {
$ nfsdir = $ ient - > { nfsdir } ;
$ nfsdir =~ s!^/!! ;
}
}
2012-04-29 22:42:59 +00:00
# special case for redhat6, fedora12/13/14
if ( & using_dracut ( $ osver ) ) {
$ kcmdline = "root=nfs:$nfssrv:$nfsdir/rootimg:ro STATEMNT=" ;
} else {
$ kcmdline = "NFSROOT=$nfssrv:$nfsdir STATEMNT=" ;
}
} else {
$ kcmdline = "imgurl=http://$imgsrv/$rootimgdir/rootimg-statelite.gz STATEMNT=" ;
}
2011-03-02 09:50:17 +00:00
# add support for subVars in the value of "statemnt"
my $ statemnt = "" ;
if ( exists ( $ stateHash - > { $ node } ) ) {
$ statemnt = $ stateHash - > { $ node } - > [ 0 ] - > { statemnt } ;
if ( grep /\$/ , $ statemnt ) {
my ( $ server , $ dir ) = split ( /:/ , $ statemnt ) ;
#if server is blank, then its the directory
unless ( $ dir ) {
$ dir = $ server ;
$ server = '' ;
}
if ( grep /\$|#CMD/ , $ dir ) {
2012-04-29 22:42:59 +00:00
$ dir = xCAT::SvrUtils - > subVars ( $ dir , $ node , 'dir' , $ callback ) ;
2011-03-02 09:50:17 +00:00
$ dir = ~ s/\/\//\//g ;
}
if ( $ server ) {
2012-04-29 22:42:59 +00:00
$ server = xCAT::SvrUtils - > subVars ( $ server , $ node , 'server' , $ callback ) ;
2011-03-02 09:50:17 +00:00
}
$ statemnt = $ server . ":" . $ dir ;
}
}
$ kcmdline . = $ statemnt . " " ;
$ kcmdline . =
"XCAT=$xcatmaster:$xcatdport " ;
# BEGIN service node
my $ isSV = xCAT::Utils - > isServiceNode ( ) ;
my $ res = xCAT::Utils - > runcmd ( "hostname" , 0 ) ;
my $ sip = inet_ntoa ( inet_aton ( $ res ) ) ; # this is the IP of service node
if ( $ isSV and ( ( $ xcatmaster eq $ sip ) or ( $ xcatmaster eq $ res ) ) ) {
# if the NFS directory in litetree is on the service node,
# and it is not exported, then it will be mounted automatically
2012-04-29 22:42:59 +00:00
xCAT::SvrUtils - > setupNFSTree ( $ node , $ sip , $ callback ) ;
2011-03-02 09:50:17 +00:00
# then, export the statemnt directory if it is on the service node
if ( $ statemnt ) {
2012-04-29 22:42:59 +00:00
xCAT::SvrUtils - > setupStatemnt ( $ sip , $ statemnt , $ callback ) ;
2011-03-02 09:50:17 +00:00
}
}
# END service node
}
else
{
$ kcmdline =
2011-07-28 10:21:12 +00:00
"imgurl=http://$imgsrv/$rootimgdir/rootimg.$suffix " ;
2012-04-29 22:42:59 +00:00
$ kcmdline . = "XCAT=$xcatmaster:$xcatdport " ;
}
# add one parameter: ifname=<eth0>:<mac address>
# which is used for dracut
# the redhat5.x os will ignore it
my $ useifname = 0 ;
if ( $ reshash - > { $ node } - > [ 0 ] and $ reshash - > { $ node } - > [ 0 ] - > { installnic } and $ reshash - > { $ node } - > [ 0 ] - > { installnic } ne "mac" ) {
$ useifname = 1 ;
$ kcmdline . = "ifname=" . $ reshash - > { $ node } - > [ 0 ] - > { installnic } . ":" ;
} elsif ( $ nodebootif ) {
$ useifname = 1 ;
$ kcmdline . = "ifname=$nodebootif:" ;
} elsif ( $ reshash - > { $ node } - > [ 0 ] and $ reshash - > { $ node } - > [ 0 ] - > { primarynic } and $ reshash - > { $ node } - > [ 0 ] - > { primarynic } ne "mac" ) {
$ useifname = 1 ;
$ kcmdline . = "ifname=" . $ reshash - > { $ node } - > [ 0 ] - > { primarynic } . ":" ;
2011-03-02 09:50:17 +00:00
}
2012-04-29 22:42:59 +00:00
#else { #no, we autodetect and don't presume anything
# $kcmdline .="eth0:";
# print "eth0 is used as the default booting network devices...\n";
#}
# append the mac address
my $ mac ;
if ( $ useifname && $ machash - > { $ node } - > [ 0 ] && $ machash - > { $ node } - > [ 0 ] - > { 'mac' } ) {
# TODO: currently, only "mac" attribute with classic style is used, the "|" delimited string of "macaddress!hostname" format is not used
$ mac = $ machash - > { $ node } - > [ 0 ] - > { 'mac' } ;
# if ( (index($mac, "|") eq -1) and (index($mac, "!") eq -1) ) {
#convert to linux format
if ( $ mac !~ /:/ ) {
$ mac =~ s/(..)(..)(..)(..)(..)(..)/$1:$2:$3:$4:$5:$6/ ;
}
# } else {
# $callback->({ error=>[ qq{In the "mac" table, the "|" delimited string of "macaddress!hostname" format is not supported by "nodeset <nr> netboot|statelite if installnic/primarynic is set".}], errorcode=>[1]});
# return;
# }
}
if ( $ useifname && $ mac ) {
$ kcmdline . = "$mac " ;
}
# add "netdev=<eth0>" or "BOOTIF=<mac>"
# which are used for other scenarios
my $ netdev = "" ;
if ( $ reshash - > { $ node } - > [ 0 ] and $ reshash - > { $ node } - > [ 0 ] - > { installnic } and $ reshash - > { $ node } - > [ 0 ] - > { installnic } ne "mac" ) {
$ kcmdline . = "netdev=" . $ reshash - > { $ node } - > [ 0 ] - > { installnic } . " " ;
} elsif ( $ nodebootif ) {
$ kcmdline . = "netdev=" . $ nodebootif . " " ;
} elsif ( $ reshash - > { $ node } - > [ 0 ] and $ reshash - > { $ node } - > [ 0 ] - > { primarynic } and $ reshash - > { $ node } - > [ 0 ] - > { primarynic } ne "mac" ) {
$ kcmdline . = "netdev=" . $ reshash - > { $ node } - > [ 0 ] - > { primarynic } . " " ;
} else {
if ( $ useifname && $ mac ) {
$ kcmdline . = "BOOTIF=" . $ mac . " " ;
}
}
my % client_nethash = xCAT::DBobjUtils - > getNetwkInfo ( [ $ node ] ) ;
if ( $ client_nethash { $ node } { mgtifname } =~ /hf/ )
{
$ kcmdline . = "rdloaddriver=hf_if " ;
}
2011-03-02 09:50:17 +00:00
if ( defined $ sent - > { serialport } )
{
#my $sent = $hmtab->getNodeAttribs($node,['serialspeed','serialflow']);
unless ( $ sent - > { serialspeed } )
{
$ callback - > (
{
error = > [
"serialport defined, but no serialspeed for $node in nodehm table"
] ,
errorcode = > [ 1 ]
}
) ;
next ;
}
$ kcmdline . =
"console=tty0 console=ttyS" . $ sent - > { serialport } . "," . $ sent - > { serialspeed } ;
if ( $ sent - > { serialflow } =~ /(hard|tcs|ctsrts)/ )
{
$ kcmdline . = "n8r" ;
}
}
# add the addkcmdline attribute to the end
# of the command, if it exists
#my $addkcmd = $addkcmdhash->{$node}->[0];
# add the extra addkcmd command info, if in the table
#if ($addkcmd->{'addkcmdline'}) {
# $kcmdline .= " ";
# $kcmdline .= $addkcmd->{'addkcmdline'};
#}
my $ kernstr = "xcat/netboot/$osver/$arch/$profile/kernel" ;
if ( $ xenstyle ) {
$ kernstr . = "!xcat/netboot/$osver/$arch/$profile/hypervisor" ;
}
2012-04-29 22:42:59 +00:00
my $ initrdstr = "xcat/netboot/$osver/$arch/$profile/initrd-stateless.gz" ;
$ initrdstr = "xcat/netboot/$osver/$arch/$profile/initrd-statelite.gz" if ( $ statelite ) ;
# special case for the dracut-enabled OSes
if ( & using_dracut ( $ osver ) ) {
if ( $ statelite and $ rootfstype eq "ramdisk" ) {
$ initrdstr = "xcat/netboot/$osver/$arch/$profile/initrd-stateless.gz" ;
}
}
if ( $ statelite )
{
my $ statelitetb = xCAT::Table - > new ( 'statelite' ) ;
my $ mntopts = $ statelitetb - > getNodeAttribs ( $ node , [ 'mntopts' ] ) ;
my $ mntoptions = $ mntopts - > { 'mntopts' } ;
unless ( defined ( $ mntoptions ) )
{
$ kcmdline . = " MNTOPTS=" ;
}
else
{
$ kcmdline . = " MNTOPTS=$mntoptions" ;
}
}
2011-03-02 09:50:17 +00:00
$ bptab - > setNodeAttribs (
$ node ,
{
kernel = > "$kernstr" ,
2012-04-29 22:42:59 +00:00
initrd = > "$initrdstr" ,
2011-03-02 09:50:17 +00:00
kcmdline = > $ kcmdline
}
) ;
}
2012-08-09 04:07:40 +00:00
#my $rc = xCAT::TableUtils->create_postscripts_tar();
2011-03-02 09:50:17 +00:00
#if ( $rc != 0 ) {
# xCAT::MsgUtils->message( "S", "Error creating postscripts tar file." );
#}
}
sub getplatform {
my $ os = shift ;
my $ platform ;
2012-08-09 08:49:43 +00:00
if ( $ os =~ /debian.*/ ) {
$ platform = "debian" ;
2011-03-02 09:50:17 +00:00
}
2012-08-09 08:49:43 +00:00
elsif ( $ os =~ /ubuntu.*/ ) {
$ platform = "ubuntu" ;
2011-03-02 09:50:17 +00:00
}
return $ platform ;
}
# sub subVars
# copied from litetreee.pm
# TODO: need to move the function to xCAT::Utils?
# some directories will have xCAT database values, like:
# $nodetype.os. If that is the case we need to open up
# the database and look at them. We need to make sure
# we do this sparingly... We don't like tons of hits
# to the database.
sub subVars ()
{
my $ dir = shift ;
my $ node = shift ;
my $ type = shift ;
my $ callback = shift ;
# parse all the dollar signs...
# if its a directory then it has a / in it, so you have to parse it.
# if its a server, it won't have one so don't worry about it.
my @ arr = split ( "/" , $ dir ) ;
my $ fdir = "" ;
foreach my $ p ( @ arr ) {
# have to make this geric so $ can be in the midle of the name: asdf$foobar.sitadsf
if ( $ p =~ /\$/ ) {
my $ pre ;
my $ suf ;
my @ fParts ;
if ( $ p =~ /([^\$]*)([^# ]*)(.*)/ ) {
$ pre = $ 1 ;
$ p = $ 2 ;
$ suf = $ 3 ;
}
# have to sub here:
# get rid of the $ sign.
foreach my $ part ( split ( '\$' , $ p ) ) {
if ( $ part eq '' ) { next ; }
#$callback->({error=>["part is $part"],errorcode=>[1]});
# check if p is just the node name:
if ( $ part eq 'node' ) {
# it is so, just return the node.
#$fdir .= "/$pre$node$suf";
push @ fParts , $ node ;
} else {
# ask the xCAT DB what the attribute is.
my ( $ table , $ col ) = split ( '\.' , $ part ) ;
unless ( $ col ) { $ col = 'UNDEFINED' } ;
my $ tab = xCAT::Table - > new ( $ table ) ;
unless ( $ tab ) {
$ callback - > ( { error = > [ "$table does not exist" ] , errorcode = > [ 1 ] } ) ;
return ;
}
my $ ent ;
my $ val ;
if ( $ table eq 'site' ) {
$ val = $ tab - > getAttribs ( { key = > "$col" } , 'value' ) ;
$ val = $ val - > { 'value' } ;
} else {
$ ent = $ tab - > getNodeAttribs ( $ node , [ $ col ] ) ;
$ val = $ ent - > { $ col } ;
}
unless ( $ val ) {
# couldn't find the value!!
$ val = "UNDEFINED"
}
push @ fParts , $ val ;
}
}
my $ val = join ( '.' , @ fParts ) ;
if ( $ type eq 'dir' ) {
$ fdir . = "/$pre$val$suf" ;
} else {
$ fdir . = $ pre . $ val . $ suf ;
}
} else {
# no substitution here
$ fdir . = "/$p" ;
}
}
# now that we've processed variables, process commands
# this isn't quite rock solid. You can't name directories with #'s in them.
if ( $ fdir =~ /#CMD=/ ) {
my $ dir ;
foreach my $ p ( split ( /#/ , $ fdir ) ) {
if ( $ p =~ /CMD=/ ) {
$ p =~ s/CMD=// ;
my $ cmd = $ p ;
#$callback->({info=>[$p]});
$ p = `$p 2>&1` ;
chomp ( $ p ) ;
#$callback->({info=>[$p]});
unless ( $ p ) {
$ p = "#CMD=$p did not return output#" ;
}
}
$ dir . = $ p ;
}
$ fdir = $ dir ;
}
return $ fdir ;
}
sub setupNFSTree {
my $ node = shift ;
my $ sip = shift ;
my $ callback = shift ;
my $ cmd = "litetree $node" ;
my @ uris = xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
foreach my $ uri ( @ uris ) {
# parse the result
# the result looks like "nodename: nfsserver:directory";
$ uri =~ m/\Q$node\E:\s+(.+):(.+)$/ ;
my $ nfsserver = $ 1 ;
my $ nfsdirectory = $ 2 ;
if ( $ nfsserver eq $ sip ) { # on the service node
unless ( - d $ nfsdirectory ) {
if ( - e $ nfsdirectory ) {
unlink $ nfsdirectory ;
}
mkpath $ nfsdirectory ;
}
$ cmd = "showmount -e $nfsserver" ;
my @ entries = xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
shift @ entries ;
if ( grep /\Q$nfsdirectory\E/ , @ entries ) {
$ callback - > ( { data = > [ "$nfsdirectory has been exported already!" ] } ) ;
} else {
$ cmd = "/usr/sbin/exportfs :$nfsdirectory" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
# exportfs can export this directory immediately
$ callback - > ( { data = > [ "now $nfsdirectory is exported!" ] } ) ;
$ cmd = "cat /etc/exports" ;
@ entries = xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
unless ( my $ entry = grep /\Q$nfsdirectory\E/ , @ entries ) {
# if no entry in /etc/exports, one entry with default options will be added
$ cmd = qq{ echo "$nfsdirectory *(rw,no_root_squash,sync,no_subtree_check)" >> /etc/exports } ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
$ callback - > ( { data = > [ "$nfsdirectory is added to /etc/exports with default option" ] } ) ;
}
}
}
}
}
sub setupStatemnt {
my $ sip = shift ;
my $ statemnt = shift ;
my $ callback = shift ;
$ statemnt =~ m/^(.+):(.+)$/ ;
my $ nfsserver = $ 1 ;
my $ nfsdirectory = $ 2 ;
if ( $ sip eq inet_ntoa ( inet_aton ( $ nfsserver ) ) ) {
unless ( - d $ nfsdirectory ) {
if ( - e $ nfsdirectory ) {
unlink $ nfsdirectory ;
}
mkpath $ nfsdirectory ;
}
my $ cmd = "showmount -e $nfsserver" ;
my @ entries = xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
shift @ entries ;
if ( grep /\Q$nfsdirectory\E/ , @ entries ) {
$ callback - > ( { data = > [ "$nfsdirectory has been exported already!" ] } ) ;
} else {
$ cmd = "/usr/sbin/exportfs :$nfsdirectory -o rw,no_root_squash,sync,no_subtree_check" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
$ callback - > ( { data = > [ "now $nfsdirectory is exported!" ] } ) ;
# add the directory into /etc/exports if not exist
$ cmd = "cat /etc/exports" ;
@ entries = xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( my $ entry = grep /\Q$nfsdirectory\E/ , @ entries ) {
unless ( $ entry =~ m/rw/ ) {
$ callback - > ( { data = > [ "The $nfsdirectory should be with rw option in /etc/exports" ] } ) ;
}
} else {
xCAT::Utils - > runcmd ( qq{ echo "$nfsdirectory *(rw,no_root_squash,sync,no_subtree_check)" >> /etc/exports } , 0 ) ;
$ callback - > ( { data = > [ "$nfsdirectory is added into /etc/exports with default options" ] } ) ;
}
}
}
}
1 ;