newwanode.in 7.93 KB
Newer Older
1 2 3
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
4
# Copyright (c) 2000-2008 University of Utah and the Flux Group.
5 6 7 8 9 10 11 12 13 14
# All rights reserved.
#
use English;
use Getopt::Std;

#
# Add a new node to the DB. Strictly for widearea nodes right now.
# 
sub usage()
{
Leigh B. Stoller's avatar
Leigh B. Stoller committed
15 16
    print "Usage: ".
	"newwanode [-w] [-n nickname] -t <nodetype> -i <ip address>\n";
17 18
    exit(1);
}
19
sub fatal($);
20
my  $optlist = "wt:i:a:n:";
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

#
# Configure variables
#
my $TB		= "@prefix@";
my $TBOPS       = "@TBOPSEMAIL@";
my $TBLOGS      = "@TBLOGSEMAIL@";
my $named_setup = "$TB/sbin/named_setup";

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

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

# Load the Testbed support stuff.
use lib "@prefix@/lib";
use libdb;
use libtestbed;
43
use NodeType;
44 45 46 47 48 49 50 51 52 53 54 55 56

#
# This is run from the web page, but tbadmins can run it from the command
# line. 
#
if ($UID != getpwnam("nobody") && !TBAdmin($UID)) {
    die("*** $0:\n".
	"    You do not have permission to run this script!\n");
}

my $nodetype;
my $nodeip;
my $fromweb = 0;
57
my $reuse   = 0;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
58
my $nickname;
59 60
my $nodename;
my $nodevtype;
61
my $nodeauxtype;
62
my $nodevname;
63 64 65 66
my $pid;
my $eid;
my $nextid;
my $nextpri;
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

#
# 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{"w"})) {
    $fromweb = 1;
}
if (defined($options{"i"})) {
    $nodeip = $options{"i"};
}
if (defined($options{"t"})) {
    $nodetype = $options{"t"};
}
85 86
if (defined($options{"a"})) {
    $nodeauxtype = $options{"a"};
Leigh B. Stoller's avatar
Leigh B. Stoller committed
87 88 89 90
}
if (defined($options{"n"})) {
    $nickname = $options{"n"};
}
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
if (!defined($nodeip) || !defined($nodetype)) {
    usage();
}

#
# Taint check.
#
if ($nodetype =~ /^([\w]+)$/) {
    $nodetype = $1;
}
else {
    die("*** Bad data in $nodetype\n");
}
if ($nodeip =~ /^([\d\.]+)$/) {
    $nodeip = $1;
}
else {
    die("*** Bad data in $nodeip\n");
}
110 111 112
if (defined($nodeauxtype)) {
    if ($nodeauxtype =~ /^([\w]+)$/) {
	$nodeauxtype = $1;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
113 114
    }
    else {
115
	die("*** Bad data in $nodeauxtype\n");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
116 117 118 119 120 121 122 123 124 125
    }
}
if (defined($nickname)) {
    if ($nickname =~ /^([-\w]+)$/) {
	$nickname = $1;
    }
    else {
	die("*** Bad data in $nickname\n");
    }
}
126 127 128 129

#
# Must be a valid type.
#
130 131
my $typeinfo = NodeType->Lookup($nodetype);
if (!defined($typeinfo)) {
132 133 134
    fatal("*** $0:\n".
	  "    No such nodetype $nodetype is defined in the DB!\n");
}
135 136 137 138 139 140 141 142 143 144
my ($defosid,$control_iface);

if ($typeinfo->default_osid(\$defosid) || !$defosid) {
    fatal("*** $0:\n".
	  "    No default OSID for $nodetype is defined in the DB!\n");
}
if ($typeinfo->control_interface(\$control_iface) || !$control_iface) {
    fatal("*** $0:\n".
	  "    No control interface for $nodetype is defined in the DB!\n");
}
145 146 147 148 149 150 151 152 153

#
# For now, just pcwa/pcron is allowed until we have more DB state that says
# how to build the virtual nodes, although that is temporary as well.
#
if ($nodetype ne "pcwa" && $nodetype ne "pcron") {
    fatal("Can only handle pcwa/pcron nodetype right now!");
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
154
#
155
# Create the virtual type name. Again, this is bogus.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
156
#
157 158 159 160 161
if ($nodetype eq "pcwa") {
    $nodevtype = "pcvwa";
    $nodeauxtype = "pcvwainet"
	if (!defined($nodeauxtype));
}    
162
else {
163 164 165
    $nodevtype = "pcvron";
    $nodeauxtype = "pcvroninet"
	if (!defined($nodeauxtype));
166
}
167

168
#
169 170 171 172 173 174 175 176 177
# Again, this is bogus.
#
if ($nodetype eq "pcwa") {
    $pid = "emulab-ops";
    $eid = "widearea-nodes";
}    
else {
    $pid = "ron";
    $eid = "all";
178 179
}

180 181 182 183 184 185
my $exptidx;
if (!TBExptIDX($pid, $eid, \$exptidx)) {
    fatal("*** $0:\n".
	  "    No such experiment $pid/$eid!\n");
}

186
#
187
# Lets see if a known IP. If so we want to reuse the existing record.
188
#
189 190 191 192 193 194 195 196 197 198
if (TBIPtoNodeID($nodeip, \$nodename)) {
    #
    # We need the existing priority for creating the vnodes below.
    #
    $query_result =
	DBQueryFatal("select priority from nodes where node_id='$nodename'");

    my %row  = $query_result->fetchhash();
    $nextpri = $row{'priority'};
    $reuse   = 1;
199 200
}
else {
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
    #
    # We need the next id and priority.
    # 
    DBQueryFatal("lock tables nextfreenode write");

    $query_result =
	DBQueryFatal("select nextid,nextpri from nextfreenode ".
		     "where nodetype='$nodetype'");

    if (!$query_result->numrows) {
	fatal("nodetype $nodetype is not in the nextfreenode table!");
    }
    my %row  = $query_result->fetchhash();
    $nextid  = $row{'nextid'};
    $nextpri = $row{'nextpri'};

    DBQueryFatal("update nextfreenode ".
		 "set nextid=nextid+1,nextpri=nextpri+1 ".
		 "where nodetype='$nodetype'");

    DBQueryFatal("unlock tables");

    #
    # Form a new node name! Bogus. need more DB state.
    #
    if ($nodetype =~ /^pc(\w+)$/) {
	$nodename = "${1}${nextid}";
    }
    else {
	fatal("Could not determine a name from type for $nodetype!");
    }
232
}
233

Leigh B. Stoller's avatar
Leigh B. Stoller committed
234 235 236 237 238
if (!defined($nickname)) {
    $nickname = $nodename;
}

#
239
# Enter the records
Leigh B. Stoller's avatar
Leigh B. Stoller committed
240
#
241 242
if ($reuse) {
    print "Reusing exiting record for $nodename. IP=$nodeip\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
243
}
244 245 246 247
else {
    print "Creating widearea node $nodename ...\n";
    DBQueryFatal("insert into nodes ".
		 "(node_id, type, phys_nodeid, role, priority, ".
248
		 " op_mode, def_boot_osid) ".
249
		 "values ('$nodename', '$nodetype', '$nodename', ".
250
		 "        'testnode', $nextpri, 'NORMAL', ".
251
		 "        '$defosid') ");
252

253 254 255
    DBQueryFatal("insert into node_hostkeys (node_id) ".
		 "values ('$nodename')");

256 257
    DBQueryFatal("insert into node_auxtypes ".
		 "(node_id, type, count) ".
258 259 260 261 262
		 "values ('$nodename', '$nodeauxtype', 20)");

    DBQueryFatal("insert into node_auxtypes ".
		 "(node_id, type, count) ".
		 "values ('$nodename', '$nodevtype', 20)");
263

264 265 266 267
    DBQueryFatal("replace into node_status ".
		 "(node_id, status, status_timestamp) ".
		 "values ('$nodename', 'down', now()) ");

268 269
    # Note that card/port are arbitrary for remote nodes since they are
    # not connected to local switches! 
270
    my $ifacerole = TBDB_IFACEROLE_CONTROL();
271
        
272
    DBQueryFatal("insert into interfaces ".
273
		 "(node_id, card, port, IP, interface_type, iface, role) ".
274 275
		 "values ('$nodename', 0, 1, '$nodeip', ".
		 "        'fxp', '$control_iface', '$ifacerole')");
276

277 278 279 280
    DBQueryFatal("insert into interface_state ".
		 "(node_id, card, port, iface) ".
		 "values ('$nodename', 0, 1, 'fxp')");

281
    DBQueryFatal("insert into reserved ".
282 283 284
		 "(node_id, exptidx, pid, eid, rsrv_time, vname) ".
		 "values ('$nodename', $exptidx, ".
		 "        '$pid', '$eid', now(), '$nickname')");
285 286 287 288 289
}

#
# Always create these. I'll kill off the old ones as needed for now.
# 
Leigh B. Stoller's avatar
Leigh B. Stoller committed
290
for ($i = 1; $i < 9; $i++) {
291
    my $priority  = ($nextpri * 100) + $i;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
292
    $nodevname = "v${nodename}-${i}";
293

294
    print "Creating widearea virtual node $nodevname ...\n";
295 296
    DBQueryFatal("insert into nodes ".
		 "(node_id, type, phys_nodeid, role, priority, ".
297
		 " op_mode, def_boot_osid, update_accounts) ".
298
		 "values ('$nodevname', '$nodevtype', '$nodename', ".
299
		 "        'virtnode', $priority, 'NORMAL', ".
300
		 "        '$defosid', 1) ");
301 302 303

    DBQueryFatal("insert into node_hostkeys (node_id) ".
		 "values ('$nodevname')");
304 305
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
306
#
307
# Lets log it.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
308
#
309 310 311 312 313 314
my $subject;
my $message;
if ($reuse) {
    $subject = "Existing WA node has reinstalled";
    $message = "Existing WA node has been reinstalled";
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
315
else {
316 317
    $subject = "New WA node created";
    $message = "New Wide Area node has been created";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
318
}
319

320 321
SENDMAIL($TBLOGS, $subject,
	 "$message\n".
322 323 324 325 326
	 "\n".
	 "Type:      $nodetype\n".
	 "Name:      $nodename\n".
	 "IP:        $nodeip\n".
	 "Vtype:     $nodevtype\n".
327
	 "Auxtype:   $nodeauxtype\n".
328 329 330
	 "Vname:     $nodevname (actually the last vnode)\n".
	 "Nickname:  $nickname\n",
	 $TBOPS);
331 332 333 334 335

#
# update the named maps. Do it in the background since we do not
# want to hold up the caller.
#
336
print "Forcing a named map update ...\n";
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
my $logname = TBMakeLogname("newwanode");
if (TBBackGround($logname)) {
    #
    # Parent exits normally
    #
    exit(0);
}
system("$named_setup");
unlink($logname);
exit(0);

sub fatal($) {
    my ($msg) = @_;

    print STDERR "$msg\n";
    SENDMAIL($TBOPS, "Failure creating new WA node", $msg, $TBOPS);
    exit(1);
}