Commit 78503406 authored by Leigh B. Stoller's avatar Leigh B. Stoller
Browse files

Redo the entire template library. I've been meaning to use perl

"object" and this was a good opportunity to see if they are useful and
easy enough to use. Yep they are; the code is much cleaner with many
fewer utility functions to get at stuff. I recommend this approach
from now on.

The problem is the php side, which ends up duplicating some stuff, but
in the old style. This is not so bad for the template code since I
have made it a point not to do anything but display functions in php;
all modifications are handled in the backend.
parent f8d54de3
...@@ -23,7 +23,7 @@ BIN_STUFF = power snmpit tbend tbprerun tbreport \ ...@@ -23,7 +23,7 @@ BIN_STUFF = power snmpit tbend tbprerun tbreport \
tbswap nseswap tarfiles_setup node_history tbrsync \ tbswap nseswap tarfiles_setup node_history tbrsync \
node_attributes archive_control template_create \ node_attributes archive_control template_create \
template_swapin template_swapout template_graph \ template_swapin template_swapout template_graph \
template_exprun template_delete template_exprun template_delete template_metadata
SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \ SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
batch_daemon exports_setup reload_daemon sched_reserve \ batch_daemon exports_setup reload_daemon sched_reserve \
...@@ -53,7 +53,7 @@ LIBEXEC_STUFF = rmproj wanlinksolve wanlinkinfo \ ...@@ -53,7 +53,7 @@ LIBEXEC_STUFF = rmproj wanlinksolve wanlinkinfo \
spewrpmtar webtarfiles_setup webfrisbeekiller gentopofile \ spewrpmtar webtarfiles_setup webfrisbeekiller gentopofile \
webnodeattributes webarchive_control webtemplate_create \ webnodeattributes webarchive_control webtemplate_create \
webtemplate_swapin webtemplate_swapout webtemplate_exprun \ webtemplate_swapin webtemplate_swapout webtemplate_exprun \
webtemplate_graph webtemplate_graph webtemplate_metadata
LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \ LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \
snmpit_cisco.pm snmpit_lib.pm snmpit_apc.pm power_rpc27.pm \ snmpit_cisco.pm snmpit_lib.pm snmpit_apc.pm power_rpc27.pm \
...@@ -62,7 +62,7 @@ LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \ ...@@ -62,7 +62,7 @@ LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \
snmpit_nortel.pm \ snmpit_nortel.pm \
libaudit.pm libreboot.pm libosload.pm libtestbed.py \ libaudit.pm libreboot.pm libosload.pm libtestbed.py \
libadminmfs.pm libtblog.pm libtblog_simple.pm libArchive.pm \ libadminmfs.pm libtblog.pm libtblog_simple.pm libArchive.pm \
power_mail.pm power_whol.pm libTemplates.pm power_mail.pm power_whol.pm Template.pm
ifeq ($(SYSTEM),FreeBSD) ifeq ($(SYSTEM),FreeBSD)
FBSDVERSION := $(shell uname -v | sed -e 's/FreeBSD \([0-9]\).*/FreeBSD\1/') FBSDVERSION := $(shell uname -v | sed -e 's/FreeBSD \([0-9]\).*/FreeBSD\1/')
......
This diff is collapsed.
...@@ -53,7 +53,7 @@ if ($UID) { ...@@ -53,7 +53,7 @@ if ($UID) {
use lib "@prefix@/lib"; use lib "@prefix@/lib";
use libdb; use libdb;
use libtestbed; use libtestbed;
use libTemplates; use Template;
# Be careful not to exit on transient error; 0 means infinite retry. # Be careful not to exit on transient error; 0 means infinite retry.
$libdb::DBQUERY_MAXTRIES = 0; $libdb::DBQUERY_MAXTRIES = 0;
...@@ -92,9 +92,7 @@ my $userdir; ...@@ -92,9 +92,7 @@ my $userdir;
my $workdir; my $workdir;
my $user_name = "Testbed Operations"; my $user_name = "Testbed Operations";
my $user_email = "$TBOPS"; my $user_email = "$TBOPS";
my $istemplate; my $template;
my $guid;
my $version;
# #
# Turn off line buffering on output # Turn off line buffering on output
...@@ -360,11 +358,10 @@ sub dosomething($$) ...@@ -360,11 +358,10 @@ sub dosomething($$)
# We still generate the log file, but it is not available via the # We still generate the log file, but it is not available via the
# web interface. Needs more thought. # web interface. Needs more thought.
# #
my $exptidx = $exphash->{'idx'}; my $exptidx = $exphash->{'idx'};
$istemplate = libTemplates::IsTemplateInstanceExperiment($exptidx); my $instance = Template::Instance->LookupByExptidx($exptidx);
if ($istemplate) { if (defined($instance)) {
libTemplates::MapExptidxtoTemplate($exptidx, \$guid, \$version) == 0 $template = $instance->template();
or fatal("Error template info the experiment $pid/$eid");
} }
# #
...@@ -593,8 +590,11 @@ sub swapexp($;$) ...@@ -593,8 +590,11 @@ sub swapexp($;$)
my $running = ($exphash->{'state'} eq EXPTSTATE_ACTIVE); my $running = ($exphash->{'state'} eq EXPTSTATE_ACTIVE);
if ($running) { if ($running) {
if ($istemplate) { if (defined($template)) {
system("$template_swapout -b -e $eid $guid/$version"); my $guid = $template->guid();
my $vers = $template->vers();
system("$template_swapout -b -e $eid $guid/$vers");
} }
else { else {
system("$swapexp -b -s out $pid $eid"); system("$swapexp -b -s out $pid $eid");
...@@ -637,8 +637,11 @@ sub cancelexp($) ...@@ -637,8 +637,11 @@ sub cancelexp($)
# It does not matter if the experiment is running; endexp does the # It does not matter if the experiment is running; endexp does the
# right thing. # right thing.
# #
if ($istemplate) { if (defined($template)) {
system("$template_swapout -b -e $eid $guid/$version"); my $guid = $template->guid();
my $vers = $template->vers();
system("$template_swapout -b -e $eid $guid/$vers");
} }
else { else {
system("$endexp -b $pid $eid"); system("$endexp -b $pid $eid");
......
...@@ -1280,7 +1280,7 @@ END { ...@@ -1280,7 +1280,7 @@ END {
# We are screwed; a recursive error. Someone will have to clean # We are screwed; a recursive error. Someone will have to clean
# up by hand. # up by hand.
# #
SENDMAIL(TBOPS, SENDMAIL($TBOPS,
"Experiment Configure Failure: $pid/$eid", "Experiment Configure Failure: $pid/$eid",
"Recursive error in cleanup! This is very bad."); "Recursive error in cleanup! This is very bad.");
$? = $saved_exitcode; $? = $saved_exitcode;
......
...@@ -36,7 +36,7 @@ use lib "@prefix@/lib"; ...@@ -36,7 +36,7 @@ use lib "@prefix@/lib";
use libaudit; use libaudit;
use libdb; use libdb;
use libtestbed; use libtestbed;
use libTemplates; use Template;
# Locals. # Locals.
my $idleswap = 0; my $idleswap = 0;
...@@ -162,13 +162,10 @@ $EUID = $UID = $unix_uid; ...@@ -162,13 +162,10 @@ $EUID = $UID = $unix_uid;
$ENV{'USER'} = $creator; $ENV{'USER'} = $creator;
$ENV{'LOGNAME'} = $creator; $ENV{'LOGNAME'} = $creator;
if (libTemplates::IsTemplateInstanceExperiment($exptidx)) { if (my $instance = Template::Instance->LookupByExptidx($exptidx)) {
my ($guid, $vers); my $guid = $instance->guid();
my $vers = $instance->vers();
if (libTemplates::MapExptidxtoTemplate($exptidx, \$guid, \$vers) < 0) {
die("*** $0:\n".
" Error mapping experiment to its template!\n");
}
exec "$template_swapout -e $eid $guid/$vers"; exec "$template_swapout -e $eid $guid/$vers";
} }
else { else {
......
This diff is collapsed.
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
# All rights reserved. # All rights reserved.
# #
use English; use English;
use strict;
use Getopt::Std; use Getopt::Std;
use POSIX qw(isatty setsid); use POSIX qw(isatty setsid);
use POSIX qw(strftime); use POSIX qw(strftime);
...@@ -44,12 +45,12 @@ my $description = ""; ...@@ -44,12 +45,12 @@ my $description = "";
my $modify = 0; my $modify = 0;
my $pid; my $pid;
my $tid; my $tid;
my $eid;
my $gid; my $gid;
my $inputfile; my $inputfile;
# For modify. # For modify.
my $parent_guid; my $parent_guid;
my $parent_vers; my $parent_vers;
my $parent_template;
# #
# Configure variables # Configure variables
...@@ -66,9 +67,11 @@ my $CONTROL = "@USERNODE@"; ...@@ -66,9 +67,11 @@ my $CONTROL = "@USERNODE@";
# Locals # Locals
my $user_name; my $user_name;
my $user_email; my $user_email;
my $template;
my $dbuid; my $dbuid;
my $guid; my $guid;
my $version = 1; my $vers;
my $eid;
my $archive_idx = 0; my $archive_idx = 0;
# For the END block below. # For the END block below.
my $cleaning = 0; my $cleaning = 0;
...@@ -93,7 +96,7 @@ use libdb; ...@@ -93,7 +96,7 @@ use libdb;
use libtestbed; use libtestbed;
use libtblog; use libtblog;
use libArchive; use libArchive;
use libTemplates; use Template;
# Be careful not to exit on transient error # Be careful not to exit on transient error
$libdb::DBQUERY_MAXTRIES = 120; $libdb::DBQUERY_MAXTRIES = 120;
...@@ -163,78 +166,20 @@ if (! TBProjAccessCheck($dbuid, $pid, $gid, TB_PROJECT_CREATEEXPT)) { ...@@ -163,78 +166,20 @@ if (! TBProjAccessCheck($dbuid, $pid, $gid, TB_PROJECT_CREATEEXPT)) {
# On modify, must check access to the parent template. # On modify, must check access to the parent template.
# #
if ($modify) { if ($modify) {
if (!libTemplates::TBValidExperimentTemplate($parent_guid, $parent_vers)) { $parent_template = Template->Lookup($parent_guid, $parent_vers);
if (!defined($parent_template)) {
tbdie("Experiment template $parent_guid/$parent_vers does not exist!"); tbdie("Experiment template $parent_guid/$parent_vers does not exist!");
} }
if (!libTemplates::TBExptTemplateAccessCheck($dbuid,
$parent_guid, if (!$parent_template->AccessCheck($dbuid, TB_EXPT_READINFO)) {
TB_EXPT_READINFO)) {
tbdie("You do not have permission to modify experiment template ". tbdie("You do not have permission to modify experiment template ".
"$parent_guid/$parent_vers"); "$parent_guid/$parent_vers");
} }
# Hmm, this is redundant in the table.
$guid = $parent_guid;
}
else {
#
# Otherwise, grab new guid before tables are locked.
#
if (libTemplates::NewGUID(\$guid) < 0) {
tbdie("Could not get a new GUID!");
}
} }
# #
# Create a template record; the tid has to be unique within the project, # Create a template record.
# across both the experiments and template tables, since there will be
# two paths to experiment creation for the near term. See corresponding
# code in batchexp.
#
DBQueryFatal("lock tables experiments write, ".
" experiment_templates write");
my $query_result =
DBQueryFatal("select pid,tid from experiment_templates ".
"where tid='$tid' and pid='$pid'");
if ($query_result->numrows) {
DBQueryWarn("unlock tables");
tbdie("Template ID $tid in project $pid is already in use!");
}
#
# Find unused version number now that tables are locked.
#
if ($modify) {
$query_result =
DBQueryFatal("select MAX(vers) from experiment_templates ".
"where guid='$guid'");
$version = ($query_result->fetchrow_array())[0];
$version++;
}
# Currently, we make up an eid using the guid and version. This will
# change later.
$eid = "T${guid}-${version}";
#
# Sanity check; make sure this eid is not in use. Tables are still locked.
#
$query_result =
DBQueryFatal("select pid,eid from experiments ".
"where eid='$eid' and pid='$pid'");
if ($query_result->numrows) {
DBQueryWarn("unlock tables");
tbdie("Experiment ID $eid in project $pid is already in use!");
}
#
# Create a template record to "reserve" the tid. We pass the rest of
# it off to the normal experiment path right now (too much stuff to
# duplicate with a deadline looming right around the corner).
# #
my %args = (); my %args = ();
...@@ -242,21 +187,16 @@ if ($modify) { ...@@ -242,21 +187,16 @@ if ($modify) {
$args{'parent_guid'} = $parent_guid; $args{'parent_guid'} = $parent_guid;
$args{'parent_vers'} = $parent_vers; $args{'parent_vers'} = $parent_vers;
} }
$args{'guid'} = $guid;
$args{'vers'} = $version;
$args{'pid'} = $pid; $args{'pid'} = $pid;
$args{'gid'} = $gid; $args{'gid'} = $gid;
$args{'tid'} = $tid; $args{'tid'} = $tid;
$args{'eid'} = $eid;
$args{'uid'} = $dbuid; $args{'uid'} = $dbuid;
$args{'description'} = DBQuoteSpecial($description); $args{'description'} = DBQuoteSpecial($description);
$args{'description'} =~ s/^\'(.*)\'$/$1/; $args{'description'} =~ s/^\'(.*)\'$/$1/;
if (libTemplates::NewTemplateRecord(\%args) < 0) { if (! ($template = Template->Create(\%args))) {
tbdie("Could not create a new template record!"); tbdie("Could not create a new template record!");
} }
# Now safe to unlock; the tid/eid is reserved;
DBQueryFatal("unlock tables");
# #
# At this point, we need to force a cleanup no matter how we exit. # At this point, we need to force a cleanup no matter how we exit.
...@@ -267,29 +207,32 @@ $justexit = 0; ...@@ -267,29 +207,32 @@ $justexit = 0;
# #
# The description is versioned metadata the user can modify. # The description is versioned metadata the user can modify.
# #
libTemplates::NewTemplateMetadata($guid, $version, $template->NewMetadata("description", $description, $dbuid) == 0
"description", $description, $dbuid) == 0
or fatal(-1, "Failed to insert metadata record for description"); or fatal(-1, "Failed to insert metadata record for description");
# #
# The TID is versioned metadata the user can modify. # The TID is versioned metadata the user can modify.
# #
libTemplates::NewTemplateMetadata($guid, $version, "TID", $tid, $dbuid) == 0 $template->NewMetadata("TID", $tid, $dbuid) == 0
or fatal(-1, "Failed to insert metadata record for description"); or fatal(-1, "Failed to insert metadata record for description");
# #
# Copy the rest of the metadata. # Copy the rest of the metadata from parent to child
# #
if ($modify) { if ($modify) {
libTemplates::CopyTemplateMetadata($parent_guid, $template->CopyMetadata($parent_template, $dbuid) == 0
$parent_vers, $version, $dbuid) or fatal(-1, "Failed to copy metadata records");
== 0 or fatal(-1, "Failed to copy metadata records");
} }
# Grab stuff we need out of the template.
$guid = $template->guid();
$vers = $template->vers();
$eid = $template->eid();
# Now invoke batchexp to preload the experiment. Note special -x option. # Now invoke batchexp to preload the experiment. Note special -x option.
system("$batchexp ". system("$batchexp ".
"-x " . ($modify ? "T${parent_guid}-${parent_vers}" : "-") . " " . "-x " . ($modify ? $parent_template->eid() : "-") . " " .
"-q -i -f -E 'Experiment Template Preload $guid/$version' ". "-q -i -f -E 'Experiment Template Preload $guid/$vers' ".
"-p $pid -e $eid $inputfile"); "-p $pid -e $eid $inputfile");
fatal($? >> 8, "Oops") fatal($? >> 8, "Oops")
if ($?); if ($?);
...@@ -298,8 +241,9 @@ fatal($? >> 8, "Oops") ...@@ -298,8 +241,9 @@ fatal($? >> 8, "Oops")
$exptcreated = 1; $exptcreated = 1;
# Input files are kept in the DB, with the template. # Input files are kept in the DB, with the template.
exit(-1) fatal(-1, "Could not add NS file to template store")
if (libTemplates::AddTemplateInputFile($guid, $version, $inputfile) < 0); if ($template->AddInputFile($inputfile) < 0);
# #
# Grab archive index for new templates. # Grab archive index for new templates.
# #
...@@ -317,14 +261,14 @@ else { ...@@ -317,14 +261,14 @@ else {
# Grab the archive index for the parent; the archive is shared. # Grab the archive index for the parent; the archive is shared.
# #
libArchive::TBExperimentArchiveInfo($pid, libArchive::TBExperimentArchiveInfo($pid,
"T${parent_guid}-${parent_vers}", $parent_template->eid(),
\$archive_idx, undef) \$archive_idx, undef)
>= 0 or fatal(-1, "Could not get archive index for parent!"); >= 0 or fatal(-1, "Could not get archive index for parent!");
# Do a commit point on the template archive since it does not actually # Do a commit point on the template archive since it does not actually
# change after it is created (instances are branches). # change after it is created (instances are branches).
libArchive::TBCommitExperimentArchive($pid, libArchive::TBCommitExperimentArchive($pid,
"T${parent_guid}-${parent_vers}", $parent_template->eid(),
"TemplateCreate") "TemplateCreate")
>= 0 or fatal(-1, "Failed to commit experiment archive!"); >= 0 or fatal(-1, "Failed to commit experiment archive!");
} }
...@@ -333,7 +277,7 @@ else { ...@@ -333,7 +277,7 @@ else {
%args = (); %args = ();
$args{'archive_idx'} = $archive_idx; $args{'archive_idx'} = $archive_idx;
libTemplates::UpdateTemplateRecord($guid, $version, \%args) == 0 $template->Update(\%args) == 0
or fatal(-1, "Could not update template record!"); or fatal(-1, "Could not update template record!");
# #
...@@ -342,7 +286,7 @@ libTemplates::UpdateTemplateRecord($guid, $version, \%args) == 0 ...@@ -342,7 +286,7 @@ libTemplates::UpdateTemplateRecord($guid, $version, \%args) == 0
# to get the parameters is via the parser, but we want to save this # to get the parameters is via the parser, but we want to save this
# info forever (after the underlying experiment is terminated). # info forever (after the underlying experiment is terminated).
# #
$query_result = my $query_result =
DBQueryWarn("select name,value from virt_parameters ". DBQueryWarn("select name,value from virt_parameters ".
"where pid='$pid' and eid='$eid'"); "where pid='$pid' and eid='$eid'");
...@@ -350,18 +294,7 @@ fatal(-1, "Could not get virt_parameters for $pid/$eid") ...@@ -350,18 +294,7 @@ fatal(-1, "Could not get virt_parameters for $pid/$eid")
if (! $query_result); if (! $query_result);
while (my ($name, $value) = $query_result->fetchrow_array()) { while (my ($name, $value) = $query_result->fetchrow_array()) {
if (defined($value)) { $template->NewFormalParameter($name, $value) == 0
$value = DBQuoteSpecial($value);
}
else {
$value = "NULL";
}
DBQueryWarn("insert into experiment_template_parameters set ".
" parent_guid='$guid', ".
" parent_vers='$version', ".
" pid='$pid', tid='$tid', ".
" name='$name', value=$value")
or fatal(-1, "Could not set formal parameter for $pid/$eid") or fatal(-1, "Could not set formal parameter for $pid/$eid")
} }
...@@ -526,11 +459,8 @@ sub cleanup() ...@@ -526,11 +459,8 @@ sub cleanup()
# And delete all the other stuff? # And delete all the other stuff?
} }
libTemplates::DeleteTemplateInputFiles($guid, $version) $template->Delete()
if (defined($guid)); if (defined($template));
libTemplates::DeleteTemplateRecord($guid, $version)
if (defined($guid));
} }
sub fatal($$) sub fatal($$)
...@@ -558,7 +488,7 @@ END { ...@@ -558,7 +488,7 @@ END {
# We are screwed; a recursive error. Someone will have to clean # We are screwed; a recursive error. Someone will have to clean
# up by hand. # up by hand.
# #
SENDMAIL(TBOPS, SENDMAIL($TBOPS,
"Template Creation Failure: $pid/$tid", "Template Creation Failure: $pid/$tid",
"Recursive error in cleanup! This is very bad."); "Recursive error in cleanup! This is very bad.");
$? = $saved_exitcode; $? = $saved_exitcode;
......
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
# All rights reserved. # All rights reserved.
# #
use English; use English;
use strict;
use Getopt::Std; use Getopt::Std;
use POSIX qw(isatty setsid); use POSIX qw(setsid);
use POSIX qw(strftime); use POSIX qw(strftime);
# #
...@@ -61,8 +62,9 @@ my $dbuid; ...@@ -61,8 +62,9 @@ my $dbuid;
my $logname; my $logname;
my $user_name; my $user_name;
my $user_email; my $user_email;
my @versionlist = (); my $template;
my %instances = (); my @templates = ();
my %instances = (); # Indexed by vers.
# Protos # Protos
sub ParseArgs(); sub ParseArgs();
...@@ -76,7 +78,7 @@ use lib "@prefix@/lib"; ...@@ -76,7 +78,7 @@ use lib "@prefix@/lib";
use libdb; use libdb;
use libtestbed; use libtestbed;
use libtblog; use libtblog;
use libTemplates; use Template;
# Be careful not to exit on transient error # Be careful not to exit on transient error
$libdb::DBQUERY_MAXTRIES = 0; $libdb::DBQUERY_MAXTRIES = 0;
...@@ -130,118 +132,100 @@ if ($waitmode) { ...@@ -130,118 +132,100 @@ if ($waitmode) {
# #
# Grab template info. # Grab template info.
# #
if (libTemplates::TemplateInfo($guid, $version) < 0) { $template = Template->Lookup($guid, $version);
tbdie("Could not get info for template $guid/$version!");
if (!defined($template)) {
tbdie("Experiment template $guid/$version does not exist!");
}
if (! TBProjAccessCheck($dbuid,
$template->pid(), $template->gid(),
TB_PROJECT_CREATEEXPT)) {
tberror("You do not have permission to delete template $guid/$version");