verify-ns.in 4.34 KB
Newer Older
1 2 3
#!/usr/bin/perl -wT

#
4
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# 
# {{{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/>.
# 
# }}}
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 55 56 57 58 59 60 61
#

use English;
use Getopt::Std;
use Socket;
use File::Basename;

sub usage()
{
    print STDOUT "Usage: nsverify <pid> <gid> <eid> <nsfile>\n";
 
    exit(-1);
}

#
# Configure variables
#
my $TB       = "@prefix@";
my $TBOPS    = "@TBOPSEMAIL@";
my $CONTROL  = "@USERNODE@";

# Locals
my $SAVEUID  = $UID;
my $outfile = "nsltmap";

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

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

if ($EUID != 0) {
    # We don't want to run this script unless its the real version.
62
    die("Must be root! Maybe its a development version?");
63 64 65 66 67
}

# This script is setuid, so please do not run it as root. Hard to track
# what has happened.
if ($UID == 0) {
68
    die("Please do not run this as root! Its already setuid!");
69 70 71 72 73 74 75 76 77
}

#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
use libtblog;
78
use User;
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120

if (@ARGV != 4) {
    usage();
}

my $pid   = $ARGV[0];
my $gid   = $ARGV[1];
my $eid   = $ARGV[2];
my $nsfile= $ARGV[3];

#
# Must taint check!
#
if ($pid =~ /^([-\w]+)$/) {
    $pid = $1;
}
else {
    die("Bad data in argument: $pid.");
}
if ($gid =~ /^([-\w]+)$/) {
    $gid = $1;
}
else {
    die("Bad data in argument: $gid.");
}
if ($eid =~ /^([-\w]+)$/) {
    $eid = $1;
}
else {
    die("Bad data in argument: $eid.");
}
if ($nsfile =~ /^([-\w\/\.]+)$/) {
    $nsfile = $1;
}
else {
    die("Bad data in argument: $nsfile.");
}

#
# Get DB uid for sending over to ops. In testmode, it runs locally
# as the user running the testsuite, obviously.
#
121 122
my $this_user = User->ThisUser();
if (! defined($this_user)) {
123 124
    tbdie("You do not exist in the Emulab Database!");
}
125
my $user_uid = $this_user->uid();
126 127 128 129 130

# Run as the user for most of this script.
$EUID = $UID;

my $cmdargs = "$TB/libexec/ns2ir/parse.proxy ";
131
$cmdargs .= " -u $user_uid -v -- $pid $gid $eid";
132

133 134 135 136 137 138
# create the output file as the user for quota purposes
unlink $outfile;
open(FOO, ">$outfile") ||
    tbdie("Cannot create parser output file $outfile");
close(FOO);

139 140 141 142 143 144 145
$EUID = $UID = 0;
system("sshtb -host $CONTROL $cmdargs < $nsfile > $outfile");
$EUID = $UID = $SAVEUID;

if ($?) {
    my $exit_status = $? >> 8;
    
Timothy Stack's avatar
Timothy Stack committed
146
    tbdie("Verify parsing failed (error code $exit_status)!");
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
}

open(NSLTMAP, "sort $outfile |");
open(DBLTMAP, "sort ltmap |");

my $done = 0;

sub fcmp($$$) {
    my ($v1, $v2, $tol) = @_;

    return (abs($v1 - $v2) < $tol);
}

while (!$done) {
    my $nsline = <NSLTMAP>;
    my $dbline = <DBLTMAP>;

    if (!$nsline && !$dbline) {
	$done = 1;
    }
    elsif (!$nsline || !$dbline) {
168
	tbdie("Topology verification failed (short file)!");
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
    }
    elsif ($nsline =~ /^l \S+ \S+ \d+ \d+\.\d+ \d+\.\d+ \S+ \S+$/ &&
	   $dbline =~ /^l \S+ \S+ \d+ \d+\.\d+ \d+\.\d+ \S+ \S+$/) {
	my @nsmatches;
	my @dbmatches;

	@nsmatches = ($nsline =~
		/^l (\S+) (\S+) (\d+) (\d+\.\d+) (\d+\.\d+) (\S+) (\S+)$/);
	@dbmatches = ($dbline =~
		/^l (\S+) (\S+) (\d+) (\d+\.\d+) (\d+\.\d+) (\S+) (\S+)$/);
	for (my $lpc = 0; $lpc < 7; $lpc++) {
	    if ($lpc == 3 &&
		fcmp($nsmatches[$lpc], $dbmatches[$lpc], 0.0003)) {
	    }
	    elsif ($lpc == 4 &&
		   fcmp($nsmatches[$lpc], $dbmatches[$lpc], 0.000010)) {
	    }
	    elsif ($nsmatches[$lpc] ne $dbmatches[$lpc]) {
		print "'$nsmatches[$lpc]' != '$dbmatches[$lpc]' in\n";
		print "ns: $nsline";
		print "db: $dbline";
190
		tbdie("Topology verification failed!");
191 192 193 194
	    }
	}
    }
    elsif ($nsline ne $dbline) {
195 196
	chomp $nsline;
	chomp $dbline;
197
	tbdie("Topology verification failed ('$nsline'!='$dbline')!");
198 199 200 201
    }
}

exit(0);