eventsys_control.in 4.91 KB
Newer Older
1
#!/usr/bin/perl -wT
Leigh B. Stoller's avatar
Leigh B. Stoller committed
2 3 4

#
# EMULAB-COPYRIGHT
5
# Copyright (c) 2000-2006 University of Utah and the Flux Group.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
6 7 8
# All rights reserved.
#

9 10 11 12 13 14 15 16 17 18 19 20 21
use English;
use Getopt::Std;
use POSIX ":sys_wait_h";

#
# Start/Stop the event scheduler for an experiment. This script is
# setuid so that the stop function can send a signal regardless of
# who is running the script (must have appropriate permission of course).
# This is temporary; we eventually want to use the event system to control
# the event system, but lets see how well this event stuff works first.
#
sub usage()
{
22 23
    print STDOUT
	"Usage: eventsys_control [-f] <start|stop|replay> <pid> <eid>\n";
24 25
    exit(-1);
}
26
my  $optlist = "dfa";
27 28 29 30 31 32

#
# Configure variables
#
my $TB		= "@prefix@";
my $TBOPS       = "@TBOPSEMAIL@";
33
my $CONTROL     = "@USERNODE@";
34
my $EVENTSYS    = @EVENTSYS@;
35
my $TESTMODE    = @TESTMODE@;
36 37
my $UNIFIED     = @UNIFIED_BOSS_AND_OPS@;
my $DBIFACE     = 0;
38 39 40 41 42 43 44 45

#
# The event system is currently optional.
#
if (! $EVENTSYS) {
    exit(0);
}

46 47 48 49
#
# Do nothing when testing.
#
if ($TESTMODE) {
50 51 52 53 54
#    print "Testing run - no event system.\n";
#    exit(0);
}

if ($EUID != 0) {
55
    die("Must be root! Maybe its a development version?\n");
56 57
}

58 59 60 61 62 63
#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
Kevin Atkinson's avatar
Kevin Atkinson committed
64
use libtblog;
65
use Template;
66 67 68 69 70 71 72

#
# Turn off line buffering on output
#
$| = 1;

# un-taint path
73
$ENV{'PATH'} = "/bin:/usr/bin:/usr/local/bin:$TB/bin";
74 75
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

76 77
my $proxy	= "$TB/sbin/eventsys.proxy";
my $debug	= 1;
78
my $force       = 0;
79
my $agent       = 0;
80
my $expstate;
81
my $exptidx;
82
my $dbuid;
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
    usage();
}
if (@ARGV != 3) {
    usage();
}
if (defined($options{"d"})) {
    $debug = 1;
}
98 99 100
if (defined($options{"f"})) {
    $force = 1;
}
101 102 103
if (defined($options{"a"})) {
    $agent = 1;
}
104 105 106 107 108 109 110
my $action = $ARGV[0];
my $pid    = $ARGV[1];
my $eid    = $ARGV[2];

#
# Untaint args.
#
111 112 113 114
if ($action =~ /^(start|stop|replay)$/) {
    $action = $1;
}
else {
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
    usage();
}
if ($pid =~ /^([-\@\w]+)$/) {
    $pid = $1;
}
else {
    die("Bad data in pid: $pid.");
}
if ($eid =~ /^([-\@\w]+)$/) {
    $eid = $1;
}
else {
    die("Bad data in eid: $eid.");
}

130
if (! ($expstate = ExpState($pid, $eid))) {
131
    tbdie("No such experiment $pid/$eid!");
132 133
}

134
if (! UNIX2DBUID($UID, \$dbuid)) {
135
    tbdie("You do not exist in the Emulab Database!");
136 137
}

138
#
139 140
# Check permission. Only people with permission to destroy the experiment
# can do this.
141
#
142
if (! TBExptAccessCheck($UID, $pid, $eid, TB_EXPT_DESTROY)) {
143
    tbdie("You do not have permission to control the event system!");
144 145
}

146
#
147 148
# Do not allow an event system to be controlled if the experiment is not
# active (or swapping).
149
#
150 151
if ($expstate ne EXPTSTATE_ACTIVE &&
    $expstate ne EXPTSTATE_ACTIVATING &&
152
    $expstate ne EXPTSTATE_MODIFY_RESWAP &&
153
    $expstate ne EXPTSTATE_SWAPPING) {
Mike Hibler's avatar
Mike Hibler committed
154
    tbdie("Experiment $pid/$eid must be active (or swapping)!");
155 156 157
}

#
158 159
# If being asked to start the event system, but there are no nodes in
# the experiment, balk unless force mode is on.
160
#
161
if ($action eq "start" && !$force && !ExpNodes($pid, $eid)) {
162 163
    tbnotice("There are no nodes in $pid/$eid. ".
	     "Not starting a scheduler.");
164 165 166
    exit(0);
}

167 168 169 170 171 172 173 174
#
# Delete the TIME START event.
#
if ($action eq "replay" || $action eq "stop") {
    DBQueryFatal("DELETE FROM eventlist WHERE " .
		 "pid='$pid' and eid='$eid' and objecttype=3 and eventtype=1");
}

175 176 177 178 179 180 181 182 183 184 185 186
#
# Do we need a program agent on ops?
#
if ($action ne "stop" && ! $agent) {
    my $query_result =
	DBQueryFatal("select vname from virt_agents as v ".
		     "left join event_objecttypes as o on o.idx=v.objecttype ".
		     "where v.pid='$pid' and v.eid='$eid' and ".
		     "      o.type='PROGRAM' and v.vnode='ops'");
    $agent = $query_result->numrows;
}

187 188 189 190 191
# Need the unix_gid info to pass to boss.
my $gid = ExpGroup($pid, $eid);
my ($unix_gid, $unix_gidname);

if (! TBGroupUnixInfo($pid, $gid, \$unix_gid, \$unix_gidname)) {
192
    tbdie("Could not get unix group info for $pid/$gid!");
193 194
}

195 196 197 198 199
# Need this to see if its a template experiment.
if (! TBExptIDX($pid, $eid, \$exptidx)) {
    tbdie("Could not get experiment index for $pid/$gid!");
}

200
#
201 202 203
# Pase the whole thing off to the proxy, which might be local when running
# in UNIFIED_BOSS_AND_OPS mode. Become real root either way; the proxy will
# flip back. 
204
#
205 206 207
my $cmd = $proxy;
$cmd .= " -d"
    if ($debug);
208 209
$cmd .= " -a"
    if ($agent);
210 211
$cmd .= " -t " . TBExptUserDir($pid, $eid) . "/archive/events"
    if (Template::Instance->LookupByExptidx($exptidx));
212 213
$cmd .= " -l " . TBExptUserDir($pid, $eid) . "/logs/event-sched.log";
$cmd .= " -k " . TBDB_EVENTKEY($pid, $eid);
214
$cmd .= " -g " . $unix_gidname;
215 216 217
$cmd .= " -e $pid/$eid";
$cmd .= " -u $dbuid";
$cmd .= " $action";
218

219 220 221
$UID=0;
if ($UNIFIED || $DBIFACE) {
    exec($cmd);
222
}
223 224
else {
    exec("sshtb -host $CONTROL $cmd");
225
}
226
tbdie("Could not exec '$cmd'");