Commit b04e2f74 authored by Leigh Stoller's avatar Leigh Stoller

Improvements to code for hiding and showing templates in the graph.

parent 5ae26605
......@@ -24,7 +24,7 @@ BIN_STUFF = power snmpit tbend tbprerun tbreport \
node_attributes archive_control template_create \
template_swapin template_swapout template_graph \
template_exprun template_delete template_metadata \
template_export
template_export template_control
SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
batch_daemon exports_setup reload_daemon sched_reserve \
......@@ -54,7 +54,8 @@ LIBEXEC_STUFF = rmproj wanlinksolve wanlinkinfo \
spewrpmtar webtarfiles_setup webfrisbeekiller gentopofile \
webnodeattributes webarchive_control webtemplate_create \
webtemplate_swapin webtemplate_swapout webtemplate_exprun \
webtemplate_graph webtemplate_metadata webtemplate_export
webtemplate_graph webtemplate_metadata webtemplate_export \
webtemplate_control
LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \
snmpit_cisco.pm snmpit_lib.pm snmpit_apc.pm power_rpc27.pm \
......
......@@ -118,6 +118,10 @@ sub tid($) { return ((! ref($_[0])) ? -1 : $_[0]->{'TEMPLATE'}->{'tid'}); }
sub path($) { return ((! ref($_[0])) ? -1 : $_[0]->{'TEMPLATE'}->{'path'}); }
sub archive_idx($) {
return ((! ref($_[0])) ? -1 : $_[0]->{'TEMPLATE'}->{'archive_idx'}); }
sub parent_guid($) {
return ((! ref($_[0])) ? -1 : $_[0]->{'TEMPLATE'}->{'parent_guid'}); }
sub IsRoot($) {
return ! defined($_[0]->{'TEMPLATE'}->{'parent_guid'}); }
#
# Lookup a template given an experiment index.
......@@ -1252,6 +1256,116 @@ sub CopyDataStore($$$)
return 0;
}
#
# Hide Template, optionally hiding all children.
#
sub Hide($$)
{
my ($self, $recursive) = @_;
# Must be a real reference.
return -1
if (! ref($self));
my $guid = $self->guid();
my $vers = $self->vers();
DBQueryWarn("update experiment_templates set hidden=1 ".
"where guid='$guid' and ".
" vers='$vers'")
or return -1;
Refresh($self) == 0
or return -1;
if ($recursive) {
$self->Recurse("hidden=1") == 0
or return -1;
}
# This can fail; it is not critical.
Template::mysystem("$makegraph $guid");
return 0;
}
#
# Show Template, optionally showing all children.
#
sub Show($$)
{
my ($self, $recursive) = @_;
# Must be a real reference.
return -1
if (! ref($self));
my $guid = $self->guid();
my $vers = $self->vers();
DBQueryWarn("update experiment_templates set hidden=0 ".
"where guid='$guid' and ".
" vers='$vers'")
or return -1;
Refresh($self) == 0
or return -1;
if ($recursive) {
$self->Recurse("hidden=0") == 0
or return -1;
}
# This can fail; it is not critical.
Template::mysystem("$makegraph $guid");
return 0;
}
# Improve this at some point.
sub Recurse($$)
{
my ($self, $string) = @_;
my %children = ();
# Must be a real reference.
return -1
if (! ref($self));
my $template_guid = $self->guid();
my $template_vers = $self->vers();
my $query_result =
DBQueryWarn("select vers,parent_vers from experiment_templates ".
"where guid='$template_guid' ".
"order by vers");
return -1
if (!$query_result);
# Build up lists of childen.
while (my ($vers,$parent_vers) = $query_result->fetchrow_array()) {
next
if (!defined($parent_vers));
$children{$parent_vers} = []
if (!exists($children{$parent_vers}));
push(@{ $children{$parent_vers} }, $vers);
}
# Recurse through all the children of this template.
my @kids = @{ $children{$template_vers} };
while (@kids) {
my $kid = shift(@kids);
DBQueryWarn("update experiment_templates set $string ".
"where guid='$template_guid' and vers='$kid'")
or return -1;
push(@kids, @{ $children{$kid} })
if (exists($children{$kid}));
}
return 0;
}
############################################################################
package Template::Instance;
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2006 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use strict;
use Getopt::Std;
#
# Do various things to templates.
#
# Exit codes are important; they tell the web page what has happened so
# it can say something useful to the user. Fatal errors are mostly done
# with die(), but expected errors use this routine. At some point we will
# use the DB to communicate the actual error.
#
# $status < 0 - Fatal error. Something went wrong we did not expect.
# $status = 0 - Everything okay.
# $status > 0 - Expected error. User not allowed for some reason.
#
sub usage()
{
print(STDERR
"Usage: template_control -a <action> <guid/vers> [args ...]\n".
"switches and arguments:\n".
"-a <action> - add, delete or modify\n".
"<guid/vers> - GUID and version of template\n");
exit(-1);
}
my $optlist = "a:";
my %options = ();
my $action;
my $template_guid;
my $template_vers;
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
# Locals
my $dbuid;
my $template;
my $instance;
# For the END block below.
my $cleaning = 0;
my $justexit = 1;
# Protos
sub ParseArgs();
sub HideTemplate();
sub ShowTemplate();
sub ShowHidden();
sub HideHidden();
#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
use libtblog;
use Template;
# Be careful not to exit on transient error
$libdb::DBQUERY_MAXTRIES = 0;
#
# Turn off line buffering on output
#
$| = 1;
#
# Untaint the path
#
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Verify user and get his DB uid.
#
if (! UNIX2DBUID($UID, \$dbuid)) {
tbdie("You do not exist in the Emulab Database!");
}
# Now parse arguments.
ParseArgs();
#
# Grab template and do access check.
#
$template = Template->Lookup($template_guid, $template_vers);
if (!defined($template)) {
tbdie("Experiment template $template_guid/$template_vers does not exist!");
}
if (! TBProjAccessCheck($dbuid,
$template->pid(), $template->gid(),
TB_PROJECT_CREATEEXPT)) {
tberror("You do not have permission to add metadata to template ".
"$template_guid/$template_vers");
exit(1);
}
#
# Do the action.
#
if ($action eq "hide") {
exit(HideTemplate());
}
elsif ($action eq "show") {
exit(ShowTemplate());
}
elsif ($action eq "showhidden") {
exit(ShowHidden());
}
elsif ($action eq "hidehidden") {
exit(HideHidden());
}
usage();
sub HideTemplate()
{
my $optlist = "r";
my $recursive = 0;
my %options;
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"r"})) {
$recursive = 1;
}
$template->Hide($recursive) == 0
or return -1;
return 0;
}
sub ShowTemplate()
{
my $optlist = "r";
my $recursive = 0;
my %options;
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"r"})) {
$recursive = 1;
}
$template->Show($recursive) == 0
or return -1;
return 0;
}
sub ShowHidden()
{
if (! $template->IsRoot()) {
print STDERR "Must apply to the root template!\n";
return -1;
}
# We overload the hidden bit on the root template
$template->Show(0) == 0
or return -1;
return 0;
}
sub HideHidden()
{
if (! $template->IsRoot()) {
print STDERR "Must apply to the root template!\n";
return -1;
}
# We overload the hidden bit on the root template
$template->Hide(0) == 0
or return -1;
return 0;
}
#
# Parse command arguments. Once we return from getopts, all that are
# left are the required arguments.
#
sub ParseArgs()
{
my %options;
if (! getopts($optlist, \%options)) {
usage();
}
if (@ARGV < 1) {
usage();
}
#
# Pick up guid/version and untaint.
#
my $tmp = shift(@ARGV);
if ($tmp =~ /^([\w]*)\/([\d]*)$/) {
$template_guid = $1;
$template_vers = $2;
}
else {
usage();
}
if (!defined($options{"a"})) {
tbdie("Must supply -a option");
}
$action = $options{"a"};
}
......@@ -17,17 +17,15 @@ sub usage()
print(STDERR
"Usage: template_graph [-a] <guid>\n".
"switches and arguments:\n".
"-v - be more chatty\n".
"-a - Show all templates (ignore hidden bit)\n".
"-p <prefix> - prefix for output files.\n".
"<guid> - GUID to graph\n");
exit(-1);
}
my $optlist = "vap:z:";
my $optlist = "p:z:d";
my %options = ();
my $verbose = 0;
my $debug = 0;
my $prefix = "/tmp/dot$$";
my $showall = 0;
my $scale = 1.0;
my $zoom;
my $guid;
......@@ -46,6 +44,7 @@ my $CONTROL = "@USERNODE@";
# Protos
sub ParseArgs();
sub SetParent($@);
# Locals
my $DOT = "/usr/local/bin/dot";
......@@ -111,11 +110,12 @@ if (! $query_result->num_rows) {
}
#
# Build up lists of children.
# Build up lists of children (and associated stuff like hidden,description).
#
my %hidden = ();
my %tids = ();
my %children = ();
my %parents = ();
my %descriptions= ();
my $rootnode = 1; # XXX
......@@ -134,15 +134,11 @@ while (my ($vers,$parent_vers,$hidden,$tid,$description) =
}
#
# If the root node is hidden (a silly thing to do), then we are done.
# We overload the hidden bit on the root template. If its set, that means
# to hide hidden templates, otherwise it means to show hidden templates.
#
if ($hidden{$rootnode}) {
print "Root node hidden; clearing graph entry for template $guid ...\n";
DBQueryFatal("delete from experiment_template_graphs ".
"where parent_guid='$guid'");
exit(0);
}
my $showall = ($hidden{$rootnode} == 0);
$hidden{$rootnode} = 0;
# Defaults;
my $size = 8;
......@@ -197,14 +193,43 @@ print DOT " edge [arrowsize=$arrowsize]\n";
print DOT " subgraph guid {\n";
print DOT " label = \"$guid\";\n";
# Start with root and decend all children where hidden=0.
my @kids = ($rootnode);
#
# Do a recursive decent to figure out the parent for each template.
# We do this cause we want to skip hidden templates, but pick it up
# again down the line when hidden=0.
#
sub SetParent($@)
{
my ($parent, @kids) = @_;
foreach my $kid (@kids) {
if (!$showall && $hidden{$kid}) {
# pass our parent to children, thereby skipping a level.
SetParent($parent, @{ $children{$kid} })
if (exists($children{$kid}));
}
else {
$parents{$kid} = $parent;
SetParent($kid, @{ $children{$kid} })
if (exists($children{$kid}));
}
}
}
$parents{$rootnode} = undef;
SetParent($rootnode, @{ $children{$rootnode} });
while (@kids) {
my $vers = shift(@kids);
#
# The parents hash now has all the templates that are visible.
#
foreach my $kid (sort {$a <=> $b} keys(%parents)) {
my $vers = $kid;
my $parent = $parents{$vers};
my $tid = $tids{$vers};
my $url = "$TBBASE/template_show.php?guid=$guid&version=$vers";
my $color = "black";
my $tid = $tids{$vers};
my $url = "$TBBASE/template_show.php?guid=$guid&version=$vers";
print DOT " $parent -> $kid;\n"
if (defined($parent));
# Shorten the description
my $description = $descriptions{$vers};
......@@ -252,20 +277,14 @@ while (@kids) {
# But we do not want the font arbitrarily large.
$fontsize = 12
if ($fontsize > 12);
$color = "blue"
if ($hidden{$vers});
if (!exists($versions{"$vers"})) {
print DOT " $vers [fontsize=$fontsize,".
print DOT " $vers [fontsize=$fontsize,color=$color,".
"label=\"$tid\",href=\"$url\",tooltip=\"$tooltip\"];\n";
$versions{"$vers"} = $vers;
}
foreach my $kid (@{ $children{$vers} }) {
next
if ($hidden{$kid});
print DOT " $vers -> $kid;\n";
push(@kids, $kid);
}
}
print DOT " }\n";
print DOT "}\n";
......@@ -300,10 +319,10 @@ DBQueryFatal("replace into experiment_template_graphs set ".
" image=$gifdata, ".
" imap=$imapdata");
unlink($dotfile, $giffile, $imapfile);
unlink($dotfile, $giffile, $imapfile)
if (!$debug);
exit(0);
#
# Parse command arguments. Once we return from getopts, all that are
# left are the required arguments.
......@@ -339,8 +358,8 @@ sub ParseArgs()
tbdie("Bad data in argument: $prefix");
}
}
if (defined($options{"a"})) {
$showall = 1;
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"z"})) {
$zoom = $options{"z"};
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2006 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
#
# This gets invoked from the Web interface. Simply a wrapper ...
#
#
# Configure variables
#
my $TB = "@prefix@";
#
# Run the real thing, and never return.
#
exec "$TB/bin/template_control", @ARGV;
die("webtemplate_control: Could not exec template_control: $!");
......@@ -67,34 +67,59 @@ function CheckArguments($guid, $version) {
CheckArguments($guid, $version);
if (isset($action) || isset($zoomin) || isset($zoomout)) {
if (isset($action)) {
if ($action == "hide") {
DBQueryFatal("UPDATE experiment_templates SET hidden=1 ".
"WHERE guid='$guid' and vers='$version'");
if (isset($show) || isset($hide) || isset($showhidden) || isset($hidehidden) ||
isset($zoomin) || isset($zoomout)) {
# Need this for scripts.
TBGroupUnixInfo($pid, $gid, $unix_gid, $unix_name);
# Hide or show templates.
if (isset($show) || isset($hide) ||
isset($showhidden) || isset($hidehidden)) {
$optarg = ((isset($recursive) && $recursive == "Yep") ? "-r" : "");
$reqarg = "-a ";
if (isset($show)) {
$reqarg .= "show";
}
else if ($action == "show") {
DBQueryFatal("UPDATE experiment_templates SET hidden=0 ".
"WHERE guid='$guid' and vers='$version'");
elseif (isset($hide)) {
$reqarg .= "hide";
}
else if ($action == "showall") {
DBQueryFatal("UPDATE experiment_templates SET hidden=0 ".
"WHERE guid='$guid'");
elseif (isset($showhidden)) {
$reqarg .= "showhidden";
}
}
$optarg = "";
if (isset($zoomin) && $zoomin == "zoomin") {
$optarg = "-z in";
}
elseif (isset($zoomout) && $zoomout == "zoomout") {
$optarg = "-z out";
}
elseif (isset($hidehidden)) {
$reqarg .= "hidehidden";
}
$reqarg .= " $guid/";
# Need to update the template graph.
TBGroupUnixInfo($pid, $gid, $unix_gid, $unix_name);
if (isset($show) || isset($hide)) {
$reqarg .= $version;
}
else {
# Applies only to root template
$reqarg .= 1;
}
SUEXEC($uid, "$pid,$unix_gid",
"webtemplate_control $reqarg $optarg",
SUEXEC_ACTION_DIE);
}
else {
$optarg = "";
if (isset($zoomin)) {
$optarg = "-z in";
}
elseif (isset($zoomout)) {
$optarg = "-z out";
}
SUEXEC($uid, "$pid,$unix_gid", "webtemplate_graph $optarg $guid",
SUEXEC_ACTION_DIE);
# Need to update the template graph.
SUEXEC($uid, "$pid,$unix_gid", "webtemplate_graph $optarg $guid",
SUEXEC_ACTION_DIE);
}
}
#
......@@ -120,19 +145,6 @@ else {
WRITESUBMENUBUTTON("Modify Template",
"template_modify.php?guid=$guid&version=$version");
if (! $template->IsRoot()) {
if ($template->IsHidden()) {
WRITESUBMENUBUTTON("Show Template",
"template_show.php?guid=$guid".
"&version=$version&action=show");
}
else {
WRITESUBMENUBUTTON("Hide Template",
"template_show.php?guid=$guid".
"&version=$version&action=hide");
}
}
WRITESUBMENUBUTTON("Instantiate Template",
"template_swapin.php?guid=$guid&version=$version");
......@@ -168,13 +180,35 @@ if (!isset($show) || $show == "graph") {
$template->ShowGraph();
#
# Define the zoom buttons. This should go elsewhere.
# Define the control buttons.
#
echo "<center>\n";
echo "<form action='template_show.php?guid=$guid&version=$version'
method=post>\n";
echo "<button name=action type=submit value=showall>";
echo " Show All Templates</button></a>&nbsp &nbsp ";
if (! $template->IsRoot()) {
if ($template->IsHidden()) {
echo "<button name=show type=submit value=Show>";
echo " Show Template</button></a>&nbsp ";
}
else {
echo "<button name=hide type=submit value=Hide>";
echo " Hide Template</button></a>&nbsp ";
}
echo "<input type=checkbox name=recursive value=Yep>Recursive? &nbsp ";
echo "&nbsp &nbsp &nbsp ";
}
$root = Template::LookupRoot($guid);
# We overload the hidden bit on the root.
if ($root->IsHidden()) {
echo "<button name=showhidden type=submit value=showhidden>";
echo " Show Hidden Templates</button></a>&nbsp &nbsp &nbsp &nbsp ";
}
else {
echo "<button name=hidehidden type=submit value=hidehidden>";
echo " Hide Hidden Templates</button></a>&nbsp &nbsp &nbsp &nbsp ";
}
echo "<button name=zoomout type=submit value=zoomout>";
echo " Zoom Out</button>\n";
echo "<button name=zoomin type=submit value=zoomin>";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment