Commit dcaca0b0 authored by Jonathon Duerig's avatar Jonathon Duerig

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

parents e3ab9a50 e1a1e002
......@@ -163,7 +163,7 @@ use vars qw(@ISA @EXPORT);
);
use English;
use vars qw($TB $TBOPS $TBOPSPID $EXPTLOGNAME $PROJROOT);
use vars qw($TB $TBOPS $TBOPSPID $EXPTLOGNAME $PROJROOT $MAINSITE);
# Configure variables
$TB = "@prefix@";
......@@ -171,6 +171,7 @@ $TBOPS = "@TBOPSEMAIL@";
$TBOPSPID = "emulab-ops";
$EXPTLOGNAME = "activity.log";
$PROJROOT = "@PROJROOT_DIR@";
$MAINSITE = @TBMAINSITE@;
1;
@SELFLOADER_DATA@
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2009, 2010 University of Utah and the Flux Group.
# All rights reserved.
#
package EmulabFeatures;
use strict;
use Exporter;
use vars qw(@ISA @EXPORT $debug $verbose);
@ISA = "Exporter";
@EXPORT = qw();
# Configure variables
my $TB = "@prefix@";
my $BOSSNODE = "@BOSSNODE@";
my $TBDOCBASE = "@TBDOCBASE@";
my $MAINSITE = @TBMAINSITE@;
$debug = 0;
$verbose = 1;
use emdb;
#
# Lookup a feature by its name.
#
sub Lookup($$)
{
my ($class, $token) = @_;
if (! ($token =~ /^[-\w]+$/)) {
return undef;
}
my $query_result =
DBQueryWarn("select * from emulab_features where feature='$token'");
return undef
if (! ($query_result && $query_result->numrows));
my $self = {};
$self->{"DBROW"} = $query_result->fetchrow_hashref();
bless($self, $class);
return $self;
}
sub feature($) { return $_[0]->{'DBROW'}->{'feature'}; }
sub description($) { return $_[0]->{'DBROW'}->{'description'}; }
# Global disable flag.
sub disabled($) { return $_[0]->{'DBROW'}->{'disabled'}; }
# Global enable flag.
sub enabled($) { return $_[0]->{'DBROW'}->{'enabled'}; }
sub added($) { return $_[0]->{'DBROW'}->{'added'}; }
#
# Make a new feature.
#
sub Create($$$)
{
my ($class, $featurename, $description) = @_;
my $feature = EmulabFeatures->Lookup($featurename);
return $feature
if (defined($feature));
my $safe_description = DBQuoteSpecial($description);
DBQueryWarn("replace into emulab_features set ".
" feature='$featurename', added=now(), ".
" description=$safe_description")
or return undef;
return EmulabFeatures->Lookup($featurename);
}
#
# Delete a feature.
#
sub Delete($)
{
my ($self) = @_;
my $featurename = $self->feature();
DBQueryWarn("delete from user_features where feature='$featurename'")
or return -1;
DBQueryWarn("delete from group_features where feature='$featurename'")
or return -1;
DBQueryWarn("delete from experiment_features where feature='$featurename'")
or return -1;
DBQueryWarn("delete from emulab_features where feature='$featurename'")
or return -1;
return 0;
}
#
# Set/Clear the global enable and disable flags
#
sub SetGlobalEnable($$)
{
my ($self, $value) = @_;
my $featurename = $self->feature();
$value = ($value ? 1 : 0);
DBQueryWarn("update emulab_features set enable='$value' ".
"where feature='$featurename'")
or return -1;
return 0;
}
sub SetGlobalDisable($$)
{
my ($self, $value) = @_;
my $featurename = $self->feature();
$value = ($value ? 1 : 0);
DBQueryWarn("update emulab_features set disable='$value' ".
"where feature='$featurename'")
or return -1;
return 0;
}
#
# Add a feature to a group or user.
#
sub Enable($$)
{
my ($self, $target) = @_;
my $featurename = $self->feature();
if (ref($target) eq "User") {
my $uid_idx = $target->uid_idx();
my $uid = $target->uid();
my $query_result =
DBQueryWarn("select * from user_features ".
"where feature='$featurename' and uid_idx='$uid_idx'");
return -1
if (!$query_result);
return 0
if ($query_result->numrows);
DBQueryWarn("replace into user_features set ".
" feature='$featurename', added=now(), ".
" uid='$uid', uid_idx='$uid_idx'")
or return -1;
return 0;
}
elsif (ref($target) eq "Group" || ref($target) eq "Project") {
if (ref($target) eq "Project") {
$target = $target->GetProjectGroup();
}
my $pid_idx = $target->pid_idx();
my $gid_idx = $target->gid_idx();
my $pid = $target->pid();
my $gid = $target->gid();
my $query_result =
DBQueryWarn("select * from group_features ".
"where feature='$featurename' and gid_idx='$gid_idx'");
return -1
if (!$query_result);
return 0
if ($query_result->numrows);
DBQueryWarn("replace into group_features set ".
" feature='$featurename', added=now(), ".
" gid='$gid', gid_idx='$gid_idx', ".
" pid='$pid', pid_idx='$pid_idx'")
or return -1;
return 0;
}
elsif (ref($target) eq "Experiment") {
my $exptidx = $target->idx();
my $pid = $target->pid();
my $eid = $target->eid();
my $query_result =
DBQueryWarn("select * from experiment_features ".
"where feature='$featurename' and exptidx='$exptidx'");
return -1
if (!$query_result);
return 0
if ($query_result->numrows);
DBQueryWarn("replace into experiment_features set ".
" feature='$featurename', added=now(), ".
" eid='$eid', pid='$pid', exptidx='$exptidx'")
or return -1;
return 0;
}
return -1;
}
#
# Remove a feature from a group or user.
#
sub Disable($$)
{
my ($self, $target) = @_;
my $featurename = $self->feature();
if (ref($target) eq "User") {
my $uid_idx = $target->uid_idx();
my $uid = $target->uid();
DBQueryWarn("delete from user_features ".
"where feature='$featurename' and uid_idx='$uid_idx'")
or return -1;
return 0;
}
elsif (ref($target) eq "Group" || ref($target) eq "Project") {
if (ref($target) eq "Project") {
$target = $target->GetProjectGroup();
}
my $pid_idx = $target->pid_idx();
my $gid_idx = $target->gid_idx();
my $pid = $target->pid();
my $gid = $target->gid();
DBQueryWarn("delete from group_features ".
"where feature='$featurename' and gid_idx='$gid_idx'")
or return -1;
return 0;
}
elsif (ref($target) eq "Experiment") {
my $exptidx = $target->idx();
DBQueryWarn("delete from experiment_features ".
"where feature='$featurename' and exptidx='$exptidx'")
or return -1;
return 0;
}
return -1;
}
#
# Delete all features for a target, as when that target is deleted.
#
sub DeleteAll($$)
{
my ($class, $target) = @_;
if (ref($target) eq "User") {
my $uid_idx = $target->uid_idx();
DBQueryWarn("delete from user_features where uid_idx='$uid_idx'")
or return -1;
return 0;
}
elsif (ref($target) eq "Group") {
my $gid_idx = $target->gid_idx();
DBQueryWarn("delete from group_features where gid_idx='$gid_idx'")
or return -1;
return 0;
}
elsif (ref($target) eq "Project") {
my $pid_idx = $target->pid_idx();
DBQueryWarn("delete from group_features where pid_idx='$pid_idx'")
or return -1;
return 0;
}
elsif (ref($target) eq "Experiment") {
my $exptidx = $target->idx();
DBQueryWarn("delete from experiment_features where exptidx='$exptidx'")
or return -1;
return 0;
}
return -1;
}
sub FeatureEnabled($$$$)
{
my ($class, $featurename, $user, $group, $experiment) = @_;
print STDERR "Checking for feature $featurename.\n";
#
# See if feature is globally disabled;
#
my $feature = EmulabFeatures->Lookup($featurename);
# A non existent feature is always disabled.
# Do not warn; not all sites will have the same set.
if (!defined($feature)) {
print STDERR
"*** Checking for non-existent Emulab Feature: $featurename\n"
if ($MAINSITE || $debug);
return 0;
}
# Globally disabled.
if ($feature->disabled()) {
print STDERR " Feature is globally disabled\n"
if ($debug);
return 0;
}
# Globally enabled.
if ($feature->enabled()) {
print STDERR " Feature is globally enabled\n"
if ($debug);
return 1;
}
my $enabled = 0;
if (defined($user)) {
my $uid_idx = $user->uid_idx();
my $query_result =
DBQueryWarn("select * from user_features ".
"where feature='$featurename' and uid_idx='$uid_idx'");
return 0
if (!$query_result);
print STDERR " Feature is " .
($query_result->numrows ? "enabled" : "disabled") . " for $user\n"
if ($debug);
$enabled += $query_result->numrows;
}
if (defined($group)) {
my $pid_idx = $group->pid_idx();
my $gid_idx = $group->gid_idx();
my $query_result =
DBQueryWarn("select * from group_features ".
"where feature='$featurename' and ".
" pid_idx='$pid_idx' and gid_idx='$gid_idx'");
return 0
if (!$query_result);
print STDERR " Feature is " .
($query_result->numrows ? "enabled" : "disabled") . " for $group\n"
if ($debug);
$enabled += $query_result->numrows;
}
if (defined($experiment)) {
my $exptidx = $experiment->idx();
my $query_result =
DBQueryWarn("select * from experiment_features ".
"where feature='$featurename' and ".
" exptidx='$exptidx'");
return 0
if (!$query_result);
print STDERR " Feature is " .
($query_result->numrows ? "enabled" : "disabled") .
" for $experiment\n"
if ($debug);
$enabled += $query_result->numrows;
}
print STDERR " Feature is " . ($enabled ? "enabled\n" : "disabled\n")
if ($verbose);
return $enabled;
}
#
# List of all current features.
#
sub List($)
{
my ($class) = @_;
my @features = ();
my $query_result =
DBQueryWarn("select feature from emulab_features order by feature");
return undef
if (!defined($query_result));
while (my ($featurename) = $query_result->fetchrow_array()) {
my $feature = EmulabFeatures->Lookup($featurename);
push(@features, $feature)
if (defined($feature));
}
return @features;
}
#
# List users and groups a feature is enabled for.
#
sub ListEnabled($$$$)
{
my ($self, $pusers, $pgroups, $pexp) = @_;
my $featurename = $self->feature();
my @users = ();
my @groups = ();
my @experiments = ();
require Group;
require User;
require Experiment;
my $query_result =
DBQueryWarn("select uid_idx from user_features ".
"where feature='$featurename' ".
"order by uid");
return -1
if (!defined($query_result));
while (my ($uid_idx) = $query_result->fetchrow_array()) {
my $user = User->Lookup($uid_idx);
push(@users, $user)
if (defined($user));
}
$query_result =
DBQueryWarn("select gid_idx from group_features ".
"where feature='$featurename' ".
"order by pid,gid");
return -1
if (!defined($query_result));
while (my ($gid_idx) = $query_result->fetchrow_array()) {
my $group = Group->Lookup($gid_idx);
push(@groups, $group)
if (defined($group));
}
$query_result =
DBQueryWarn("select exptidx from experiment_features ".
"where feature='$featurename' ".
"order by pid,eid");
return -1
if (!defined($query_result));
while (my ($idx) = $query_result->fetchrow_array()) {
my $experiment = Experiment->Lookup($idx);
push(@experiments, $experiment)
if (defined($experiment));
}
@$pusers = @users;
@$pgroups = @groups;
@$pexp = @experiments;
return 0;
}
1;
......@@ -3101,6 +3101,7 @@ sub ClearBackupState($)
sub RemovePhysicalState($)
{
my ($self) = @_;
require Lan;
# Must be a real reference.
return -1
......@@ -3172,6 +3173,7 @@ sub RemovePhysicalState($)
sub BackupPhysicalState($;$$)
{
my ($self, $directory, $regression) = @_;
require Lan;
# Must be a real reference.
return -1
......@@ -3277,6 +3279,7 @@ sub BackupPhysicalState($;$$)
sub RestorePhysicalState($)
{
my ($self) = @_;
require Lan;
# Must be a real reference.
return -1
......
......@@ -30,7 +30,7 @@ LIB_SCRIPTS = libdb.pm Node.pm libdb.py libadminctrl.pm Experiment.pm \
NodeType.pm Interface.pm User.pm Group.pm Project.pm \
Image.pm OSinfo.pm Archive.pm Logfile.pm Lan.pm emdbi.pm \
emdb.pm emutil.pm Firewall.pm VirtExperiment.pm libGeni.pm \
libEmulab.pm EmulabConstants.pm TraceUse.pm
libEmulab.pm EmulabConstants.pm TraceUse.pm EmulabFeatures.pm
# Stuff installed on plastic.
USERSBINS = genelists.proxy dumperrorlog.proxy backup
......
......@@ -11,8 +11,8 @@ SUBDIR = os/imagezip
DISTFILES = global.h imagehdr.h queue.h sliceinfo.h \
imagedump.c imagedump.8 imagezip.c imagezip.8 \
imageunzip.c crc.c disksize.c imageunzip.8 \
extfs/*.[hc] ext4fs/*.[hc] fat/*.[hc] ffs/*.[hc] ntfs/*.[hc] shd/*.[hc] \
hashmap/*.[hc]
extfs/*.[hc] ext4fs/*.[hc] fat/*.[hc] ffs/*.[hc] \
ntfs/*.[hc] hashmap/*.[hc]
EXPANDCOPYRIGHT = /usr/site/lib/copyright/expand-copyr
......@@ -182,7 +182,7 @@ imagehash: imagehash.o version.o
imagehash.o: imagehash.c
$(CC) -c $(HASHCFLAGS) -o imagehash.o $<
ffs extfs ext4fs ntfs fat shd hashmap:
$(SUBDIRS):
@$(MAKE) SUBDIRCFLAGS="$(SUBDIRCFLAGS)" -C $@ all
imagezip.o: sliceinfo.h imagehdr.h global.h
......@@ -231,4 +231,4 @@ imagezip.tar: Makefile.sa Makefile-linux.sa
tar cf imagezip.tar imagezip-dist
rm -rf imagezip-dist
.PHONY: $(SUBDIRS)
.PHONY: $(SUBDIRS)
......@@ -686,9 +686,9 @@ read_doslabel(int infd, int lsect, int pstart, struct doslabel *label)
fprintf(stderr, " P%d: ", bsdix + 1);
smap = getslicemap(label->parts[i].dp_typ);
if (smap == 0)
fprintf(stderr, "%-10s", "UNKNOWN");
fprintf(stderr, "%-12s", "UNKNOWN");
else
fprintf(stderr, "%-10s", smap->desc);
fprintf(stderr, "%-12s", smap->desc);
start = label->parts[i].dp_start;
#if 0
......@@ -720,6 +720,35 @@ read_image(u_int32_t bbstart, int pstart, u_int32_t extstart)
if (read_doslabel(infd, bbstart, pstart, &doslabel) != 0)
return 1;
/*
* Quick, brute-force check for overlap of partitions.
* XXX right now, any overlap is bad and we bail. In the future,
* we could determine all areas of intersection and be conservative
* with those areas; i.e., always save unless overlap is strictly
* between unused/ignored partitions.
*/
for (i = 0; i < NDOSPART-1; i++) {
u_int32_t start1, size1, start2, size2;
int i2;
if ((size1 = doslabel.parts[i].dp_size) == 0)
continue;
start1 = bbstart + doslabel.parts[i].dp_start;
for (i2 = i+1; i2 < NDOSPART; i2++) {
if ((size2 = doslabel.parts[i2].dp_size) == 0)
continue;
start2 = bbstart + doslabel.parts[i2].dp_start;
if (start2+size2 > start1 &&
start1+size1 > start2) {
warnx("P%d and P%d overlap!", i+1, i2+1);
rval++;
}
}
}
if (rval)
return 1;
/*
* Now operate on individual slices.
*/
......
......@@ -230,7 +230,10 @@ sub ExpireSlices()
goto skip;
}
}
print STDERR "$slice is idle; releasing.\n";
print STDERR "$slice ($experiment) is idle; releasing.\n";
}
else {
print STDERR "$slice ($experiment) has expired; releasing.\n";
}
cleanup:
if (GeniCM::CleanupDeadSlice($slice) != 0) {
......
......@@ -18,6 +18,7 @@ import xmlrpclib
import M2Crypto
from M2Crypto import X509
import socket
import time;
# Debugging output.
debug = 0
......@@ -246,23 +247,31 @@ def do_method(module, method, params, URI=None, quiet=False, version=None,
#
# Make the call.
#
try:
response = apply(meth, meth_args)
while True:
try:
response = apply(meth, meth_args)
break
except xmlrpclib.Fault, e:
if not quiet: print >> sys.stderr, e.faultString
if e.faultCode == 511:
print >> sys.stderr, "Will try again in a moment. Be patient!"
time.sleep(5.0)
continue
pass
return (-1, None)
except xmlrpclib.ProtocolError, e:
if not quiet: print >> sys.stderr, e.errmsg
return (-1, None)
except M2Crypto.SSL.Checker.WrongHost, e:
if not quiet:
print >> sys.stderr, "Warning: certificate host name mismatch."
print >> sys.stderr, "Please consult:"
print >> sys.stderr, " http://www.protogeni.net/trac/protogeni/wiki/HostNameMismatch"
print >> sys.stderr, "for recommended solutions."
print >> sys.stderr, e
pass
return (-1, None)
pass
except xmlrpclib.Fault, e:
if not quiet: print >> sys.stderr, e.faultString
return (-1, None)
except xmlrpclib.ProtocolError, e:
if not quiet: print >> sys.stderr, e.errmsg