Commit 79ae0bfe authored by Leigh Stoller's avatar Leigh Stoller

Next checkpoint of graphing code. On a currently active template

instance there are graphs on the instance show page and on the
individual run show pages. On the run pages, the graphs select just
the packets between start and stop of the run. I also added drop down
menus to select particular source and destination vnodes.
parent 28f917c6
...@@ -7,8 +7,7 @@ ...@@ -7,8 +7,7 @@
use English; use English;
use strict; use strict;
use Getopt::Std; use Getopt::Std;
use POSIX qw(isatty setsid); use Date::Parse;
use POSIX qw(strftime);
use Errno qw(EDQUOT); use Errno qw(EDQUOT);
use Data::Dumper; use Data::Dumper;
...@@ -46,6 +45,8 @@ my $runidx; ...@@ -46,6 +45,8 @@ my $runidx;
my $guid; my $guid;
my $version; my $version;
my $graphtype; my $graphtype;
my $srclan;
my $dstlan;
my $srcvnode; my $srcvnode;
my $dstvnode; my $dstvnode;
...@@ -165,6 +166,7 @@ if (! keys(%runlist)) { ...@@ -165,6 +166,7 @@ if (! keys(%runlist)) {
if ($instance->Instantiated()) { if ($instance->Instantiated()) {
my $experiment = Experiment->Lookup($instance->pid(), $instance->eid()); my $experiment = Experiment->Lookup($instance->pid(), $instance->eid());
my $eid = $instance->eid();
fatal(-1, "Could not get experiment object from $instance!") fatal(-1, "Could not get experiment object from $instance!")
if (!defined($experiment)); if (!defined($experiment));
...@@ -173,8 +175,51 @@ if ($instance->Instantiated()) { ...@@ -173,8 +175,51 @@ if ($instance->Instantiated()) {
if (! $experiment->dpdb() || !$experiment->dpdbname()); if (! $experiment->dpdb() || !$experiment->dpdbname());
my $dbname = $experiment->dpdbname(); my $dbname = $experiment->dpdbname();
my $optargs = "";
#
# For a specific run, figure out the start and end times of the run
# and pass those along as options to the graphing code.
#
if (defined($runidx)) {
my $rowref = $runlist{$runidx};
my $start = $rowref->{"start_time"};
my $stop = $rowref->{"stop_time"};
if (defined($stop)) {
$optargs = "-r " . str2time($start) . ":" . str2time($stop);
}
else {
$optargs = "-r " . str2time($start) . ":0";
}
}
if (defined($srcvnode)) {
my $query_result =
DBQueryFatal("select ip from virt_lans ".
"where vname='$srclan' and vnode='$srcvnode' and ".
" pid='$pid' and eid='$eid'");
if ($query_result->numrows) {
my ($ip) = $query_result->fetchrow_array();
$optargs .= " -s $ip";
}
}
system("$dbcontrol graphdb $dbname $graphtype") == 0 or if (defined($dstvnode)) {
my $query_result =
DBQueryFatal("select ip from virt_lans ".
"where vname='$dstlan' and vnode='$dstvnode' and ".
" pid='$pid' and eid='$eid'");
if ($query_result->numrows) {
my ($ip) = $query_result->fetchrow_array();
$optargs .= " -t $ip";
}
}
# SENDMAIL($TBOPS, "foo", "$dbname $graphtype $optargs");
system("$dbcontrol graphdb $dbname $graphtype $optargs") == 0 or
fatal(-1, "Failed to generate requested graph!"); fatal(-1, "Failed to generate requested graph!");
} }
exit(0); exit(0);
...@@ -244,33 +289,26 @@ sub ParseArgs() ...@@ -244,33 +289,26 @@ sub ParseArgs()
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR)) { TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR)) {
tbdie("Improper run index!"); tbdie("Improper run index!");
} }
# real check.
if ($runidx =~ /^([\w]*)$/) {
$runidx = $1;
}
else {
tbdie("Bad data in argument: $runidx");
}
}
else {
tbdie("You must supply the -r option!");
} }
# These are really linkname/vnode ... so we can find exact IP addr.
if (defined($options{"s"})) { if (defined($options{"s"})) {
$srcvnode = $options{"s"}; my $tmp = $options{"s"};
if ($srcvnode =~ /^([-\w]+)$/) { if ($tmp =~ /^([-\w]+)\/([-\w]+)$/) {
$srcvnode = $1; $srclan = $1;
$srcvnode = $2;
} }
else { else {
tbdie("Bad srcvnode name: $srcvnode!"); tbdie("Bad srcvnode name: $srcvnode!");
} }
} }
if (defined($options{"t"})) { if (defined($options{"t"})) {
$dstvnode = $options{"s"}; my $tmp = $options{"t"};
if ($dstvnode =~ /^([-\w]+)$/) { if ($tmp =~ /^([-\w]+)\/([-\w]+)$/) {
$dstvnode = $1; $dstlan = $1;
$dstvnode = $2;
} }
else { else {
tbdie("Bad dstvnode name: $dstvnode!"); tbdie("Bad dstvnode name: $dstvnode!");
......
...@@ -772,10 +772,12 @@ sub DelTempDB(@) ...@@ -772,10 +772,12 @@ sub DelTempDB(@)
# #
sub GraphDB(@) sub GraphDB(@)
{ {
my ($dbname, $which, $filename) = @_;
usage() usage()
if (@_ < 2 || @_ > 3); if (@_ < 2);
my $dbname = shift(@_);
my $which = shift(@_);
my @optargs = ();
# #
# Untaint args. # Untaint args.
...@@ -792,22 +794,22 @@ sub GraphDB(@) ...@@ -792,22 +794,22 @@ sub GraphDB(@)
else { else {
die("Bad data in which: $which"); die("Bad data in which: $which");
} }
# Note different taint check (allow /).
if (defined($filename)) { # Check the rest of the args with a generic test.
if ($filename =~ /^([-\w\.\/]+)$/) { foreach my $arg (@_) {
$filename = $1; # Note different taint check (allow /).
if ($arg =~ /^([-\w\.\/\:]+)$/) {
$arg = $1;
} }
else { else {
tbdie("Bad data in filename: $filename"); tbdie("Bad data in argument: $arg");
} }
} push(@optargs, $arg);
else {
$filename = "";
} }
print "Graphing DB '$dbname' from mysql database on $CONTROL.\n" print "Graphing DB '$dbname' from mysql database on $CONTROL.\n"
if ($debug); if ($debug);
my $retval = DoOpsStuff("graphdb $dbname $which $filename"); my $retval = DoOpsStuff("graphdb $dbname $which @optargs");
if ($retval) { if ($retval) {
fatal("$OPSDBPROXY failed on $CONTROL!"); fatal("$OPSDBPROXY failed on $CONTROL!");
} }
......
...@@ -555,10 +555,55 @@ sub SaveGraph($$) ...@@ -555,10 +555,55 @@ sub SaveGraph($$)
sub GraphDB(@) sub GraphDB(@)
{ {
my ($dbname, $which, $filename) = @_;
usage() usage()
if (@_ < 2 || @_ > 3); if (@_ < 2);
my $dbname = shift(@_);
my $which = shift(@_);
my $filename;
my $start;
my $stop;
my $srcip;
my $dstip;
# Parse the rest of the options.
while (@_) {
my $arg = shift(@_);
if ($arg eq "-f") {
usage()
if (@_ == 0);
$filename = shift(@_);
}
elsif ($arg eq "-r") {
usage()
if (@_ == 0);
$arg = shift(@_);
if ($arg =~ /^(\d*):(\d*)$/) {
$start = $1;
if ($2) {
$stop = $2;
}
}
else {
usage();
}
}
elsif ($arg eq "-s") {
usage()
if (@_ == 0);
$srcip = shift(@_);
}
elsif ($arg eq "-t") {
usage()
if (@_ == 0);
$dstip = shift(@_);
}
else {
usage();
}
}
my $exists = DBExists($dbname); my $exists = DBExists($dbname);
return -1 return -1
...@@ -614,11 +659,49 @@ sub GraphDB(@) ...@@ -614,11 +659,49 @@ sub GraphDB(@)
if ($which eq "pps" || $which eq "bps") { if ($which eq "pps" || $which eq "bps") {
my $query_result; my $query_result;
my $timeclause;
my $ipclause;
my $whereclause = "";
if (defined($start) && defined($stop)) {
$timeclause = "(timestamp >= FROM_UNIXTIME('$start') and ".
"timestamp <= FROM_UNIXTIME('$stop')) ";
}
elsif (defined($start)) {
$timeclause = "(timestamp >= FROM_UNIXTIME('$start')) ";
}
elsif (defined($stop)) {
$timeclause = "(timestamp <= FROM_UNIXTIME('$stop')) ";
}
if (defined($srcip) && defined($dstip)) {
$ipclause = "(ip_src=INET_ATON('$srcip') ".
"and ip_dst=INET_ATON('$dstip'))";
}
elsif (defined($srcip)) {
$ipclause = "(ip_src=INET_ATON('$srcip'))";
}
elsif (defined($dstip)) {
$ipclause = "(ip_dst=INET_ATON('$dstip'))";
}
if (defined($timeclause) && defined($ipclause)) {
$whereclause = "where $timeclause and $ipclause ";
}
elsif (defined($timeclause)) {
$whereclause = "where $timeclause ";
}
elsif (defined($ipclause)) {
$whereclause = "where $ipclause ";
}
if ($which eq "pps") { if ($which eq "pps") {
$query_result = $query_result =
DBQueryFatal("select UNIX_TIMESTAMP(timestamp),count(*) ". DBQueryFatal("select UNIX_TIMESTAMP(timestamp),count(*) ".
" from event ". " from event as e ".
"left join iphdr as i on ".
" i.sid=e.sid and i.cid=e.cid ".
$whereclause . " " .
"group by timestamp order by timestamp"); "group by timestamp order by timestamp");
} }
else { else {
...@@ -627,8 +710,12 @@ sub GraphDB(@) ...@@ -627,8 +710,12 @@ sub GraphDB(@)
" from event as e ". " from event as e ".
"left join iphdr as i on ". "left join iphdr as i on ".
" i.sid=e.sid and i.cid=e.cid ". " i.sid=e.sid and i.cid=e.cid ".
$whereclause . " " .
"group by timestamp order by timestamp"); "group by timestamp order by timestamp");
} }
return 0
if (! $query_result->numrows);
my ($tstart,$first) = $query_result->fetchrow_array(); my ($tstart,$first) = $query_result->fetchrow_array();
@x_data = (0); @x_data = (0);
......
...@@ -34,3 +34,27 @@ function IframeDocument(id) ...@@ -34,3 +34,27 @@ function IframeDocument(id)
} }
return oDoc; return oDoc;
} }
function GraphChange_cb(html) {
grapharea = getObjbyName('grapharea');
if (grapharea) {
grapharea.innerHTML = html;
}
}
function GraphChange(which) {
var arg0 = "all";
var arg1 = "all";
var srcvnode = getObjbyName('trace_srcvnode');
if (srcvnode) {
arg0 = srcvnode.options[srcvnode.selectedIndex].value;
}
var dstvnode = getObjbyName('trace_dstvnode');
if (dstvnode) {
arg1 = dstvnode.options[dstvnode.selectedIndex].value;
}
x_GraphShow(which, arg0, arg1, GraphChange_cb);
return false;
}
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
# #
include("defs.php3"); include("defs.php3");
include_once("template_defs.php"); include_once("template_defs.php");
require("Sajax.php");
sajax_init();
sajax_export("GraphShow");
# #
# Only known and logged in users ... # Only known and logged in users ...
...@@ -46,11 +49,6 @@ if (!TBvalid_integer($runidx)) { ...@@ -46,11 +49,6 @@ if (!TBvalid_integer($runidx)) {
PAGEARGERROR("Invalid characters in run ID!"); PAGEARGERROR("Invalid characters in run ID!");
} }
#
# Standard Testbed Header after argument checking.
#
PAGEHEADER("Experiment Run");
# #
# Check to make sure this is a valid template and user has permission. # Check to make sure this is a valid template and user has permission.
# #
...@@ -72,6 +70,31 @@ if (! $instance->ValidRun($runidx)) { ...@@ -72,6 +70,31 @@ if (! $instance->ValidRun($runidx)) {
USERERROR("The run $runidx is not a valid experiment run!", 1); USERERROR("The run $runidx is not a valid experiment run!", 1);
} }
#
# For the Sajax Interface
#
function GraphShow($which, $arg0, $arg1)
{
global $template, $instance, $runidx;
ob_start();
$instance->ShowGraphArea($which, $runidx, $arg0, $arg1);
$html = ob_get_contents();
ob_end_clean();
return $html;
}
#
# See if this request is to the above function. Does not return
# if it is. Otherwise return and continue on.
#
sajax_handle_client_request();
#
# Standard Testbed Header after argument checking.
#
PAGEHEADER("Experiment Run");
echo "<font size=+2>Experiment Run<b> " . echo "<font size=+2>Experiment Run<b> " .
MakeLink("instance", MakeLink("instance",
"guid=$guid&version=$version&exptidx=$exptidx", "guid=$guid&version=$version&exptidx=$exptidx",
...@@ -79,9 +102,20 @@ echo "<font size=+2>Experiment Run<b> " . ...@@ -79,9 +102,20 @@ echo "<font size=+2>Experiment Run<b> " .
"</b></font>\n"; "</b></font>\n";
echo "<br><br>\n"; echo "<br><br>\n";
$instance->ShowRun($runidx); $instance->ShowRun($runidx);
echo "<script type='text/javascript' language='javascript'>\n";
sajax_show_javascript();
echo "</script>\n";
#
# Throw up graph stuff.
#
echo "<center>\n";
echo "<br>";
$instance->ShowGraphArea("pps", $runidx);
echo "</center>\n";
# #
# Standard Testbed Footer # Standard Testbed Footer
# #
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
# #
include("defs.php3"); include("defs.php3");
include_once("template_defs.php"); include_once("template_defs.php");
require("Sajax.php");
sajax_init();
sajax_export("GraphShow");
# #
# Only known and logged in users ... # Only known and logged in users ...
...@@ -39,11 +42,6 @@ if (!TBvalid_integer($exptidx)) { ...@@ -39,11 +42,6 @@ if (!TBvalid_integer($exptidx)) {
PAGEARGERROR("Invalid characters in instance ID!"); PAGEARGERROR("Invalid characters in instance ID!");
} }
#
# Standard Testbed Header after argument checking.
#
PAGEHEADER("Template Instance");
# #
# Check to make sure this is a valid template and user has permission. # Check to make sure this is a valid template and user has permission.
# #
...@@ -62,6 +60,31 @@ if (!$instance) { ...@@ -62,6 +60,31 @@ if (!$instance) {
"template $guid/$version!", 1); "template $guid/$version!", 1);
} }
#
# For the Sajax Interface
#
function GraphShow($which, $arg0, $arg1)
{
global $template, $instance;
ob_start();
$instance->ShowGraphArea($which, -1, $arg0, $arg1);
$html = ob_get_contents();
ob_end_clean();
return $html;
}
#
# See if this request is to the above function. Does not return
# if it is. Otherwise return and continue on.
#
sajax_handle_client_request();
#
# Standard Testbed Header after argument checking.
#
PAGEHEADER("Template Instance");
echo "<font size=+2>Template Instance <b>" . echo "<font size=+2>Template Instance <b>" .
MakeLink("template", MakeLink("template",
"guid=$guid&version=$version", "$guid/$version") . "guid=$guid&version=$version", "$guid/$version") .
...@@ -70,6 +93,18 @@ echo "<br><br>\n"; ...@@ -70,6 +93,18 @@ echo "<br><br>\n";
$instance->Show(1); $instance->Show(1);
echo "<script type='text/javascript' language='javascript'>\n";
sajax_show_javascript();
echo "</script>\n";
#
# Throw up graph stuff.
#
echo "<center>\n";
echo "<br>";
$instance->ShowGraphArea("pps");
echo "</center>\n";
# #
# Standard Testbed Footer # Standard Testbed Footer
# #
......
...@@ -31,12 +31,42 @@ if (!$instance) { ...@@ -31,12 +31,42 @@ if (!$instance) {
USERERROR("The instance $exptidx is not a valid instance!", 1); USERERROR("The instance $exptidx is not a valid instance!", 1);
} }
# Optional runidx for graphing just a specific run.
$runarg = "";
$vnodes = "";
if (isset($runidx) && $runidx != "") {
if (!TBvalid_integer($runidx)) {
PAGEARGERROR("Invalid characters in run index!");
}
else {
$runarg = "-r $runidx";
}
}
# Optional src and dst arguments.
if (isset($srcvnode) && $srcvnode != "") {
if (! preg_match("/^[-\w\/]*$/", $srcvnode)) {
PAGEARGERROR("Invalid characters in src vnode!");
}
else {
$vnodes .= " -s " . escapeshellarg($srcvnode);
}
}
if (isset($dstvnode) && $dstvnode != "") {
if (! preg_match("/^[-\w\/]*$/", $dstvnode)) {
PAGEARGERROR("Invalid characters in dst vnode!");
}
else {
$vnodes .= " -t " . escapeshellarg($dstvnode);
}
}
# #
# Spit out the image with a content header. # Spit out the image with a content header.
# #
$eid = $instance->eid(); $eid = $instance->eid();
$pid = $instance->pid(); $pid = $instance->pid();
$runidx = $instance->runidx();
$guid = $instance->guid(); $guid = $instance->guid();
$vers = $instance->vers(); $vers = $instance->vers();
$which = "pps"; $which = "pps";
...@@ -57,7 +87,7 @@ if (!TBExptGroup($pid, $eid, $gid)) { ...@@ -57,7 +87,7 @@ if (!TBExptGroup($pid, $eid, $gid)) {
TBGroupUnixInfo($pid, $gid, $unix_gid, $unix_name); TBGroupUnixInfo($pid, $gid, $unix_gid, $unix_name);
if ($fp = popen("$TBSUEXEC_PATH $uid $unix_name webtemplate_linkgraph " . if ($fp = popen("$TBSUEXEC_PATH $uid $unix_name webtemplate_linkgraph " .
"-i $exptidx -r $runidx $guid/$vers $which", "r")) { "-i $exptidx $runarg $vnodes $guid/$vers $which", "r")) {
header("Content-type: image/gif"); header("Content-type: image/gif");
fpassthru($fp); fpassthru($fp);
} }
......
...@@ -1160,9 +1160,15 @@ class TemplateInstance ...@@ -1160,9 +1160,15 @@ class TemplateInstance
if (!isset($stop)) if (!isset($stop))
$stop = "&nbsp"; $stop = "&nbsp";
echo "<center>\n";
echo "<table border=0 bgcolor=#000 color=#000 class=stealth ".
" cellpadding=0 cellspacing=0>\n";
echo "<tr valign=top>";
echo "<td class=stealth align=center>\n";
echo "<center> echo "<center>
<h3>Experiment Run</h3> <h3>Details</h3>
</center>\n"; </center>\n";
echo "<table align=center cellpadding=2 cellspacing=2 border=1>\n"; echo "<table align=center cellpadding=2 cellspacing=2 border=1>\n";
...@@ -1194,14 +1200,17 @@ class TemplateInstance ...@@ -1194,14 +1200,17 @@ class TemplateInstance
</tr>\n"; </tr>\n";
} }
echo "</table>\n"; echo "</table>\n";
echo "</td>\n";
$query_result = $query_result =
DBQueryFatal("select * from experiment_run_bindings ". DBQueryFatal("select * from experiment_run_bindings ".
"where exptidx='$exptidx' and runidx='$runidx'"); "where exptidx='$exptidx' and runidx='$runidx'");
if (mysql_num_rows($query_result)) { if (mysql_num_rows($query_result)) {
echo "<td align=center class=stealth> &nbsp &nbsp &nbsp </td>\n";
echo "<td align=center class=stealth>\n";
echo "<center> echo "<center>
<h3>Experiment Run Bindings</h3> <h3>Bindings</h3>
</center> </center>
<table align=center border=1 cellpadding=5 cellspacing=2>\n"; <table align=center border=1 cellpadding=5 cellspacing=2>\n";
...@@ -1223,7 +1232,10 @@ class TemplateInstance ...@@ -1223,7 +1232,10 @@ class TemplateInstance
</tr>\n"; </tr>\n";
} }
echo "</table>\n"; echo "</table>\n";
echo "</td>\n";
} }
echo "</tr>\n";
echo "</table>\n";
} }
# #
...@@ -1269,6 +1281,117 @@ class TemplateInstance ...@@ -1269,6 +1281,117 @@ class TemplateInstance
} }
return 0; return 0;
} }
#
# Show graph stuff, either for entire instance or for a run. Very hacky.
#
function ShowGraph($graphtype = "pps",
$runidx = -1, $src = "all", $dst = "all" ) {
$exptidx = $this->exptidx();
$runarg = ($runidx >= 0 ? "&runidx=$runidx" : "");
$srcarg = "";
$dstarg = "";
# Make the link unique to force reload on the client side.
$now = time();
$pid = $this->pid();
$eid = $this->eid();
#
# Lets check args!
#
if (! preg_match("/^[\w]*$/", $graphtype) ||
! preg_match("/^[-\d]*$/", $runidx) ||
! preg_match("/^[-\w\/]*$/", $src) ||
! preg_match("/^[-\w\/]*$/", $dst)) {
return "";
}
# Pass along the src/dst args to the graphing page.
if ($src != "" && $src != "all")
$srcarg = "&srcvnode=$src";
if ($dst != "" && $dst != "all")
$dstarg = "&dstvnode=$dst";
#
# Grab a list of vnode names so that user can select a specific
# source and destination.
#
$query_result =
DBQueryFatal("select vname,vnode from virt_lans ".
"where pid='$pid' and eid='$eid' and trace_db!=0");