newwanode.in 7.09 KB
Newer Older
1
2
3
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
4
# Copyright (c) 2000-2003 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);
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
19
my  $optlist = "wt:i:v:n:";
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

#
# 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;

#
# 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;
55
my $reuse   = 0;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
56
my $nickname;
57
58
59
my $nodename;
my $nodevtype;
my $nodevname;
60
61
62
63
my $pid;
my $eid;
my $nextid;
my $nextpri;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

#
# 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"};
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
82
83
84
85
86
87
if (defined($options{"v"})) {
    $nodevtype = $options{"v"};
}
if (defined($options{"n"})) {
    $nickname = $options{"n"};
}
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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");
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
if (defined($nodevtype)) {
    if ($nodevtype =~ /^([\w]+)$/) {
	$nodevtype = $1;
    }
    else {
	die("*** Bad data in $nodevtype\n");
    }
}
if (defined($nickname)) {
    if ($nickname =~ /^([-\w]+)$/) {
	$nickname = $1;
    }
    else {
	die("*** Bad data in $nickname\n");
    }
}
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

#
# Must be a valid type.
#
my $query_result =
    DBQueryFatal("select osid,control_net from node_types ".
		 "where type='$nodetype'");
if (! $query_result->numrows) {
    fatal("*** $0:\n".
	  "    No such nodetype $nodetype is defined in the DB!\n");
}
my ($defosid,$control_net) = $query_result->fetchrow_array();

#
# 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
144
145
146
147
148
149
150
151
152
153
154
155
#
# Make sure its a valid vtype too!
#
if (defined($nodevtype)) {
    $query_result =
	DBQueryFatal("select * from node_types where type='$nodevtype'");
    
    if (! $query_result->numrows) {
	fatal("*** $0:\n".
	      "    No such nodevtype $nodevtype is defined in the DB!\n");
    }
}
156
157
158
159
160
161
162
163
164
165
166
else {
    #
    # Create the virtual type name. Again, this is bogus.
    #
    if ($nodetype eq "pcwa") {
	$nodevtype = "pcvwainet";
    }    
    else {
	$nodevtype = "pcvroninet";
    }
}
167
#
168
169
170
171
172
173
174
175
176
# Again, this is bogus.
#
if ($nodetype eq "pcwa") {
    $pid = "emulab-ops";
    $eid = "widearea-nodes";
}    
else {
    $pid = "ron";
    $eid = "all";
177
178
179
}

#
180
# Lets see if a known IP. If so we want to reuse the existing record.
181
#
182
183
184
185
186
187
188
189
190
191
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;
192
193
}
else {
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
    #
    # 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!");
    }
225
}
226

Leigh B. Stoller's avatar
Leigh B. Stoller committed
227
228
229
230
231
if (!defined($nickname)) {
    $nickname = $nodename;
}

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

246
247
248
249
    DBQueryFatal("replace into node_status ".
		 "(node_id, status, status_timestamp) ".
		 "values ('$nodename', 'down', now()) ");

250
251
    my $ifacerole = TBDB_IFACEROLE_CONTROL();
    
252
    DBQueryFatal("insert into interfaces ".
253
		 "(node_id, card, port, IP, interface_type, iface, role) ".
254
		 "values ('$nodename', $control_net, 1, '$nodeip', ".
255
		 "        'fxp', 'eth0', '$ifacerole')");
256
257
258
259

    DBQueryFatal("insert into reserved ".
		 "(node_id, pid, eid, rsrv_time, vname) ".
		 "values ('$nodename', '$pid', '$eid', now(), '$nickname')");
260

261
262
263
264
265
}

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

270
271
272
    if (TBValidNodeName($nodevname)) {
	next;
    }
273
    print "Creating widearea virtual node $nodevname ...\n";
274
275
    DBQueryFatal("insert into nodes ".
		 "(node_id, type, phys_nodeid, role, priority, ".
276
		 " op_mode, def_boot_osid, update_accounts) ".
277
		 "values ('$nodevname', '$nodevtype', '$nodename', ".
278
		 "        'virtnode', $priority, 'NORMAL', ".
279
		 "        '$defosid', 1) ");
280
281
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
282
#
283
# Lets log it.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
284
#
285
286
287
288
289
290
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
291
else {
292
293
    $subject = "New WA node created";
    $message = "New Wide Area node has been created";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
294
}
295

296
297
SENDMAIL($TBLOGS, $subject,
	 "$message\n".
298
299
300
301
302
303
304
305
	 "\n".
	 "Type:      $nodetype\n".
	 "Name:      $nodename\n".
	 "IP:        $nodeip\n".
	 "Vtype:     $nodevtype\n".
	 "Vname:     $nodevname (actually the last vnode)\n".
	 "Nickname:  $nickname\n",
	 $TBOPS);
306
307
308
309
310

#
# update the named maps. Do it in the background since we do not
# want to hold up the caller.
#
311
print "Forcing a named map update ...\n";
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
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);
}