2007-10-26 22:44:33 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
package xCAT_plugin::destiny ;
use xCAT::NodeRange ;
use Data::Dumper ;
2008-02-07 21:48:21 +00:00
use xCAT::Utils ;
2007-10-26 22:44:33 +00:00
use Sys::Syslog ;
2008-09-25 03:04:56 +00:00
use xCAT::GlobalDef ;
2009-03-24 13:51:56 +00:00
use xCAT::Table ;
2008-09-25 03:04:56 +00:00
use xCAT_monitoring::monitorctrl ;
2007-10-26 22:44:33 +00:00
use strict ;
my $ request ;
my $ callback ;
my $ subreq ;
my $ errored = 0 ;
2008-07-11 19:02:39 +00:00
#DESTINY SCOPED GLOBALS
my $ chaintab ;
my $ iscsitab ;
my $ bptab ;
my $ typetab ;
my $ restab ;
my $ sitetab ;
my $ hmtab ;
2008-10-30 14:37:56 +00:00
my $ tftpdir = "/tftpboot" ;
2008-07-11 19:02:39 +00:00
2009-03-24 13:51:56 +00:00
my $ nonodestatus = 0 ;
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
if ( $ sitetab ) {
2009-03-24 19:44:23 +00:00
( my $ ref1 ) = $ sitetab - > getAttribs ( { key = > 'nodestatus' } , 'value' ) ;
2009-03-24 23:56:42 +00:00
if ( $ ref1 ) {
2009-03-24 19:44:23 +00:00
if ( $ ref1 - > { value } =~ /0|n|N/ ) { $ nonodestatus = 1 ; }
2009-03-24 13:51:56 +00:00
}
}
2007-10-26 22:44:33 +00:00
sub handled_commands {
return {
setdestiny = > "destiny" ,
getdestiny = > "destiny" ,
nextdestiny = > "destiny"
}
}
sub process_request {
$ request = shift ;
$ callback = shift ;
$ subreq = shift ;
2009-06-11 19:09:03 +00:00
if ( xCAT::Utils - > isMN ( ) ) {
my $ result = xCAT::Utils - > checkCredFiles ( $ callback ) ;
}
2007-10-26 22:44:33 +00:00
if ( $ request - > { command } - > [ 0 ] eq 'getdestiny' ) {
2008-09-30 20:00:46 +00:00
getdestiny ( 0 ) ;
2007-10-26 22:44:33 +00:00
}
if ( $ request - > { command } - > [ 0 ] eq 'nextdestiny' ) {
2008-10-28 18:04:11 +00:00
nextdestiny ( 0 , 1 ) ; #it is called within dodestiny
2007-10-26 22:44:33 +00:00
}
if ( $ request - > { command } - > [ 0 ] eq 'setdestiny' ) {
2008-09-30 20:00:46 +00:00
setdestiny ( $ request , 0 ) ;
2007-10-26 22:44:33 +00:00
}
}
sub relay_response {
my $ resp = shift ;
$ 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 ] ) ) {
$ errored = 1 ;
}
foreach ( @ { $ resp - > { node } } ) {
if ( $ _ - > { error } or $ _ - > { errorcode } ) {
$ errored = 1 ;
}
2007-10-26 22:44:33 +00:00
}
}
sub setdestiny {
my $ req = shift ;
2008-09-30 20:00:46 +00:00
my $ flag = shift ;
2009-03-28 04:25:03 +00:00
my $ noupdate = shift ;
2008-09-30 20:00:46 +00:00
2008-07-11 19:02:39 +00:00
$ chaintab = xCAT::Table - > new ( 'chain' , - create = > 1 ) ;
2007-10-26 22:44:33 +00:00
my @ nodes = @ { $ req - > { node } } ;
my $ state = $ req - > { arg } - > [ 0 ] ;
2007-11-29 21:57:24 +00:00
my % nstates ;
2009-03-28 04:25:03 +00:00
if ( $ state eq "enact" ) {
2009-09-22 15:37:40 +00:00
my $ nodetypetab = xCAT::Table - > new ( 'nodetype' , - create = > 1 ) ;
2009-03-28 04:25:03 +00:00
my % nodestates ;
my % stents = % { $ chaintab - > getNodesAttribs ( $ req - > { node } , "currstate" ) } ;
2009-09-22 15:37:40 +00:00
my % ntents = % { $ nodetypetab - > getNodesAttribs ( $ req - > { node } , "provmethod" ) } ;
2009-03-28 04:25:03 +00:00
my $ state ;
2009-09-22 15:37:40 +00:00
my $ sninit = 0 ;
if ( exists ( $ req - > { inittime } ) ) { # this is called in AAsn.pm
$ sninit = $ req - > { inittime } - > [ 0 ] ;
}
2009-03-28 04:25:03 +00:00
foreach ( @ { $ req - > { node } } ) { #First, build a hash of all of the states to attempt to keep things as aggregated as possible
if ( $ stents { $ _ } - > [ 0 ] - > { currstate } ) {
$ state = $ stents { $ _ } - > [ 0 ] - > { currstate } ;
$ state =~ s/ .*// ;
2009-09-22 15:37:40 +00:00
#get the osimagename if nodetype.provmethod has osimage specified
2010-02-19 18:39:56 +00:00
if ( ( $ sninit == 1 ) && ( ( $ state eq 'install' ) || ( $ state eq 'netboot' ) || ( $ state eq 'statelite' ) ) ) {
2009-09-22 15:37:40 +00:00
my $ osimage = $ ntents { $ _ } - > [ 0 ] - > { provmethod } ;
2010-02-19 18:39:56 +00:00
if ( ( $ osimage ) && ( $ osimage ne 'install' ) && ( $ osimage ne 'netboot' ) && ( $ osimage ne 'statelite' ) ) {
2009-09-22 15:37:40 +00:00
$ state = "osimage=$osimage" ;
}
}
2009-03-28 04:32:13 +00:00
push @ { $ nodestates { $ state } } , $ _ ;
2009-03-28 04:25:03 +00:00
}
}
foreach ( keys % nodestates ) {
$ req - > { arg } - > [ 0 ] = $ _ ;
2009-03-28 04:32:13 +00:00
$ req - > { node } = $ nodestates { $ _ } ;
2009-03-28 04:25:03 +00:00
setdestiny ( $ req , 30 , 1 ) ; #ludicrous flag to denote no table updates can be inferred.
}
return ;
} elsif ( $ state eq "next" ) {
2008-09-30 20:00:46 +00:00
return nextdestiny ( $ flag + 1 ) ; #this is special case where updateflag is called
2008-02-07 21:48:21 +00:00
} elsif ( $ state eq "iscsiboot" ) {
my $ iscsitab = xCAT::Table - > new ( 'iscsi' ) ;
unless ( $ iscsitab ) {
$ callback - > ( { error = > "Unable to open iscsi table to get iscsiboot parameters" , errorcode = > [ 1 ] } ) ;
}
2008-07-11 19:02:39 +00:00
my $ bptab = xCAT::Table - > new ( 'bootparams' , - create = > 1 ) ;
2008-10-30 14:37:56 +00:00
my $ nodetype = xCAT::Table - > new ( 'nodetype' ) ;
my $ ntents = $ nodetype - > getNodesAttribs ( $ req - > { node } , [ qw( os arch profile ) ] ) ;
2008-07-11 19:02:39 +00:00
my $ ients = $ iscsitab - > getNodesAttribs ( $ req - > { node } , [ qw( kernel kcmdline initrd ) ] ) ;
2008-02-07 21:48:21 +00:00
foreach ( @ { $ req - > { node } } ) {
2008-07-11 19:02:39 +00:00
my $ ient = $ ients - > { $ _ } - > [ 0 ] ; #$iscsitab->getNodeAttribs($_,[qw(kernel kcmdline initrd)]);
2008-10-30 14:37:56 +00:00
my $ ntent = $ ntents - > { $ _ } - > [ 0 ] ;
2008-02-07 21:48:21 +00:00
unless ( $ ient and $ ient - > { kernel } ) {
2010-05-13 20:23:30 +00:00
unless ( $ ntent and $ ntent - > { arch } =~ /x86/ and - f ( "$tftpdir/undionly.kpxe" or - f "$tftpdir/xcat/xnba.kpxe" ) ) { $ callback - > ( { error = > "$_: No iscsi boot data available" , errorcode = > [ 1 ] } ) ; } #If x86 node and undionly.kpxe exists, presume they know what they are doing
2008-02-07 21:48:21 +00:00
next ;
}
my $ hash ;
$ hash - > { kernel } = $ ient - > { kernel } ;
if ( $ ient - > { initrd } ) { $ hash - > { initrd } = $ ient - > { initrd } }
if ( $ ient - > { kcmdline } ) { $ hash - > { kcmdline } = $ ient - > { kcmdline } }
2009-12-04 00:59:53 +00:00
$ bptab - > setNodeAttribs ( $ _ , $ hash ) ;
2008-02-07 21:48:21 +00:00
}
2009-12-15 20:38:34 +00:00
} elsif ( $ state =~ /^install[=\$]/ or $ state eq 'install' or $ state =~ /^netboot[=\$]/ or $ state eq 'netboot' or $ state eq "image" or $ state eq "winshell" or $ state =~ /^osimage/ or $ state =~ /^statelite/ ) {
2007-11-06 21:28:02 +00:00
chomp ( $ state ) ;
2009-06-26 13:11:49 +00:00
my $ target ;
if ( $ state =~ /=/ ) {
( $ state , $ target ) = split /=/ , $ state , 2 ;
}
2009-09-22 15:37:40 +00:00
my $ nodetypetable = xCAT::Table - > new ( 'nodetype' , - create = > 1 ) ;
2009-09-22 17:59:56 +00:00
if ( $ state ne 'osimage' ) {
2009-06-26 13:11:49 +00:00
my $ updateattribs ;
2009-09-22 15:37:40 +00:00
if ( $ target ) {
my $ archentries = $ nodetypetable - > getNodesAttribs ( $ req - > { node } , [ 'supportedarchs' ] ) ;
2010-04-23 16:01:54 +00:00
if ( $ target =~ /^([^-]*)-([^-]*)-(.*)/ ) {
2009-09-22 15:37:40 +00:00
$ updateattribs - > { os } = $ 1 ;
$ updateattribs - > { arch } = $ 2 ;
2010-04-23 16:01:54 +00:00
$ updateattribs - > { profile } = $ 3 ;
2009-09-22 17:59:56 +00:00
my $ nodearch = $ 2 ;
2009-09-22 15:37:40 +00:00
foreach ( @ { $ req - > { node } } ) {
2009-09-22 17:59:56 +00:00
if ( $ archentries - > { $ _ } - > [ 0 ] - > { supportedarchs } and $ archentries - > { $ _ } - > [ 0 ] - > { supportedarchs } !~ /(^|,)$nodearch(\z|,)/ ) {
$ callback - > ( { errorcode = > 1 , error = > "Requested architecture " . $ nodearch . " is not one of the architectures supported by $_ (per nodetype.supportedarchs, it supports " . $ archentries - > { $ _ } - > [ 0 ] - > { supportedarchs } . ")" } ) ;
2009-09-22 15:37:40 +00:00
return ;
}
} #end foreach
} else {
$ updateattribs - > { profile } = $ target ;
2009-09-14 12:51:51 +00:00
}
2009-09-22 15:37:40 +00:00
} #end if($target)
$ updateattribs - > { provmethod } = $ state ;
2009-06-26 13:11:49 +00:00
$ nodetypetable - > setNodesAttribs ( $ req - > { node } , $ updateattribs ) ;
2009-09-22 17:59:56 +00:00
} else {
2009-09-22 15:37:40 +00:00
if ( @ { $ req - > { node } } == 0 ) { return ; }
if ( $ target ) {
my $ osimagetable = xCAT::Table - > new ( 'osimage' ) ;
( my $ ref ) = $ osimagetable - > getAttribs ( { imagename = > $ target } , 'provmethod' , 'osvers' , 'profile' , 'osarch' ) ;
if ( $ ref ) {
if ( $ ref - > { provmethod } ) {
$ state = $ ref - > { provmethod } ;
} else {
$ errored = 1 ; $ callback - > ( { error = > "osimage.provmethod for $target must be set." } ) ;
return ;
}
} else {
$ errored = 1 ; $ callback - > ( { error = > "Cannot find the OS image $target on the osimage table." } ) ;
return ;
}
my $ updateattribs ;
$ updateattribs - > { provmethod } = $ target ;
$ updateattribs - > { profile } = $ ref - > { profile } ;
$ updateattribs - > { os } = $ ref - > { osvers } ;
$ updateattribs - > { arch } = $ ref - > { osarch } ;
$ nodetypetable - > setNodesAttribs ( $ req - > { node } , $ updateattribs ) ;
} else {
$ errored = 1 ; $ callback - > ( { error = > "OS image name must be specified." } ) ;
return ;
}
}
#print Dumper($req);
2009-05-07 04:31:33 +00:00
$ errored = 0 ;
2007-11-06 21:28:02 +00:00
$ subreq - > ( { command = > [ "mk$state" ] ,
node = > $ req - > { node } } , \ & relay_response ) ;
if ( $ errored ) { return ; }
2009-09-22 15:37:40 +00:00
my $ ntents = $ nodetypetable - > getNodesAttribs ( $ req - > { node } , [ qw( os arch profile ) ] ) ;
2007-10-26 22:44:33 +00:00
foreach ( @ { $ req - > { node } } ) {
2007-11-29 21:57:24 +00:00
$ nstates { $ _ } = $ state ; #local copy of state variable for mod
2008-07-11 19:02:39 +00:00
my $ ntent = $ ntents - > { $ _ } - > [ 0 ] ; #$nodetype->getNodeAttribs($_,[qw(os arch profile)]);
2008-10-27 13:50:19 +00:00
if ( $ state ne "winshell" ) {
if ( $ ntent and $ ntent - > { os } ) {
$ nstates { $ _ } . = " " . $ ntent - > { os } ;
} else { $ errored = 1 ; $ callback - > ( { error = > "nodetype.os not defined for $_" } ) ; }
} else {
$ nstates { $ _ } . = " winpe" ;
}
2007-10-26 22:44:33 +00:00
if ( $ ntent and $ ntent - > { arch } ) {
2007-11-29 21:57:24 +00:00
$ nstates { $ _ } . = "-" . $ ntent - > { arch } ;
2008-01-19 16:38:03 +00:00
} else { $ errored = 1 ; $ callback - > ( { error = > "nodetype.arch not defined for $_" } ) ; }
2008-10-27 13:50:19 +00:00
if ( $ state ne "winshell" ) {
if ( $ ntent and $ ntent - > { profile } ) {
$ nstates { $ _ } . = "-" . $ ntent - > { profile } ;
} else { $ errored = 1 ; $ callback - > ( { error = > "nodetype.profile not defined for $_" } ) ; }
}
2008-01-19 16:38:03 +00:00
if ( $ errored ) { return ; }
2009-12-04 00:59:53 +00:00
#statelite
unless ( $ state =~ /^netboot|^statelite/ ) { $ chaintab - > setNodeAttribs ( $ _ , { currchain = > "boot" } ) ; } ;
2007-10-26 22:44:33 +00:00
}
2008-02-27 16:22:32 +00:00
} elsif ( $ state eq "shell" or $ state eq "standby" or $ state =~ /^runcmd/ or $ state =~ /^runimage/ ) {
2008-07-11 19:02:39 +00:00
$ restab = xCAT::Table - > new ( 'noderes' , - create = > 1 ) ;
2008-04-25 15:36:56 +00:00
my $ bootparms = xCAT::Table - > new ( 'bootparams' , - create = > 1 ) ;
2007-10-26 22:44:33 +00:00
my $ nodetype = xCAT::Table - > new ( 'nodetype' ) ;
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
2008-01-29 13:50:41 +00:00
my $ nodehm = xCAT::Table - > new ( 'nodehm' ) ;
2008-07-11 19:02:39 +00:00
my $ hments = $ nodehm - > getNodesAttribs ( \ @ nodes , [ 'serialport' , 'serialspeed' , 'serialflow' ] ) ;
2007-10-26 22:44:33 +00:00
( my $ portent ) = $ sitetab - > getAttribs ( { key = > 'xcatdport' } , 'value' ) ;
( my $ mastent ) = $ sitetab - > getAttribs ( { key = > 'master' } , 'value' ) ;
2008-07-11 19:02:39 +00:00
my $ enthash = $ nodetype - > getNodesAttribs ( \ @ nodes , [ qw( arch ) ] ) ;
my $ resents = $ restab - > getNodeAttribs ( \ @ nodes , [ qw( xcatmaster ) ] ) ;
2007-10-26 22:44:33 +00:00
foreach ( @ nodes ) {
2008-07-11 19:02:39 +00:00
my $ ent = $ enthash - > { $ _ } - > [ 0 ] ; #$nodetype->getNodeAttribs($_,[qw(arch)]);
2007-10-26 22:44:33 +00:00
unless ( $ ent and $ ent - > { arch } ) {
$ callback - > ( { error = > [ "No archictecture defined in nodetype table for $_" ] , errorcode = > [ 1 ] } ) ;
return ;
}
my $ arch = $ ent - > { arch } ;
2008-07-11 19:02:39 +00:00
my $ ent = $ resents - > { $ _ } - > [ 0 ] ; #$restab->getNodeAttribs($_,[qw(xcatmaster)]);
2007-10-26 22:44:33 +00:00
my $ master ;
2008-04-09 21:12:36 +00:00
my $ kcmdline = "quiet " ;
2007-10-26 22:44:33 +00:00
if ( $ mastent and $ mastent - > { value } ) {
$ master = $ mastent - > { value } ;
}
if ( $ ent and $ ent - > { xcatmaster } ) {
$ master = $ ent - > { xcatmaster } ;
}
2008-07-11 19:02:39 +00:00
$ ent = $ hments - > { $ _ } - > [ 0 ] ; #$nodehm->getNodeAttribs($_,['serialport','serialspeed','serialflow']);
2008-01-29 13:50:41 +00:00
if ( $ ent and defined ( $ ent - > { serialport } ) ) {
2009-09-15 17:59:11 +00:00
$ kcmdline . = "console=tty0 console=ttyS" . $ ent - > { serialport } ;
2008-04-25 15:36:56 +00:00
#$ent = $nodehm->getNodeAttribs($_,['serialspeed']);
2008-01-29 13:50:41 +00:00
unless ( $ ent and defined ( $ ent - > { serialspeed } ) ) {
$ callback - > ( { error = > [ "Serial port defined in noderes, but no nodehm.serialspeed set for $_" ] , errorcode = > [ 1 ] } ) ;
return ;
}
$ kcmdline . = "," . $ ent - > { serialspeed } ;
2008-04-25 15:36:56 +00:00
#$ent = $nodehm->getNodeAttribs($_,['serialflow']);
2008-01-29 13:50:41 +00:00
if ( $ ent and ( $ ent - > { serialflow } eq 'hard' or $ ent - > { serialflow } eq 'rtscts' ) ) {
$ kcmdline . = "n8r" ;
}
$ kcmdline . = " " ;
}
2007-10-26 22:44:33 +00:00
unless ( $ master ) {
$ callback - > ( { error = > [ "No master in site table nor noderes table for $_" ] , errorcode = > [ 1 ] } ) ;
return ;
}
my $ xcatdport = "3001" ;
if ( $ portent and $ portent - > { value } ) {
$ xcatdport = $ portent - > { value } ;
}
2009-12-04 00:59:53 +00:00
$ bootparms - > setNodeAttribs ( $ _ , { kernel = > "xcat/nbk.$arch" ,
2007-10-26 22:44:33 +00:00
initrd = > "xcat/nbfs.$arch.gz" ,
2009-12-04 00:59:53 +00:00
kcmdline = > $ kcmdline . "xcatd=$master:$xcatdport" } ) ;
2007-10-26 22:44:33 +00:00
}
2010-01-28 07:01:08 +00:00
} elsif ( $ state eq "offline" ) {
1 ;
2007-10-26 22:44:33 +00:00
} elsif ( ! ( $ state eq "boot" ) ) {
$ callback - > ( { error = > [ "Unknown state $state requested" ] , errorcode = > [ 1 ] } ) ;
return ;
}
2009-09-22 17:59:56 +00:00
#blank out the nodetype.provmethod if the previous provisioning method is not 'install'
if ( $ state eq "iscsiboot" or $ state eq "boot" ) {
my $ nodetype = xCAT::Table - > new ( 'nodetype' , - create = > 1 ) ;
my $ osimagetab = xCAT::Table - > new ( 'osimage' , - create = > 1 ) ;
my $ ntents = $ nodetype - > getNodesAttribs ( $ req - > { node } , [ qw( os arch profile provmethod ) ] ) ;
my @ nodestoblank = ( ) ;
my % osimage_hash = ( ) ;
foreach ( @ { $ req - > { node } } ) {
my $ ntent = $ ntents - > { $ _ } - > [ 0 ] ;
#if the previous nodeset staute is not install, then blank nodetype.provmethod
if ( $ ntent and $ ntent - > { provmethod } ) {
my $ provmethod = $ ntent - > { provmethod } ;
2010-02-19 18:39:56 +00:00
if ( ( $ provmethod ne 'install' ) && ( $ provmethod ne 'netboot' ) && ( $ provmethod ne 'statelite' ) ) {
2009-09-22 17:59:56 +00:00
if ( exists ( $ osimage_hash { $ provmethod } ) ) {
$ provmethod = $ osimage_hash { $ provmethod } ;
} else {
( my $ ref ) = $ osimagetab - > getAttribs ( { imagename = > $ provmethod } , 'provmethod' ) ;
if ( ( $ ref ) && $ ref - > { provmethod } ) {
$ osimage_hash { $ provmethod } = $ ref - > { provmethod } ;
$ provmethod = $ ref - > { provmethod } ;
}
}
}
if ( $ provmethod ne 'install' ) {
push ( @ nodestoblank , $ _ ) ;
}
}
} #end foreach
#now blank out the nodetype.provmethod
#print "nodestoblank=@nodestoblank\n";
if ( @ nodestoblank > 0 ) {
my $ newhash ;
$ newhash - > { provmethod } = "" ;
$ nodetype - > setNodesAttribs ( \ @ nodestoblank , $ newhash ) ;
}
}
2009-03-28 04:25:03 +00:00
if ( $ noupdate ) { return ; } #skip table manipulation if just doing 'enact'
2007-10-26 22:44:33 +00:00
foreach ( @ nodes ) {
2007-11-29 21:57:24 +00:00
my $ lstate = $ state ;
if ( $ nstates { $ _ } ) {
$ lstate = $ nstates { $ _ } ;
}
2009-12-04 00:59:53 +00:00
$ chaintab - > setNodeAttribs ( $ _ , { currstate = > $ lstate } ) ;
2007-10-26 22:44:33 +00:00
}
2008-09-30 20:00:46 +00:00
return getdestiny ( $ flag + 1 ) ;
2007-10-26 22:44:33 +00:00
}
sub nextdestiny {
2008-09-30 20:00:46 +00:00
my $ flag = shift ;
2008-02-27 17:08:26 +00:00
my $ callnodeset = 0 ;
if ( scalar ( @ _ ) ) {
$ callnodeset = 1 ;
}
2007-10-26 22:44:33 +00:00
my @ nodes ;
if ( $ request and $ request - > { node } ) {
if ( ref ( $ request - > { node } ) ) {
@ nodes = @ { $ request - > { node } } ;
} else {
@ nodes = ( $ request - > { node } ) ;
}
#TODO: service third party getdestiny..
} else { #client asking to move along its own chain
#TODO: SECURITY with this, any one on a node could advance the chain, for node, need to think of some strategy to deal with...
2008-01-25 15:07:53 +00:00
unless ( $ request - > { '_xcat_clienthost' } - > [ 0 ] ) {
2007-10-26 22:44:33 +00:00
#ERROR? malformed request
return ; #nothing to do here...
}
2008-01-25 15:07:53 +00:00
my $ node = $ request - > { '_xcat_clienthost' } - > [ 0 ] ;
2007-10-26 22:44:33 +00:00
( $ node ) = noderange ( $ node ) ;
unless ( $ node ) {
#not a node, don't trust it
return ;
}
@ nodes = ( $ node ) ;
}
my $ node ;
2008-07-11 19:02:39 +00:00
$ chaintab = xCAT::Table - > new ( 'chain' ) ;
my $ chainents = $ chaintab - > getNodesAttribs ( \ @ nodes , [ qw( currstate currchain chain ) ] ) ;
2007-10-26 22:44:33 +00:00
foreach $ node ( @ nodes ) {
unless ( $ chaintab ) {
syslog ( "local1|err" , "ERROR: $node requested destiny update, no chain table" ) ;
return ; #nothing to do...
}
2008-07-11 19:02:39 +00:00
my $ ref = $ chainents - > { $ node } - > [ 0 ] ; #$chaintab->getNodeAttribs($node,[qw(currstate currchain chain)]);
2007-11-26 19:09:11 +00:00
unless ( $ ref - > { chain } or $ ref - > { currchain } ) {
2007-11-26 15:44:23 +00:00
syslog ( "local1|err" , "ERROR: node requested destiny update, no path in chain.currchain" ) ;
2007-10-26 22:44:33 +00:00
return ; #Can't possibly do anything intelligent..
}
unless ( $ ref - > { currchain } ) { #If no current chain, copy the default
$ ref - > { currchain } = $ ref - > { chain } ;
}
2008-02-27 16:47:12 +00:00
my @ chain = split /[,;]/ , $ ref - > { currchain } ;
2007-10-26 22:44:33 +00:00
$ ref - > { currstate } = shift @ chain ;
$ ref - > { currchain } = join ( ',' , @ chain ) ;
unless ( $ ref - > { currchain } ) { #If we've gone off the end of the chain, have currchain stick
$ ref - > { currchain } = $ ref - > { currstate } ;
}
2009-12-04 00:59:53 +00:00
$ chaintab - > setNodeAttribs ( $ node , $ ref ) ; #$ref is in a state to commit back to db
2008-09-25 03:04:56 +00:00
2007-10-26 22:44:33 +00:00
my % requ ;
$ requ { node } = [ $ node ] ;
$ requ { arg } = [ $ ref - > { currstate } ] ;
2008-09-30 20:00:46 +00:00
setdestiny ( \ % requ , $ flag + 1 ) ;
2007-10-26 22:44:33 +00:00
}
2008-09-25 03:04:56 +00:00
2008-02-27 17:08:26 +00:00
if ( $ callnodeset ) {
$ subreq - > ( { command = > [ 'nodeset' ] ,
node = > \ @ nodes ,
arg = > [ 'enact' ] } ) ;
}
2008-09-25 03:04:56 +00:00
2007-10-26 22:44:33 +00:00
}
sub getdestiny {
2008-09-30 20:00:46 +00:00
my $ flag = shift ;
# flag value:
# 0--getdestiny is called by dodestiny
# 1--called by nextdestiny in dodestiny. The node calls nextdestiny before boot and runcmd.
# 2--called by nodeset command
# 3--called by updateflag after the node finished installation and before booting
2007-10-26 22:44:33 +00:00
my @ args ;
my @ nodes ;
if ( $ request - > { node } ) {
if ( ref ( $ request - > { node } ) ) {
@ nodes = @ { $ request - > { node } } ;
} else {
@ nodes = ( $ request - > { node } ) ;
}
} else { # a client asking for it's own destiny.
2008-01-25 15:07:53 +00:00
unless ( $ request - > { '_xcat_clienthost' } - > [ 0 ] ) {
2007-10-26 22:44:33 +00:00
$ callback - > ( { destiny = > [ 'discover' ] } ) ;
return ;
}
2008-01-25 15:07:53 +00:00
my ( $ node ) = noderange ( $ request - > { '_xcat_clienthost' } - > [ 0 ] ) ;
2007-10-26 22:44:33 +00:00
unless ( $ node ) { # it had a valid hostname, but isn't a node
$ callback - > ( { destiny = > [ 'discover' ] } ) ;
return ;
}
@ nodes = ( $ node ) ;
}
my $ node ;
2008-07-11 19:02:39 +00:00
$ restab = xCAT::Table - > new ( 'noderes' ) ;
2008-07-22 12:45:41 +00:00
my $ chaintab = xCAT::Table - > new ( 'chain' ) ;
2008-07-11 19:02:39 +00:00
my $ chainents = $ chaintab - > getNodesAttribs ( \ @ nodes , [ qw( currstate chain ) ] ) ;
my $ nrents = $ restab - > getNodesAttribs ( \ @ nodes , [ qw( tftpserver xcatmaster ) ] ) ;
$ bptab = xCAT::Table - > new ( 'bootparams' , - create = > 1 ) ;
my $ bpents = $ bptab - > getNodesAttribs ( \ @ nodes , [ qw( kernel initrd kcmdline xcatmaster ) ] ) ;
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
( my $ sent ) = $ sitetab - > getAttribs ( { key = > 'master' } , 'value' ) ;
2008-09-30 20:00:46 +00:00
my % node_status = ( ) ;
2007-10-26 22:44:33 +00:00
foreach $ node ( @ nodes ) {
unless ( $ chaintab ) { #Without destiny, have the node wait with ssh hopefully open at least
$ callback - > ( { node = > [ { name = > [ $ node ] , data = > [ 'standby' ] , destiny = > [ 'standby' ] } ] } ) ;
return ;
}
2008-07-11 19:02:39 +00:00
my $ ref = $ chainents - > { $ node } - > [ 0 ] ; #$chaintab->getNodeAttribs($node,[qw(currstate chain)]);
2007-10-26 22:44:33 +00:00
unless ( $ ref ) {
2008-09-30 20:00:46 +00:00
#collect node status for certain states
2009-03-24 13:51:56 +00:00
if ( ( $ nonodestatus == 0 ) && ( ( $ flag == 0 ) || ( $ flag == 3 ) ) ) {
2008-09-30 20:00:46 +00:00
my $ stat = xCAT_monitoring::monitorctrl - > getNodeStatusFromNodesetState ( "standby" , "getdestiny" ) ;
#print "node=$node, stat=$stat\n";
if ( $ stat ) {
if ( exists ( $ node_status { $ stat } ) ) {
my $ pa = $ node_status { $ stat } ;
push ( @$ pa , $ node ) ;
}
else { $ node_status { $ stat } = [ $ node ] ; }
}
}
2007-10-26 22:44:33 +00:00
$ callback - > ( { node = > [ { name = > [ $ node ] , data = > [ 'standby' ] , destiny = > [ 'standby' ] } ] } ) ;
2008-09-30 20:00:46 +00:00
next ;
2007-10-26 22:44:33 +00:00
}
unless ( $ ref - > { currstate } ) { #Has a record, but not yet in a state...
2010-01-21 06:11:24 +00:00
# we set a 1 here so that it does the nodeset to create tftpboot files
return nextdestiny ( 0 , 1 ) ; #Becomes a nextdestiny...
2008-10-03 23:16:57 +00:00
# my @chain = split /,/,$ref->{chain};
# $ref->{currstate} = shift @chain;
# $chaintab->setNodeAttribs($node,{currstate=>$ref->{currstate}});
2007-10-26 22:44:33 +00:00
}
my % response ;
$ response { name } = [ $ node ] ;
$ response { data } = [ $ ref - > { currstate } ] ;
$ response { destiny } = [ $ ref - > { currstate } ] ;
2008-07-11 19:02:39 +00:00
my $ nrent = $ nrents - > { $ node } - > [ 0 ] ; #$noderestab->getNodeAttribs($node,[qw(tftpserver xcatmaster)]);
my $ bpent = $ bpents - > { $ node } - > [ 0 ] ; #$bptab->getNodeAttribs($node,[qw(kernel initrd kcmdline xcatmaster)]);
2008-04-25 15:36:56 +00:00
if ( defined $ bpent - > { kernel } ) {
$ response { kernel } = $ bpent - > { kernel } ;
2007-10-26 22:44:33 +00:00
}
2008-04-25 15:36:56 +00:00
if ( defined $ bpent - > { initrd } ) {
$ response { initrd } = $ bpent - > { initrd } ;
2007-10-26 22:44:33 +00:00
}
2008-04-25 15:36:56 +00:00
if ( defined $ bpent - > { kcmdline } ) {
$ response { kcmdline } = $ bpent - > { kcmdline } ;
2007-10-26 22:44:33 +00:00
}
if ( defined $ nrent - > { tftpserver } ) {
$ response { imgserver } = $ nrent - > { tftpserver } ;
} elsif ( defined $ nrent - > { xcatmaster } ) {
$ response { imgserver } = $ nrent - > { xcatmaster } ;
} elsif ( defined ( $ sent - > { value } ) ) {
$ response { imgserver } = $ sent - > { value } ;
2008-02-07 21:48:21 +00:00
} else {
$ response { imgserver } = xCAT::Utils - > my_ip_facing ( $ node ) ;
2007-10-26 22:44:33 +00:00
}
2008-09-30 20:00:46 +00:00
#collect node status for certain states
if ( ( $ flag == 0 ) || ( $ flag == 3 ) ) {
my $ stat = xCAT_monitoring::monitorctrl - > getNodeStatusFromNodesetState ( $ response { destiny } - > [ 0 ] , "getdestiny" ) ;
#print "node=$node, stat=$stat\n";
if ( $ stat ) {
if ( exists ( $ node_status { $ stat } ) ) {
my $ pa = $ node_status { $ stat } ;
push ( @$ pa , $ node ) ;
}
else { $ node_status { $ stat } = [ $ node ] ; }
}
}
2007-10-26 22:44:33 +00:00
$ callback - > ( { node = > [ \ % response ] } ) ;
}
2008-09-30 20:00:46 +00:00
#setup the nodelist.status
2009-03-24 13:51:56 +00:00
if ( ( $ nonodestatus == 0 ) && ( ( $ flag == 0 ) || ( $ flag == 3 ) ) ) {
2008-09-30 20:00:46 +00:00
#print "save status\n";
if ( keys ( % node_status ) > 0 ) { xCAT_monitoring::monitorctrl:: setNodeStatusAttributes ( \ % node_status , 1 ) ; }
}
2007-10-26 22:44:33 +00:00
}
1 ;