Commit d7d27c36 authored by David Johnson's avatar David Johnson
Browse files

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

parents 25711c9c 195d87c8
......@@ -4523,8 +4523,6 @@ sub ReserveSharedBandwidth($;$$)
# This is how much we need to release.
#
if ($isupdate && defined($previous_result)) {
$previous_result = $previous_result->WrapForSeek();
while (my ($node_id,$unit,$iface,$bw) =
$previous_result->fetchrow_array()) {
......
......@@ -3060,6 +3060,7 @@ sub RecordVLanDeletion($$)
sub RecordVLanModification($$$$)
{
my ($class, $lanid, $added, $removed) = @_;
my %current = ();
my $query_result =
DBQueryWarn("select members from vlans where id='$lanid'");
......@@ -3067,7 +3068,9 @@ sub RecordVLanModification($$$$)
return -1
if (!$query_result);
my ($current) = $query_result->fetchrow_array();
my %current = map { $_ => $_ } split(/\s+/, $current);
if (defined($current) && $current ne "") {
%current = map { $_ => $_ } split(/\s+/, $current);
}
if ($added) {
foreach my $port (@$added) {
......
......@@ -55,13 +55,14 @@ sub checknodeid($$)
my ($nid,$msg) = @_;
if ($nid =~ /^(.*)\x0/) {
my $onid = $nid;
$nid = $1;
if (!exists($carped{$nid}) && open(MAIL, "| /usr/sbin/sendmail -t")) {
$carped{$nid} = 1;
require Carp;
my $TBOPS = "@TBOPSEMAIL@";
print MAIL "To: $TBOPS\n";
print MAIL "Subject: NUL in node_id '$nid'\n";
print MAIL "Subject: NUL in node_id '$nid' ('$onid')\n";
print MAIL "$msg\n";
print MAIL "\n";
print MAIL Carp::longmess();
......@@ -167,8 +168,18 @@ sub Lookup($$)
return undef
if (!$query_result || !$query_result->numrows);
#
# Make a copy of the array. Still fighting memory corruption error.
#
my $hash_orig = $query_result->fetchrow_hashref();
my $hash_copy = {};
foreach my $key (keys(%{ $hash_orig })) {
my $val = $hash_orig->{$key};
$hash_copy->{$key} = $val;
}
my $self = {};
$self->{"DBROW"} = $query_result->fetchrow_hashref();
$self->{"DBROW"} = $hash_copy;
$self->{"RSRV"} = undef;
$self->{"TYPEINFO"} = undef;
$self->{"ATTRS"} = undef;
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2005 University of Utah and the Flux Group.
# Copyright (c) 2005-2011 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Mysql;
#
# usage: dumperrorlog.proxy
......@@ -44,6 +43,7 @@ $| = 1;
# Load the Testbed support stuff.
use lib "@prefix@/lib";
use libtestbed;
use libtbdb;
sub fatal($) {
my ($msg) = @_;
......@@ -78,17 +78,10 @@ else {
fatal("Bad characters in password!");
}
my $DB = Mysql->connect('localhost', $DBNAME, $DBUSER, $pwd);
fatal("Could not connect to errorlog DB!")
if (!defined($DB));
my $query_result =
$DB->query("load data infile '${tempfile}.${tablename}' ".
"replace into table $tablename");
if (! defined($query_result)) {
fatal("DB Error: " . $DB->errstr . "\n");
if (TBDBConnect($DBNAME, $DBUSER, $pwd) < 0) {
fatal("Could not connect to errorlog database!");
}
DBQueryFatal("load data infile '${tempfile}.${tablename}' ".
"replace into table $tablename");
exit(0);
......@@ -42,6 +42,8 @@ sub TBDBConnect($) { return emdbi::TBDBConnect($_[0], $DBNAME); }
sub TBDBReconnect($) { return emdbi::TBDBReconnect($_[0]); }
sub TBDBDisconnect() { return emdbi::TBDBDisconnect(); }
sub NewTBDBHandle() { return emdbi::NewTBDBHandle($DBNAME); }
sub DBHandle() { return emdbi::DBHandleN(0); }
sub DBHandleN($) { return emdbi::DBHandleN($_[0]); }
sub DBQueryN($$) { return emdbi::DBQueryN($_[0], $_[1]); }
sub DBQuery($) { return emdbi::DBQuery($_[0]); }
sub DBQueryFatalN($$) { return emdbi::DBQueryFatalN($_[0], $_[1]); }
......
......@@ -753,6 +753,17 @@ sub DBKeyExistsN($$$)
}
sub DBKeyExists($$) { return DBKeyExistsN(0,$_[0],$_[1]); }
sub DBHandleN($)
{
my ($dbnum) = @_;
my $dbw = $DB[$dbnum];
my $db = $dbw->dbh();
return $db;
}
sub DBHandle() { return DBHandleN(0); }
END {
# Call it here otherwise may get:
# (in cleanup) Can't call method "FETCH" on an undefined value at
......
......@@ -299,7 +299,7 @@ sub DBQuoteSpecial($;$)
if (!defined($handle)) {
$dbhandle = $DB;
} else {
$dbhandle = $dbhandle->{'DB'};
$dbhandle = $handle->{'DB'};
}
$string = $dbhandle->quote($string);
......@@ -320,7 +320,7 @@ sub DBDateTime(;$)
$seconds = 0;
}
return strftime("20%y-%m-%d %H:%M:%S", localtime(time() + $seconds));
return strftime("20%y-%m-%d %H:%M:%S", localtime(time() + $seconds));
}
# Binary mode for database query
......@@ -336,7 +336,7 @@ sub DBDateTime(;$)
sub DBBinaryQuery {
my ($handle, $statement, @data) = @_;
my $dbh = $handle->{'DB'}->{'dbh'};
my $dbh = $handle->{'DB'};
my $sth = $dbh->prepare($statement);
if (!$sth) {
$DBErrorString =
......
......@@ -2,7 +2,7 @@
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2002 University of Utah and the Flux Group.
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -27,18 +27,17 @@ if ($#ARGV >= 1 || $#ARGV < 0) {
print "parameter (like 'myhost:0') on the command line, and it will \n";
print "attempt to open it.\n";
die("\n");
} else {
use Mysql;
require "ctime.pl";
}
use lib '@prefix@/lib';
use libtestbed;
use emdb;
require "ctime.pl";
my $display = shift;
my $v = 0; # Verbose
my $dbh = Mysql->connect("localhost","@TBDBNAME@","script","none");
my @tbls = $dbh->listtables;
my @tbls = map { $_ =~ s/.*\.//; $_ } emdb::DBHandle()->tables();
my $date = &ctime(time);
......@@ -79,7 +78,7 @@ my %forkeys=();
foreach $tbl ( @tbls ) {
push(@tablelist,$tbl);
print "Found $tbl:\n" if $v;
if ($sth = $dbh->query("describe $tbl") ) {
if ($sth = DBQueryFatal("describe $tbl") ) {
while ( @data = $sth->fetchrow()) {
$col = $data[0];
$col =~ s/[0-9\-]+$//;
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
#
use strict;
......@@ -38,30 +38,6 @@ my $extraopts = ($isvers5 ? "--skip-opt" : "");
#
my $mysqldump = "mysqldump $extraopts -t $DBNAME sitevariables";
#
# We use Mysql module instead of the testbed libraries, so that we can get
# a more precise feel for what the error is.
#
use Mysql;
#
# Check to see if the mysqld is running by trying to connect to it.
#
my $dbh = Mysql->connect(undef,undef,undef,undef);
if (!$dbh) {
fatal("Unable to connect to mysqld - Either it's not running or \n" .
"permission was denied.\n");
}
#
# Check to see if the database exists
#
my @dbs = $dbh->listdbs();
if (! grep (/^$DBNAME$/,@dbs)) {
fatal("Database $DBNAME does not exist in the running database\n");
}
undef $dbh;
#
# Make sure we can write the temporary file
#
......
#
# Snmpit changes. vlan tags are managed exclusively in the DB now
# rather then on the switches. All of vlans are associated with an
# experiment; system vlans are associated with emulab-ops/vlan-holding.
# This script simply creates the holding experiment; a later script
# will do the rest of whatever is needed.
#
use strict;
use libinstall;
use emdb;
use OSinfo;
use NodeType;
my $EID = "vlan-holding";
my $DESC = "Holding experiment for internal vlans";
my $SUDO = "/usr/local/bin/sudo";
my $BATCHEXP = "$TBROOT/bin/batchexp";
sub InstallUpdate($$)
{
my ($version, $phase) = @_;
my $pid = "emulab-ops";
if ($phase eq "pre") {
Phase "vlan-holding", "Setting up vlan holding support", sub {
#
# Holding experiment.
#
Phase "experiment", "Creating vlan holding experiment", sub {
PhaseSkip("Experiment exists")
if (-d "$PROJROOT/$pid/exp/$EID");
ExecQuietFatal("$SUDO -u $PROTOUSER $WAP $BATCHEXP ".
" -q -i -k -j -w -f -n ".
" -S 'System Experiment' ".
" -L 'System Experiment' ".
" -E '$DESC - DO NOT DELETE' ".
" -p $pid -e $EID");
PhaseSucceed();
};
PhaseSucceed();
};
}
return 0;
}
1;
......@@ -35,7 +35,9 @@ struct emulab_ha_extra_info {
char *pid; /* project */
char *gid; /* group */
char *eid; /* experiment */
char *suid; /* swapper user name */
char *sname; /* swapper user name */
int suid; /* swapper's unix uid */
int egid; /* experiment's unix gid */
};
static char *MC_BASEADDR = FRISEBEEMCASTADDR;
......@@ -184,7 +186,7 @@ emulab_free_host_authinfo(struct config_host_authinfo *ai)
FREE(ei->pid);
FREE(ei->gid);
FREE(ei->eid);
FREE(ei->suid);
FREE(ei->sname);
free(ai->extra);
}
free(ai);
......@@ -333,7 +335,7 @@ allow_stddirs(char *imageid,
snprintf(tpath, sizeof tpath, "%s/%s/%s", GROUPSDIR, ei->pid, ei->gid);
gdir = mystrdup(tpath);
snprintf(tpath, sizeof tpath, "%s/%s", USERSDIR, ei->suid);
snprintf(tpath, sizeof tpath, "%s/%s", USERSDIR, ei->sname);
udir = mystrdup(tpath);
if (SCRATCHDIR) {
......@@ -375,6 +377,7 @@ allow_stddirs(char *imageid,
ci->sig = NULL;
ci->get_options = NULL;
ci->get_methods = 0;
ci->get_uid = ci->get_gid = -1;
ci->put_options = NULL;
ci->extra = NULL;
}
......@@ -408,6 +411,8 @@ allow_stddirs(char *imageid,
ci->sig = NULL;
set_get_options(get, i);
set_get_methods(get, i);
ci->get_uid = ei->suid;
ci->get_gid = ei->egid;
ci->put_options = NULL;
ci->extra = NULL;
}
......@@ -455,6 +460,7 @@ allow_stddirs(char *imageid,
ci->sig = NULL;
ci->get_options = NULL;
ci->get_methods = 0;
ci->get_uid = ci->get_gid = -1;
ci->put_options = NULL;
ci->extra = NULL;
}
......@@ -475,6 +481,8 @@ allow_stddirs(char *imageid,
ci->sig = NULL;
set_get_options(get, 0);
set_get_methods(get, 0);
ci->get_uid = ei->suid;
ci->get_gid = ei->egid;
ci->put_options = NULL;
ci->extra = NULL;
}
......@@ -699,12 +707,17 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
free(proxy);
}
/* Find the pid/gid to which the node is currently assigned */
res = mydb_query("SELECT e.pid,e.gid,r.eid,u.uid"
" FROM reserved AS r,experiments AS e,users AS u"
/*
* Find the pid/gid to which the node is currently assigned
* and also the unix uid of the swapper and unix gid for the
* experiment in case we need to run a server process.
*/
res = mydb_query("SELECT e.pid,e.gid,r.eid,u.uid,u.unix_uid,g.unix_gid"
" FROM reserved AS r,experiments AS e,"
" users AS u,groups as g"
" WHERE r.pid=e.pid AND r.eid=e.eid"
" AND e.swapper_idx=u.uid_idx"
" AND r.node_id='%s'", 4, node);
" AND e.swapper_idx=u.uid_idx AND e.gid=g.gid"
" AND r.node_id='%s'", 6, node);
assert(res != NULL);
/* Node is free */
......@@ -717,8 +730,8 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
}
row = mysql_fetch_row(res);
if (!row[0] || !row[1] || !row[2] || !row[3]) {
error("config_host_authinfo: null pid/gid/eid/uid!?");
if (!row[0] || !row[1] || !row[2] || !row[3] || !row[4] || !row[5]) {
error("config_host_authinfo: null pid/gid/eid/uname/uid!?");
mysql_free_result(res);
emulab_free_host_authinfo(get);
emulab_free_host_authinfo(put);
......@@ -731,7 +744,9 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
ei->pid = mystrdup(row[0]);
ei->gid = mystrdup(row[1]);
ei->eid = mystrdup(row[2]);
ei->suid = mystrdup(row[3]);
ei->sname = mystrdup(row[3]);
ei->suid = atoi(row[4]);
ei->egid = atoi(row[5]);
get->extra = ei;
}
if (put != NULL) {
......@@ -739,7 +754,9 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
ei->pid = mystrdup(row[0]);
ei->gid = mystrdup(row[1]);
ei->eid = mystrdup(row[2]);
ei->suid = mystrdup(row[3]);
ei->sname = mystrdup(row[3]);
ei->suid = atoi(row[4]);
ei->egid = atoi(row[5]);
put->extra = ei;
}
mysql_free_result(res);
......@@ -828,6 +845,7 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
ci->sig = NULL;
ci->get_methods = 0;
ci->get_options = NULL;
ci->get_uid = ci->get_gid = -1;
ci->put_options = NULL;
ii = mymalloc(sizeof *ii);
ii->DB_imageid = atoi(row[4]);
......@@ -896,6 +914,8 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
ci->sig = NULL;
set_get_methods(get, get->numimages);
set_get_options(get, get->numimages);
ci->get_uid = ei->suid;
ci->get_gid = ei->egid;
ci->put_options = NULL;
ii = mymalloc(sizeof *ii);
ii->DB_imageid = atoi(row[4]);
......
......@@ -5,9 +5,11 @@
*/
/*
* Configuration "file" handling for Emulab.
* Configuration "file" handling for a "null" or default configuration.
* Just uses globally configurated info for all images:
*
* Uses info straight from the Emulab database.
* - images get/put to a standard image directory
* - servers run as same user as master server
*/
#ifdef USE_NULL_CONFIG
......@@ -103,8 +105,13 @@ set_get_options(struct config_host_authinfo *ai, int ix)
/*
* We use a small server inactive timeout since we no longer have
* to start up a frisbeed well in advance of the client(s).
*
* XXX we cranked this from 60 to 180 seconds to account for clients
* with lots of write buffer memory but slow disks, giving them time
* to flush all their buffers and report their stats before we give
* up on them.
*/
strcat(str, " -T 60");
strcat(str, " -T 180");
ai->imageinfo[ix].get_options = mystrdup(str);
}
......@@ -282,6 +289,7 @@ allow_stddirs(char *imageid,
ci->sig = NULL;
ci->get_options = NULL;
ci->get_methods = 0;
ci->get_uid = ci->get_gid = -1;
ci->put_options = NULL;
ci->extra = NULL;
}
......@@ -311,6 +319,7 @@ allow_stddirs(char *imageid,
ci->sig = NULL;
set_get_options(get, i);
set_get_methods(get, i);
ci->get_uid = ci->get_gid = -1;
ci->put_options = NULL;
ci->extra = NULL;
}
......@@ -433,6 +442,7 @@ null_get_host_authinfo(struct in_addr *req, struct in_addr *host,
ci->sig = NULL;
ci->get_methods = 0;
ci->get_options = NULL;
ci->get_uid = ci->get_gid = -1;
ci->put_options = NULL;
ci->extra = NULL;
}
......@@ -452,6 +462,7 @@ null_get_host_authinfo(struct in_addr *req, struct in_addr *host,
ci->sig = NULL;
set_get_methods(get, 0);
set_get_options(get, 0);
ci->get_uid = ci->get_gid = -1;
ci->put_options = NULL;
ci->extra = NULL;
}
......
......@@ -12,6 +12,8 @@ struct config_imageinfo {
int flags; /* */
char *get_options; /* options for GET operation */
int get_methods; /* allowed GET transfer mechanisms */
int get_uid; /* UID to run frisbee server as */
int get_gid; /* GID to run frisbee server as */
char *put_options; /* options for PUT operation */
void *extra; /* config-type specific info */
};
......
......@@ -48,6 +48,8 @@ int debug = 0;
static int dumpconfig = 0;
static int onlymethods = (MS_METHOD_UNICAST|MS_METHOD_MULTICAST);
static int parentmethods = (MS_METHOD_UNICAST|MS_METHOD_MULTICAST);
static int myuid = -1;
static int mygid = -1;
/*
* For recursively GETing images:
......@@ -85,10 +87,13 @@ main(int argc, char **argv)
get_options(argc, argv);
myuid = geteuid();
mygid = getegid();
MasterServerLogInit();
log("mfrisbeed daemon starting, methods=%s (debug level %d)",
GetMSMethods(onlymethods), debug);
log("mfrisbeed daemon starting as %d/%d, methods=%s (debug level %d)",
myuid, mygid, GetMSMethods(onlymethods), debug);
if (fetchfromabove)
log(" using parent %s:%d%s, methods=%s",
inet_ntoa(parentip), parentport,
......@@ -203,6 +208,8 @@ struct childinfo {
int method;
int pid;
char *pidfile;
int uid; /* UID to run child as */
int gid; /* GID to run child as */
int retries;
in_addr_t servaddr; /* -S arg */
in_addr_t ifaceaddr; /* -i arg */
......@@ -269,6 +276,8 @@ copy_imageinfo(struct config_imageinfo *ii)
(nii->get_options = strdup(ii->get_options)) == NULL)
goto fail;
nii->get_methods = ii->get_methods;
nii->get_uid = ii->get_uid;
nii->get_gid = ii->get_gid;
/* XXX don't care about put_options and extra right now */
return nii;
......@@ -854,9 +863,9 @@ handle_get(int sock, struct sockaddr_in *sip, struct sockaddr_in *cip,
}
in.s_addr = htonl(ci->addr);
log("%s: started %s server on %s:%d (pid %d)",
log("%s: started %s server on %s:%d (pid %d, ugid %d/%d)",
imageid, GetMSMethods(ci->method),
inet_ntoa(in), ci->port, ci->pid);
inet_ntoa(in), ci->port, ci->pid, ci->uid, ci->gid);
/*
* Watch for an immediate death so we don't tell our client
......@@ -885,13 +894,13 @@ handle_get(int sock, struct sockaddr_in *sip, struct sockaddr_in *cip,
}
in.s_addr = htonl(ci->addr);
if (wantstatus)
log("%s: STATUS is running %s on %s:%d (pid %d)",
log("%s: STATUS is running %s on %s:%d (pid %d, ugid %d/%d)",
imageid, GetMSMethods(ci->method),
inet_ntoa(in), ci->port, ci->pid);
inet_ntoa(in), ci->port, ci->pid, ci->uid, ci->gid);
else
log("%s: %s server already running on %s:%d (pid %d)",
log("%s: %s server already running on %s:%d (pid %d, ugid %d/%d)",
imageid, GetMSMethods(ci->method),
inet_ntoa(in), ci->port, ci->pid);
inet_ntoa(in), ci->port, ci->pid, ci->uid, ci->gid);
}
msg->body.getreply.hisize = htonl(isize >> 32);
......@@ -1206,6 +1215,15 @@ startchild(struct childinfo *ci)
struct in_addr in;
char *pname;
if (myuid == 0) {
if ((ci->gid != mygid && setgid(ci->gid) != 0) ||
(ci->uid != myuid && setuid(ci->uid) != 0)) {
error("could not setuid/gid to %d/%d",
ci->uid, ci->gid);
exit(-2);
}
}
pname = (ci->ptype == PTYPE_SERVER) ?
FRISBEE_SERVER : FRISBEE_CLIENT;
in.s_addr = htonl(ci->ifaceaddr);
......@@ -1305,6 +1323,22 @@ startserver(struct config_imageinfo *ii, in_addr_t meaddr, in_addr_t youaddr,
if (ci->method == MS_METHOD_UNICAST)
ci->addr = youaddr;
/*
* If we are running as root, prefer to run the frisbee server
* for the image as indicated in the imageinfo (if set).
* Otherwise just run it as our uid/gid.
*/
if (myuid == 0) {
if (ii->get_uid >= 0 && myuid != ii->get_uid)
ci->uid = ii->get_uid;
else
ci->uid = myuid;
if (ii->get_gid >= 0 && mygid != ii->get_gid)
ci->gid = ii->get_gid;
else
ci->gid = mygid;
}
ci->servaddr = meaddr;
ci->ifaceaddr = meaddr;
ci->imageinfo = copy_imageinfo(ii);
......@@ -1397,6 +1431,10 @@ startclient(struct config_imageinfo *ii, in_addr_t meaddr, in_addr_t youaddr,
ci->ptype = PTYPE_CLIENT;
ci->retries = 0;
/* For now, we just run the client as us */
ci->uid = myuid;
ci->gid = mygid;
ce = ci->extra = malloc(sizeof(struct clientextra));
if (ce == NULL) {
free(ci);
......
......@@ -144,7 +144,14 @@ sub GetCredential($)
"Malformed URN in the certificate")
if (!GeniHRN::IsValid($urn));
my ($auth, $type, $id) = GeniHRN::Parse($urn);