nfstrace.in 6.11 KB
Newer Older
1 2 3 4
#!/usr/bin/perl -wT

#
# EMULAB-COPYRIGHT
5
# Copyright (c) 2005, 2006 University of Utah and the Flux Group.
6 7 8 9 10 11 12 13 14 15 16 17 18
# All rights reserved.
#

use English;
use IPC::Open2;

#
# Configure variables
#
my $TB		= "@prefix@";
my $TBOPS       = "@TBOPSEMAIL@";
my $TESTMODE    = @TESTMODE@;
my $FSNODE      = "@FSNODE@";
19
my $NFSTRACESUPPORT= @NFSTRACESUPPORT@;
20

21 22 23 24
my $FSDIR_GROUPS = "@FSDIR_GROUPS@";
my $FSDIR_PROJ = "@FSDIR_PROJ@";
my $FSDIR_USERS = "@FSDIR_USERS@";
my $FSDIR_SHARE = "@FSDIR_SHARE@";
25
my $FSDIR_SCRATCH = "@FSDIR_SCRATCH@";
26

27 28 29 30 31 32 33 34 35 36 37 38
# Note no -n option. We redirect stdin from the new exports file below.
my $SSH		= "$TB/bin/sshtb -l root -host $FSNODE";
my $DBPROG	= "$TB/sbin/nfsdump2db";
my $PROG	= "$TB/sbin/nfstrace.proxy";
my $TMPFILE     = "/var/nfstrace/temp";
my $dbg		= 1;
my @row;

#
# Handle command-line arguments
#
sub usage() {
39
    warn "Usage: $0 <gc|get|transfer|stats|add> pid eid\n";
40 41 42 43 44 45 46 47 48
    return 1;
}

my $cmd = shift @ARGV;
if (!$cmd) {
    exit usage();
}

# Check the operation type
49
if ($cmd !~ /^(gc|get|transfer|stats|add)$/) {
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
    exit usage();
} else {
    # Untaint operation
    $cmd = $1;
}

my $pid;
my $eid;

if (@ARGV == 2) {
    $pid = $ARGV[0];
    $eid = $ARGV[1];

    #
    # Untaint args.
    #
    if ($pid =~ /^([-\@\w]+)$/) {
	$pid = $1;
    }
    else {
	die_noretry("Bad data in pid: $pid.");
    }
    if ($eid =~ /^([-\@\w]+)$/) {
	$eid = $1;
    }
    else {
	die_noretry("Bad data in eid: $eid.");
    }
}
elsif ($cmd ne "stats") {
    print "Project ID and Experiment ID missing.";
    exit usage();
}

#
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
    die("*** $0:\n".
	"    Must be root! Maybe its a development version?\n");
}

92 93 94 95 96 97 98 99
#
# If no bugdb support, just exit. 
#
if (! $NFSTRACESUPPORT) {
    print "NFS trace support is not enabled. Exit ...\n";
    exit(0);
}

100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

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

#
# Testbed Support libraries
# 
use lib "@prefix@/lib";
use libdb;
use libtestbed;
115
use libArchive;
116

117 118 119 120 121 122
my $PROJROOT    = PROJROOT();
my $GROUPROOT   = GROUPROOT();
my $USERROOT    = USERROOT();
my $SHAREROOT   = SHAREROOT();
my $SCRATCHROOT = SCRATCHROOT();

123 124
$UID = 0;

125 126 127 128
if ($cmd eq "add") {
    exit libArchive::TBExperimentArchiveAddTracedFiles($pid, $eid);
}

129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
if ($cmd ne "stats") {
    my $expstate;
    
    if (! ($expstate = ExpState($pid, $eid))) {
	die("*** $0:\n".
	    "    No such experiment $pid/$eid!\n");
    }

    if ($expstate ne EXPTSTATE_ACTIVE &&
	$expstate ne EXPTSTATE_ACTIVATING &&
	$expstate ne EXPTSTATE_MODIFY_RESWAP &&
	$expstate ne EXPTSTATE_SWAPPING) {
	die("*** $0:\n".
	    "    Experiment $pid/$eid must be active (or swapping)! $expstate\n");
    }
}

my $exptidx;
my $rsrcidx;
my $query_result;
149 150
my $cmdline = "$SSH $PROG $cmd";

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
if ($cmd eq "get" || $cmd eq "transfer") {
    if ($cmd eq "transfer") {
	$cmdline = "$SSH $PROG -m get";
	
	$query_result =
	    DBQueryFatal("SELECT e.idx,s.rsrcidx FROM experiments as e ".
			 "left join experiment_stats as s on e.idx=s.exptidx ".
			 "where e.pid='$pid' and e.eid='$eid'");
	
	if ($query_result->num_rows() != 1) {
	    die("*** $0:\n".
		"    Experiment $pid/$eid has no stats!\n");
	}
	($exptidx, $rsrcidx) = $query_result->fetchrow_array();
    }
166 167 168 169 170 171 172
    $cmdline .= " -m $FSDIR_GROUPS:$GROUPROOT";
    $cmdline .= " -m $FSDIR_PROJ:$PROJROOT";
    $cmdline .= " -m $FSDIR_USERS:$USERROOT";
    $cmdline .= " -m $FSDIR_SHARE:SHAREROOT";
    if ($FSDIR_SCRATCH) {
	$cmdline .= " -m $FSDIR_SCRATCH:$SCRATCHROOT";
    }
173 174 175
    $cmdline .= " $pid $eid";
}
elsif ($cmd eq "gc") {
176
    $cmdline .= " $pid $eid";
177 178 179
}

local (*NT_READER, *NT_WRITER);
180
$ntpid = open2(\*NT_READER, \*NT_WRITER, $cmdline);
181

182
if ($cmd eq "gc" && defined($pid)) {
183 184 185 186 187 188 189 190
    #
    # First gather up all the nodes that are reserved and the required info.
    # Order by pid,gid first so that they're all grouped together and we avoid
    # extra db queries.
    #
    # VIRTNODE HACK: Virtual nodes are special, so do not export. (isvirtnode).
    #
    $nodes_result =
191
	DBQueryFatal("select r.vname,i.IP from reserved as r ".
192 193
		     "left join nodes on r.node_id=nodes.node_id ".
		     "left join node_types on node_types.type=nodes.type ".
194 195
		     "left join interfaces as i on i.node_id=r.node_id ".
		     "where nodes.role='testnode' ".
196 197
		     "       and node_types.isvirtnode=0 ".
		     "       and node_types.isremotenode=0 ".
198
		     "       and i.role='" . TBDB_IFACEROLE_CONTROL() . "' ".
199 200
		     "       and pid='$pid' and eid='$eid'");
    
201 202
    while (my ($vname,$ip) = $nodes_result->fetchrow_array) {
	print NT_WRITER "$vname:$ip\n";
203 204 205 206 207
    }
}

close(NT_WRITER);

208 209 210 211 212
sub InsertFile($)
{
    my ($fn) = @_;
    my $retval = -1;
    
213 214 215 216 217 218 219
    $fn =~ s|^$FSDIR_GROUPS|$GROUPROOT|;
    $fn =~ s|^$FSDIR_PROJ|$PROJROOT|;
    $fn =~ s|^$FSDIR_USERS|$USERROOT|;
    $fn =~ s|^$FSDIR_SHARE|$SHAREROOT|;
    if ($FSDIR_SCRATCH) {
	$fn =~ s|^$FSDIR_SCRATCH|$SCRATCHROOT|;
    }
220
    
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
    $fn = DBQuoteSpecial($fn);

    $query = "INSERT IGNORE INTO accessed_files (fn) VALUES ($fn)";
    $query_result = DBQueryWarn($query);
    if (!$query_result) {
	print STDERR
	    "*** WARNING $0:\n".
	    "    Failed to insert a new file access record for ".
		"$pid/$eid\n";
    }

    $query_result =
	DBQueryFatal("SELECT idx FROM accessed_files WHERE fn=$fn");
    
    if ($query_result->num_rows() != 1) {
	die("*** $0:\n".
	    "    Missing file $fn!\n");
    }
    ($retval) = $query_result->fetchrow_array();

    return $retval;
}

244
while (<NT_READER>) {
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
    if ($cmd eq "transfer") {
	if ($_ =~ /^\s?(r|w|rw)\s+(\d+)\s+(.+)$/) {
	    my $fileidx = InsertFile($3);

	    $query = "REPLACE INTO fs_resources ".
		"(rsrcidx, fileidx, exptidx, type, size) VALUES (".
		"$rsrcidx, $fileidx, $exptidx, '$1', $2)";
	    DBQueryFatal($query);
	}
	elsif ($_ =~ /^\s+link\s+(.+)$/) {
	    my $fileidx = InsertFile($1);

	    $query = "REPLACE INTO fs_resources ".
		"(rsrcidx, fileidx, exptidx, type, size) VALUES (".
		"$rsrcidx, $fileidx, $exptidx, 'l', 0)";
	    DBQueryFatal($query);
	}
	else {
	    print "No match: $_";
	}
    }
    else {
	print "$_";
    }
269 270 271 272 273 274
}

close(NT_READER);
waitpid($ntpid, 0);

exit(0);