Commit d1536506 authored by Jonathon Duerig's avatar Jonathon Duerig
Browse files

Merge branch 'master' of git-public.flux.utah.edu:/flux/git/emulab-devel

parents ee14c9d5 f135521c
event/trafgen/tg2.0
event/linktest/iperf/iperf-2.0.2
event/linktest/rude/rude-0.70
sensors/nfstrace/nfsdump2/Makefile
sensors/nfstrace/nfsdump2/config.h
sensors/nfstrace/nfsdump2/config.log
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2008 University of Utah and the Flux Group.
# Copyright (c) 2000-2008, 2010 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
......@@ -18,8 +18,9 @@ sub usage()
print("Usage: newimageid [-v] <xmlfile>\n");
exit(-1);
}
my $optlist = "dv";
my $optlist = "dvf";
my $debug = 0;
my $force = 0;
my $verify = 0; # Check data and return status only.
#
......@@ -68,6 +69,9 @@ if (! getopts($optlist, \%options)) {
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"f"})) {
$force = 1;
}
if (defined($options{"v"})) {
$verify = 1;
}
......@@ -266,11 +270,32 @@ foreach $key (keys(%{ $xmlparse->{'attribute'} })) {
if (! $this_user->IsAdmin());
}
# Now check that the value is legal.
if (! TBcheck_dbslot($value, "images",
$dbslot, TBDB_CHECKDBSLOT_ERROR)) {
$errors{$key} = TBFieldErrorString();
next;
#
# Special case osids so they can be in pid,osname format.
#
if (($dbslot eq "default_osid" || $dbslot =~ /^part\d/) &&
$value =~ /^.+,.+$/) {
my ($pid,$osname) = ($value =~ /^(.*),(.*)$/);
# Now check that the value is legal.
if (! TBcheck_dbslot($pid, "projects",
"pid", TBDB_CHECKDBSLOT_ERROR)) {
$errors{$key} = TBFieldErrorString();
next;
}
if (! TBcheck_dbslot($osname, "os_info",
"osname", TBDB_CHECKDBSLOT_ERROR)) {
$errors{$key} = TBFieldErrorString();
next;
}
}
else {
# Now check that the value is legal.
if (! TBcheck_dbslot($value, "images",
$dbslot, TBDB_CHECKDBSLOT_ERROR)) {
$errors{$key} = TBFieldErrorString();
next;
}
}
$newimageid_args{$key} = $value;
......@@ -460,7 +485,7 @@ foreach $key (@mtype_keys) {
}
}
UserError("Node Types: Must select at least one node type")
if ($node_types_selected == 0);
if ($node_types_selected == 0 && !$force);
#
# Check sanity of node name and that user can create an image from it.
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2008 University of Utah and the Flux Group.
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
......@@ -18,8 +18,9 @@ sub usage()
print("Usage: newimageid [-v] <xmlfile>\n");
exit(-1);
}
my $optlist = "dv";
my $optlist = "dvf";
my $debug = 0;
my $force = 0;
my $verify = 0; # Check data and return status only.
#
......@@ -68,6 +69,9 @@ if (! getopts($optlist, \%options)) {
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"f"})) {
$force = 1;
}
if (defined($options{"v"})) {
$verify = 1;
}
......@@ -487,7 +491,7 @@ foreach $key (@mtype_keys) {
}
}
UserError("Node Types: Must select at least one node type")
if ($node_types_selected == 0);
if ($node_types_selected == 0 && !$force);
#
# We perform a further check for non-admins. When a node to snapshot
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
......@@ -132,7 +132,7 @@ my %xmlfields =
# XML Field Name DB slot name Flags Default
("description" => ["description", $SLOT_REQUIRED],
"osname" => ["osname" , $SLOT_REQUIRED],
"project" => ["pid_idx", $SLOT_REQUIRED],
"pid" => ["pid", $SLOT_REQUIRED],
"OS" => ["OS", $SLOT_REQUIRED],
"version" => ["version", $SLOT_OPTIONAL, ""],
"path" => ["path", $SLOT_OPTIONAL, "NULL"],
......@@ -257,12 +257,32 @@ foreach $key (keys(%{ $xmlparse->{'attribute'} })) {
$errors{$key} = "Administrators only"
if (! $this_user->IsAdmin());
}
#
# Special case nextosid so it can be in pid,osname format.
#
if ($dbslot eq "nextosid" && $value =~ /^.+,.+$/) {
my ($pid,$osname) = ($value =~ /^(.*),(.*)$/);
# Now check that the value is legal.
if (! TBcheck_dbslot($value, "os_info",
$dbslot, TBDB_CHECKDBSLOT_ERROR)) {
$errors{$key} = TBFieldErrorString();
next;
# Now check that the value is legal.
if (! TBcheck_dbslot($pid, "projects",
"pid", TBDB_CHECKDBSLOT_ERROR)) {
$errors{$key} = TBFieldErrorString();
next;
}
if (! TBcheck_dbslot($osname, "os_info",
"osname", TBDB_CHECKDBSLOT_ERROR)) {
$errors{$key} = TBFieldErrorString();
next;
}
}
else {
# Now check that the value is legal.
if (! TBcheck_dbslot($value, "os_info",
$dbslot, TBDB_CHECKDBSLOT_ERROR)) {
$errors{$key} = TBFieldErrorString();
next;
}
}
$newosid_args{$key} = $value;
......@@ -273,9 +293,9 @@ UserError()
#
# Now do special checks.
#
my $project = Project->Lookup($newosid_args{"project"});
my $project = Project->Lookup($newosid_args{"pid"});
if (!defined($project)) {
UserError("Project: No such project ($project)");
UserError("Project: No such project");
}
if (!$project->AccessCheck($this_user, TB_PROJECT_MAKEOSID())) {
UserError("Project: Not enough permission");
......@@ -297,6 +317,8 @@ if (exists($newosid_args{"nextosid"})) {
if (!defined($nextos)) {
UserError("Nextosid: Does not exist");
}
# Might be in pid,osname format.
$newosid_args{"nextosid"} = $nextos->osid();
}
# Mere users have to supply a version, but admin people do not.
......
......@@ -8,7 +8,7 @@ package Experiment;
use strict;
use Exporter;
use vars qw(@ISA @EXPORT);
use vars qw(@ISA @EXPORT $AUTOLOAD);
@ISA = "Exporter";
@EXPORT = qw ( );
......@@ -108,6 +108,7 @@ my $EXPT_RESOURCESHOSED = 0;
"event_groups",
"virt_firewalls",
"firewall_rules",
"elabinelab_attributes",
"virt_tiptunnels",
"ipsubnets");
......@@ -274,78 +275,38 @@ sub Lookup($$;$)
return $self;
}
# accessors
sub field($$) { return ((! ref($_[0])) ? -1 : $_[0]->{'EXPT'}->{$_[1]}); }
sub stats($$) { return ((! ref($_[0])) ? -1 : $_[0]->{'STATS'}->{$_[1]});}
sub resources($$) { return ((! ref($_[0])) ? -1 : $_[0]->{'RSRC'}->{$_[1]}); }
# To avoid writting out all the methods.
sub AUTOLOAD {
my $self = shift;
my $type = ref($self) or die("$self is not an object\n");
my $name = $AUTOLOAD;
$name =~ s/.*://; # strip fully-qualified portion
if (exists($self->{'EXPT'}->{$name})) {
return $self->{'EXPT'}->{$name};
}
elsif (exists($self->{'STATS'}->{$name})) {
return $self->{'STATS'}->{$name};
}
elsif (exists($self->{'RSRC'}->{$name})) {
return $self->{'RSRC'}->{$name};
}
print STDERR "$self: tried to access unknown slot $name\n";
return undef;
}
sub dbrow($$) { return $_[0]->{'EXPT'}; }
sub pid($) { return field($_[0], 'pid'); }
sub gid($) { return field($_[0], 'gid'); }
sub pid_idx($) { return field($_[0], 'pid_idx'); }
sub gid_idx($) { return field($_[0], 'gid_idx'); }
sub eid($) { return field($_[0], 'eid'); }
sub idx($) { return field($_[0], 'idx'); }
sub uuid($) { return field($_[0], 'eid_uuid'); }
sub eid_uuid($) { return field($_[0], 'eid_uuid'); }
sub description($) { return field($_[0], 'expt_name'); }
sub path($) { return field($_[0], 'path'); }
sub state($) { return field($_[0], 'state'); }
sub batchstate($) { return field($_[0], 'batchstate'); }
sub batchmode($) { return field($_[0], 'batchmode'); }
sub rsrcidx($) { return stats($_[0], 'rsrcidx'); }
sub lastrsrc($) { return stats($_[0], 'lastrsrc'); }
sub creator($) { return field($_[0], 'expt_head_uid');}
sub locked($) { return field($_[0], 'expt_locked'); }
sub elabinelab($) { return field($_[0], 'elab_in_elab');}
sub elabinelab_eid($) { return field($_[0], 'elabinelab_eid');}
sub elabinelab_exptidx($){return field($_[0], 'elabinelab_exptidx');}
sub elabinelab_nosetup($){return field($_[0], 'elabinelab_nosetup');}
sub elabinelab_singlenet($){return field($_[0], 'elabinelab_singlenet');}
sub elabinelab_cvstag($){return field($_[0], 'elabinelab_cvstag');}
sub lockdown($) { return field($_[0], 'lockdown'); }
sub geniflags($) { return field($_[0], 'geniflags'); }
sub created($) { return field($_[0], 'expt_created'); }
sub swapper($) { return field($_[0], 'expt_swap_uid');}
sub swappable($) { return field($_[0], 'swappable');}
sub idleswap($) { return field($_[0], 'idleswap');}
sub autoswap($) { return field($_[0], 'autoswap');}
sub noswap_reason($) { return field($_[0], 'noswap_reason');}
sub noidleswap_reason($){ return field($_[0], 'noidleswap_reason');}
sub idleswap_timeout($) { return field($_[0], 'idleswap_timeout');}
sub autoswap_timeout($) { return field($_[0], 'autoswap_timeout');}
sub prerender_pid($) { return field($_[0], 'prerender_pid');}
sub dpdb($) { return field($_[0], 'dpdb');}
sub dpdbname($) { return field($_[0], 'dpdbname');}
sub dpdbpassword($) { return field($_[0], 'dpdbpassword');}
sub instance_idx($) { return field($_[0], 'instance_idx'); }
sub creator_idx($) { return field($_[0], 'creator_idx');}
sub swapper_idx($) { return field($_[0], 'swapper_idx');}
sub use_ipassign($) { return field($_[0], 'use_ipassign');}
sub ipassign_args($) { return field($_[0], 'ipassign_args');}
sub security_level($) { return field($_[0], 'security_level');}
sub linktest_pid($) { return field($_[0], 'linktest_pid');}
sub linktest_level($) { return field($_[0], 'linktest_level');}
sub logfile($) { return field($_[0], 'logfile');}
sub eventkey($) { return field($_[0], 'eventkey');}
sub keyhash($) { return field($_[0], 'keyhash');}
sub paniced($) { return field($_[0], 'paniced');}
sub cpu_usage($) { return field($_[0], 'cpu_usage');}
sub encap_style($) { return field($_[0], 'encap_style');}
sub minimum_nodes($) { return field($_[0], 'minimum_nodes');}
sub maximum_nodes($) { return field($_[0], 'maximum_nodes');}
sub multiplex_factor($) { return field($_[0], 'multiplex_factor');}
sub delay_capacity($) { return field($_[0], 'delay_capacity');}
sub virtnode_count($) { return field($_[0], 'virtnode_count');}
sub archive_idx($) { return stats($_[0], 'archive_idx'); }
sub swapin_count($) { return stats($_[0], 'swapin_count'); }
sub destroyed($) { return stats($_[0], 'destroyed'); }
sub archive_tag($) { return resources($_[0], 'archive_tag'); }
sub thumbnail($) { return resources($_[0], 'thumbnail'); }
sub swapin_time($) { return resources($_[0], 'swapin_time'); }
sub swapout_time($) { return resources($_[0], 'swapout_time'); }
sub lastidx($) { return resources($_[0], 'lastidx'); }
sub input_data_idx($) { return resources($_[0], 'input_data_idx'); }
# Break circular reference someplace to avoid exit errors.
sub DESTROY {
my $self = shift;
$self->{"EXPT"} = undef;
$self->{"STATS"} = undef;
$self->{"RSRC"} = undef;
$self->{'VIRTEXPT'} = undef;
}
#
# For canceled, goto to the DB.
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2007, 2008 University of Utah and the Flux Group.
# Copyright (c) 2007-2010 University of Utah and the Flux Group.
# All rights reserved.
#
package Image;
......@@ -139,6 +139,7 @@ sub ezid($) { return field($_[0], "ezid"); }
sub shared($) { return field($_[0], "shared"); }
sub global($) { return field($_[0], "global"); }
sub updated($) { return field($_[0], "updated"); }
sub mbr_version($) { return field($_[0], "mbr_version"); }
sub access_key($) { return field($_[0], "access_key"); }
#
......
......@@ -2478,5 +2478,32 @@ sub LookupWideArea($$)
return Node->Lookup($node_id);
}
#
# Return the partition that an OSID is loaded on.
#
sub IsOSLoaded($$)
{
my ($self, $osinfo) = @_;
if (!ref($osinfo)) {
my $tmp = OSinfo->Lookup($osinfo);
if (!defined($tmp)) {
print STDERR "Cannot lookup osinfo for $osinfo\n";
return -1;
}
$osinfo = $tmp;
}
my $osid = $osinfo->osid();
my $nodeid = $self->node_id();
my $query_result =
DBQueryWarn("select osid from partitions as p ".
"where p.node_id='$nodeid' and p.osid='$osid'");
return -1
if (!$query_result);
return $query_result->numrows;
}
# _Always_ make sure that this 1 is at the end of the file...
1;
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2007-2009 University of Utah and the Flux Group.
# Copyright (c) 2007-2010 University of Utah and the Flux Group.
# All rights reserved.
#
package OSinfo;
......@@ -19,6 +19,7 @@ use libdb;
use libtestbed;
use Project;
use User;
use Image;
use English;
use Data::Dumper;
use overload ('""' => 'Stringify');
......@@ -70,6 +71,10 @@ my %WAITTIMES = ("Linux" => 120,
# OP modes. Mirrored in the web interface. The value is a user-okay flag.
my %OPMODES = ("NORMALv2" => 1,
"NORMALv1" => 0,
"PXEFBSD" => 0,
"RELOAD" => 0,
"OPSNODEBSD" => 0,
"PCVM" => 0,
"MINIMAL" => 1,
"NORMAL" => 1,
"ALWAYSUP" => 1 );
......@@ -433,6 +438,17 @@ sub ValidOpMode($$)
return (exists($OPMODES{$opmode}) ? 1 : 0);
}
#
# Is the osinfo "generic"
#
sub IsGeneric($)
{
my ($self) = @_;
my $version = $self->version();
return ((defined($version) && $version ne "") ? 0 : 1);
}
#
# Boot command like. The caller supplies the default in $pref.
#
......@@ -561,6 +577,16 @@ sub ResolveNextOSID($;$)
return OSinfo->Lookup($osid);
}
#
# Set the nextosid.
#
sub SetNextOS($$)
{
my ($self, $nextosinfo) = @_;
return $self->Update({"nextosid" => $nextosinfo->osid()});
}
#
# Check if a particular feature is supported.
#
......@@ -618,5 +644,28 @@ sub RunsOnParent($$)
return 1;
}
#
# Map an osinfo and node type to the actual image.
#
sub MapToImage($$)
{
my ($self, $type) = @_;
if (ref($type)) {
$type = $type->type();
}
my $osid = $self->osid();
my $query_result =
DBQueryWarn("select imageid from osidtoimageid ".
"where type='$type' and osid='$osid'");
return undef
if (!defined($query_result) || !$query_result->numrows);
my ($imageid) = $query_result->fetchrow_array();
return Image->Lookup($imageid);
}
# _Always_ make sure that this 1 is at the end of the file...
1;
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2009 University of Utah and the Flux Group.
# Copyright (c) 2009-2010 University of Utah and the Flux Group.
# All rights reserved.
#
package VirtExperiment;
......@@ -69,6 +69,7 @@ my $debug = 0;
"event_groups" => [ "group_name", "agent_name" ],
"virt_firewalls" => [ "fwname", "type", "style" ],
"firewall_rules" => [ "fwname", "ruleno", "rule" ],
"elabinelab_attributes" => [ "role", "attrkey", "ordering" ],
"virt_tiptunnels" => [ "host", "vnode" ],
"virt_parameters" => [ "name", "value" ],
);
......@@ -627,7 +628,7 @@ sub NewRow($$)
$argref->{$key} = $self->{'COUNTER'}++;
}
else {
carp("Missing table key for new table in $tablename");
carp("Missing table key $key for new table in $tablename");
return undef;
}
}
......@@ -1178,5 +1179,10 @@ use vars qw(@ISA);
@ISA = "VirtExperiment::VirtTableRow";
use VirtExperiment;
package VirtExperiment::VirtTableRow::elabinelab_attributes;
use vars qw(@ISA);
@ISA = "VirtExperiment::VirtTableRow";
use VirtExperiment;
# _Always_ make sure that this 1 is at the end of the file...
1;
......@@ -111,7 +111,7 @@ mysystem("$TB/sbin/mkproj -s $pid");
#
# Get the list of users and admin status. Admin users get a real shell
# on boss. Create the users, and not that we have to do this before the
# on boss. Create the users, and note that we have to do this before the
# groups are created (tbacct add does not do a setgroups).
#
my $users_result =
......@@ -153,7 +153,7 @@ while (my ($gid_idx) = $query_result->fetchrow_array()) {
# Now do a setgroups.
#
$users_result->dataseek(0);
while (my ($uid,$admin,$status) = $users_result->fetchrow_array()) {
while (my ($uid,$uid_idx,$admin,$status) = $users_result->fetchrow_array()) {
next
if ($uid eq "elabman");
next
......@@ -177,7 +177,20 @@ mysystem("$TB/sbin/exports_setup");
# So for the moment, we tweak the DB to rewrite everything to use the BSD
# tools.
#
# XXX this should go away if we once again settle on a single set of tools.
# Note that re-writing the pxe_boot_path doesn't have any effect for elabs
# NOT using the SINGLE_CONTROLNET setting. This is because as long as
# outer (real) boss responds first, the filename it returns is what gets
# used. We could rewrite pxe_boot_path in the real boss DB for nodes
# that are in an elabinelab, but then we could lose custom per-node settings
# for that field. To fix that, we could introduce a temporary field for
# holding any custom value, but I don't want to go there...
#
# Anyway, the way we work around the non-SINGLE_CONTROLNET problem is to
# find all the custom pxe_boot_path values (in nodes or node_type_attributes)
# and "create" them on the inner boss by symlinking them to the standard
# pxeboot. SWEET!
#
# XXX this should go away if/when we settle on a single set of tools.
#
if (1) {
# first find the OSIDs for the "standard" MFSes
......@@ -199,6 +212,21 @@ if (1) {
# make sure newnode MFS points to the correct place
DBQueryFatal("update os_info set path='$nmfspath' where osid=$nmfs");
# collect up non-standard PXE boot paths, first from node_type_attributes..
my @bogoboots = ();
$qr = DBQueryFatal("select attrvalue from node_type_attributes ".
"where attrkey='pxe_boot_path' and attrvalue!='' ".
"group by attrvalue");
while (my ($path) = $qr->fetchrow_array()) {
push @bogoboots, $path;
}
# ..and then from nodes
$qr = DBQueryFatal("select pxe_boot_path from nodes ".
"where pxe_boot_path is not NULL and role='testnode'");
while (my ($path) = $qr->fetchrow_array()) {
push @bogoboots, $path;
}
# and find all the node types and update their attributes.
$qr = DBQueryFatal("select type from node_types where class='pc'");
while (my ($ntype) = $qr->fetchrow_array()) {
......@@ -211,6 +239,27 @@ if (1) {
" where attrkey='diskloadmfs_osid' and type='$ntype'");
}
# fixup any nodes table entries with non-standard pxe_boot_path's
DBQueryFatal("update nodes set pxe_boot_path=NULL ".
" where pxe_boot_path is not NULL");
#
# Now symlink all the alternate boots to pxeboot.emu
# XXX we assume everything is at the top level of /tftpboot right now.
#
foreach my $boot (@bogoboots) {
if ($boot =~ /^\/tftpboot\/([^\/]+)$/) {
$boot = $1;
if (! -e "/tftpboot/$boot") {
if (system("ln -s pxeboot.emu /tftpboot/$boot")) {
print STDERR
"*** could not symlink non-standard boot '$boot';",
" some inner nodes will not boot properly!\n";
}
}
}
}
#
# Remake the dhcpd.conf file to reflect any pxeboot change.
# XXX dhcpd is not running yet so don't need this.
......
......@@ -2,7 +2,7 @@
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2009 University of Utah and the Flux Group.
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -655,6 +655,7 @@ sub TBDB_PHYSICAL_NODE_TABLES() {
'nodeuidlastlogin' => [ 'node_id' ],
'ntpinfo' => [ 'node_id' ],
'outlets' => [ 'node_id' ],
'outlets_remoteauth' => [ 'node_id' ],
'partitions' => [ 'node_id' ],
'plab_slice_nodes' => [ 'node_id' ],
'port_counters' => [ 'node_id' ],
......@@ -1305,26 +1306,6 @@ sub TBOSMaxConcurrent ($)
return $osinfo->max_concurrent();
}
#
# Returns the reboot waittime.
#
# usage: TBOSIDRebootWaittime(char *osid)
# returns >= 1 if there is a waittime
# returns undef if there is no waittime
# returns 0 if not valid.
#
sub TBOSIDRebootWaittime ($)
{
my ($osid) = @_;
require OSinfo;
my $osinfo = OSinfo->Lookup($osid);