2007-11-19 21:15:45 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
package xCAT_plugin::yaboot ;
use Data::Dumper ;
use Sys::Syslog ;
2008-02-03 00:01:35 +00:00
use xCAT::Scope ;
2012-08-09 04:07:40 +00:00
use xCAT::Utils ;
use xCAT::TableUtils ;
2013-08-27 16:24:02 +00:00
use xCAT::ServiceNodeUtils ;
2010-05-12 03:09:08 +00:00
use xCAT::NetworkUtils ;
2012-03-16 10:31:33 +00:00
use xCAT::MsgUtils ;
2008-03-04 16:28:06 +00:00
use File::Path ;
2007-11-19 21:15:45 +00:00
use Socket ;
2009-08-03 02:00:13 +00:00
use Getopt::Long ;
2013-04-25 12:15:09 +00:00
use xCAT::Table ;
2007-11-19 21:15:45 +00:00
my $ request ;
2008-07-11 20:57:46 +00:00
my % breaknetbootnodes ;
2013-10-31 14:07:37 +00:00
our % normalnodes ;
2007-11-19 21:15:45 +00:00
my $ callback ;
2007-11-29 16:01:49 +00:00
my $ sub_req ;
2007-11-19 21:15:45 +00:00
my $ dhcpconf = "/etc/dhcpd.conf" ;
2012-08-09 04:07:40 +00:00
my $ globaltftpdir = xCAT::TableUtils - > getTftpDir ( ) ;
2007-11-19 21:15:45 +00:00
#my $dhcpver = 3;
my % usage = (
2012-12-11 20:59:50 +00:00
"nodeset" = > "Usage: nodeset <noderange> [install|shell|boot|runcmd=bmcsetup|netboot|iscsiboot|osimage[=<imagename>]|offline]" ,
2007-11-19 21:15:45 +00:00
) ;
sub handled_commands {
return {
nodeset = > "noderes:netboot"
}
}
sub check_dhcp {
2008-05-15 21:16:33 +00:00
return 1 ;
2007-11-19 21:15:45 +00:00
#TODO: omapi magic to do things right
my $ node = shift ;
my $ dhcpfile ;
open ( $ dhcpfile , $ dhcpconf ) ;
while ( <$dhcpfile> ) {
if ( /host $node\b/ ) {
close $ dhcpfile ;
return 1 ;
}
}
close $ dhcpfile ;
return 0 ;
}
2012-03-29 18:14:03 +00:00
sub _slow_get_tftpdir { #make up for paths where tftpdir is not passed in
2012-03-29 19:12:25 +00:00
my $ node = shift ;
my $ nrtab = xCAT::Table - > new ( 'noderes' , - create = > 0 ) ; #in order to detect per-node tftp directories
2012-03-29 18:14:03 +00:00
unless ( $ nrtab ) { return $ globaltftpdir ; }
my $ ent = $ nrtab - > getNodeAttribs ( $ node , [ "tftpdir" ] ) ;
if ( $ ent and $ ent - > { tftpdir } ) {
return $ ent - > { tftpdir } ;
} else {
return $ globaltftpdir ;
}
}
2007-11-19 21:15:45 +00:00
sub getstate {
my $ node = shift ;
2012-02-15 21:04:42 +00:00
my $ tftpdir = shift ;
2012-03-29 18:14:03 +00:00
unless ( $ tftpdir ) { $ tftpdir = _slow_get_tftpdir ( $ node ) ; }
2007-11-19 21:15:45 +00:00
if ( check_dhcp ( $ node ) ) {
if ( - r $ tftpdir . "/etc/" . $ node ) {
my $ fhand ;
open ( $ fhand , $ tftpdir . "/etc/" . $ node ) ;
my $ headline = <$fhand> ;
close $ fhand ;
$ headline =~ s/^#// ;
chomp ( $ headline ) ;
return $ headline ;
} else {
return "boot" ;
}
} else {
return "discover" ;
}
}
sub setstate {
= pod
This function will manipulate the yaboot structure to match what the noderes / chain tables indicate the node should be booting .
= cut
my $ node = shift ;
2008-07-11 20:57:46 +00:00
my % bphash = % { shift ( ) } ;
my % chainhash = % { shift ( ) } ;
my % machash = % { shift ( ) } ;
2012-02-15 21:04:42 +00:00
my $ tftpdir = shift ;
2012-02-20 07:20:41 +00:00
my % nrhash = % { shift ( ) } ;
2013-04-25 12:15:09 +00:00
my $ linuximghash = shift ( ) ;
2008-07-11 20:57:46 +00:00
my $ kern = $ bphash { $ node } - > [ 0 ] ; #$bptab->getNodeAttribs($node,['kernel','initrd','kcmdline']);
2009-03-18 14:11:30 +00:00
if ( $ kern - > { kcmdline } =~ /!myipfn!/ ) {
2012-08-09 04:07:40 +00:00
my $ ipfn = xCAT::NetworkUtils - > my_ip_facing ( $ node ) ;
2009-03-18 19:37:54 +00:00
unless ( $ ipfn ) {
2012-02-20 07:20:41 +00:00
my $ servicenodes = $ nrhash { $ node } - > [ 0 ] ;
if ( $ servicenodes and $ servicenodes - > { servicenode } ) {
my @ sns = split /,/ , $ servicenodes - > { servicenode } ;
foreach my $ sn ( @ sns ) {
# We are in the service node pools, print error if no facing ip.
if ( xCAT::InstUtils - > is_me ( $ sn ) ) {
2012-08-09 04:07:40 +00:00
my @ myself = xCAT::NetworkUtils - > determinehostname ( ) ;
2012-02-20 07:20:41 +00:00
my $ myname = $ myself [ ( scalar @ myself ) - 1 ] ;
2013-10-09 16:17:42 +00:00
$ ::callback - > (
2012-02-20 07:20:41 +00:00
{
error = > [
"$myname: Unable to determine the image server for $node on service node $sn"
] ,
errorcode = > [ 1 ]
}
) ;
return ;
}
}
} else {
2013-10-09 16:17:42 +00:00
$ ::callback - > (
2012-02-20 07:20:41 +00:00
{
error = > [
"$myname: Unable to determine the image server for $node"
] ,
errorcode = > [ 1 ]
}
) ;
return ;
}
} else {
$ kern - > { kcmdline } =~ s/!myipfn!/$ipfn/g ;
2009-03-18 19:37:54 +00:00
}
2009-03-18 14:11:30 +00:00
}
2009-06-29 18:41:00 +00:00
if ( $ kern - > { addkcmdline } ) {
$ kern - > { kcmdline } . = " " . $ kern - > { addkcmdline } ;
}
2013-04-25 12:15:09 +00:00
if ( $ linuximghash and $ linuximghash - > { 'addkcmdline' } )
{
unless ( $ linuximghash - > { 'boottarget' } )
{
$ kern - > { kcmdline } . = " " . $ linuximghash - > { 'addkcmdline' } ;
}
}
2007-11-19 21:15:45 +00:00
my $ pcfg ;
2008-03-04 16:28:06 +00:00
unless ( - d "$tftpdir/etc" ) {
mkpath ( "$tftpdir/etc" ) ;
}
2012-11-21 07:37:23 +00:00
my $ nodemac ;
2011-05-05 15:41:39 +00:00
my % client_nethash = xCAT::DBobjUtils - > getNetwkInfo ( [ $ node ] ) ;
if ( $ client_nethash { $ node } { mgtifname } =~ /hf/ ) {
my $ mactab = xCAT::Table - > new ( 'mac' ) ;
if ( $ mactab ) {
my $ ment = $ machash { $ node } - > [ 0 ] ; #$mactab->getNodeAttribs($node,['mac']);
if ( $ ment and $ ment - > { mac } ) {
my @ macs = split ( /\|/ , $ ment - > { mac } ) ;
my $ count = 0 ;
foreach my $ mac ( @ macs ) {
if ( $ mac !~ /!(.*)/ ) {
2011-06-30 08:14:24 +00:00
my $ hostname ;
if ( $ node !~ /^(.*)-hf(.*)$/ ) {
$ hostname = $ node . "-hf" . $ count ;
} else {
$ hostname = $ 1 . "-hf" . $ count ;
}
2011-05-05 15:41:39 +00:00
open ( $ pcfg , '>' , $ tftpdir . "/etc/" . $ hostname ) ;
my $ cref = $ chainhash { $ node } - > [ 0 ] ; #$chaintab->getNodeAttribs($node,['currstate']);
if ( $ cref - > { currstate } ) {
print $ pcfg "#" . $ cref - > { currstate } . "\n" ;
}
print $ pcfg "timeout=5\n" ;
$ normalnodes { $ node } = 1 ;
if ( $ cref and $ cref - > { currstate } eq "boot" ) {
$ breaknetbootnodes { $ node } = 1 ;
delete $ normalnodes { $ node } ; #Signify to omit this from one makedhcp command
#$sub_req->({command=>['makedhcp'], #batched elsewhere, this code is stale, hopefully
# node=>[$node],
# arg=>['-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$callback);
print $ pcfg "bye\n" ;
close ( $ pcfg ) ;
} elsif ( $ kern and $ kern - > { kernel } ) {
#It's time to set yaboot for this node to boot the kernel..
print $ pcfg "image=" . $ kern - > { kernel } . "\n\tlabel=xcat\n" ;
if ( $ kern and $ kern - > { initrd } ) {
print $ pcfg "\tinitrd=" . $ kern - > { initrd } . "\n" ;
}
if ( $ kern and $ kern - > { kcmdline } ) {
my $ kcmdline = $ kern - > { kcmdline } ;
2012-11-30 08:22:56 +00:00
$ kcmdline =~ s/(.*ifname=.*):@macs[0].*( netdev.*)/$1:$mac$2/g ;
2011-05-05 15:41:39 +00:00
print $ pcfg "\tappend=\"" . $ kcmdline . "\"\n" ;
}
close ( $ pcfg ) ;
my $ inetn = xCAT::NetworkUtils - > getipaddr ( $ node ) ;
unless ( $ inetn ) {
2013-10-22 07:51:50 +00:00
syslog ( "local1|err" , "xCAT unable to resolve IP for $node in yaboot plugin" ) ;
2011-05-05 15:41:39 +00:00
return ;
}
} else { #TODO: actually, should possibly default to xCAT image?
print $ pcfg "bye\n" ;
close ( $ pcfg ) ;
}
if ( $ mac =~ /:/ ) {
2012-11-21 07:37:23 +00:00
$ nodemac = $ mac ;
2011-05-05 15:41:39 +00:00
my $ tmp = $ mac ;
$ tmp =~ s/(..):(..):(..):(..):(..):(..)/$1-$2-$3-$4-$5-$6/g ;
my $ pname = "25-" . $ tmp ;
unlink ( $ tftpdir . "/etc/" . $ pname ) ;
link ( $ tftpdir . "/etc/" . $ hostname , $ tftpdir . "/etc/" . $ pname ) ;
}
}
$ count = $ count + 2 ;
}
}
}
} else {
open ( $ pcfg , '>' , $ tftpdir . "/etc/" . $ node ) ;
my $ cref = $ chainhash { $ node } - > [ 0 ] ; #$chaintab->getNodeAttribs($node,['currstate']);
if ( $ cref - > { currstate } ) {
print $ pcfg "#" . $ cref - > { currstate } . "\n" ;
}
print $ pcfg "timeout=5\n" ;
$ normalnodes { $ node } = 1 ; #Assume a normal netboot (well, normal dhcp,
2008-07-11 20:57:46 +00:00
#which is normally with a valid 'filename' field,
#but the typical ppc case will be 'special' makedhcp
#to clear the filename field, so the logic is a little
#opposite
2011-05-05 15:41:39 +00:00
# $sub_req->({command=>['makedhcp'], #This is currently batched elswhere
# node=>[$node]},$callback); #It hopefully will perform correctly
if ( $ cref and $ cref - > { currstate } eq "boot" ) {
$ breaknetbootnodes { $ node } = 1 ;
delete $ normalnodes { $ node } ; #Signify to omit this from one makedhcp command
#$sub_req->({command=>['makedhcp'], #batched elsewhere, this code is stale, hopefully
# node=>[$node],
# arg=>['-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$callback);
print $ pcfg "bye\n" ;
close ( $ pcfg ) ;
} elsif ( $ kern and $ kern - > { kernel } ) {
#It's time to set yaboot for this node to boot the kernel..
print $ pcfg "image=" . $ kern - > { kernel } . "\n\tlabel=xcat\n" ;
if ( $ kern and $ kern - > { initrd } ) {
print $ pcfg "\tinitrd=" . $ kern - > { initrd } . "\n" ;
}
if ( $ kern and $ kern - > { kcmdline } ) {
print $ pcfg "\tappend=\"" . $ kern - > { kcmdline } . "\"\n" ;
}
close ( $ pcfg ) ;
my $ inetn = xCAT::NetworkUtils - > getipaddr ( $ node ) ;
unless ( $ inetn ) {
2013-10-22 07:51:50 +00:00
syslog ( "local1|err" , "xCAT unable to resolve IP for $node in yaboot plugin" ) ;
2011-05-05 15:41:39 +00:00
return ;
}
} else { #TODO: actually, should possibly default to xCAT image?
print $ pcfg "bye\n" ;
close ( $ pcfg ) ;
2007-11-19 21:15:45 +00:00
}
2011-05-05 15:41:39 +00:00
my $ ip = xCAT::NetworkUtils - > getipaddr ( $ node ) ;
unless ( $ ip ) {
2013-10-22 07:51:50 +00:00
syslog ( "local1|err" , "xCAT unable to resolve IP in yaboot plugin" ) ;
2011-05-05 15:41:39 +00:00
return ;
2007-11-19 21:15:45 +00:00
}
2011-05-05 15:41:39 +00:00
my $ mactab = xCAT::Table - > new ( 'mac' ) ;
my % ipaddrs ;
$ ipaddrs { $ ip } = 1 ;
if ( $ mactab ) {
my $ ment = $ machash { $ node } - > [ 0 ] ; #$mactab->getNodeAttribs($node,['mac']);
if ( $ ment and $ ment - > { mac } ) {
2008-02-28 00:17:24 +00:00
my @ macs = split ( /\|/ , $ ment - > { mac } ) ;
foreach ( @ macs ) {
2012-11-21 07:37:23 +00:00
$ nodemac = $ _ ;
2008-02-28 00:17:24 +00:00
if ( /!(.*)/ ) {
2010-05-12 03:09:08 +00:00
my $ ipaddr = xCAT::NetworkUtils - > getipaddr ( $ 1 ) ;
if ( $ ipaddr ) {
$ ipaddrs { $ ipaddr } = 1 ;
2008-03-21 20:00:07 +00:00
}
2008-02-28 00:17:24 +00:00
}
}
2011-05-05 15:41:39 +00:00
}
}
# Do not use symbolic link, p5 does not support symbolic link in /tftpboot
# my $hassymlink = eval { symlink("",""); 1 };
foreach $ ip ( keys % ipaddrs ) {
my @ ipa = split ( /\./ , $ ip ) ;
my $ pname = sprintf ( "%02x%02x%02x%02x" , @ ipa ) ;
unlink ( $ tftpdir . "/etc/" . $ pname ) ;
link ( $ tftpdir . "/etc/" . $ node , $ tftpdir . "/etc/" . $ pname ) ;
}
2008-02-28 00:17:24 +00:00
}
2012-11-21 07:37:23 +00:00
if ( $ nodemac =~ /:/ ) {
my $ tmp = $ nodemac ;
$ tmp =~ s/(..):(..):(..):(..):(..):(..)/$1-$2-$3-$4-$5-$6/g ;
my $ pname = "yaboot.conf-" . $ tmp ;
unlink ( $ tftpdir . "/" . $ pname ) ;
link ( $ tftpdir . "/etc/" . $ node , $ tftpdir . "/" . $ pname ) ;
2013-08-06 07:53:30 +00:00
}
return ;
2007-11-19 21:15:45 +00:00
}
my $ errored = 0 ;
sub pass_along {
my $ resp = shift ;
2009-08-03 22:39:01 +00:00
# print Dumper($resp);
2007-11-19 21:15:45 +00:00
$ callback - > ( $ resp ) ;
2008-05-07 20:45:48 +00:00
if ( $ resp and ( $ resp - > { errorcode } and $ resp - > { errorcode } - > [ 0 ] ) or ( $ resp - > { error } and $ resp - > { error } - > [ 0 ] ) ) {
2007-11-19 21:15:45 +00:00
$ errored = 1 ;
}
2008-05-07 20:45:48 +00:00
foreach ( @ { $ resp - > { node } } ) {
if ( $ _ - > { error } or $ _ - > { errorcode } ) {
$ errored = 1 ;
}
}
2007-11-19 21:15:45 +00:00
}
2008-01-27 20:45:31 +00:00
2008-05-02 01:37:02 +00:00
sub preprocess_request {
2009-08-03 02:00:13 +00:00
my $ req = shift ;
if ( $ req - > { _xcatpreprocessed } - > [ 0 ] == 1 ) { return [ $ req ] ; }
2009-08-10 21:18:38 +00:00
my $ callback1 = shift ;
2009-08-03 02:00:13 +00:00
my $ command = $ req - > { command } - > [ 0 ] ;
my $ sub_req = shift ;
my @ args = ( ) ;
if ( ref ( $ req - > { arg } ) ) {
@ args = @ { $ req - > { arg } } ;
} else {
@ args = ( $ req - > { arg } ) ;
}
@ ARGV = @ args ;
2013-08-27 16:24:02 +00:00
my $ nodes = $ req - > { node } ;
2009-08-03 02:00:13 +00:00
#use Getopt::Long;
Getopt::Long:: Configure ( "bundling" ) ;
Getopt::Long:: Configure ( "pass_through" ) ;
if ( ! GetOptions ( 'h|?|help' = > \ $ HELP , 'v|version' = > \ $ VERSION ) ) {
if ( $ usage { $ command } ) {
my % rsp ;
$ rsp { data } - > [ 0 ] = $ usage { $ command } ;
2009-08-03 22:39:01 +00:00
$ callback1 - > ( \ % rsp ) ;
2009-08-03 02:00:13 +00:00
}
return ;
}
if ( $ HELP ) {
if ( $ usage { $ command } ) {
my % rsp ;
$ rsp { data } - > [ 0 ] = $ usage { $ command } ;
2009-08-03 22:39:01 +00:00
$ callback1 - > ( \ % rsp ) ;
2009-08-03 02:00:13 +00:00
}
return ;
}
if ( $ VERSION ) {
my $ ver = xCAT::Utils - > Version ( ) ;
my % rsp ;
$ rsp { data } - > [ 0 ] = "$ver" ;
2009-08-03 22:39:01 +00:00
$ callback1 - > ( \ % rsp ) ;
2009-08-03 02:00:13 +00:00
return ;
}
if ( @ ARGV == 0 ) {
if ( $ usage { $ command } ) {
my % rsp ;
$ rsp { data } - > [ 0 ] = $ usage { $ command } ;
2009-08-03 22:39:01 +00:00
$ callback1 - > ( \ % rsp ) ;
2009-08-03 02:00:13 +00:00
}
return ;
}
2008-05-02 01:37:02 +00:00
#Assume shared tftp directory for boring people, but for cool people, help sync up tftpdirectory contents when
2013-08-27 16:24:02 +00:00
#if they specify no sharedtftp in site table
2012-08-09 04:07:40 +00:00
my @ entries = xCAT::TableUtils - > get_site_attribute ( "sharedtftp" ) ;
2012-05-23 06:58:26 +00:00
my $ t_entry = $ entries [ 0 ] ;
if ( defined ( $ t_entry ) and ( $ t_entry == 0 or $ t_entry =~ /no/i ) ) {
2013-08-27 16:24:02 +00:00
# check for computenodes and servicenodes from the noderange, if so error out
my @ SN ;
my @ CN ;
xCAT::ServiceNodeUtils - > getSNandCPnodes ( \ @$ nodes , \ @ SN , \ @ CN ) ;
if ( ( @ SN > 0 ) && ( @ CN > 0 ) ) { # there are both SN and CN
my $ rsp ;
$ rsp - > { data } - > [ 0 ] =
"Nodeset was run with a noderange containing both service nodes and compute nodes. This is not valid. You must submit with either compute nodes in the noderange or service nodes. \n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback1 ) ;
return ;
}
2008-05-02 01:37:02 +00:00
$ req - > { '_disparatetftp' } = [ 1 ] ;
2009-03-28 15:03:36 +00:00
if ( $ req - > { inittime } - > [ 0 ] ) {
2009-03-28 06:15:05 +00:00
return [ $ req ] ;
}
2013-09-13 12:00:12 +00:00
if ( @ CN > 0 ) { # if compute nodes broadcast to all servicenodes
return xCAT::Scope - > get_broadcast_scope ( $ req , @ _ ) ;
}
2008-05-02 01:37:02 +00:00
}
return [ $ req ] ;
}
2007-11-19 21:15:45 +00:00
sub process_request {
$ request = shift ;
$ callback = shift ;
2013-10-09 16:17:42 +00:00
$ ::callback = $ callback ;
2007-11-29 16:01:49 +00:00
$ sub_req = shift ;
2009-08-03 02:00:13 +00:00
my $ command = $ request - > { command } - > [ 0 ] ;
2008-07-11 20:57:46 +00:00
% breaknetbootnodes = ( ) ;
2008-10-15 17:53:05 +00:00
% normalnodes = ( ) ;
2008-06-25 14:50:11 +00:00
2007-11-19 21:15:45 +00:00
my @ args ;
my @ nodes ;
2008-02-03 00:01:35 +00:00
my @ rnodes ;
2007-11-19 21:15:45 +00:00
if ( ref ( $ request - > { node } ) ) {
2008-02-03 00:01:35 +00:00
@ rnodes = @ { $ request - > { node } } ;
2007-11-19 21:15:45 +00:00
} else {
2008-02-03 00:01:35 +00:00
if ( $ request - > { node } ) { @ rnodes = ( $ request - > { node } ) ; }
2007-11-19 21:15:45 +00:00
}
2008-02-03 00:01:35 +00:00
unless ( @ rnodes ) {
2007-11-19 21:15:45 +00:00
if ( $ usage { $ request - > { command } - > [ 0 ] } ) {
$ callback - > ( { data = > $ usage { $ request - > { command } - > [ 0 ] } } ) ;
}
return ;
}
2008-06-25 14:50:11 +00:00
2008-05-02 01:37:02 +00:00
#if not shared tftpdir, then filter, otherwise, set up everything
2009-04-19 03:22:20 +00:00
if ( $ request - > { '_disparatetftp' } - > [ 0 ] ) { #reading hint from preprocess_command
2008-05-02 01:37:02 +00:00
@ nodes = ( ) ;
foreach ( @ rnodes ) {
2012-08-09 04:07:40 +00:00
if ( xCAT::NetworkUtils - > nodeonmynet ( $ _ ) ) {
2008-05-02 01:37:02 +00:00
push @ nodes , $ _ ;
2011-12-05 14:53:13 +00:00
} else {
2012-03-16 10:31:33 +00:00
xCAT::MsgUtils - > message ( "S" , "$_: yaboot netboot: stop configuration because of none sharedtftp and not on same network with its xcatmaster." ) ;
2008-05-02 01:37:02 +00:00
}
}
} else {
@ nodes = @ rnodes ;
}
2012-03-16 10:31:33 +00:00
# return directly if no nodes in the same network
unless ( @ nodes ) {
xCAT::MsgUtils - > message ( "S" , "xCAT: yaboot netboot: no valid nodes. Stop the operation on this server." ) ;
return ;
}
2008-02-03 00:01:35 +00:00
2007-11-19 21:15:45 +00:00
if ( ref ( $ request - > { arg } ) ) {
@ args = @ { $ request - > { arg } } ;
} else {
@ args = ( $ request - > { arg } ) ;
}
2009-04-19 03:22:20 +00:00
2009-08-10 21:18:38 +00:00
#now run the begin part of the prescripts
unless ( $ args [ 0 ] eq 'stat' ) { # or $args[0] eq 'enact') {
$ errored = 0 ;
if ( $ request - > { '_disparatetftp' } - > [ 0 ] ) { #the call is distrubuted to the service node already, so only need to handles my own children
$ sub_req - > ( { command = > [ 'runbeginpre' ] ,
node = > \ @ nodes ,
arg = > [ $ args [ 0 ] , '-l' ] } , \ & pass_along ) ;
} else { #nodeset did not distribute to the service node, here we need to let runednpre to distribute the nodes to their masters
$ sub_req - > ( { command = > [ 'runbeginpre' ] ,
node = > \ @ rnodes ,
arg = > [ $ args [ 0 ] ] } , \ & pass_along ) ;
}
2011-05-16 19:59:10 +00:00
if ( $ errored ) {
my $ rsp ;
$ rsp - > { errorcode } - > [ 0 ] = 1 ;
$ rsp - > { error } - > [ 0 ] = "Failed in running begin prescripts.\n" ;
$ callback - > ( $ rsp ) ;
return ;
}
2009-08-10 21:18:38 +00:00
}
#back to normal business
2009-09-22 15:37:40 +00:00
my $ inittime = 0 ;
if ( exists ( $ request - > { inittime } ) ) { $ inittime = $ request - > { inittime } - > [ 0 ] ; }
if ( ! $ inittime ) { $ inittime = 0 ; }
2009-04-19 03:22:20 +00:00
$ errored = 0 ;
2009-03-28 04:25:03 +00:00
unless ( $ args [ 0 ] eq 'stat' ) { # or $args[0] eq 'enact') {
2007-11-19 21:15:45 +00:00
$ sub_req - > ( { command = > [ 'setdestiny' ] ,
2009-09-22 15:37:40 +00:00
node = > \ @ nodes ,
inittime = > [ $ inittime ] ,
2013-07-04 05:17:03 +00:00
arg = > \ @ args } , \ & pass_along ) ;
2007-11-19 21:15:45 +00:00
}
if ( $ errored ) { return ; }
2009-08-03 02:00:13 +00:00
2008-07-11 20:57:46 +00:00
my $ bptab = xCAT::Table - > new ( 'bootparams' , - create = > 1 ) ;
2009-06-29 18:41:00 +00:00
my $ bphash = $ bptab - > getNodesAttribs ( \ @ nodes , [ 'kernel' , 'initrd' , 'kcmdline' , 'addkcmdline' ] ) ;
2008-07-23 17:50:21 +00:00
my $ chaintab = xCAT::Table - > new ( 'chain' , - create = > 1 ) ;
2008-07-11 20:57:46 +00:00
my $ chainhash = $ chaintab - > getNodesAttribs ( \ @ nodes , [ 'currstate' ] ) ;
2012-02-15 21:04:42 +00:00
my $ noderestab = xCAT::Table - > new ( 'noderes' , - create = > 1 ) ;
my $ nodereshash = $ noderestab - > getNodesAttribs ( \ @ nodes , [ 'tftpdir' ] ) ;
2008-07-11 20:57:46 +00:00
my $ mactab = xCAT::Table - > new ( 'mac' , - create = > 1 ) ;
2008-10-14 17:47:03 +00:00
my $ machash = $ mactab - > getNodesAttribs ( \ @ nodes , [ 'mac' ] ) ;
2012-02-20 07:20:41 +00:00
my $ nrtab = xCAT::Table - > new ( 'noderes' , - create = > 1 ) ;
my $ nrhash = $ nrtab - > getNodesAttribs ( \ @ nodes , [ 'servicenode' ] ) ;
2012-11-21 07:37:23 +00:00
my $ typetab = xCAT::Table - > new ( 'nodetype' , - create = > 1 ) ;
2013-10-22 07:51:50 +00:00
my $ typehash = $ typetab - > getNodesAttribs ( \ @ nodes , [ 'os' , 'provmethod' , 'arch' , 'profile' ] ) ;
2013-04-25 12:15:09 +00:00
my $ linuximgtab = xCAT::Table - > new ( 'linuximage' , - create = > 1 ) ;
2013-10-22 07:51:50 +00:00
my $ osimagetab = xCAT::Table - > new ( 'osimage' , - create = > 1 ) ;
2013-04-25 12:15:09 +00:00
2009-03-18 14:11:30 +00:00
my $ rc ;
my $ errstr ;
2008-07-11 20:57:46 +00:00
2012-11-21 07:37:23 +00:00
my $ tftpdir ;
2007-11-19 21:15:45 +00:00
foreach ( @ nodes ) {
my % response ;
2012-02-15 21:04:42 +00:00
if ( $ nodereshash - > { $ _ } and $ nodereshash - > { $ _ } - > [ 0 ] and $ nodereshash - > { $ _ } - > [ 0 ] - > { tftpdir } ) {
$ tftpdir = $ nodereshash - > { $ _ } - > [ 0 ] - > { tftpdir } ;
} else {
$ tftpdir = $ globaltftpdir ;
}
2007-11-19 21:15:45 +00:00
$ response { node } - > [ 0 ] - > { name } - > [ 0 ] = $ _ ;
if ( $ args [ 0 ] eq 'stat' ) {
2012-02-15 21:04:42 +00:00
$ response { node } - > [ 0 ] - > { data } - > [ 0 ] = getstate ( $ _ , $ tftpdir ) ;
2007-11-19 21:15:45 +00:00
$ callback - > ( \ % response ) ;
} elsif ( $ args [ 0 ] ) { #If anything else, send it on to the destiny plugin, then setstate
2013-04-25 12:15:09 +00:00
my $ ent = $ typehash - > { $ _ } - > [ 0 ] ;
my $ osimgname = $ ent - > { 'provmethod' } ;
my $ linuximghash = undef ;
unless ( $ osimgname =~ /^(install|netboot|statelite)$/ ) {
$ linuximghash = $ linuximgtab - > getAttribs ( { imagename = > $ osimgname } , 'boottarget' , 'addkcmdline' ) ;
}
( $ rc , $ errstr ) = setstate ( $ _ , $ bphash , $ chainhash , $ machash , $ tftpdir , $ nrhash , $ linuximghash ) ;
2009-03-18 14:11:30 +00:00
if ( $ rc ) {
$ response { node } - > [ 0 ] - > { errorcode } - > [ 0 ] = $ rc ;
$ response { node } - > [ 0 ] - > { errorc } - > [ 0 ] = $ errstr ;
$ callback - > ( \ % response ) ;
2009-03-18 14:30:09 +00:00
}
2007-11-19 21:15:45 +00:00
}
2012-11-21 07:37:23 +00:00
} # end of foreach node
2009-08-03 02:00:13 +00:00
2008-10-15 17:53:05 +00:00
my @ normalnodeset = keys % normalnodes ;
2008-07-11 20:57:46 +00:00
my @ breaknetboot = keys % breaknetbootnodes ;
2009-08-03 02:00:13 +00:00
#print "yaboot:inittime=$inittime; normalnodeset=@normalnodeset; breaknetboot=@breaknetboot\n";
2013-10-22 07:51:50 +00:00
my % osimagenodehash ;
2012-11-21 07:37:23 +00:00
for my $ nn ( @ normalnodeset ) {
#record the os version for node
2013-10-22 07:51:50 +00:00
my $ ent = $ typehash - > { $ nn } - > [ 0 ] ;
my $ osimage = $ ent - > { 'provmethod' } ;
if ( $ osimage =~ /^(install|netboot|statelite)$/ ) {
$ osimage = ( $ ent - > { 'os' } ) . '-' . ( $ ent - > { 'arch' } ) . '-' . ( $ ent - > { 'provmethod' } ) . '-' . ( $ ent - > { 'profile' } ) ;
}
push @ { $ osimagenodehash { $ osimage } } , $ nn ;
2012-11-21 07:37:23 +00:00
}
2013-10-22 07:51:50 +00:00
foreach my $ osimage ( keys % osimagenodehash ) {
my $ osimgent = $ osimagetab - > getAttribs ( { imagename = > $ osimage } , 'osvers' ) ;
my $ os = $ osimgent - > { 'osvers' } ;
2012-11-21 07:37:23 +00:00
my $ osv ;
my $ osn ;
my $ osm ;
if ( $ os =~ /(\D+)(\d+)\.(\d+)/ ) {
$ osv = $ 1 ;
$ osn = $ 2 ;
$ osm = $ 3 ;
} elsif ( $ os =~ /(\D+)(\d+)/ ) {
$ osv = $ 1 ;
$ osn = $ 2 ;
$ osm = 0 ;
}
2013-10-22 07:51:50 +00:00
2012-11-21 07:37:23 +00:00
if ( ( $ osv =~ /rh/ and int ( $ osn ) < 6 ) or
( $ osv =~ /sles/ and int ( $ osn ) < 11 ) ) {
2013-10-22 12:10:07 +00:00
# check if yaboot-xcat installed
2012-11-21 07:37:23 +00:00
my $ yf = $ tftpdir . "/yaboot" ;
unless ( - e $ yf ) {
my $ rsp ;
push @ { $ rsp - > { data } } ,
2013-10-22 12:10:07 +00:00
"stop configuration because yaboot-xcat need to be installed for $os.\n" ;
2012-11-21 07:37:23 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return ;
}
} elsif ( ( $ osv =~ /rh/ and int ( $ osn ) >= 6 ) or
( $ osv =~ /sles/ and int ( $ osn ) >= 11 ) ) {
# copy yaboot from cn's repository
my $ cmd = '/usr/bin/rsync' ;
if ( ! - f $ cmd || ! - x $ cmd ) {
my $ rsp ;
push @ { $ rsp - > { data } } ,
"stop configuration because rsync does not exist or is not executable.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return ;
}
2013-10-22 07:51:50 +00:00
my $ yabootpath = $ tftpdir . "/yb/" . $ os ;
mkpath $ yabootpath ;
my $ linuximgent = $ linuximgtab - > getAttribs ( { imagename = > $ osimage } , 'pkgdir' ) ;
my @ pkgdirlist = split /,/ , $ linuximgent - > { 'pkgdir' } ;
my $ pkgdir = $ pkgdirlist [ 0 ] ;
$ pkgdir =~ s/\/+$// ;
2012-11-21 07:37:23 +00:00
my $ yabootfile ;
if ( $ os =~ /sles/ ) {
2013-10-22 07:51:50 +00:00
$ yabootfile = $ pkgdir . "/1/suseboot/yaboot" ;
2012-11-21 07:37:23 +00:00
} elsif ( $ os =~ /rh/ ) {
2013-10-22 07:51:50 +00:00
$ yabootfile = $ pkgdir . "/ppc/chrp/yaboot" ;
2012-11-21 07:37:23 +00:00
}
unless ( - e "$yabootfile" ) {
my $ rsp ;
push @ { $ rsp - > { data } } ,
"stop configuration because Unable to find the os shipped yaboot file.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return ;
}
$ cmd = $ cmd . " " . $ yabootfile . " " . $ yabootpath ; #???
( $ rc , $ errstr ) = xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ rc )
{
my $ rsp ;
push @ { $ rsp - > { data } } ,
"stop configuration because $synccmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return ;
}
}
2013-10-22 11:54:50 +00:00
} #end of foreach osimagenodehash
2012-11-21 07:37:23 +00:00
2009-08-03 05:49:30 +00:00
#Don't bother to try dhcp binding changes if sub_req not passed, i.e. service node build time
2010-03-03 18:33:34 +00:00
unless ( ( $ args [ 0 ] eq 'stat' ) || ( $ inittime ) || ( $ args [ 0 ] eq 'offline' ) ) {
2009-08-03 05:49:30 +00:00
#dhcp stuff
my $ do_dhcpsetup = 1 ;
2012-05-23 06:58:26 +00:00
#my $sitetab = xCAT::Table->new('site');
#if ($sitetab) {
#(my $ref) = $sitetab->getAttribs({key => 'dhcpsetup'}, 'value');
2012-08-09 04:07:40 +00:00
my @ entries = xCAT::TableUtils - > get_site_attribute ( "dhcpsetup" ) ;
2012-05-23 06:58:26 +00:00
my $ t_entry = $ entries [ 0 ] ;
if ( defined ( $ t_entry ) ) {
if ( $ t_entry =~ /0|n|N/ ) { $ do_dhcpsetup = 0 ; }
2009-08-03 05:49:30 +00:00
}
2012-05-23 06:58:26 +00:00
#}
2009-08-03 05:49:30 +00:00
if ( $ do_dhcpsetup ) {
2013-10-22 11:54:50 +00:00
if ( % osimagenodehash ) {
foreach my $ osimage ( keys % osimagenodehash ) {
my $ osimgent = $ osimagetab - > getAttribs ( { imagename = > $ osimage } , 'osvers' ) ;
my $ osentry = $ osimgent - > { 'osvers' } ;
2012-11-21 07:37:23 +00:00
my $ osv ;
my $ osn ;
my $ osm ;
if ( $ osentry =~ /(\D+)(\d+)\.(\d+)/ ) {
$ osv = $ 1 ;
$ osn = $ 2 ;
$ osm = $ 3 ;
} elsif ( $ osentry =~ /(\D+)(\d+)/ ) {
$ osv = $ 1 ;
$ osn = $ 2 ;
$ osm = 0 ;
}
if ( ( $ osv =~ /rh/ and int ( $ osn ) >= 6 ) or
( $ osv =~ /sles/ and int ( $ osn ) >= 11 ) ) {
my $ fpath = "/yb/" . $ osentry . "/yaboot" ;
if ( $ request - > { '_disparatetftp' } - > [ 0 ] ) { #reading hint from preprocess_command
$ sub_req - > ( { command = > [ 'makedhcp' ] ,
2013-10-22 11:54:50 +00:00
node = > \ @ { $ osimagenodehash { $ osimage } } ,
2012-11-21 07:37:23 +00:00
arg = > [ '-l' , '-s' , 'filename = \"' . $ fpath . '\";' ] } , $ callback ) ;
} else {
$ sub_req - > ( { command = > [ 'makedhcp' ] ,
2013-10-22 11:54:50 +00:00
node = > \ @ { $ osimagenodehash { $ osimage } } ,
2012-11-21 07:37:23 +00:00
arg = > [ '-s' , 'filename = \"' . $ fpath . '\";' ] } , $ callback ) ;
}
} else {
if ( $ request - > { '_disparatetftp' } - > [ 0 ] ) { #reading hint from preprocess_command, only change local settings if already farmed
$ sub_req - > ( { command = > [ 'makedhcp' ] , arg = > [ '-l' ] ,
2013-10-22 11:54:50 +00:00
node = > \ @ { $ osimagenodehash { $ osimage } } } , $ callback ) ;
2012-11-21 07:37:23 +00:00
} else {
$ sub_req - > ( { command = > [ 'makedhcp' ] ,
2013-10-22 11:54:50 +00:00
node = > \ @ { $ osimagenodehash { $ osimage } } } , $ callback ) ;
2012-11-21 07:37:23 +00:00
}
}
}
} else {
if ( $ request - > { '_disparatetftp' } - > [ 0 ] ) { #reading hint from preprocess_command, only change local settings if already farmed
$ sub_req - > ( { command = > [ 'makedhcp' ] , arg = > [ '-l' ] ,
node = > \ @ normalnodeset } , $ callback ) ;
} else {
$ sub_req - > ( { command = > [ 'makedhcp' ] ,
node = > \ @ normalnodeset } , $ callback ) ;
}
}
if ( $ request - > { '_disparatetftp' } - > [ 0 ] ) { #reading hint from preprocess_command
$ sub_req - > ( { command = > [ 'makedhcp' ] ,
node = > \ @ breaknetboot ,
arg = > [ '-l' , '-s' , 'filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";' ] } , $ callback ) ;
} else {
$ sub_req - > ( { command = > [ 'makedhcp' ] ,
node = > \ @ breaknetboot ,
arg = > [ '-s' , 'filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";' ] } , $ callback ) ;
}
2009-08-03 05:49:30 +00:00
}
}
2009-08-03 02:00:13 +00:00
#now run the end part of the prescripts
unless ( $ args [ 0 ] eq 'stat' ) { # or $args[0] eq 'enact')
$ errored = 0 ;
if ( $ request - > { '_disparatetftp' } - > [ 0 ] ) { #the call is distrubuted to the service node already, so only need to handles my own children
$ sub_req - > ( { command = > [ 'runendpre' ] ,
node = > \ @ nodes ,
arg = > [ $ args [ 0 ] , '-l' ] } , \ & pass_along ) ;
} else { #nodeset did not distribute to the service node, here we need to let runednpre to distribute the nodes to their masters
$ sub_req - > ( { command = > [ 'runendpre' ] ,
node = > \ @ rnodes ,
arg = > [ $ args [ 0 ] ] } , \ & pass_along ) ;
}
2011-05-16 19:59:10 +00:00
if ( $ errored ) {
my $ rsp ;
$ rsp - > { errorcode } - > [ 0 ] = 1 ;
$ rsp - > { error } - > [ 0 ] = "Failed in running end prescripts\n" ;
$ callback - > ( $ rsp ) ;
return ;
}
2009-03-27 22:09:54 +00:00
}
2007-11-19 21:15:45 +00:00
}
2008-09-26 23:07:45 +00:00
#----------------------------------------------------------------------------
= head3 getNodesetStates
returns the nodeset state for the given nodes . The possible nodeset
states are: netboot , install , boot and discover .
Arguments:
nodes - - - a pointer to an array of nodes
states - - a pointer to a hash table . This hash will be filled by this
2009-03-25 02:56:58 +00:00
function . The key is the nodeset status and the value is a pointer
to an array of nodes .
2008-09-26 23:07:45 +00:00
Returns:
( return code , error message )
= cut
#-----------------------------------------------------------------------------
sub getNodesetStates {
my $ noderef = shift ;
if ( $ noderef =~ /xCAT_plugin::yaboot/ ) {
$ noderef = shift ;
}
my @ nodes = @$ noderef ;
my $ hashref = shift ;
2012-03-29 18:14:03 +00:00
my $ noderestab = xCAT::Table - > new ( 'noderes' ) ; #in order to detect per-node tftp directories
my % nrhash = % { $ noderestab - > getNodesAttribs ( \ @ nodes , [ qw( tftpdir ) ] ) } ;
2008-09-26 23:07:45 +00:00
if ( @ nodes > 0 ) {
foreach my $ node ( @ nodes ) {
2012-03-29 18:14:03 +00:00
my $ tftpdir ;
if ( $ nrhash { $ node } - > [ 0 ] and $ nrhash { $ node } - > [ 0 ] - > { tftpdir } ) {
$ tftpdir = $ nrhash { $ node } - > [ 0 ] - > { tftpdir } ;
} else {
$ tftpdir = $ globaltftpdir ;
}
2012-03-29 22:22:32 +00:00
my $ tmp = getstate ( $ node , $ tftpdir ) ;
2008-09-26 23:07:45 +00:00
my @ a = split ( ' ' , $ tmp ) ;
$ stat = $ a [ 0 ] ;
2009-03-25 02:56:58 +00:00
if ( exists ( $ hashref - > { $ stat } ) ) {
my $ pa = $ hashref - > { $ stat } ;
push ( @$ pa , $ node ) ;
}
else {
$ hashref - > { $ stat } = [ $ node ] ;
}
2008-09-26 23:07:45 +00:00
}
}
return ( 0 , "" ) ;
}
2007-11-19 21:15:45 +00:00
1 ;