node_admin.in 5.56 KB
Newer Older
1
#!/usr/bin/perl -wT
Leigh B. Stoller's avatar
Leigh B. Stoller committed
2
#
3
# Copyright (c) 2000-2009 University of Utah and the Flux Group.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
23
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
24
use strict;
25
26
27
28
use English;
use Getopt::Std;

#
29
# Turn on/off admin mode for nodes and optionally reboot/wait.
30
31
32
#
sub usage()
{
33
    print STDOUT "Usage: node_admin [-h] [-n | -w] <on | off> [node ....]\n";
34
    print STDOUT "       node_admin [-h] [-n | -w] -e pid,eid <on | off>\n";
Mike Hibler's avatar
Mike Hibler committed
35
36
37
38
39
40
    print STDOUT "-h     This message\n";
    print STDOUT "-n     Do not reboot node\n";
    print STDOUT "-w     Wait for node to come back up if rebooted\n";
    print STDOUT "-e     Operate on all nodes in an experiment\n";
    print STDOUT "-c cmd Run command in MFS and wait for completion\n".
		 "       (-n and -w apply after the command is run).\n";
41
42
    exit(-1);
}
Mike Hibler's avatar
Mike Hibler committed
43
my $optlist  = "hnwe:c:";
44
45
my $waitmode = 0;
my $reboot   = 1;
Mike Hibler's avatar
Mike Hibler committed
46
my $runcmd   = "";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
47
my $onoff;
48
49
50
51
52
53
54
55
56
57
58
59

#
# Configure variables
#
my $TB		= "@prefix@";

#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
Mike Hibler's avatar
Mike Hibler committed
60
use libadminmfs;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
61
62
63
use User;
use Node;
use Experiment;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

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

#
# Untaint the path
# 
$ENV{'PATH'} = "/bin:/sbin:/usr/bin:";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

#
# 
#
my $nodereboot	= "$TB/bin/node_reboot";
80
my $osselect    = "$TB/bin/os_select";
81
my @nodes       = ();
82
83
84
85
86

#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
87
my %options = ();
88
89
90
if (! getopts($optlist, \%options)) {
    usage();
}
91
if (defined($options{h})) {
92
93
    usage();
}
94
95
96
97
98
99
if (defined($options{"n"})) {
    $reboot = 0;
}
if (defined($options{"w"})) {
    $waitmode = 1;
}
Mike Hibler's avatar
Mike Hibler committed
100
101
102
if (defined($options{"c"})) {
    $runcmd = $options{"c"};
    $onoff = "on";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
103
104
}
else {
Mike Hibler's avatar
Mike Hibler committed
105
106
107
108
109
    if (!@ARGV) {
	usage();
    }
    $onoff  = shift(@ARGV);
}
110
111
112
113
114

if ($onoff ne "on" && $onoff ne "off") {
    usage();
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
115
116
117
118
119
120
121
122
123
#
# Verify user and get his DB uid and other info for later.
#
my $this_user = User->ThisUser();
if (! defined($this_user)) {
    die("*** $0:\n".
	"    You ($UID) do not exist!\n");
}

124
125
126
127
128
129
130
if (defined($options{"e"})) {
    #
    # Reboot all nodes in an experiment
    #
    if (@ARGV) {
	usage();
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
131
132
    my $experiment = Experiment->Lookup($options{"e"});
    if (!defined($experiment)) {
133
	die("*** $0:\n".
Leigh B. Stoller's avatar
Leigh B. Stoller committed
134
	    "    Unknown experiment!\n");
135
136
137
138
139
140
141
    }

    #
    # Verify permission to muck with this experiment. This is to head off
    # permission problems early; the nodes are indvidually checked later
    # in the library.
    #
Leigh B. Stoller's avatar
Leigh B. Stoller committed
142
143
    if ($UID && !$this_user->IsAdmin() &&
	! $experiment->AccessCheck($this_user, TB_EXPT_MODIFY)) {
144
	die("*** $0:\n".
Leigh B. Stoller's avatar
Leigh B. Stoller committed
145
	    "    You not have permission to reboot nodes in $experiment!\n");
146
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
147
148
    @nodes = $experiment->NodeList();
    if (! @nodes) {
149
	die("*** $0:\n".
Leigh B. Stoller's avatar
Leigh B. Stoller committed
150
            "    There are no nodes reserved in $experiment\n");
151
    }
152
153
}
else {
154
155
156
    if (! @ARGV) {
	usage();
    }
157

Leigh B. Stoller's avatar
Leigh B. Stoller committed
158
159
160
    foreach my $n (@ARGV) {
	my $node = Node->Lookup($n);
	if (!defined($node)) {
161
	    die("*** $0:\n".
Leigh B. Stoller's avatar
Leigh B. Stoller committed
162
		"    Node $n does not exist!\n");
163
	}
164
165
166
	if (!$node->IsReserved()) {
	    die("*** $0:\n".
		"    Node $n is not reserved; reserve it first!\n");
167
168
169
170
171
172
173
174
175
176
177
178
	}
	if ($UID && !$this_user->IsAdmin()) {
	    if (! $node->AccessCheck($this_user, TB_NODEACCESS_LOADIMAGE)) {
		die("*** $0:\n".
		    "    You are not allowed to put $node into admin mode!\n");
	    }
	    if ($node->IsTainted("useronly") || 
		$node->IsTainted("blackbox")) {
		die("*** $0:\n".
		    "    $node is running a restricted image. Admin mode ".
		    "not allowed!\n");
	    }
179
	}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
180
	push(@nodes, $node);
181
182
183
    }
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
184
my @nodeids = map($_->node_id(), @nodes);
Mike Hibler's avatar
Mike Hibler committed
185
186
187
188
189
190
191
192
193
194
my @bad;
my %args;

if ($runcmd ne "") {
    #
    # Reboot into admin more and run the command
    #
    %args = ();
    $args{'name'} = $0;
    $args{'command'} = $runcmd;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
195
    if (TBAdminMfsRunCmd(\%args, undef, @nodeids)) {
196
	die("*** $0:\n".
Leigh B. Stoller's avatar
Leigh B. Stoller committed
197
	    "    Failed to run '$runcmd' on some of @nodeids!\n");
198
    }
199

Mike Hibler's avatar
Mike Hibler committed
200
201
202
203
204
205
206
    #
    # Turn admin mode back off and optionally reboot back to the old OS
    #
    %args = ();
    $args{'name'} = $0;
    $args{'on'} = 0;
    $args{'clearall'} = 0;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
207
    if (TBAdminMfsSelect(\%args, \@bad, @nodeids)) {
Mike Hibler's avatar
Mike Hibler committed
208
209
210
	die("*** $0:\n".
	    "    Could not turn admin mode off for @bad!\n");
    }
211

Mike Hibler's avatar
Mike Hibler committed
212
213
214
215
216
217
    if ($reboot) {
	%args = ();
	$args{'name'} = $0;
	$args{'on'} = 0;
	$args{'reboot'} = $reboot;
	$args{'wait'} = $waitmode;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
218
	if (TBAdminMfsBoot(\%args, \@bad, @nodeids)) {
219
	    die("*** $0:\n".
Mike Hibler's avatar
Mike Hibler committed
220
		"    Did not properly reboot @bad after command!\n");
221
222
	}
    }
Mike Hibler's avatar
Mike Hibler committed
223
224
    exit(0);
}
225

Mike Hibler's avatar
Mike Hibler committed
226
227
228
$args{'name'} = $0;
$args{'on'} = ($onoff eq "on");
$args{'clearall'} = 0;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
229
if (TBAdminMfsSelect(\%args, \@bad, @nodeids)) {
Mike Hibler's avatar
Mike Hibler committed
230
231
232
233
234
235
236
237
238
    die("*** $0:\n".
	"    Could not turn admin mode $onoff for @bad!\n");
}
if ($reboot) {
    %args = ();
    $args{'name'} = $0;
    $args{'on'} = ($onoff eq "on");
    $args{'reboot'} = $reboot;
    $args{'wait'} = $waitmode;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
239
    if (TBAdminMfsBoot(\%args, \@bad, @nodeids)) {
240
	die("*** $0:\n".
Mike Hibler's avatar
Mike Hibler committed
241
	    "    Did not properly reboot @bad!\n");
242
    }
243
244
}
exit(0);