newwanode.in 7.21 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

#
# Must be a valid type.
#
my $query_result =
128
    DBQueryFatal("select osid,control_iface from node_types ".
129
130
131
132
133
		 "where type='$nodetype'");
if (! $query_result->numrows) {
    fatal("*** $0:\n".
	  "    No such nodetype $nodetype is defined in the DB!\n");
}
134
my ($defosid,$control_iface) = $query_result->fetchrow_array();
135
136
137
138
139
140
141
142
143

#
# 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
    # Note that card/port are arbitrary for remote nodes since they are
    # not connected to local switches! 
252
    my $ifacerole = TBDB_IFACEROLE_CONTROL();
253
        
254
    DBQueryFatal("insert into interfaces ".
255
		 "(node_id, card, port, IP, interface_type, iface, role) ".
256
257
		 "values ('$nodename', 0, 1, '$nodeip', ".
		 "        'fxp', '$control_iface', '$ifacerole')");
258
259
260
261

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

263
264
265
266
267
}

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

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

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

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

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