Commit 72da5af8 authored by Leigh Stoller's avatar Leigh Stoller

The first commit of the Workbench code. Turned off in the main tree,

you can turn it on in your devel tree by setting the $EXPOSETEMPLATES
variable in www/defs.php3.in to 1. BE SURE NOT TO CHECK THAT CHANGE IN!
parent 57d17989
......@@ -26,7 +26,7 @@ use vars qw(@ISA @EXPORT);
NODEBOOTSTATUS_OKAY NODEBOOTSTATUS_FAILED NODEBOOTSTATUS_UNKNOWN
NODESTARTSTATUS_NOSTATUS PROJMEMBERTRUST_NONE PROJMEMBERTRUST_USER
PROJMEMBERTRUST_ROOT PROJMEMBERTRUST_GROUPROOT
PROJMEMBERTRUST_PROJROOT
PROJMEMBERTRUST_PROJROOT PROJMEMBERTRUST_LOCALROOT
PROJROOT GROUPROOT USERROOT TBOPSPID EXPTLOGNAME
PLABMOND_PID PLABMOND_EID PLABHOLDING_PID PLABHOLDING_EID
......@@ -635,6 +635,7 @@ sub TBDB_STATS_FLAGS_IDLESWAP() { 0x01; }
sub TBDB_STATS_FLAGS_PREMODIFY(){ 0x02; }
sub TBDB_STATS_FLAGS_START() { 0x04; }
sub TBDB_STATS_FLAGS_PRESWAPIN(){ 0x08; }
sub TBDB_STATS_FLAGS_BATCHCTRL(){ 0x10; }
# Do not export these variables!
my $TBDB_STATS_STARTCLOCK;
my $TBDB_STATS_SAVEDSWAPUID;
......@@ -3347,6 +3348,7 @@ sub TBExptContainsNodeCT($$$)
"virt_node_startloc",
"virt_simnode_attributes",
"virt_user_environment",
"virt_parameters",
# vis_nodes is locked during update in prerender, so we
# will get a consistent dataset when we backup.
"vis_nodes",
......@@ -4726,6 +4728,7 @@ sub GatherSwapStats($$$$$;$)
{
my ($pid, $eid, $uid, $mode, $ecode, $flags) = @_;
my ($pnodes,$vnodes,$duration);
my $batchctrl = 0;
# Optional argument to modify the stats gathering.
$flags = 0
......@@ -4740,7 +4743,6 @@ sub GatherSwapStats($$$$$;$)
$TBDB_STATS_STARTCLOCK = time();
return;
}
my $session = tblog_session();
$session = 'NULL' unless defined $session;
......
......@@ -2,7 +2,7 @@
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
# Copyright (c) 2000-2006 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -135,6 +135,10 @@ my %virtual_tables =
tag => "tiptunnels",
row => "tiptunnel",
attrs => [ "host", "vnode" ]},
"virt_parameters" => { rows => undef,
tag => "parameters",
row => "parameter",
attrs => [ "name", "value" ]},
# This is a fake table. See below. If we add more, lets generalize.
"external_sourcefiles" => { rows => undef,
tag => "nsfiles",
......
......@@ -452,6 +452,31 @@ CREATE TABLE experiment_resources (
KEY lastidx (lastidx)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_run_bindings`
--
CREATE TABLE experiment_run_bindings (
exptidx int(10) unsigned NOT NULL default '0',
runid varchar(32) NOT NULL default '',
name varchar(64) NOT NULL default '',
value tinytext NOT NULL,
PRIMARY KEY (exptidx,runid,name)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_runs`
--
CREATE TABLE experiment_runs (
exptidx int(10) unsigned NOT NULL default '0',
runid varchar(32) NOT NULL default '',
description tinytext,
start_time datetime default NULL,
stop_time datetime default NULL,
PRIMARY KEY (exptidx,runid)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_stats`
--
......@@ -487,6 +512,183 @@ CREATE TABLE experiment_stats (
KEY rsrcidx (rsrcidx)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_template_graphs`
--
CREATE TABLE experiment_template_graphs (
parent_guid varchar(16) NOT NULL default '',
image mediumblob,
imap mediumtext,
PRIMARY KEY (parent_guid)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_template_input_data`
--
CREATE TABLE experiment_template_input_data (
idx int(10) unsigned NOT NULL auto_increment,
md5 varchar(32) NOT NULL default '',
input mediumtext,
PRIMARY KEY (idx),
UNIQUE KEY md5 (md5)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_template_inputs`
--
CREATE TABLE experiment_template_inputs (
idx int(10) unsigned NOT NULL auto_increment,
parent_guid varchar(16) NOT NULL default '',
parent_vers smallint(5) unsigned NOT NULL default '0',
pid varchar(12) NOT NULL default '',
tid varchar(32) NOT NULL default '',
input_idx int(10) unsigned NOT NULL default '0',
PRIMARY KEY (parent_guid,parent_vers,idx),
KEY pidtid (pid,tid)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_template_instance_bindings`
--
CREATE TABLE experiment_template_instance_bindings (
parent_guid varchar(16) NOT NULL default '',
parent_vers smallint(5) unsigned NOT NULL default '0',
exptidx int(10) unsigned NOT NULL default '0',
pid varchar(12) NOT NULL default '',
eid varchar(32) NOT NULL default '',
name varchar(64) NOT NULL default '',
value tinytext NOT NULL,
PRIMARY KEY (exptidx,name),
KEY parent_guid (parent_guid,parent_vers),
KEY pidtid (pid,eid)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_template_instances`
--
CREATE TABLE experiment_template_instances (
parent_guid varchar(16) NOT NULL default '',
parent_vers smallint(5) unsigned NOT NULL default '0',
exptidx int(10) unsigned NOT NULL default '0',
pid varchar(12) NOT NULL default '',
eid varchar(32) NOT NULL default '',
uid varchar(8) NOT NULL default '',
start_time datetime default NULL,
stop_time datetime default NULL,
PRIMARY KEY (exptidx),
KEY parent_guid (parent_guid,parent_vers),
KEY pid (pid,eid)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_template_metadata`
--
CREATE TABLE experiment_template_metadata (
guid varchar(16) NOT NULL default '',
vers smallint(5) unsigned NOT NULL default '0',
parent_guid varchar(16) default NULL,
parent_vers smallint(5) unsigned NOT NULL default '0',
template_guid varchar(16) NOT NULL default '',
template_vers smallint(5) unsigned NOT NULL default '0',
name varchar(64) NOT NULL default '',
value tinytext,
created datetime default NULL,
PRIMARY KEY (guid,vers,name),
KEY parent_guid (parent_guid,parent_vers),
KEY template_guid (template_guid,template_vers)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_template_parameters`
--
CREATE TABLE experiment_template_parameters (
parent_guid varchar(16) NOT NULL default '',
parent_vers smallint(5) unsigned NOT NULL default '0',
pid varchar(12) NOT NULL default '',
tid varchar(32) NOT NULL default '',
name varchar(64) NOT NULL default '',
value tinytext,
PRIMARY KEY (parent_guid,parent_vers,name),
KEY pidtid (pid,tid)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_template_settings`
--
CREATE TABLE experiment_template_settings (
parent_guid varchar(16) NOT NULL default '',
parent_vers smallint(5) unsigned NOT NULL default '0',
pid varchar(12) NOT NULL default '',
tid varchar(32) NOT NULL default '',
uselinkdelays tinyint(4) NOT NULL default '0',
forcelinkdelays tinyint(4) NOT NULL default '0',
multiplex_factor smallint(5) default NULL,
uselatestwadata tinyint(4) NOT NULL default '0',
usewatunnels tinyint(4) NOT NULL default '1',
wa_delay_solverweight float default '0',
wa_bw_solverweight float default '0',
wa_plr_solverweight float default '0',
sync_server varchar(32) default NULL,
cpu_usage tinyint(4) unsigned NOT NULL default '0',
mem_usage tinyint(4) unsigned NOT NULL default '0',
veth_encapsulate tinyint(4) NOT NULL default '1',
allowfixnode tinyint(4) NOT NULL default '1',
jail_osname varchar(20) default NULL,
delay_osname varchar(20) default NULL,
use_ipassign tinyint(4) NOT NULL default '0',
ipassign_args varchar(255) default NULL,
linktest_level tinyint(4) NOT NULL default '0',
linktest_pid int(11) default '0',
useprepass tinyint(1) NOT NULL default '0',
elab_in_elab tinyint(1) NOT NULL default '0',
elabinelab_eid varchar(32) default NULL,
elabinelab_cvstag varchar(64) default NULL,
elabinelab_nosetup tinyint(1) NOT NULL default '0',
security_level tinyint(1) NOT NULL default '0',
delay_capacity tinyint(3) unsigned default NULL,
savedisk tinyint(1) NOT NULL default '0',
PRIMARY KEY (parent_guid,parent_vers),
KEY pidtid (pid,tid)
) TYPE=MyISAM;
--
-- Table structure for table `experiment_templates`
--
CREATE TABLE experiment_templates (
guid varchar(16) NOT NULL default '',
vers smallint(5) unsigned NOT NULL default '0',
parent_guid varchar(16) default NULL,
parent_vers smallint(5) unsigned default NULL,
pid varchar(12) NOT NULL default '',
gid varchar(16) NOT NULL default '',
tid varchar(32) NOT NULL default '',
uid varchar(8) NOT NULL default '',
description mediumtext,
eid varchar(32) NOT NULL default '',
created datetime default NULL,
modified datetime default NULL,
locked datetime default NULL,
state varchar(16) NOT NULL default 'new',
path tinytext,
maximum_nodes int(6) unsigned default NULL,
minimum_nodes int(6) unsigned default NULL,
logfile tinytext,
logfile_open tinyint(4) NOT NULL default '0',
prerender_pid int(11) default '0',
PRIMARY KEY (guid,vers),
KEY pidtid (pid,tid),
KEY pideid (pid,eid)
) TYPE=MyISAM;
--
-- Table structure for table `experiments`
--
......@@ -2468,6 +2670,18 @@ CREATE TABLE virt_nodes (
KEY pid (pid,eid,vname)
) TYPE=MyISAM;
--
-- Table structure for table `virt_parameters`
--
CREATE TABLE virt_parameters (
pid varchar(12) NOT NULL default '',
eid varchar(32) NOT NULL default '',
name varchar(64) NOT NULL default '',
value tinytext,
PRIMARY KEY (pid,eid,name)
) TYPE=MyISAM;
--
-- Table structure for table `virt_programs`
--
......
......@@ -777,6 +777,21 @@ REPLACE INTO table_regex VALUES ('node_attributes','attrkey','text','regex','^[-
REPLACE INTO table_regex VALUES ('node_attributes','attrvalue','text','regex','^[-\\w\\.+,\\s]+$',0,255,NULL);
REPLACE INTO table_regex VALUES ('archive_tags','description','text','redirect','projects:why',1,2048,NULL);
REPLACE INTO table_regex VALUES ('archive_tags','tag','text','regex','^[a-zA-Z][-\\w\\.\\+]+$',3,64,NULL);
REPLACE INTO table_regex VALUES ('experiment_templates','description','text','regex','^[\\040-\\176\\012\\015\\011]*$',1,4096,NULL);
REPLACE INTO table_regex VALUES ('experiment_templates','guid','text','regex','^[\\w]+$',1,32,NULL);
REPLACE INTO table_regex VALUES ('experiment_template_metadata','name','text','regex','^[\\040-\\176]*$',1,64,NULL);
REPLACE INTO table_regex VALUES ('experiment_template_metadata','value','text','regex','^[\\040-\\176\\012\\015\\011]*$',1,2048,NULL);
REPLACE INTO table_regex VALUES ('virt_parameters','pid','text','redirect','projects:pid',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_parameters','eid','text','redirect','experiments:eid',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_parameters','name','text','regex','^\\w[-\\w]+$',1,64,NULL);
REPLACE INTO table_regex VALUES ('virt_parameters','value','text','redirect','default:tinytext',0,256,NULL);
REPLACE INTO table_regex VALUES ('experiment_template_instance_bindings','name','text','regex','^\\w[-\\w]+$',1,64,NULL);
REPLACE INTO table_regex VALUES ('experiment_template_instance_bindings','value','text','redirect','default:tinytext',0,256,NULL);
REPLACE INTO table_regex VALUES ('experiment_runs','runid','text','redirect','experiments:eid',0,0,NULL);
REPLACE INTO table_regex VALUES ('experiment_runs','description','text','regex','^[\\040-\\176\\012\\015\\011]*$',1,256,NULL);
REPLACE INTO table_regex VALUES ('experiment_run_bindings','name','text','regex','^\\w[-\\w]+$',1,64,NULL);
REPLACE INTO table_regex VALUES ('experiment_run_bindings','value','text','redirect','default:tinytext',0,256,NULL);
--
-- Dumping data for table `testsuite_preentables`
......
......@@ -3225,3 +3225,8 @@ last_net_act,last_cpu_act,last_ext_act);
those entries from the "log" table using:
delete from log where type = 'thecause';
4.41: A lot of Template stuff. This is experimental!
mysql tbdb < templates.sql
This diff is collapsed.
......@@ -21,7 +21,8 @@ BIN_STUFF = power snmpit tbend tbprerun tbreport \
node_reboot nscheck node_update savelogs node_control \
portstats checkports eventsys_control os_select tbrestart \
tbswap nseswap tarfiles_setup node_history tbrsync \
node_attributes archive_control
node_attributes archive_control template_create \
template_swapin template_swapout template_graph
SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
batch_daemon exports_setup reload_daemon sched_reserve \
......@@ -49,7 +50,8 @@ LIBEXEC_STUFF = rmproj wanlinksolve wanlinkinfo \
spewlogfile staticroutes routecalc wanassign \
webnodereboot webrmuser webidleswap switchmac \
spewrpmtar webtarfiles_setup webfrisbeekiller gentopofile \
webnodeattributes webarchive_control
webnodeattributes webarchive_control webtemplate_create \
webtemplate_swapin webtemplate_swapout
LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \
snmpit_cisco.pm snmpit_lib.pm snmpit_apc.pm power_rpc27.pm \
......@@ -58,7 +60,7 @@ LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \
snmpit_nortel.pm \
libaudit.pm libreboot.pm libosload.pm libtestbed.py \
libadminmfs.pm libtblog.pm libtblog_simple.pm libArchive.pm \
power_mail.pm power_whol.pm
power_mail.pm power_whol.pm libTemplates.pm
ifeq ($(SYSTEM),FreeBSD)
FBSDVERSION := $(shell uname -v | sed -e 's/FreeBSD \([0-9]\).*/FreeBSD\1/')
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2005, 2006 University of Utah and the Flux Group.
# All rights reserved.
#
# XXX Need to deal with locking at some point ...
#
package libTemplates;
use strict;
use Exporter;
use vars qw(@ISA @EXPORT);
@ISA = "Exporter";
@EXPORT = qw ( );
# Must come after package declaration!
use lib '@prefix@/lib';
use libdb;
use libtestbed;
use libtblog;
use English;
# Configure variables
my $TB = "@prefix@";
my $MD5 = "/sbin/md5";
#
# Grab a new GUID for a template. We do not have to use it of course.
#
sub NewGUID($)
{
my ($pidx) = @_;
my $idx;
DBQueryFatal("lock tables emulab_indicies write");
my $query_result =
DBQueryFatal("select idx from emulab_indicies ".
"where name='next_guid'");
if (! $query_result->num_rows) {
$idx = 10000;
DBQueryFatal("insert into emulab_indicies (name, idx) ".
"values ('next_guid', $idx)");
}
else {
($idx) = $query_result->fetchrow_array();
}
my $nextidx = $idx + 1;
DBQueryFatal("update emulab_indicies set idx='$nextidx' ".
"where name='next_guid'");
DBQueryFatal("unlock tables");
$$pidx = $idx;
return 0;
}
#
# Check for valid template.
#
sub TBValidExperimentTemplate($$)
{
my ($guid, $version) = @_;
my $query_result =
DBQueryFatal("select guid from experiment_templates ".
"where guid='$guid' and vers='$version'");
return $query_result->num_rows;
}
#
# Template permission checks. Using the experiment access check stuff!
#
# Usage: TBExptTemplateAccessCheck($uid, $guid, $access_type)
# returns 0 if not allowed.
# returns 1 if allowed.
#
sub TBExptTemplateAccessCheck($$$)
{
my ($uid, $guid, $access_type) = @_;
my $mintrust;
if ($access_type < TB_EXPT_MIN ||
$access_type > TB_EXPT_MAX) {
die("*** Invalid access type: $access_type!");
}
#
# Admins do whatever they want!
#
if (TBAdmin($uid)) {
return 1;
}
$uid = MapNumericUID($uid);
my $query_result =
DBQueryFatal("select pid,gid from experiment_templates where ".
"guid='$guid' limit 1");
if ($query_result->numrows == 0) {
return 0;
}
my @row = $query_result->fetchrow_array();
my $pid = $row[0];
my $gid = $row[1];
#
# An experiment may be destroyed by the experiment creator or the
# project/group leader.
#
if ($access_type == TB_EXPT_READINFO) {
$mintrust = PROJMEMBERTRUST_USER;
}
else {
$mintrust = PROJMEMBERTRUST_LOCALROOT;
}
#
# Either proper permission in the group, or group_root in the project.
# This lets group_roots muck with other people's experiments, including
# those in groups they do not belong to.
#
return TBMinTrust(TBGrpTrust($uid, $pid, $gid), $mintrust) ||
TBMinTrust(TBGrpTrust($uid, $pid, $pid), PROJMEMBERTRUST_GROUPROOT);
}
#
# Create a new template record from the args provided. We assume that
# the table is locked by the caller.
#
# Usage: int NewTemplateRecord(\%args)
#
sub NewTemplateRecord($)
{
my ($args) = @_;
my $query = "insert into experiment_templates set ".
join(",", map("$_='" . $args->{$_} . "'", keys(%{$args})));
# Append some default value stuff.
$query .= ",created=now()";
return -1
if (! DBQueryWarn($query));
return 0;
}
#
# Delete a template (all tables).
#
sub DeleteTemplateRecord($$)
{
my ($guid, $vers) = @_;
# Make sure the experiment_templates table is always last, in case
# something goes wrong.
my @tables = ("experiment_templates");
foreach my $table (@tables) {
DBQueryFatal("delete from $table ".
"where guid='$guid' and vers='$vers'");
}
}
#
# Create a new template instance record from the args provided.
#
# Usage: int NewTemplateInstanceRecord(\%args)
#
sub NewTemplateInstanceRecord($)
{
my ($args) = @_;
my $query = "insert into experiment_template_instances set ".
join(",", map("$_='" . $args->{$_} . "'", keys(%{$args})));
# Append some default value stuff.
$query .= ",start_time=now()";
return -1
if (! DBQueryWarn($query));
return 0;
}
#
# Delete a template instance record.
#
sub DeleteTemplateInstanceRecord($$$)
{
my ($guid, $vers, $exptidx) = @_;
DBQueryFatal("delete from experiment_template_instances ".
"where parent_guid='$guid' and parent_vers='$vers' and ".
" exptidx='$exptidx'");
return 0;
}
#
# Finalize a template instance record; usage is similar to above
#
# Usage: int FinalizeTemplateInstanceRecord($guid, $vers, $exptidx, \%args)
#
sub FinalizeTemplateInstanceRecord($$$;$)
{
my ($guid, $vers, $exptidx, $args) = @_;
my $query = "update experiment_template_instances set stop_time=now() ";
if (defined($args) && scalar(keys%{$args})) {
$query .= ",";
$query .= join(",", map("$_='" . $args->{$_} . "'", keys(%{$args})));
}
$query .= " where parent_guid='$guid' and parent_vers='$vers' and ".
" exptidx='$exptidx'";
return -1
if (! DBQueryWarn($query));
return 0;
}
#
# Create a new template instance record from the args provided.
#
# Usage: int NewTemplateInstanceRecord(\%args)
#
sub NewTemplateInstanceBindingRecord($)
{
my ($args) = @_;
my $query = "insert into experiment_template_instance_bindings set ".
join(",", map("$_='" . $args->{$_} . "'", keys(%{$args})));
return -1
if (! DBQueryWarn($query));
return 0;
}
#
# Delete template instance binding records
#
sub DeleteTemplateInstanceBindingRecords($$$)
{
my ($guid, $vers, $exptidx) = @_;
DBQueryFatal("delete from experiment_template_instance_bindings ".
"where parent_guid='$guid' and parent_vers='$vers' and ".
" exptidx='$exptidx'");
return 0;
}
#
# Utility routine to get the pid,tid,gid of a template.
#
sub TemplateInfo($$$$;$)
{
my ($guid, $version, $ppid, $ptid, $pgid) = @_;
my $query_result =
DBQueryWarn("select pid,tid,gid from experiment_templates ".
"where guid='$guid' and vers='$version'");
return -1
if (!$query_result || !$query_result->numrows);
my ($pid, $tid, $gid) = $query_result->fetchrow_array();
$$ppid = $pid;
$$ptid = $tid;
$$pgid = $gid
if (defined($pgid));
return 0;
}
#
# Create the directory for a template, update the DB, and return that
# path to the caller.
#
#sub CreateTemplateDirectory($$$)
#{
# my ($guid, $vers, $ppath) = @_;
#
# # See mkexpdir.
# my $template_dir = PROJROOT() . "/$pid/templates/$guid/$vers";
#
# if (! -e $template_dir) {
# system("/bin/mkdir -p $template_dir") == 0
# or return -1;
# }
# DBQueryWarn("update experiment_templates set path='$template_dir' ".
# "where guid='$guid' and vers='$vers'")
# or return -1;
#
# $$ppath = $template_dir;
# return 0;
#}
#
# Add an input file to the template. The point of this is to reduce
# duplication by taking an md5 of the input file, and sharing that
# record/file.
#
sub AddTemplateInputFile($$$)
{
my ($guid, $version, $inputfile) = @_;
my $input_idx;
my $data_string = `cat $inputfile`;
return -1
if ($?);
# pid/tid are inserted for debugging.
my ($pid,$tid) = ();
if (TemplateInfo($guid, $version, \$pid, \$tid) < 0) {
tberror("Could not find pid,tid for experiment template '$guid'!");
return -1;
}
if ($data_string) {
# As you can see, we md5 the raw data.
$data_string = DBQuoteSpecial($data_string);
if (length($data_string) >= DBLIMIT_NSFILESIZE()) {
tberror("Input file is too big (> " . DBLIMIT_NSFILESIZE() . ")!");
return -1;
}
#
# Grab an MD5 of the file to see if we already have a copy of it.
# Avoids needless duplication.
#
my $md5 = `$MD5 -q $inputfile`;
chomp($md5);
my $query_result =
DBQueryWarn("select idx from experiment_template_input_data ".
"where md5='$md5'");
return -1
if (!$query_result);
if ($query_result->numrows) {
($input_idx) = $query_result->fetchrow_array();
}
else {
$query_result =
DBQueryWarn("insert into experiment_template_input_data ".
"(idx, md5, input) ".
"values (NULL, '$md5', $data_string)");
return -1
if (!$query_result);
$input_idx = $query_result->insertid;
}
return -1
if (!DBQueryWarn("insert into experiment_template_inputs ".
" (idx, parent_guid, parent_vers, ".
" pid, tid, input_idx) values ".
" (NULL, '$guid', '$version', '$pid', '$tid', ".
" '$input_idx')"));
}
return 0;
}
#
# Find out if an experiment is a template instantiation; used by existing