console_setup.in 4.61 KB
Newer Older
1
#!/usr/bin/perl -wT
Leigh Stoller's avatar
Leigh Stoller committed
2
#
3
# Copyright (c) 2000-2014 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 Stoller's avatar
Leigh Stoller committed
23
#
24
use English;
25
use strict;
26 27 28 29

#
# usage: console_setup node [node node ...]
#
30 31 32 33 34
sub usage()
{
    print STDOUT "Usage: console_setup node [node ...]\n";
    exit(-1);
}
35 36 37 38 39

#
# Configure variables
#
my $TB		= "@prefix@";
40
my $TESTMODE	= @TESTMODE@;
41
my $TBPID	= "@TBADMINGROUP@";
42 43

#
44
# Testbed Support libraries
45
#
46 47 48
use lib "@prefix@/lib";
use libdb;
use libtestbed;
49 50 51

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

53 54 55 56 57 58 59 60
#
# We put a timeout on the SSH commands. If they fail, it probably means
# the tipserver is screwed up or dead. This is bad, but the experiment
# can continue without it so don't hang. We include the Protocol=2 spec
# so we don't try twice which would double the effective timeout wait.
#
my $SSH		= "$TB/bin/sshtb -o ConnectTimeout=5 -o Protocol=2 -n ";

Leigh Stoller's avatar
Leigh Stoller committed
61
my $PROG	= "/usr/testbed/sbin/console_setup.proxy";
62
my %cmdargs     = ();
63 64 65 66 67 68 69
my @row;

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

#
70 71 72 73 74
# Parse command arguments. Once we return from getopts, all that should
# left are the required arguments.
#
if (@ARGV == 0) {
    usage();
75
}
76
my @nodes = @ARGV;
77 78 79 80 81 82

#
# Script must be setuid root. We don't worry about who called us or what
# nodes are specified since this script always does the right thing.
#
if ($EUID != 0) {
Leigh Stoller's avatar
Leigh Stoller committed
83 84
    die("*** $0:\n".
	"    Must be root! Maybe its a development version?\n");
85 86 87 88 89 90 91
}

#
# Build of a list of nodes/pid pairs and then send the command over to
# plastic.
# 
foreach my $node (@nodes) {
92
    my($db_result);
93
    my $pid;
94
    
95 96 97 98 99 100
    #
    # Untaint the argument. 
    #
    if ($node =~ /^([-\@\w.]+)$/) {
	$node = $1;
    }
101 102 103
    else {
	die("Tainted node name: $node");
    }
104 105

    #
106 107 108 109
    # We need to know all of the tiplines associated with this node,
    # and where they live. There might not be any at all, in which
    # case we are done. This query could probably be rolled into the
    # next query, but that would be confusing.
110
    #
111
    my $tiplines_result =
112 113 114 115 116
	DBQueryFatal("select t.tipname,t.server,t.disabled from tiplines as t ".
		     "left join nodes as n on n.node_id=t.node_id ".
		     "left join node_types as nt on nt.type=n.type ".
		     "where t.node_id='$node' and nt.isvirtnode=0 and ".
		     "      t.server!='' and t.keydata is not null");
117 118 119

    if (! $tiplines_result->numrows) {
	next;
120
    }
121 122 123 124 125

    #
    # Determine the unix group for the node. 
    #
    $db_result =
126 127 128 129 130
	DBQueryFatal("select g.unix_name from reserved as r ".
		     "left join experiments as e on ".
		     " r.pid=e.pid and r.eid=e.eid ".
		     "left join groups as g on ".
		     " g.pid=e.pid and g.gid=e.gid ".
131 132
		     "where r.node_id='$node'");

133
    if ($db_result->numrows > 0) {
134 135 136 137 138 139
	@row = $db_result->fetchrow_array();
	$pid = $row[0];
    }
    else {
	$pid = $TBPID;
    }
140 141

    #
142 143 144 145
    # For each tipline associated with the node (might be more than one),
    # we want to issue the proxy command. However, we want to group all
    # commands for each server together to avoid a zillion ssh calls. So,
    # use an array of command arguments, indexed by the tip server.
146
    #
147 148 149
    while (@row = $tiplines_result->fetchrow_array()) {
	my $tipname = $row[0];
	my $server  = $row[1];
150 151 152 153 154 155 156 157 158 159
	my $disabled= $row[2];

	#
	# Let people know that a console line is disabled cause
	# otherwise we will all forgot about it.
	#
	if ($disabled) {
	    print "Skipping disabled tipline: $tipname on $server ...\n";
	    next;
	}
160 161 162 163 164 165 166

	if (defined($cmdargs{$server})) {
	    $cmdargs{$server} = $cmdargs{$server} . " $tipname $pid";
	}
	else {
	    $cmdargs{$server} = "$tipname $pid ";
	}
167 168 169 170 171
    }
}

if ($TESTMODE) {
    exit 0;
172 173
}

174 175 176
#
# Run the console setup program on the tip server nodes.
# 
177
$UID = 0;
178 179 180
foreach my $server (keys(%cmdargs)) {
    my $args = $cmdargs{$server};

181
    if (system("$SSH -host $server $PROG $args")) {
182
	print STDERR "*** Failed: $SSH -host $server $PROG $args: $?\n";
183 184
	exit 1;
    }
185
}
186 187

exit 0;