Commit 2b2b8ca1 authored by Leigh Stoller's avatar Leigh Stoller

Death to proxydhcp; one less specialized daemon. DHCP will return the

filename to boot, and all local nodes will boot the same pxeboot kernel,
which has been extended to allow for jumping directly into a specific MFS
(in addition to the usual testbed boot into a partition or multiboot
kernel).

Bootinfo and the bootwhat protocol extended to tell the client node what
MFS to jump into directly, without a reboot. pxe_boot_path and
next_pxe_boot_path are now deprecated, with bootinfo used to control which
MFS to boot. Nodes now boot a single pxeboot kernel, and bootinfo tells
them what to do next.

Bootinfo greatly simplifed. temp_boot_osid has been added to allow for
temporary booting of different kernels (such as with ndoe_admin or
create_image). Unlike next_boot_osid which is a one-shot boot,
temp_boot_osid causes the node to boot that OS until told not too.

next_boot_path and def_boot_path in the nodes table are now ignored.
Bootinfo gets path info strictly from the os_info table entry for the osid
given in one of def_boot_osid, temp_boot_osid, or next_boot_osid.  This
makes the selection of what to do in bootinfo a lot simpler (and for
TBBootWhat in libdb). The os_info table also modified to include an MFS
flag so that bootinfo knows to tell the client that the path refers to an
MFS and not a multiboot kernel.

Change to boot sequence; free nodes no longer boot into the default OSID.
Instead, they are told to wait in pxeboot until told what to do, which
will typically be when the node is allocated and a specific OSID
picked. If the node needs to be reloaded, then the node is told to jump
directly into the Frisbee MFS, which saves one complete reboot cycle
whether the node has the requested OS installed, or not.  New program
added called "bootinfosend" that is used by node_reboot to "wake up" up
nodes sitting in pxewait mode, so that they query bootinfo again and boot.

node_reboot changed to look at the event state of a node, and use
bootinfosend to wake up nodes, rather then power cycle, since pxeboot does
not repsond to pings. Retry (if the UDP packet is lost) is handled by
stated.

Event support added to bootinfo, to replace the event generation that was
in proxydhcp. I have not included the caching that Mac had in proxydhcp
since it does not appear that bootinfo packets are lost very
often. Cleaned up all of the event and DB queury code to use lib/libtb for
DB access, and moved all of the event code into a separate file.  The
event sequence when a node boots now looks like this:

	'SHUTDOWN'    --> 'PXEBOOTING'  (BootInfo)
	'PXEBOOTING', --> 'PXEBOOTING'  (BootInfo Retry)
	'PXEBOOTING', --> 'BOOTING'     (Node Not Free)
	'PXEBOOTING', --> 'PXEWAIT'     (Node is Free)
	'PXEWAIT',    --> 'PXEWAKEUP'   (Node Allocated)
	'PXEWAKEUP',  --> 'PXEWAKEUP'   (Bootinfo Retry)
	'PXEWAKEUP',  --> 'PXEBOOTING'  (Node Woke Up)

Change stated to support resending PXEWAKEUP events when node times out.
After 3 tries, node is power cycled. Other minor cleanup in stated.

Clean up and simplify os_select, while adding support for temp_next_boot
and removing all trace of def_boot_path and next_boot_path processing.
Remove all pxe_boot_path and next_pxe_boot_path processing.  Changed
command line interface to support "clearing" fields. For example,
node_admin changed to call os_select like this to have the node
temporarily boot the FreeBSD MFS:

	os_select -t FREEBSD-MFS pcXXX

which sets temp_boot_osid. To turn admin mode off:

	os_select -c -t pcXXX

which says to clear temp_boot_osid.

sql/database-fill-supplemental.sql modifed to add os_info table
entries for the FreeBSD, Frisbee, and newnode MFS's.

Be sure to change dhcpd config, restart dhcp, kill proxydhcp, restart
bootinfo,
parent 899be6af
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2003 University of Utah and the Flux Group.
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -16,7 +16,7 @@ include $(OBJDIR)/Makeconf
# Force dependencies on the scripts so that they will be rerun through
# configure if the .in file is changed.
#
all: proxydhcp bootinfo proxydhcp.restart bootinfo.restart
all: proxydhcp bootinfo bootinfosend proxydhcp.restart bootinfo.restart
include $(TESTBED_SRCDIR)/GNUmakerules
......@@ -28,15 +28,19 @@ BI_DBOBJ = bootinfo_null.o bootinfo_cfile.o bootinfo_mysql.o
PR_DBSRC = proxydhcp_cfile.c proxydhcp_mysql.c
PR_DBOBJ = proxydhcp_cfile.o proxydhcp_mysql.o
INCS = -I/usr/local/include
INCS = -I${OBJDIR} -I/usr/local/include -I$(TESTBED_SRCDIR)/lib/libtb
CFLAGS += $(INCS) $(DBFLAG) -DSOLARIS -DHAVE_SOCKADDR_SA_LEN -DUSE_RECVMSG \
-DCONFPATH='"$(INSTALL_ETCDIR)/"' -DTBDBNAME='"$(TBDBNAME)"' \
-DFALLBACK_HOST='"$(BOSSNODE)"' -DBOSSNODE='"$(BOSSNODE)"' \
-DDEFAULT_PATH='"/tftpboot/pxeboot.newnode"' \
-DLOG_TESTBED=$(LOG_TESTBED)
CFLAGS += -Wall \
$(INCS) $(DBFLAG) -DSOLARIS -DHAVE_SOCKADDR_SA_LEN -DUSE_RECVMSG \
-DCONFPATH='"$(INSTALL_ETCDIR)/"' -DTBDBNAME='"$(TBDBNAME)"' \
-DFALLBACK_HOST='"$(BOSSNODE)"' -DBOSSNODE='"$(BOSSNODE)"' \
-DDEFAULT_PATH='"/tftpboot/pxeboot.newnode"' \
-DLOG_TESTBED=$(LOG_TESTBED)
ifeq ($(EVENTSYS),1)
BI_DBSRC += event-support.c
BI_DBOBJ += event-support.o
CFLAGS += -DEVENTSYS -I$(TESTBED_SRCDIR)/event/lib \
`elvin-config --cflags vin4c`
LFLAGS += $(OBJDIR)/event/lib/libevent.a ${OBJDIR}/lib/libtb/libtb.a \
......@@ -48,11 +52,18 @@ proxydhcp: proxydhcp.o $(PR_DBOBJ)
-o proxydhcp proxydhcp.o $(PR_DBOBJ) \
$(LFLAGS) -L/usr/local/lib/mysql -lmysqlclient
bootinfo: bootinfo.o $(BI_DBOBJ)
bootinfo: bootinfo.o bootinfo.h bootinfo_version.o bootwhat.h $(BI_DBOBJ)
cc $(CFLAGS) $(DBFLAG) $(INCS) \
-o bootinfo bootinfo.o bootinfo_version.o $(BI_DBOBJ) \
$(LFLAGS) -L/usr/local/lib/mysql -lmysqlclient
bootinfosend: bootinfosend.o bootinfo.h bootinfo_version.o bootwhat.h $(BI_DBOBJ)
cc $(CFLAGS) $(DBFLAG) $(INCS) \
-o bootinfo bootinfo.o $(BI_DBOBJ) \
-o bootinfosend bootinfosend.o bootinfo_version.o $(BI_DBOBJ) \
$(LFLAGS) -L/usr/local/lib/mysql -lmysqlclient
bootinfo_mysql.o: bootinfo.h bootwhat.h
testbootinfo_mysql: bootinfo_mysql.c
cc $(CFLAGS) -DUSE_MYSQL_DB -DTEST $(INCS) \
-o testmysql $< \
......@@ -69,12 +80,20 @@ testproxydhcp_mysql: proxydhcp_mysql.c
testproxydhcp_cfile: proxydhcp_cfile.c
cc $(CFLAGS) -DUSE_CFILE_DB -DTEST $(INCS) -o testcfile $< $(LFLAGS)
proxydhcp_version.c: proxydhcp.c proxydhcp_mysql.c
echo >$@ "char build_info[] = \"Built `date +%d-%b-%Y` by `id -nu`@`hostname | sed 's/\..*//'`:`pwd`\";"
bootinfo_version.c: bootinfo.c bootinfo_mysql.c
echo >$@ "char build_info[] = \"Built `date +%d-%b-%Y` by `id -nu`@`hostname | sed 's/\..*//'`:`pwd`\";"
install: all
install: $(INSTALL_SBINDIR)/proxydhcp \
$(INSTALL_SBINDIR)/proxydhcp.restart \
$(INSTALL_SBINDIR)/bootinfo \
$(INSTALL_SBINDIR)/bootinfo.restart \
$(INSTALL_SBINDIR)/bootinfosend \
$(INSTALL_ETCDIR)/proxydhcp.conf \
$(INSTALL_ETCDIR)/bootinfo.conf
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2003 University of Utah and the Flux Group.
* Copyright (c) 2000-2004 University of Utah and the Flux Group.
* All rights reserved.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <syslog.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "log.h"
#include "tbdefs.h"
#include "bootwhat.h"
#include "bootinfo.h"
static void log_bootwhat(struct in_addr ipaddr, boot_what_t *bootinfo);
static void onhup(int sig);
static int version = 1;
static void log_bootwhat(struct in_addr ipaddr, boot_what_t *bootinfo);
static void onhup(int sig);
static char *progname;
int debug = 0;
main()
void
usage()
{
int sock, length, data, i, mlen, err;
fprintf(stderr,
"Usage: %s <options> [-d]\n"
"options:\n"
"-d - Turn on debugging\n"
"-p port - Specify port number to listen on\n",
progname);
exit(-1);
}
int
main(int argc, char **argv)
{
int sock, length, mlen, err, c;
struct sockaddr_in name, client;
boot_info_t boot_info;
boot_what_t *boot_whatp = (boot_what_t *) &boot_info.data;
int port = BOOTWHAT_DSTPORT;
extern char build_info[];
openlog("bootinfo", LOG_PID, LOG_TESTBED);
syslog(LOG_NOTICE, "daemon starting (version %d)", version);
progname = argv[0];
while ((c = getopt(argc, argv, "p:dhv")) != -1) {
switch (c) {
case 'd':
debug++;
break;
case 'p':
port = atoi(optarg);
break;
case 'v':
fprintf(stderr, "%s\n", build_info);
exit(0);
break;
case 'h':
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
(void)daemon(0, 0);
if (argc)
usage();
if (debug)
loginit(0, 0);
else {
/* Become a daemon */
daemon(0, 0);
loginit(1, "bootinfo");
}
info("%s\n", build_info);
/* Initialize data base */
err = open_bootinfo_db();
if (err) {
syslog(LOG_ERR, "could not open database");
error("could not open database");
exit(1);
}
#ifdef EVENTSYS
err = bievent_init();
if (err) {
error("could not initialize event system");
exit(1);
}
#endif
/* Create socket from which to read. */
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
syslog(LOG_ERR, "opening datagram socket: %m");
errorc("opening datagram socket");
exit(1);
}
/* Create name. */
name.sin_family = AF_INET;
name.sin_addr.s_addr = INADDR_ANY;
name.sin_port = htons(BOOTWHAT_DSTPORT);
name.sin_port = htons((u_short) port);
if (bind(sock, (struct sockaddr *) &name, sizeof(name))) {
syslog(LOG_ERR, "binding datagram socket: %m");
errorc("binding datagram socket");
exit(1);
}
/* Find assigned port value and print it out. */
length = sizeof(name);
if (getsockname(sock, (struct sockaddr *) &name, &length)) {
syslog(LOG_ERR, "getting socket name: %m");
errorc("getting socket name");
exit(1);
}
syslog(LOG_NOTICE, "listening on port %d", ntohs(name.sin_port));
info("listening on port %d\n", ntohs(name.sin_port));
signal(SIGHUP, onhup);
while (1) {
if ((mlen = recvfrom(sock, &boot_info, sizeof(boot_info),
0, (struct sockaddr *)&client, &length))
< 0) {
syslog(LOG_ERR, "receiving datagram packet: %m");
errorc("receiving datagram packet");
exit(1);
}
switch (boot_info.opcode) {
case BIOPCODE_BOOTWHAT_REQUEST:
syslog(LOG_INFO, "%s: REQUEST",
inet_ntoa(client.sin_addr));
err = query_bootinfo_db(client.sin_addr, boot_whatp);
case BIOPCODE_BOOTWHAT_INFO:
info("%s: REQUEST (vers %d)\n",
inet_ntoa(client.sin_addr), boot_info.version);
#ifdef EVENTSYS
bievent_send(client.sin_addr,
TBDB_NODESTATE_PXEBOOTING);
#endif
err = query_bootinfo_db(client.sin_addr,
boot_info.version,
boot_whatp);
break;
default:
syslog(LOG_INFO, "%s: invalid packet",
inet_ntoa(client.sin_addr));
info("%s: invalid packet %d\n",
inet_ntoa(client.sin_addr), boot_info.opcode);
continue;
}
if (err) {
if (err)
boot_info.status = BISTAT_FAIL;
} else {
log_bootwhat(client.sin_addr, boot_whatp);
else {
boot_info.status = BISTAT_SUCCESS;
log_bootwhat(client.sin_addr, boot_whatp);
#ifdef EVENTSYS
switch (boot_whatp->type) {
case BIBOOTWHAT_TYPE_PART:
case BIBOOTWHAT_TYPE_SYSID:
case BIBOOTWHAT_TYPE_MB:
case BIBOOTWHAT_TYPE_MFS:
bievent_send(client.sin_addr,
TBDB_NODESTATE_BOOTING);
break;
case BIBOOTWHAT_TYPE_WAIT:
bievent_send(client.sin_addr,
TBDB_NODESTATE_PXEWAIT);
break;
default:
error("%s: invalid boot directive: %d\n",
inet_ntoa(client.sin_addr),
boot_whatp->type);
break;
}
#endif
}
boot_info.opcode = BIOPCODE_BOOTWHAT_REPLY;
......@@ -92,11 +178,14 @@ main()
client.sin_port = htons(BOOTWHAT_SRCPORT);
if (sendto(sock, (char *)&boot_info, sizeof(boot_info), 0,
(struct sockaddr *)&client, sizeof(client)) < 0)
syslog(LOG_ERR, "sendto: %m");
errorc("sendto");
}
close(sock);
close_bootinfo_db();
syslog(LOG_NOTICE, "daemon terminating");
#ifdef EVENTSYS
bievent_shutdown();
#endif
info("daemon terminating\n");
exit(0);
}
......@@ -105,11 +194,11 @@ onhup(int sig)
{
int err;
syslog(LOG_NOTICE, "re-initializing configuration database");
info("re-initializing configuration database\n");
close_bootinfo_db();
err = open_bootinfo_db();
if (err) {
syslog(LOG_ERR, "Could not open database");
error("Could not reopen database");
exit(1);
}
}
......@@ -122,18 +211,23 @@ log_bootwhat(struct in_addr ipaddr, boot_what_t *bootinfo)
strncpy(ipstr, inet_ntoa(ipaddr), sizeof ipstr);
switch (bootinfo->type) {
case BIBOOTWHAT_TYPE_PART:
syslog(LOG_INFO, "%s: REPLY: boot from partition %d",
ipstr, bootinfo->what.partition);
info("%s: REPLY: boot from partition %d\n",
ipstr, bootinfo->what.partition);
break;
case BIBOOTWHAT_TYPE_SYSID:
syslog(LOG_INFO, "%s: REPLY: boot from partition with sysid %d",
ipstr, bootinfo->what.sysid);
info("%s: REPLY: boot from partition with sysid %d\n",
ipstr, bootinfo->what.sysid);
break;
case BIBOOTWHAT_TYPE_MB:
syslog(LOG_INFO, "%s: REPLY: boot multiboot image %s:%s\n",
ipstr,
inet_ntoa(bootinfo->what.mb.tftp_ip),
info("%s: REPLY: boot multiboot image %s:%s\n",
ipstr, inet_ntoa(bootinfo->what.mb.tftp_ip),
bootinfo->what.mb.filename);
break;
case BIBOOTWHAT_TYPE_WAIT:
info("%s: REPLY: wait mode\n", ipstr);
break;
case BIBOOTWHAT_TYPE_MFS:
info("%s: REPLY: boot from mfs %s\n", ipstr, bootinfo->what.mfs);
break;
}
}
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2003 University of Utah and the Flux Group.
* All rights reserved.
*/
struct boot_what;
int open_bootinfo_db(void);
int close_bootinfo_db(void);
int query_bootinfo_db(struct in_addr ipaddr, int version,
struct boot_what *info);
extern int debug;
#ifdef EVENTSYS
int bievent_init(void);
int bievent_shutdown(void);
int bievent_send(struct in_addr ipaddr, char *event);
#endif
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2002 University of Utah and the Flux Group.
* Copyright (c) 2000-2003 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -11,8 +11,9 @@
#include <string.h>
#include <netdb.h>
#include <syslog.h>
#include "log.h"
#include "bootwhat.h"
#include "bootinfo.h"
/*
* Trivial config file format.
......@@ -53,7 +54,7 @@ open_bootinfo_db(void)
}
int
query_bootinfo_db(struct in_addr ipaddr, boot_what_t *info)
query_bootinfo_db(struct in_addr ipaddr, int version, boot_what_t *info)
{
struct config *configp;
......@@ -84,7 +85,7 @@ parse_host(char *name)
if (!isdigit(name[0])) {
he = gethostbyname(name);
if (he == 0) {
syslog(LOG_ERR, "%s: unknown host", name);
error("%s: unknown host", name);
return 0;
}
return *(int *)he->h_addr;
......@@ -103,7 +104,7 @@ parse_configs(char *filename)
int ipaddr;
if ((fp = fopen(filename, "r")) == NULL) {
syslog(LOG_ERR, "%s: cannot open", filename);
error("%s: cannot open", filename);
return 1;
}
......@@ -115,7 +116,7 @@ parse_configs(char *filename)
continue;
if (numconfigs >= MAX_CONFIGS) {
syslog(LOG_ERR, "%s: too many lines", filename);
error("%s: too many lines", filename);
fclose(fp);
return 1;
}
......@@ -125,7 +126,7 @@ parse_configs(char *filename)
configp = (struct config *) calloc(sizeof *configp, 1);
if (!configp) {
bad:
syslog(LOG_ERR, "%s: parse error", filename);
error("%s: parse error", filename);
fclose(fp);
close_bootinfo_db();
return 1;
......@@ -136,6 +137,7 @@ parse_configs(char *filename)
configp->client.s_addr = ipaddr;
configp->bootinfolen = sizeof *configp;
configp->bootinfo.flags = 0;
if (strncmp(action, "sysid=", 6) == 0) {
configp->bootinfo.type = BIBOOTWHAT_TYPE_SYSID;
configp->bootinfo.what.sysid = atoi(&action[6]);
......@@ -193,17 +195,6 @@ find_config(struct in_addr addr)
#ifdef TEST
#include <stdarg.h>
void
syslog(int prio, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
vfprintf(stderr, msg, ap);
va_end(ap);
fprintf(stderr, "\n");
}
static void
print_bootwhat(boot_what_t *bootinfo)
{
......
This diff is collapsed.
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2002 University of Utah and the Flux Group.
* Copyright (c) 2000-2003 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -9,6 +9,7 @@
#include <stdio.h>
#include "bootwhat.h"
#include "bootinfo.h"
#ifdef USE_NULL_DB
......@@ -24,14 +25,16 @@ open_bootinfo_db(void)
}
int
query_bootinfo_db(struct in_addr ipaddr, boot_what_t *info)
query_bootinfo_db(struct in_addr ipaddr, int version, boot_what_t *info)
{
#if 0
info->type = BIBOOTWHAT_TYPE_MB;
info->type = BIBOOTWHAT_TYPE_MB;
info->flags = 0;
info->what.mb.tftp_ip.s_addr = 0;
strcpy(info->what.mb.filename, NETBOOT);
#else
info->type = BIBOOTWHAT_TYPE_SYSID;
info->type = BIBOOTWHAT_TYPE_SYSID;
info->flags = 0;
info->what.sysid = 165; /* BSD */
#endif
return 0;
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2004 University of Utah and the Flux Group.
* All rights reserved.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <netdb.h>
#include "log.h"
#include "tbdefs.h"
#include "bootwhat.h"
#include "bootinfo.h"
static void log_bootwhat(struct in_addr ipaddr, boot_what_t *bootinfo);
int debug = 0;
static char *progname;
void
usage()
{
fprintf(stderr,
"Usage: %s <options> [-d] [-r | -q] target\n"
"options:\n"
"-d - Turn on debugging\n"
"-r - Tell node to query bootinfo again\n"
"-q - Tell node to reboot\n",
progname);
exit(-1);
}
int
main(int argc, char **argv)
{
int sock, err, c, reboot = 0, query = 0;
struct sockaddr_in name, target;
boot_info_t boot_info;
boot_what_t *boot_whatp = (boot_what_t *) &boot_info.data;
extern char build_info[];
struct hostent *he;
progname = argv[0];
while ((c = getopt(argc, argv, "dhvrq")) != -1) {
switch (c) {
case 'd':
debug++;
break;
case 'r':
reboot++;
break;
case 'q':
query++;
break;
case 'v':
fprintf(stderr, "%s\n", build_info);
exit(0);
break;
case 'h':
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
if (!argc)
usage();
if (query && reboot)
usage();
if (debug)
loginit(0, 0);
else
loginit(1, "bootinfo");
info("%s\n", build_info);
/* Make sure we can map target */
if ((he = gethostbyname(argv[0])) == NULL) {
errorc("gethostbyname(%s)", argv[0]);
exit(1);
}
bzero(&target, sizeof(target));
memcpy((char *)&target.sin_addr, he->h_addr, he->h_length);
target.sin_family = AF_INET;
target.sin_port = htons((u_short) BOOTWHAT_SRCPORT);
err = open_bootinfo_db();
if (err) {
error("could not open database");
exit(1);
}
#ifdef EVENTSYS
err = bievent_init();
if (err) {
error("could not initialize event system");
exit(1);
}
#endif
/* Create socket */
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
errorc("opening datagram socket");
exit(1);
}
err = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char *)&err, sizeof(err)) < 0)
errorc("setsockopt(SO_REUSEADDR)");
/* Create name. */
name.sin_family = AF_INET;
name.sin_addr.s_addr = INADDR_ANY;
name.sin_port = htons((u_short) BOOTWHAT_SENDPORT);
if (bind(sock, (struct sockaddr *) &name, sizeof(name))) {
errorc("binding datagram socket");
exit(1);
}
bzero(&boot_info, sizeof(boot_info));
boot_info.version = BIVERSION_CURRENT;
if (reboot) {
boot_whatp->type = BIBOOTWHAT_TYPE_REBOOT;
#ifdef EVENTSYS
bievent_send(target.sin_addr, TBDB_NODESTATE_SHUTDOWN);
#endif
}
else if (query) {
boot_whatp->type = BIBOOTWHAT_TYPE_AUTO;
#ifdef EVENTSYS
bievent_send(target.sin_addr, TBDB_NODESTATE_PXEWAKEUP);
#endif
}
else {
err = query_bootinfo_db(target.sin_addr,
boot_info.version,
boot_whatp);
if (err) {
fatal("Could not send bootinfo packet!");
}
#ifdef EVENTSYS
bievent_send(target.sin_addr, TBDB_NODESTATE_PXEBOOTING);
switch (boot_whatp->type) {
case BIBOOTWHAT_TYPE_PART:
case BIBOOTWHAT_TYPE_SYSID:
case BIBOOTWHAT_TYPE_MB:
case BIBOOTWHAT_TYPE_MFS:
bievent_send(target.sin_addr, TBDB_NODESTATE_BOOTING);
break;
case BIBOOTWHAT_TYPE_WAIT:
bievent_send(target.sin_addr, TBDB_NODESTATE_PXEWAIT);
break;
default:
error("%s: invalid boot directive: %d\n",
inet_ntoa(target.sin_addr), boot_whatp->type);
break;
}
#endif
}
log_bootwhat(target.sin_addr, boot_whatp);
boot_info.status = BISTAT_SUCCESS;
boot_info.opcode = BIOPCODE_BOOTWHAT_ORDER;
if (sendto(sock, (char *)&boot_info, sizeof(boot_info), 0,
(struct sockaddr *)&target, sizeof(target)) < 0)
errorc("sendto");
close(sock);
close_bootinfo_db();
#ifdef EVENTSYS
bievent_shutdown();
#endif
exit(0);
}
static void
log_bootwhat(struct in_addr ipaddr, boot_what_t *bootinfo)
{
char ipstr[32];
strncpy(ipstr, inet_ntoa(ipaddr), sizeof ipstr);
switch (bootinfo->type) {
case BIBOOTWHAT_TYPE_PART:
info("%s: SEND: boot from partition %d\n",
ipstr, bootinfo->what.partition);
break;
case BIBOOTWHAT_TYPE_SYSID:
info("%s: SEND: boot from partition with sysid %d\n",
ipstr, bootinfo->what.sysid);
break;
case BIBOOTWHAT_TYPE_MB:
info("%s: SEND: boot multiboot image %s:%s\n",
ipstr, inet_ntoa(bootinfo->what.mb.tftp_ip),
bootinfo->what.mb.filename);
break;
case BIBOOTWHAT_TYPE_WAIT:
info("%s: SEND: wait mode\n", ipstr);
break;
case BIBOOTWHAT_TYPE_REBOOT:
info("%s: SEND: reboot\n", ipstr);
break;
case BIBOOTWHAT_TYPE_AUTO:
info("%s: SEND: query bootinfo\n", ipstr);
break;
case BIBOOTWHAT_TYPE_MFS:
info("%s: SEND: boot from mfs %s\n", ipstr, bootinfo->what.mfs);
break;
}
}
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2002 University of Utah and the Flux Group.
* Copyright (c) 2000, 2001, 2003, 2004 University of Utah and the Flux Group.
* All rights reserved.
*
* boot/bootwhat.h from the OSKit.
*/
#ifndef _OSKIT_BOOT_BOOTWHAT_H_
#define _OSKIT_BOOT_BOOTWHAT_H_
#define BOOTWHAT_DSTPORT 6969
#define BOOTWHAT_DSTPORT 6968
#define BOOTWHAT_SRCPORT 9696
#define BOOTWHAT_SENDPORT 6970
/*
* This is the structure we pass back and forth between a oskit kernel
* This is the structure we pass back and forth between pxeboot on a node
* and a server running on some other machine, that tells what to do.
*
* The structure below was changed, adding the version slot by splitting
* the opcode from an int into a short. Old clients conveniently look like a
* version zero client. The same was done for the "type" field, splitting
* that into "flags" and "type" shorts.
*/
#define MAX_BOOT_DATA 512
#define MAX_BOOT_PATH 256
#define MAX_BOOT_CMDLINE ((MAX_BOOT_DATA - MAX_BOOT_PATH) - 32)
typedef struct {
int opcode;
short version;
short opcode;
int status;
char data[MAX_BOOT_DATA];
} boot_info_t;
......@@ -27,10 +35,21 @@ typedef struct {
/* Opcode */
#define BIOPCODE_BOOTWHAT_REQUEST 1 /* What to boot request */