diff --git a/db/Node.pm.in b/db/Node.pm.in index 131229aef6b8848910f240f802b0ece16bcbfef9..7c97aea251da31b4fa20ab854ed7d98283cdc40a 100644 --- a/db/Node.pm.in +++ b/db/Node.pm.in @@ -592,6 +592,46 @@ sub IsReserved($) return 1; } + +sub GetSubboss($$) +{ + my ($self, $service, $subboss_id) = @_; + + return 0 + if (! ref($self)); + + my $ref; + + if (defined $self->{"SUBBOSSES"}) { + my $ref = $self->{"SUBBOSSES"}->{$service}; + } + + if (!defined $ref) { + my $nodeid = $self->node_id(); + + my $query_result = + DBQueryWarn("select * from subbosses " . + "where node_id='$nodeid' and " . + "service = '$service'"); + + return 0 + if (!$query_result); + return 0 + if (!$query_result->numrows); + + if (!defined($self->{"SUBBOSSES"})) { + $self->{"SUBBOSSES"} = {}; + } + + $ref = $self->{"SUBBOSSES"}->{$service} = + $query_result->fetchrow_hashref(); + } + + $$subboss_id = $ref->{'subboss_id'}; + + return 0; +} + # # Flush the reserve info so it reloads. # diff --git a/tbsetup/GNUmakefile.in b/tbsetup/GNUmakefile.in index c944187afc9020d52a1abcce77490203c2838309..44b0991ad9b70fdc0e283da46322199f539c1c1f 100644 --- a/tbsetup/GNUmakefile.in +++ b/tbsetup/GNUmakefile.in @@ -43,7 +43,7 @@ SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \ elabinelab snmpit.proxy panic node_attributes \ nfstrace plabinelab smbpasswd_setup smbpasswd_setup.proxy \ rmproj snmpit.proxynew snmpit.proxyv2 pool_daemon \ - checknodes_daemon + checknodes_daemon subboss_frisbeelauncher_wrapper ifeq ($(ISMAINSITE),1) SBIN_STUFF += repos_daemon endif @@ -95,7 +95,7 @@ SETUID_BIN_SCRIPTS = node_reboot eventsys_control tarfiles_setup savelogs \ SETUID_SBIN_SCRIPTS = mkproj rmgroup mkgroup frisbeelauncher frisbeeimage \ rmuser idleswap named_setup exports_setup \ sfskey_update setgroups newnode_reboot vnode_setup \ - elabinelab nfstrace rmproj + elabinelab nfstrace rmproj subboss_frisbeelauncher_wrapper SETUID_LIBX_SCRIPTS = console_setup spewlogfile ifeq ($(SYSTEM),FreeBSD) @@ -231,6 +231,8 @@ endif chmod u+s $(INSTALL_SBINDIR)/mkgroup chown root $(INSTALL_SBINDIR)/frisbeelauncher chmod u+s $(INSTALL_SBINDIR)/frisbeelauncher + chown root $(INSTALL_SBINDIR)/subboss_frisbeelauncher_wrapper + chmod u+s $(INSTALL_SBINDIR)/subboss_frisbeelauncher_wrapper chown root $(INSTALL_SBINDIR)/frisbeeimage chmod u+s $(INSTALL_SBINDIR)/frisbeeimage chown root $(INSTALL_SBINDIR)/rmuser diff --git a/tbsetup/libosload.pm.in b/tbsetup/libosload.pm.in old mode 100755 new mode 100644 index 182d4f7b06ccef734594f3e7097ba68e91d130ed..78f951c406d319b6c511d6680423928a227f5ee2 --- a/tbsetup/libosload.pm.in +++ b/tbsetup/libosload.pm.in @@ -45,6 +45,7 @@ my $PROJROOT = "@PROJROOT_DIR@"; my $MAXRETRIES = 1; my $FRISBEELAUNCHER = "$TB/sbin/frisbeelauncher"; +my $SUBBOSS_FRISBEELAUNCHER = "$TB/sbin/subboss_frisbeelauncher_wrapper"; my $osselect = "$TB/bin/os_select"; my $TBUISP = "$TB/bin/tbuisp"; @@ -452,6 +453,7 @@ sub osload ($$) { my $class = $nodeobject->class(); my $isremote = $nodeobject->isremotenode(); my $isvirtnode = $nodeobject->isvirtnode(); + my $subboss; my $reload_mode; my $reload_func; my $reboot_required; @@ -465,6 +467,7 @@ sub osload ($$) { $reload_mode = "Frisbee"; $reload_func = \&SetupReloadFrisbee; $reboot_required = !$noreboot; # Reboot unless $noreboot flag set + $nodeobject->GetSubboss('frisbee', \$subboss); if (defined($nodeflags{$node}) && defined($nodeflags{$node}{'noreboot'})) { @@ -506,6 +509,7 @@ sub osload ($$) { 'zerofree' => $zerofree, 'prepare' => $prepare, 'maxwait' => $maxwait, + 'subboss' => $subboss, 'isremote' => $isremote, 'isvirtnode' => $isvirtnode }; @@ -981,6 +985,7 @@ sub SetupReloadFrisbee($) my $zerofree = $reload_info->{'zerofree'}; my $prepare = $reload_info->{'prepare'}; my $isvirtnode = $reload_info->{'isvirtnode'}; + my $subboss = $reload_info->{'subboss'}; my $osid = TBNodeDiskloadOSID($node); # @@ -1016,6 +1021,25 @@ sub SetupReloadFrisbee($) } foreach my $imageid (@$imageids) { + if (defined $subboss) { + my $image = Image->Lookup($imageid); + my $filename = $image->filename(); + my @image_stats = stat $filename; + + my $query_result = DBQueryWarn("select sync from subboss_images where " . + "subboss_id = '$subboss' and imageid = '$imageid' and sync = 1"); + + if (!$query_result || !$query_result->numrows) { + system("$SUBBOSS_FRISBEELAUNCHER " . ($debug ? "-d ": "") . + "$subboss " . "$imageid " . "\"$filename\" " . + stat[7] . ' ' . stat[9]); + if ($?) { + tberror "Subboss Frisbee Launcher ($imageid on $subboss) failed!"; + return -1; + } + return 0; + } + } system("$FRISBEELAUNCHER " . ($debug ? "-d ": "") . "$imageid"); if ($?) { tberror "Frisbee Launcher ($imageid) failed!"; diff --git a/tbsetup/subboss_frisbeelauncher_wrapper b/tbsetup/subboss_frisbeelauncher_wrapper new file mode 100755 index 0000000000000000000000000000000000000000..5124208798b721fb87a5cb8051bc123c992d083d --- /dev/null +++ b/tbsetup/subboss_frisbeelauncher_wrapper @@ -0,0 +1,81 @@ +#!/usr/bin/perl -wT +# +# EMULAB-COPYRIGHT +# Copyright (c) 2000-2007 University of Utah and the Flux Group. +# All rights reserved. +# +use strict; +use Getopt::Std; +use POSIX 'setsid'; # For &daemonize +use POSIX ":sys_wait_h"; # For &WNOHANG +use Sys::Syslog; +use English; +use Socket; +use Errno qw(EADDRINUSE); + +sub Fatal($); + +# +# This also kills a running frisbee. +# +sub usage() +{ + print "Usage: $0 [-d] [-k] \n"; + print "-k: Kill running frisbee.\n"; + print "-d: Print debugging output.\n"; + exit(1); +} +my $optlist = "dk"; +my $debug = 0; +my $killmode = 0; + +# +# Untaint the path +# +$ENV{'PATH'} = "/bin:/usr/bin"; +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; + +# Change to root +$<=$>=0; + +# Parse command arguments. Once we return from getopts, all that should be +# left are the required arguments. +# +my %options = (); +if (! getopts($optlist, \%options)) { + usage(); +} +if (defined($options{"d"})) { + $debug = 1; +} +if (defined($options{"k"})) { + $killmode = 1; +} +usage() + if (@ARGV < 5); + +# XXX HACK UGLY +# quick and dirty hack to get around taint checking +# This isn't really an issue anyway since we use the +# list form of system() which doesn't run the command +# via the shell (so no globbing or interpretation of +# metacharacters is done). +my ($subboss, $imageid, $path, $size, $mtime) = map { /(.*)/; $1 } @ARGV; +my @command = ('ssh', $subboss); + +push @command, '-d' if ($debug); +push @command, '-k' if ($killmode); +push @command, ('/usr/testbed/sbin/subboss_frisbeelauncher', $imageid, $path, $size, $mtime); + +system(@command); +if ($?) { + Fatal("Failed to launch frisbee on subboss $subboss"); +} + +sub Fatal($) +{ + my ($msg) = @_; + + die("*** $0:\n". + " $msg\n"); +}