Commit 7e4ad150 authored by Leigh Stoller's avatar Leigh Stoller

New libdb module. A library of some useful routines that will

hopefully get bigger and reduce the amount of typing that we all
do. I hacked up sched_reload and os_load to use it. Pretty simple to
start with.

I'm not planning to go much further on this until we sync up with the
dbtoir branch since it will just create needless branch merge errors.
parent 0e5db7ce
......@@ -11,6 +11,7 @@ include $(OBJDIR)/Makeconf
BIN_SCRIPTS = mac2if nalloc nfree nodeip
SBIN_SCRIPTS = avail inuse showgraph if2port backup webcontrol node_status
LIBEXEC_SCRIPTS = ptopgen
LIB_SCRIPTS = libdb.pm
# Stuff installed on plastic for mere users.
USERBINS = nalloc nfree
......@@ -19,12 +20,13 @@ USERBINS = nalloc nfree
# Force dependencies on the scripts so that they will be rerun through
# configure if the .in file is changed.
#
all: $(BIN_SCRIPTS) $(SBIN_SCRIPTS) $(LIBEXEC_SCRIPTS)
all: $(BIN_SCRIPTS) $(SBIN_SCRIPTS) $(LIBEXEC_SCRIPTS) $(LIB_SCRIPTS)
include $(TESTBED_SRCDIR)/GNUmakerules
install: $(addprefix $(INSTALL_BINDIR)/, $(BIN_SCRIPTS)) \
$(addprefix $(INSTALL_SBINDIR)/, $(SBIN_SCRIPTS)) \
$(addprefix $(INSTALL_LIBDIR)/, $(LIB_SCRIPTS)) \
$(addprefix $(INSTALL_LIBEXECDIR)/, $(LIBEXEC_SCRIPTS))
#
......
#!/usr/bin/perl -w
use English;
require Mysql;
#
# A library of useful DB stuff. Mostly things that get done a lot. Saves typing.
#
#
# Configure variables
#
my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@";
#
# Set up for querying the database.
#
my $DB = Mysql->connect("localhost", $DBNAME, "script", "none");
#
# Test admin status. Optional argument is the UID to test. If not provided,
# then test the current UID.
#
# usage: TBAdmin([int uid]);
# returns 1 if an admin type.
# returns 0 if a mere user.
#
sub TBAdmin(;$)
{
my($uid) = @_;
if (!defined($uid)) {
$uid = $UID;
}
my ($name) = getpwuid($uid)
or die "$uid not in passwd file\n";
my $query_result =
DBquery("select admin from users where uid='$name'");
my @row = $query_result->fetchrow_array();
if ($row[0] == 1) {
return 1;
}
return 0;
}
#
# Check access permission to a list of nodes. First argument is a *reference* to
# a single node, or a list of nodes. Second argument is optional uid, defaults
# to the current uid.
#
# usage: NodeAccessCheck(array or scalar \@nodelist, [int uid])
# returns 1 if the uid is allowed to muck with all the nodes.
# returns 0 if the uid is not allowed to muck with at least one of the nodes.
#
sub NodeAccessCheck($;$)
{
my($list, $uid) = @_;
my(@nodelist);
if (!defined($uid)) {
$uid = $UID;
}
if (ref($list) eq "ARRAY") {
@nodelist = @$list;
}
elsif (ref($list) eq "SCALAR") {
@nodelist = ($$list);
}
if (!defined(@nodelist) ||
scalar(@nodelist) == 0) {
die("NodeAccessCheck:\n".
" First parameter should be a reference to a node (scalar), ".
"or a list of nodes!\n");
}
#
# Admin types can do anything to any node. So can Root.
#
if ($uid == 0 || TBAdmin($uid)) {
return 1;
}
my ($name) = getpwuid($uid)
or die "$uid not in passwd file\n";
#
# Check to make sure that mere user is allowed to muck with nodes.
#
foreach my $node (@$nodelist) {
my $query_result =
DBquery("select reserved.node_id from reserved ".
"left join proj_memb on ".
"reserved.pid=proj_memb.pid and reserved.node_id='$node' ".
"where proj_memb.uid='$name'");
if ($query_result == 0 ||
$query_result->numrows == 0) {
return 0;
}
}
return 1;
}
#
# Check project membership. First argument is the project to check.
# Second argument is optional uid, defaults to the current uid.
#
# usage: ProjMember(char *pid, [int uid])
# returns 1 if the uid is a member of pid.
# returns 0 if the uid is not a member of pid.
#
sub ProjMember($;$)
{
my($pid, $uid) = @_;
if (!defined($uid)) {
$uid = $UID;
}
my ($name) = getpwuid($uid)
or die "$uid not in passwd file\n";
my $query_result =
DBquery("select * from proj_memb where uid='$name' and pid='$pid'");
if ($query_result == 0 ||
$query_result->numrows == 0) {
return 0;
}
return 1;
}
#
# Issue a DB query. Argument is a string. Returns the actual query object, so
# it is up to the caller to test it. I would not for one moment view this
# as encapsulation of the DB interface. I'm just tired of typing the same silly
# stuff over and over.
#
# usage: DBQuery(char *str)
# returns the query object result.
#
sub DBQuery($)
{
my($query) = $_[0];
my($result);
$result = $DB->query($query);
if (! $result) {
print "DB Query failed:\n".
" Query: $query\n".
" Error: " . $DB->errstr . "\n";
}
return $result;
}
#
# Same as above, but die on error.
#
sub DBQueryFatal($)
{
my($query) = $_[0];
my($result);
$result = DBQuery($query);
if (! $result) {
exit(-1);
}
return $result;
}
1;
......@@ -27,7 +27,12 @@ my $optlist = "s";
# Configure variables
#
my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@";
#
# Load the Testbed support stuff.
#
push(@INC, "$TB/lib");
require libdb;
my $NETDISK = "/tftpboot/netdisk";
my $PAPERADDR = "boss.emulab.net";
......@@ -37,7 +42,6 @@ my $dbg = 0;
my @row;
my %imageid_row = ();
my @nodes = ();
my $name = "";
my $mereuser = 0;
my $setuponly = 0;
my $failures = 0;
......@@ -85,26 +89,13 @@ foreach my $node ( @ARGV ) {
push(@nodes, $node);
}
#
# Set up for querying the database.
#
use Mysql;
my $DB = Mysql->connect("localhost", $DBNAME, "script", "none");
#
# Figure out who called us. Root and admin types can do whatever they
# want. Normal users can only change nodes in experiments in their
# own projects.
#
if ($UID != 0) {
($name) = getpwuid($UID)
or die "$UID not in passwd file\n";
$db_result = $DB->query("select admin from users where uid='$name'");
@row = $db_result->fetchrow_array();
if ($row[0] != 1) {
$mereuser = 1;
}
if ($UID && !TBAdmin($UID)) {
$mereuser = 1;
}
#
......@@ -113,7 +104,7 @@ if ($UID != 0) {
# or any image that has a null pid field, since those are defined to be
# open to anyone.
#
$db_result = $DB->query("select * from images where imageid='$imageid'");
$db_result = DBQuery("select * from images where imageid='$imageid'");
if ($db_result->numrows < 1) {
die("No such imageid $imageid!");
......@@ -125,13 +116,8 @@ if (defined($imageid_row{'pid'})) {
$imagepid = $imageid_row{'pid'};
}
if ($mereuser && $imagepid) {
$db_result = $DB->query("select * from proj_memb ".
"where uid='$name' and pid='$imagepid'");
if ($db_result->numrows < 1) {
die("You do not have permission to load imageid $imageid!");
}
if ($mereuser && $imagepid && !ProjMember($imagepid)) {
die("You do not have permission to load imageid $imageid!");
}
#
......@@ -139,12 +125,7 @@ if ($mereuser && $imagepid) {
#
if ($mereuser) {
foreach my $node (@nodes) {
$db_result = $DB->query("select reserved.node_id from reserved ".
"left join proj_memb on ".
"reserved.pid=proj_memb.pid and ".
"reserved.node_id='$node' ".
"where proj_memb.uid='$name'");
if ($db_result->numrows < 1) {
if (! NodeAccessCheck(\$node)) {
die("You do not have permission to load images on $node\n");
}
}
......@@ -188,9 +169,9 @@ foreach my $node (@nodes) {
my $pc = $node;
print STDOUT "Changing default OS for $pc to $defosid\n";
$sth = $DB->query("update nodes set ".
"def_boot_osid='$defosid',def_boot_path='' ".
"where node_id='$pc'");
$sth = DBQuery("update nodes set ".
"def_boot_osid='$defosid',def_boot_path='' ".
"where node_id='$pc'");
if ($sth == 0) {
die("Database update failed (nodes def_boot_osid).");
}
......@@ -212,13 +193,13 @@ foreach my $node (@nodes) {
if (defined($imageid_row{$partname})) {
my $osid = $imageid_row{$partname};
$sth = $DB->query("replace into partitions ".
"(partition, osid, node_id) ".
"values('$i', '$osid', '$pc')");
$sth = DBQuery("replace into partitions ".
"(partition, osid, node_id) ".
"values('$i', '$osid', '$pc')");
}
else {
$sth = $DB->query("delete from partitions ".
"where node_id='$pc' and partition='$i'");
$sth = DBQuery("delete from partitions ".
"where node_id='$pc' and partition='$i'");
}
if ($sth == 0) {
......@@ -228,10 +209,10 @@ foreach my $node (@nodes) {
}
print STDOUT "Setting up reload for $pc\n";
$sth = $DB->query("update nodes set ".
"next_boot_path='$NETDISK',".
"next_boot_cmd_line='$cmdline' ".
"where node_id='$pc'");
$sth = DBQuery("update nodes set ".
"next_boot_path='$NETDISK',".
"next_boot_cmd_line='$cmdline' ".
"where node_id='$pc'");
if ($sth == 0) {
die("Database update failed (nodes next_boot). Aborted ...");
}
......
......@@ -21,12 +21,17 @@ my $optlist = "f";
#
# Configure variables
#
my $TB = "@prefix@/bin";
my $DBNAME = "@TBDBNAME@";
my $TB = "@prefix@";
my $osload = "$TB/os_load";
#
# Load the Testbed support stuff.
#
push(@INC, "$TB/lib");
require libdb;
my $osload = "$TB/bin/os_load";
my $nalloc = "$TB/bin/nalloc";
my $name = "";
my $mereuser = 0;
my $error = 0;
my $debug = 0;
my $force = 0;
......@@ -77,31 +82,10 @@ foreach my $node ( @ARGV ) {
}
#
# Set up for querying the database.
#
use Mysql;
my $DB = Mysql->connect("localhost", $DBNAME, "script", "none");
#
# Figure out who called us. Root and admin types can do whatever they
# want. Normal users can only change nodes in experiments in their
# own projects.
#
if ($UID != 0) {
($name) = getpwuid($UID)
or die "$UID not in passwd file\n";
$db_result = $DB->query("select admin from users where uid='$name'");
@row = $db_result->fetchrow_array();
if ($row[0] != 1) {
$mereuser = 1;
}
}
#
# Mere Users cannot schedule reloads.
# Root and admin types can do whatever they want.
# Mere users cannot schedule reloads.
#
if ($mereuser) {
if ($UID && !TBAdmin($UID)) {
die("Only root or TB administrators can schedule disk reloads.\n");
}
......@@ -112,7 +96,7 @@ my @load_list=();
foreach my $node (@nodes) {
my $pc = $node;
$sth = $DB->query("select * from nodes where node_id='$pc'");
$sth = DBQuery("select * from nodes where node_id='$pc'");
if ($sth == 0) {
die("Database lookup failed (exists). Aborted...\n");
}
......@@ -122,7 +106,7 @@ foreach my $node (@nodes) {
}
print STDERR "Checking if $pc is reserved...";
$sth = $DB->query("select * from reserved where node_id='$pc'");
$sth = DBQuery("select * from reserved where node_id='$pc'");
if ($sth == 0) {
die("Database lookup failed (reserved). Aborted...\n");
}
......@@ -135,7 +119,7 @@ foreach my $node (@nodes) {
# XXX If you change testbed/reloading, be sure to update the
# test in doreboot() in tmcd/tmcd.c.
#
my $cmd = "$TB/nalloc testbed reloading $pc";
my $cmd = "$nalloc testbed reloading $pc";
if ( system($cmd) != 0 ) {
print STDERR "WARNING: Could not reserve $pc!\n";
} else {
......@@ -143,8 +127,7 @@ foreach my $node (@nodes) {
# Kill the last_reservation so that whoever gets the node next
# won't be fooled into thinking a reload is required.
#
$sth = $DB->query("delete from last_reservation ".
"where node_id='$pc'");
$sth = DBQuery("delete from last_reservation where node_id='$pc'");
push (@load_list,$pc);
$allocated = 1;
}
......@@ -162,8 +145,8 @@ foreach my $node (@nodes) {
# Put it in the reloads table so TMCD knows to free it.
print STDERR "Scheduling reload of $imageid for $pc:\n";
$sth = $DB->query("replace into reloads ".
"(node_id, image_id) values ('$pc', '$imageid')");
$sth = DBQuery("replace into reloads ".
"(node_id, image_id) values ('$pc', '$imageid')");
if ($sth == 0) {
die("Database update failed (reloads). Aborted...\n");
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment