Commit ac711ea5 authored by Mike Hibler's avatar Mike Hibler

Initial support for loading Windows7 .wim images via WinPE/ImageX.

1. Support for "one-shot" PXE booting ala the one-shot osid. Switches to
   pxelinux to boot WinPE and then switch back after done. Painful now
   because we have to HUP dhcpd everytime we change the PXE path, but we
   may be able to fix this in the future by going all-pxelinux-all-the-time.

2. Added pxe_select, analogous to os_select, for changing the pxe_boot_path
   including the one time path.

3. Added the WIMRELOAD state machine to shepherd a node through the process.
   Still has some rough edges and may need refining.
parent d7058b4e
......@@ -7206,7 +7206,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/console_reset tbsetup/bwconfig tbsetup/power_rpc27.pm \
tbsetup/power_mail.pm tbsetup/power_whol.pm \
tbsetup/os_load tbsetup/os_setup tbsetup/os_select tbsetup/power \
tbsetup/node_reboot tbsetup/nscheck \
tbsetup/node_reboot tbsetup/nscheck tbsetup/pxe_select \
tbsetup/resetvlans tbsetup/rmuser tbsetup/rmproj \
tbsetup/sched_reload tbsetup/sched_reserve tbsetup/reload_daemon \
tbsetup/batchexp tbsetup/batch_daemon tbsetup/repos_daemon \
......
......@@ -927,7 +927,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/console_reset tbsetup/bwconfig tbsetup/power_rpc27.pm \
tbsetup/power_mail.pm tbsetup/power_whol.pm \
tbsetup/os_load tbsetup/os_setup tbsetup/os_select tbsetup/power \
tbsetup/node_reboot tbsetup/nscheck \
tbsetup/node_reboot tbsetup/nscheck tbsetup/pxe_select \
tbsetup/resetvlans tbsetup/rmuser tbsetup/rmproj \
tbsetup/sched_reload tbsetup/sched_reserve tbsetup/reload_daemon \
tbsetup/batchexp tbsetup/batch_daemon tbsetup/repos_daemon \
......
......@@ -139,8 +139,8 @@ use vars qw(@ISA @EXPORT);
TBDB_EXPT_WORKDIR
TB_OSID_MBKERNEL
TB_OSID_FREEBSD_MFS TB_OSID_FRISBEE_MFS
TBDB_TBCONTROL_RESET TBDB_TBCONTROL_RELOADDONE
TBDB_TBCONTROL_RELOADDONE_V2
TBDB_TBCONTROL_PXERESET TBDB_TBCONTROL_RESET
TBDB_TBCONTROL_RELOADDONE TBDB_TBCONTROL_RELOADDONE_V2
TBDB_TBCONTROL_TIMEOUT TBDB_NO_STATE_TIMEOUT
TBDB_TBCONTROL_PXEBOOT TBDB_TBCONTROL_BOOTING
TBDB_TBCONTROL_CHECKGENISUP
......@@ -454,6 +454,7 @@ sub TBDB_ALLOCSTATE_RES_REBOOT() { "RES_REBOOT"; }
sub TBDB_ALLOCSTATE_RES_TEARDOWN() { "RES_TEARDOWN"; }
sub TBDB_ALLOCSTATE_UNKNOWN() { "UNKNOWN"; };
sub TBDB_TBCONTROL_PXERESET { "PXERESET"; }
sub TBDB_TBCONTROL_RESET { "RESET"; }
sub TBDB_TBCONTROL_RELOADDONE { "RELOADDONE"; }
sub TBDB_TBCONTROL_RELOADDONE_V2{ "RELOADDONEV2"; }
......
......@@ -2628,6 +2628,34 @@ sub OSSelect($$$$)
return Refresh($self);
}
#
#
#
sub PXESelect($$$$$)
{
my ($self, $path, $field, $debug, $changedp) = @_;
my $nodeid = $self->node_id();
my $didit = 0;
print STDERR "Setting $field for $nodeid to '$path'.\n"
if ($debug && $path);
my $cur = ($field eq "pxe_boot_path") ?
$self->pxe_boot_path() : $self->next_pxe_boot_path();
$cur = "" if (!$cur);
if ($cur ne $path) {
DBQueryWarn("update nodes set ${field}=".
($path ? "'$path'" : "NULL") .
" where node_id='$nodeid'")
or return -1;
$didit = 1;
}
$$changedp = $didit
if (defined($changedp));
return Refresh($self);
}
sub ResetNextOpMode($$)
{
my ($self,$debug) = @_;
......
......@@ -213,7 +213,8 @@ while (<IF>) {
my $nodetype = $2;
$query_result =
DBQueryWarn("select n.node_id,n.pxe_boot_path,n.type, ".
DBQueryWarn("select n.node_id,n.type, ".
" n.pxe_boot_path,n.next_pxe_boot_path,".
" i.IP,i.MAC,r.pid,r.eid,r.vname, ".
" r.inner_elab_role,r.inner_elab_boot, ".
" r.plab_role,r.plab_boot ".
......@@ -308,13 +309,17 @@ while (<IF>) {
#
# Handle alternate boot program filename if it exists.
# Use mutable nodes.pxe_boot_path if it is defined.
# Use mutable nodes.next_pxe_boot_path or
# nodes.pxe_boot_path if one is defined.
# Otherwise use the node_types.pxe_boot_path if it is
# defined. Otherwise don't set anything (use the global
# default).
#
$filename = SetupPXEBoot($node_id, $mac, 1,
$row{"pxe_boot_path"});
my $pxeboot = $row{"next_pxe_boot_path"};
if (!$pxeboot) {
$pxeboot = $row{"pxe_boot_path"};
}
$filename = SetupPXEBoot($node_id, $mac, 1, $pxeboot);
if (!$filename) {
# Get the type info for this type.
my $nodetype = NodeType->Lookup($row{"type"});
......
......@@ -275,8 +275,11 @@ if (1) {
}
# fixup any nodes table entries with non-standard pxe_boot_path's
# and clear any one-shot values
DBQueryFatal("update nodes set pxe_boot_path=NULL ".
" where pxe_boot_path is not NULL");
DBQueryFatal("update nodes set next_pxe_boot_path=NULL ".
" where next_pxe_boot_path is not NULL");
#
# Now symlink all the alternate boots to pxeboot.emu
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
#
use strict;
......@@ -351,8 +351,9 @@ if ($moveToOldReserved) {
# NOTE: this does not happen very often. elabinelab, plabinelab?
#
foreach my $node (@freed_nodes) {
if ($node->pxe_boot_path() && $node->pxe_boot_path() ne "") {
$node->Update({"pxe_boot_path" => "NULL"}) == 0 or
if ($node->pxe_boot_path() || $node->next_pxe_boot_path()) {
$node->Update({"pxe_boot_path" => "NULL",
"next_pxe_boot_path" => "NULL"}) == 0 or
die("*** $0:\n".
" Could not update pxe_boot_path for $node\n");
$mustmakeconf = 1;
......
......@@ -26,6 +26,7 @@ my $TBOPS = "@TBSTATEDEMAIL@";
my $REALTBOPS = "@TBOPSEMAIL@";
my $TBDBNAME = "@TBDBNAME@";
my $REALTBDBNAME = "tbdb"; # So we know if we're using the "real" db
my $pxeselect = "$TB/bin/pxe_select";
my $osselect = "$TB/bin/os_select";
my $nodereboot = "$TB/bin/node_reboot";
my $rebootlog = "$TB/log/nodereboot.log";
......@@ -124,6 +125,7 @@ if ($opt{d}) {
# Grab some constants into variables
my $TBANYMODE = TBDB_NODEOPMODE_ANY;
my $TBPXERESET = TBDB_TBCONTROL_PXERESET;
my $TBRESET = TBDB_TBCONTROL_RESET;
my $TBTIMEOUT = TBDB_TBCONTROL_TIMEOUT;
my $PXEBOOT = TBDB_TBCONTROL_PXEBOOT;
......@@ -891,6 +893,12 @@ sub stateTransition($$) {
CheckPortRegistration($node);
next;
};
/^$TBPXERESET$/ && do {
# We successfully booted, so reset one-shot PXEboot if any
# Check if we really need to do a reset
handleCtrlEvent($node,$trig);
next;
};
/^$TBRESET$/ && do {
# We successfully booted, so clear some flags
$nodes{$node}{noretry} = 0;
......@@ -1050,6 +1058,21 @@ sub handleCtrlEvent($$) {
info("CtrlEvent: $node, $event\n");
foreach ($event) {
/^$TBPXERESET$/ && do {
#
# Clear next_pxe_boot_path with pxe_select.
#
# Note that this will recreate the DHCPD config file and HUP it.
# It will also ssh over to any subbosses and do the same.
# Thus there is lost of potential to get hung or take a long time.
#
$cmd = "$pxeselect -d -c -1 $node";
system($cmd) and
notify("$node/$event: Could not clear next_pxe_boot_path!\n");
info("Performed $TBPXERESET for $node\n");
next;
};
/^$TBRESET$/ && do {
#
# Clear next_boot_path with os_select.
......
......@@ -329,6 +329,24 @@ REPLACE INTO mode_transitions VALUES ('SECUREBOOT','TPMSIGNOFF','NORMALv2','SHUT
REPLACE INTO mode_transitions VALUES ('SECUREBOOT','TPMSIGNOFF','PXEFBSD','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('SECUREBOOT','TPMSIGNOFF','PXEKERNEL','BOOTING','SecureBootDone');
REPLACE INTO mode_transitions VALUES ('NORMALv2','SHUTDOWN','SECURELOAD','SHUTDOWN','SecureLoadStart');
#
REPLACE INTO mode_transitions VALUES ('PXEFBSD','SHUTDOWN','WIMRELOAD','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('MINIMAL','SHUTDOWN','WIMRELOAD','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('NETBOOT','SHUTDOWN','WIMRELOAD','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('NORMAL','SHUTDOWN','WIMRELOAD','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('NORMALv1','SHUTDOWN','WIMRELOAD','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('NORMALv2','SHUTDOWN','WIMRELOAD','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('WIMRELOAD','SHUTDOWN','PXEFBSD','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('WIMRELOAD','SHUTDOWN','MINIMAL','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('WIMRELOAD','SHUTDOWN','NETBOOT','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('WIMRELOAD','SHUTDOWN','NORMAL','REBOOTING','');
REPLACE INTO mode_transitions VALUES ('WIMRELOAD','SHUTDOWN','NORMALv1','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('WIMRELOAD','SHUTDOWN','NORMALv2','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('WIMRELOAD','RELOADDONE','MINIMAL','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('WIMRELOAD','RELOADDONE','NETBOOT','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('WIMRELOAD','RELOADDONE','NORMAL','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('WIMRELOAD','RELOADDONE','NORMALv1','SHUTDOWN','');
REPLACE INTO mode_transitions VALUES ('WIMRELOAD','RELOADDONE','NORMALv2','SHUTDOWN','');
--
-- Dumping data for table `priorities`
......@@ -407,6 +425,11 @@ REPLACE INTO state_timeouts VALUES ('SECURELOAD','RELOADING',3600,'STATE:SECVIOL
REPLACE INTO state_timeouts VALUES ('SECURELOAD','RELOADSETUP',60,'STATE:SECVIOLATION');
REPLACE INTO state_timeouts VALUES ('SECURELOAD','SHUTDOWN',300,'STATE:SECVIOLATION');
REPLACE INTO state_timeouts VALUES ('SECURELOAD','TPMSIGNOFF',300,'STATE:SECVIOLATION');
#
REPLACE INTO state_timeouts VALUES ('WIMRELOAD','SHUTDOWN',240,'REBOOT');
REPLACE INTO state_timeouts VALUES ('WIMRELOAD','RELOADSETUP',60,'NOTIFY');
REPLACE INTO state_timeouts VALUES ('WIMRELOAD','RELOADING',1800,'NOTIFY');
REPLACE INTO state_timeouts VALUES ('WIMRELOAD','RELOADDONE',60,'NOTIFY');
--
-- Dumping data for table `state_transitions`
......@@ -610,6 +633,7 @@ REPLACE INTO state_transitions VALUES ('RELOAD-PUSH','RELOADDONE','SHUTDOWN','Re
REPLACE INTO state_transitions VALUES ('RELOAD-PUSH','SHUTDOWN','RELOADSETUP','ReloadSetup');
REPLACE INTO state_transitions VALUES ('SECUREBOOT','BOOTING','SECVIOLATION','QuoteFailed');
REPLACE INTO state_transitions VALUES ('SECUREBOOT','BOOTING','TPMSIGNOFF','QuoteOK');
REPLACE INTO state_transitions VALUES ('SECUREBOOT','BOOTING','PXEBOOTING','re-BootInfo');
REPLACE INTO state_transitions VALUES ('SECUREBOOT','GPXEBOOTING','PXEBOOTING','DHCP');
REPLACE INTO state_transitions VALUES ('SECUREBOOT','PXEBOOTING','BOOTING','BootInfo');
REPLACE INTO state_transitions VALUES ('SECURELOAD','BOOTING','PXEBOOTING','re-BootInfo');
......@@ -633,6 +657,14 @@ REPLACE INTO state_transitions VALUES ('NORMALv2','*','POWEROFF','Power Off');
REPLACE INTO state_transitions VALUES ('NORMAL','POWEROFF','SHUTDOWN','Power On');
REPLACE INTO state_transitions VALUES ('NORMALv1','POWEROFF','SHUTDOWN','Power On');
REPLACE INTO state_transitions VALUES ('NORMALv2','POWEROFF','SHUTDOWN','Power On');
#
REPLACE INTO state_transitions VALUES ('WIMRELOAD','SHUTDOWN','RELOADSETUP','BootOK');
REPLACE INTO state_transitions VALUES ('WIMRELOAD','RELOADSETUP','RELOADING','ReloadStart');
REPLACE INTO state_transitions VALUES ('WIMRELOAD','RELOADING','RELOADDONE','ReloadDone');
REPLACE INTO state_transitions VALUES ('WIMRELOAD','SHUTDOWN','SHUTDOWN','Retry');
REPLACE INTO state_transitions VALUES ('WIMRELOAD','SHUTDOWN','PXEBOOTING','WrongPXEboot');
REPLACE INTO state_transitions VALUES ('WIMRELOAD','RELOADSETUP','SHUTDOWN','Error');
REPLACE INTO state_transitions VALUES ('WIMRELOAD','RELOADING','SHUTDOWN','Error');
--
-- Dumping data for table `state_triggers`
......@@ -662,6 +694,11 @@ REPLACE INTO state_triggers VALUES ('*','SECUREBOOT','TPMSIGNOFF','PXEBOOT, BOOT
REPLACE INTO state_triggers VALUES ('*','SECURELOAD','BOOTING','BOOTING');
REPLACE INTO state_triggers VALUES ('*','SECURELOAD','PXEBOOTING','');
REPLACE INTO state_triggers VALUES ('*','SECURELOAD','RELOADDONE','RESET, RELOADDONE');
#
REPLACE INTO state_triggers VALUES ('*','WIMRELOAD','RELOADDONE','PXERESET, RESET, RELOADDONE');
REPLACE INTO state_triggers VALUES ('*','WIMRELOAD','PXEBOOTING','REBOOT');
REPLACE INTO state_triggers VALUES ('*','WIMRELOAD','BOOTING','REBOOT');
REPLACE INTO state_triggers VALUES ('*','WIMRELOAD','ISUP','REBOOT');
--
-- Dumping data for table `table_regex`
......
......@@ -26,6 +26,7 @@ BIN_STUFF = power snmpit snmpit_new tbend tbprerun tbreport \
node_reboot nscheck node_update savelogs node_control \
portstats checkports eventsys_control os_select tbrestart \
tbswap nseswap tarfiles_setup node_history tbrsync \
pxe_select \
archive_control template_create \
template_swapin template_swapout template_graph \
template_exprun template_delete template_metadata \
......
......@@ -44,6 +44,11 @@ my $OUTERBOSS = "@OUTERBOSS_NODENAME@";
my $TBUISP = "$TB/bin/tbuisp";
my $FRISBEE = "$TB/sbin/frisbee";
# XXX windows load
my $MAKECONF = "$TB/sbin/dhcpd_makeconf";
my $IMAGEX_OSNAME = "IMAGEX-MFS";
my $IMAGEX_PXEPATH = "/tftpboot/pxelinux/winpe";
#
# Max number of retries (per node) before its deemed fatal. This allows
# for the occasional pxeboot failure.
......@@ -215,7 +220,7 @@ sub nodeflag($$$;$)
return $retval;
}
# Get/Set the osid->osinfo mapping. Nice to keep this to avoid lookups.
# Get/Set the imageid->images mapping. Nice to keep this to avoid lookups.
sub imageinfo($$;$)
{
my ($self,$imageid,$imageinfo) = @_;
......@@ -2188,6 +2193,7 @@ sub SetupReload($$)
{
my ($self,$nodeobject) = @_;
my $node_id = $nodeobject->node_id();
my $osinfo;
$self->dprint(0,"SetupReload($node_id): setting up reload");
......@@ -2208,9 +2214,24 @@ sub SetupReload($$)
return -1
if (!$query_result);
# XXX windows load
my $needswinpe = 0;
my $idx = 1;
foreach my $imageid (@imageids) {
my $prepare0 = $idx == 1 && $prepare ? 1 : 0;
# XXX windows load
my $rowref = $self->imageinfo($imageid);
if (!defined($rowref)) {
tberror "$self: Mike make a bad assumption!";
return -1;
}
my $format = $rowref->{'format'};
if (defined($format) && $format eq "wim") {
$needswinpe++;
}
my $query_result =
DBQueryWarn("insert into current_reloads ".
"(node_id, idx, image_id, mustwipe, prepare) values ".
......@@ -2220,12 +2241,38 @@ sub SetupReload($$)
++$idx;
}
my $osinfo = OSinfo->Lookup($osid);
# XXX windows load
if ($needswinpe) {
if (@imageids > 1) {
tberror("$self: Cannot load more than one image with WinPE/ImageX");
return -1;
}
# Look up the magic osid for the imageX loader
$osinfo = OSinfo->Lookup(TB_OPSPID, $IMAGEX_OSNAME);
}
else {
$osinfo = OSinfo->Lookup($osid);
}
if ($nodeobject->OSSelect($osinfo,"next_boot_osid",$self->debug())) {
tberror "$self: os_select $osid failed!";
return -1;
}
# XXX windows load
# whether windows or not, we always make sure this is set correctly
my $changed = 0;
my $path = $needswinpe ? $IMAGEX_PXEPATH : "";
if ($nodeobject->PXESelect($path, "next_pxe_boot_path",
$self->debug(), \$changed)) {
tberror "$self: pxe_select $path failed!";
return -1;
}
if ($changed && system("$MAKECONF -i -r")) {
tberror "$self: restart DHCPD failed!";
return -1;
}
return 0;
}
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
#
# pxe_select sets the PXE boot program that should be loaded on a node,
# either one time or permanently.
sub usage() {
print <<"EOF";
Usage: pxe_select -P [-c] [-1] [<path>] <node> [<node> ...]
-h Display this help message
-d Debug mode
-c Clear the PXE boot path for nodes. Do not provide a path.
Either clears the one-time field (for -1) or resets to the default PXE boot.
-1 Apply change to one-time PXE boot field
-N Do not restart dhcpd on a change
path Path to PXE boot program (must be in /tftpboot)
node Node identifiers (ie pcXX)
EOF
exit(-1);
}
my $optlist = "hdc1lN";
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
$| = 1; #Turn off line buffering on output
# Configure variables
my $TB = "@prefix@";
my $TBOPS = "@TBSTATEDEMAIL@";
my $TBLOG = "@TBLOGFACIL@";
# Testbed Support libraries
use lib "@prefix@/lib";
use libdb;
use libtestbed;
use OSinfo;
use Node;
use English;
use Getopt::Std;
use Sys::Syslog;
# Constants
my $makeconf = "$TB/sbin/dhcpd_makeconf";
my $MBKERNEL = TB_OSID_MBKERNEL;
my %osidmap = # Map some magic OSIDs to op_modes
( $MBKERNEL => "MINIMAL");
# Functions
sub set_nextmode($;$);
sub set_boot_osid($);
sub node_opmode($);
sub debug($;$);
sub notify($);
sub info($);
sub fatal($);
sub warning($);
# Global vars
my $debug = 0; # debug/verbose
my $oneshot = 0; # apply change to next_boot_osid.
my $clear = 0; # Clear the selected boot (def,temp,next).
my $list = 0; # Just list the current settings.
my $nochange = 0; # Do not restart dhcpd on a change
my @nodes = ();
my $pxebootpath = "";
# Set up syslog
openlog("pxeselect", "pid", $TBLOG);
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) { usage(); }
if (defined($options{"h"})) { usage(); }
if (defined($options{"d"})) { $debug=1; }
if (defined($options{"1"})) { $oneshot=1; }
if (defined($options{"c"})) { $clear=1; }
if (defined($options{"l"})) { $list=1; }
if (defined($options{"N"})) { $nochange=1; }
if (! ($clear || $list)) {
usage()
if (@ARGV < 2);
$pxebootpath = shift();
# Untaint args.
if ($pxebootpath !~ /\.\./ &&
$pxebootpath =~ /^(\/tftpboot\/[-\w\+\.\/]+)$/) {
$pxebootpath = $1;
}
else {
fatal("Bad path: '$pxebootpath'");
}
}
else {
usage()
if (@ARGV < 1);
}
# Untaint the nodes.
foreach my $node ( @ARGV ) {
if ($node =~ /^([-\@\w]+)$/) {
$node = $1;
}
else {
fatal("Bad node name: $node");
}
push(@nodes, $node);
}
#
# Figure out who called us. Only root, people with admin status
# in the DB, or members of the right project can do this.
#
if ($UID && !TBAdmin($UID)) {
if ($list && !TBNodeAccessCheck($UID, TB_NODEACCESS_READINFO, @nodes)) {
fatal("pxe_select: You do not have permission to access ".
"one or more of the nodes.\n");
}
if (!$list && !TBNodeAccessCheck($UID, TB_NODEACCESS_MODIFYINFO, @nodes)) {
fatal("pxe_select: You do not have permission to modify ".
"one or more of the nodes.\n");
}
}
my $changed = 0;
foreach my $node (@nodes) {
my $nodeobject = Node->Lookup($node);
# In list mode, show all the IDs
if ($list) {
my $npb = $nodeobject->next_pxe_boot_path();
my $pb = $nodeobject->pxe_boot_path();
if (!$pb) {
$nodeobject->NodeTypeAttribute("pxe_boot_path", \$pb);
if ($pb) {
$pb = "$pb (NODE TYPE DEFAULT)";
} else {
$pb = "/tftpboot/pxeboot.emu (SYSTEM DEFAULT)";
}
}
print "$node: ";
if ($npb) {
print "next_pxeboot=$npb";
print ", ";
}
if ($pb) {
print "pxeboot=$pb";
}
print "\n";
next;
}
# The field to change in the DB.
my $field = "pxe_boot_path";
$field = "next_pxe_boot_path"
if ($oneshot);
my $did;
if ($nodeobject->PXESelect($pxebootpath, $field, $debug, \$did) != 0) {
fatal("PXESelect(): " . ($pxebootpath ? "$pxebootpath " : "") ."failed on $node");
}
$changed += $did;
}
#
# Need to remake the dhcpd.conf file if we changed a
# pxeboot path.
#
if (!$nochange && $changed) {
system("$makeconf -i -r") == 0 ||
notify("$makeconf failed!\n");
}
exit(0);
sub debug($;$)
{
my $msg = shift;
my $notice = shift || 0;
my $prio="info";
if ($notice) { $prio = "notice"; }
syslog($prio, $msg);
if ($debug) { print $msg; }
}
sub notify($)
{
my $msg = shift;
if (!$debug) {
SENDMAIL($TBOPS, "pxe_select error", $msg);
}
debug($msg, 1);
}
sub info($)
{
my $msg = shift;
debug($msg);
}
sub fatal($)
{
my $msg = shift;
notify("FATAL: $msg\n");
exit(1);
}
sub warning($)
{
my $msg = shift;
info("WARNING: $msg\n");
}
# This is called when we exit with exit() or die()
END {
closelog();
}
......@@ -9312,14 +9312,15 @@ COMMAND_PROTOTYPE(dodhcpdconf)
mysql_free_result(res);
res = mydb_query("select n.node_id,n.pxe_boot_path,i.IP,i.mac,n.type,r.eid,r.pid,"
"r.inner_elab_role,r.inner_elab_boot,r.plab_role,r.plab_boot "
"r.inner_elab_role,r.inner_elab_boot,r.plab_role,r.plab_boot,"
"n.next_pxe_boot_path "
"from nodes as n "
"left join subbosses as s on n.node_id = s.node_id "
"left join interfaces as i on n.node_id = i.node_id "
"left join reserved as r on n.node_id = r.node_id "
"where s.subboss_id = '%s' and "
"s.service='dhcp' and i.role='ctrl' order by n.priority", 11,
reqp->nodeid);
"s.service='dhcp' and i.role='ctrl' "
"order by n.priority", 12, reqp->nodeid);
if (!res) {
error("dodhcpconf: %s: "
......@@ -9475,7 +9476,17 @@ COMMAND_PROTOTYPE(dodhcpdconf)
remain -= rc;
}
if (row[1] != NULL) {
if (row[11] && row[11][0]) {
rc = snprintf(b, remain, " FILENAME=\"%s\"", row[11]);
if (rc < 0) {
error("dodhcpdconf: error creating output\n");
return 1;
}
b += rc;
remain -= rc;
} else if (row[1] && row[1][0]) {
rc = snprintf(b, remain, " FILENAME=\"%s\"", row[1]);
if (rc < 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment