Commit c3375835 authored by Jonathon Duerig's avatar Jonathon Duerig

Merge branch 'master' into no-require

parents 273a3b9a f0f635c7
......@@ -267,7 +267,7 @@ for child in tree.getroot():
#
# Watch for binding to another node in the topology.
#
if vname in nodes:
if element.text in nodes:
nodes[vname].InstantiateOn(nodes[element.text])
else:
node.component_id = URN.Node(OURDOMAIN, element.text)
......
......@@ -162,9 +162,11 @@ if (!$noumount) {
}
#
# Remove any auto generated fstab swap line
# Remove any auto generated fstab swap line.
# XXX assumes there is only one!
#
print "Removing auto-generated /etc/fstab swap line ...\n";
system("sed -i -e '/^# the following swap devices added by /,+1d' $FSTAB");
system("sed -i -e '/^# the following added by .*rc.freebsd/,+1d' $FSTAB");
#
......
#!/usr/bin/perl -w
#
# Copyright (c) 2007-2012 University of Utah and the Flux Group.
# Copyright (c) 2007-2016 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -161,7 +161,7 @@ sub addswap($$)
print STDERR "*** WARNING: could not add /dev/$dev to $FSTAB, ".
"swap enabled this boot only\n";
}
print FD "# the following added by $script\n";
print FD "# the following swap devices added by $script\n";
print FD "/dev/$dev\t\tnone\tswap\tsw\t0\t0\n";
close(FD);
print "Swap enabled\n";
......
#!/usr/bin/perl -w
#
# Copyright (c) 2007-2012 University of Utah and the Flux Group.
# Copyright (c) 2007-2016 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -161,7 +161,7 @@ sub addswap($$)
print STDERR "*** WARNING: could not add /dev/$dev to $FSTAB, ".
"swap enabled this boot only\n";
}
print FD "# the following added by $script\n";
print FD "# the following swap devices added by $script\n";
print FD "/dev/$dev\t\tnone\tswap\tsw\t0\t0\n";
close(FD);
print "Swap enabled\n";
......
#!/usr/bin/perl -w
#
# Copyright (c) 2007-2012 University of Utah and the Flux Group.
# Copyright (c) 2007-2016 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -161,7 +161,7 @@ sub addswap($$)
print STDERR "*** WARNING: could not add /dev/$dev to $FSTAB, ".
"swap enabled this boot only\n";
}
print FD "# the following added by $script\n";
print FD "# the following swap devices added by $script\n";
print FD "/dev/$dev\t\tnone\tswap\tsw\t0\t0\n";
close(FD);
print "Swap enabled\n";
......
......@@ -267,8 +267,11 @@ sub fix_swap_partitions
}
@buffer = grep {!/^[^#].*\bswap\b.*$/} <FSTAB>;
for (@swapdevs) {
push @buffer, "$_\tnone\tswap\tsw\t0 0\n";
if (@swapdevs > 0) {
push @buffer, "# the following swap devices added by linux_slicefix\n";
for (@swapdevs) {
push @buffer, "$_\tnone\tswap\tsw\t0 0\n";
}
}
seek FSTAB, 0, 0;
print FSTAB @buffer;
......
......@@ -1763,7 +1763,7 @@ sub GetTicketAuxAux($$$$$$$$$$$)
$GeniXML::EMULAB_NS)->get_nodelist();
if (defined($chassis)) {
my $chnum = GetText("chassis", $chassis);
if ($chnum !~ /^\d+$/ || $chnum < 0 || $chnum > 8) {
if ($chnum !~ /^\d+$/ || $chnum < 1 || $chnum > 13) {
$response = GeniResponse->Create(GENIRESPONSE_BADARGS, undef,
"Bad chassis number");
goto bad;
......
......@@ -265,15 +265,7 @@ sub PostImageInfo($)
if (!defined($perms_result)) {
return -1;
}
#
# Grab the current type list.
#
my $types_result =
emdb::DBQueryWarn("select distinct type from osidtoimageid ".
"where imageid='$imageid'");
if (!defined($types_result)) {
return -1;
}
# Does not return if error.
my $credential = GetServerCredential();
......@@ -284,7 +276,8 @@ sub PostImageInfo($)
if (!$image->isdataset()) {
$arch = "x86_64";
$virtualization = "raw-pc";
while (my ($type) = $types_result->fetchrow_array()) {
foreach my $nodetype ($image->TypeList()) {
my $type = $nodetype->type();
push(@types, $type);
if ($type eq "m400") {
$arch = "aarch64";
......
#!/bin/sh
# PROVIDE: reportboot_daemon
# REQUIRE: DAEMON ntpd
# BEFORE: testbed
# KEYWORD: shutdown
. /etc/rc.subr
bindir=@prefix@/sbin
if [ ! -x $bindir/reportboot_daemon ]; then
echo "*** reportboot.sh: $bindir/reportboot_daemon not installed"
exit 1
fi
if [ ! -x $bindir/reportboot ]; then
echo "*** reportboot.sh: $bindir/reportboot not installed"
exit 1
fi
case "$1" in
start|faststart|quietstart|onestart|forcestart)
;;
restart|fastrestart|quietrestart|onerestart|forcerestart)
if [ -f /var/run/reportboot_daemon.pid ]; then
kill `cat /var/run/reportboot_daemon.pid` >/dev/null 2>&1
rm -f /var/run/reportboot_daemon.pid
fi
;;
stop|faststop|quietstop|onestop|forcestop)
echo -n ' reportboot_daemon'
if [ -f /var/run/reportboot_daemon.pid ]; then
kill `cat /var/run/reportboot_daemon.pid` >/dev/null 2>&1
rm -f /var/run/reportboot_daemon.pid
fi
exit 0
;;
*)
echo "Usage: $0 {start|stop|restart}" >&2
exit 1
;;
esac
echo -n " reportboot_daemon"
rm -f /var/run/reportboot_daemon.pid
if [ -x @prefix@/sbin/daemon_wrapper ]; then
@prefix@/sbin/daemon_wrapper -i 30 -l @prefix@/log/reportboot_daemon.log \
-p /var/run/reportboot_daemon.pid @prefix@/sbin/reportboot_daemon -f
else
@prefix@/sbin/reportboot_daemon
fi
exit $?
......@@ -40,7 +40,8 @@ include $(OBJDIR)/Makeconf
RC_SCRIPTS = 2.mysql-server.sh 3.mfrisbeed.sh 3.testbed.sh \
2.dhcpd.sh 1.mysql-client.sh 2.tbdbcheck.sh
SUBBOSS_SCRIPTS = 2.dhcpd.sh 3.mfrisbeed-subboss.sh arplock.sh
SUBBOSS_SCRIPTS = 2.dhcpd.sh 3.mfrisbeed-subboss.sh arplock.sh \
3.reportboot-subboss.sh
OPS_SCRIPTS = 3.and.sh 1.mysql-client.sh 1.mysql-server.sh arplock-opsfs.sh
ifeq ($(TBMAINSITE),1)
OPS_SCRIPTS += cluster-status.sh
......
......@@ -71,6 +71,7 @@ CREATE TABLE `apt_aggregates` (
`updated` datetime NOT NULL default '0000-00-00 00:00:00',
`weburl` tinytext,
`has_datasets` tinyint(1) NOT NULL default '0',
`reservations` tinyint(1) NOT NULL default '0',
`portals` set('emulab','aptlab','cloudlab','phantomnet') default NULL,
`jsondata` text,
PRIMARY KEY (`urn`)
......
use strict;
use libdb;
sub DoUpdate($$$)
{
my ($dbhandle, $dbname, $version) = @_;
if (!DBSlotExists("apt_aggregates", "reservations")) {
DBQueryFatal("alter table apt_aggregates add " .
"`reservations` tinyint(1) NOT NULL default '0' ".
" after has_datasets");
}
return 0;
}
# Local Variables:
# mode:perl
# End:
......@@ -45,24 +45,24 @@ use Getopt::Std;
# The following commands are for persistent blockstores.
# For these, a blockstore name, "bsname", had better be unique.
#
# bscontrol [ -S server [ -P pool ] ] [-l leaseidx] [-f fstype] -s size -t type create bsname
# bscontrol [ -S server [ -P pool ] ] [-f fstype] -l leaseidx -s size -t type create bsname
# Create a blockstore of the given size with the given name.
# If the server is not specified, we pick the "best" server,
# based on availability of space.
#
# bscontrol snapshot [ -S server -P pool ] bsname [ tstamp ]
# bscontrol snapshot [ -S server [ -P pool ] ] bsname [ tstamp ]
# Create a snapshot of the named blockstore with the indicated
# timestamp. If timestamp is not provided, it will use the
# current time. bsname needs to be unique across all servers
# or the server and pool need to be explicitly specified.
#
# bscontrol desnapshot [ -S server -P pool ] bsname [ tstamp ]
# bscontrol desnapshot [ -S server [ -P pool ] ] bsname [ tstamp ]
# Delete the snapshot of the named blockstore with the indicated
# timestamp. If timestamp is not provided, delete all snapshots
# associated with the blockstore. bsname needs to be unique across
# all servers or the server and pool need to be explicitly specified.
#
# bscontrol destroy [ -S server -P pool ] bsname
# bscontrol destroy [ -S server [ -P pool ] ] bsname
# Destroy the named blockstore freeing up the space. Also destroys
# any associated snapshots. bsname needs to be unique across all
# servers or the server and pool need to be explicitly specified.
......@@ -73,13 +73,18 @@ use Getopt::Std;
#
sub usage()
{
print STDERR "Usage: bscontrol command args\n";
print STDERR "Usage: bscontrol [-hd] command args\n";
print STDERR " -h This message\n";
print STDERR " -d Print additional debug info\n";
print STDERR "commands:\n";
print STDERR " list List all blockstore servers\n";
print STDERR " avail For each server, show available storage\n";
print STDERR " info For each server, show all extant volumes\n";
print STDERR "\nAdditional persistent blockstore commands.\n";
print STDERR "bscontrol [-S server [-P pool]] [-f fstype] -l leaseidx -s size -t type create bsname\n";
print STDERR "bscontrol [-S server -P pool] destroy bsname\n";
print STDERR "bscontrol [-S server [-P pool]] snapshot bsname [tstamp]\n";
print STDERR "bscontrol [-S server [-P pool]] desnapshot bsname [tstamp]\n";
exit(-1);
}
my $optlist = "hds:t:l:S:P:Ff:I";
......@@ -560,6 +565,19 @@ sub getvolumes($$)
}
}
if ($debug && keys(%volumes) > 0) {
print STDERR "Found volumes:\n";
foreach my $v (keys(%volumes)) {
my $attrs = $volumes{$v};
print STDERR " $v: ";
foreach my $k (keys(%$attrs)) {
my $v = $attrs->{$k};
print STDERR "$k=$v ";
}
print STDERR "\n";
}
}
return \%volumes;
}
......@@ -963,7 +981,9 @@ sub bs_destroy($$$@)
}
#
# Delete the blockstore object
# Verify that the blockstore object exists and is of the right type.
# We will delete the blockstore object *after* we destroy the server-side
# object. See XXX below for rationale.
#
my $bstore = Blockstore->Lookup($srv, $name);
if (!$bstore && !$ignoredb) {
......@@ -972,9 +992,6 @@ sub bs_destroy($$$@)
if ($bstore && $bstore->role() ne "partition") {
fatal("destroy: wrong type of blockstore '$srv/$name'");
}
if ($bstore && $bstore->Delete()) {
fatal("destroy: could not delete blockstore '$srv/$name' from DB");
}
#
# Call out to the server to delete the storage.
......@@ -1003,15 +1020,41 @@ sub bs_destroy($$$@)
goto fail;
}
#
# After everything else works, delete the actual blockstore object.
#
# XXX There is a nasty circular dependency here where if we were to
# destroy the blockstore DB state first and then the object destruction
# fails, we leave behind a dangling object and potentially Lease DB
# state. But if we destroy the object first and the DB state removal
# fails, we are left with a blockstore with no server object and thus
# we cannot look it up in the future to retry the destruction.
#
# We choose to go with the latter and just create a tiny server-side
# stub object if the DB state removal fails.
#
if ($bstore && $bstore->Delete()) {
print STDERR "*** destroy: ".
"could not destroy Blockstore DB state, ".
"recreating a stub server-side object.\n";
if (bsserver_cmd($srv, "$PROXYCMD create $pool $name 1", \$outref)) {
print STDERR "*** destroy: ".
"re-creation of server-side object failed, ".
"before you can destroy this blockstore ".
"you must manually re-create the object with:\n";
print STDERR " $PROXYCMD create $pool $name 1\n";
goto fail;
}
fatal("destroy: could not delete blockstore '$srv/$name' from DB");
}
return 0;
fail:
foreach my $str (@$outref) {
print STDERR " $str\n";
}
print STDERR "*** blockstore has been removed from DB, ".
"to remove residual state do:\n".
" $0 -I -S srv -P $pool destroy $name\n";
exit(-1);
}
......
......@@ -313,7 +313,8 @@ Node instproc updatedb {DB} {
if { [regexp {:} $parent_osid] } {
set pos [lindex [split $parent_osid {:}] 0]
}
if {[lsearch -exact $subosids($os) $pos] == -1} {
if {![info exists subosids($os)] ||
[lsearch -exact $subosids($os) $pos] == -1} {
perror "subOSID $osid does not run on parent OSID $parent_osid!"
return
}
......
......@@ -31,13 +31,14 @@ use Date::Parse;
#
sub usage()
{
print STDERR "Usage: prereserve [-t typelist] [-p priority] ".
print STDERR "Usage: prereserve [-f] [-t typelist] [-p priority] ".
"[-s start] [-e end [-r]] [-n resname] pid [count | node_id ...\n";
print STDERR " prereserve -c [-r] -n resname pid\n";
print STDERR " prereserve -i -n resname pid\n";
print STDERR " prereserve -a -n resname pid\n";
print STDERR " prereserve -l\n";
print STDERR " -h This message\n";
print STDERR " -f Force pre-reservation, even if admission control is violated\n";
print STDERR " -t Comma separated list of node types\n";
print STDERR " -p Priority. Defaults to zero (least priority)\n";
print STDERR " -n Reservation name; defaults to 'default'\n";
......@@ -51,7 +52,7 @@ sub usage()
print STDERR " -a Activate a pending reservation (internal option)\n";
exit(-1);
}
my $optlist = "hdct:n:ilre:s:map:";
my $optlist = "hdct:n:ilre:s:map:f";
my $priority = 0;
my $debug = 0;
my $info = 0;
......@@ -60,6 +61,7 @@ my $clear = 0;
my $revoke = 0;
my $sendmail = 0;
my $activate = 0;
my $force = 0;
my @nodelist = ();
my $resname;
my $starttime;
......@@ -90,6 +92,7 @@ use libtestbed;
use Experiment;
use Project;
use User;
use Reservation;
#
# Turn off line buffering on output
......@@ -142,6 +145,9 @@ if (defined($options{i})) {
if (defined($options{l})) {
$list = 1;
}
if (defined($options{f})) {
$force = 1;
}
if (defined($options{"e"})) {
$endtime = $options{"e"};
if (!defined(str2time($endtime))) {
......@@ -445,17 +451,69 @@ if ($UID == 0) {
my $uid = $this_user->uid();
my $uid_idx = $this_user->uid_idx();
my %nodetypes = ();
# Sanity check the type list.
if (defined($typelist)) {
my @types = split(",", $typelist);
if( @types > 1 && !$force ) {
fatal( "Sorry, can't handle admission control check with multiple " .
"node types.\nEither make multiple pre-reservations with a " .
"dedicated node count per\nnode type, or retry with -f if " .
"you want a single count covering multiple\ntypes, bypassing " .
"admission control." );
}
$nodetypes{ $types[ 0 ] } = $count;
foreach my $typename (@types) {
my $type = NodeType->Lookup($typename);
if (!defined($type)) {
fatal("No such node type $typename");
}
}
} else {
foreach my $nodeid (@nodelist) {
my $node = Node->Lookup( $nodeid );
if( exists( $nodetypes{ $node->type() } ) ) {
$nodetypes{ $node->type() }++;
} else {
$nodetypes{ $node->type() } = 1;
}
}
}
# Run admission control now -- unfortunately there's a nasty race condition
# here. Unfortunately it's messy to make the admission control check and
# the reservation table updates atomic, because of MySQL's stupid locking
# semantics (both components want to independently lock different tables
# and MySQL forbids acquiring more locks if any are held, which precludes
# nesting either section inside the other).
#
# Let's just ignore all that for now, because the intention is that
# future reservations will eventually be used everywhere and
# prereservations will be deprecated.
if( !$force ) {
my $start = defined( $starttime ) ? str2time( $starttime ) : 0;
my $end = defined( $endtime ) ? str2time( $endtime ) : 0x7FFFFFFF;
foreach my $type ( keys( %nodetypes ) ) {
my $reservations = Reservation->LookupAll( $type );
my $res = Reservation->Create( $pid, undef, $start, $end, $type,
$nodetypes{ $type } );
push( @$reservations, $res );
my $error;
if( !Reservation->IsFeasible( $reservations, \$error ) ) {
print STDERR "prereserve: $error\n";
exit( 1 );
}
}
}
# Ideally, we would now call Reservation->BeginTransaction, but that won't
# work because we will later want to acquire table locks, so don't bother.
#
# Lets say that a current request is an error. delete and recreate.
#
......
......@@ -42,7 +42,7 @@ $(function ()
window.onbeforeunload = null;
$('#waitwait-modal').modal({ backdrop: 'static', keyboard: false, show: false });
$('#saveButton').on('click', save);
sup.DownloadOnClick($('#saveButton'), getSaveText, 'saved.py', saveComplete);
$('#loadButton').on('click', load);
$('#runButton').on('click', clickRun);
$('#settingsButton').on('click', toggleSettings);
......@@ -91,23 +91,23 @@ $(function ()
window.onbeforeunload = beforeUnload;
}
function save()
function getSaveText()
{
if (! isWaiting)
{
var scriptString = editor.getValue();
var file = new Blob([scriptString],
{ type: 'application/octet-stream' });
var a = document.createElement('a');
a.href = window.URL.createObjectURL(file);
a.download = 'saved.py';
document.body.appendChild(a);
a.click();
$('a').last().remove();
window.onbeforeunload = null;
return editor.getValue();
}
else
{
return null;
}
}
function saveComplete()
{
window.onbeforeunload = null;
}
function load()
{
if (! isWaiting)
......
......@@ -250,13 +250,17 @@ $(function ()
type = "rspec";
}
if (profile_uuid) {
$('#rspec_modal_download_button')
sup.DownloadOnClick($('#rspec_modal_download_button'),
function () { return source; },
'profile.xml');
/* $('#rspec_modal_download_button')
.attr("href",
"show-profile.php?uuid=" + profile_uuid +
"&" + type + "=true");
"&" + type + "=true");*/
}
else {
$('#rspec_modal_download_button').addClass("hidden");
sup.ClearDownloadOnClick($('#rspec_modal_download_button'));
// $('#rspec_modal_download_button').addClass("hidden");
}
$('#rspec_modal_upload_span').removeClass("hidden");
$('#rspec_modal_editbuttons').removeClass("hidden");
......@@ -277,12 +281,16 @@ $(function ()
var source = $.trim($('#profile_rspec_textarea').val());
if (profile_uuid) {
$('#rspec_modal_download_button')
sup.DownloadOnClick($('#rspec_modal_download_button'),
function () { return source; },
'profile.xml');
/* $('#rspec_modal_download_button')
.attr("href",
"show-profile.php?uuid=" + profile_uuid +
"&rspec=true");
"&rspec=true");*/
}
else {
sup.ClearDownloadOnClick($('#rspec_modal_download_button'));
$('#rspec_modal_download_button').addClass("hidden");
}
$('#rspec_modal_upload_span').addClass("hidden");
......@@ -1147,6 +1155,7 @@ $(function ()
"</code></pre>");
return;
}
sup.ClearDownloadOnClick($('#rspec_modal_download_button'));
$('#rspec_modal_download_button').addClass("hidden");
$('#rspec_modal_editbuttons').removeClass("hidden");
$('#rspec_modal_viewbuttons').addClass("hidden");
......
......@@ -36,6 +36,40 @@ function CallServerMethod(url, route, method, args, callback)
return APT_OPTIONS.CallServerMethod(url, route, method, args, callback);
}
// button is a jQuery object containing the button(s) to add event to
// getText is a function to fetch the text to be saved. Invoked per click with no arguments and expects a string result. If getText returns null or undefined, no save will happen and no callback will be called.
// filename is the default filename used
// callback is invoked with button, text, and filename as arguments after download.
//
// This function will unset all other onclick events.
function DownloadOnClick(button, getText, filename, callback)
{
button.off('click');
button.on('click', function () {
var text = getText();
if (text !== undefined && text !== null)
{
var file = new Blob([text],
{ type: 'application/octet-stream' });
var a = document.createElement('a');
a.href = window.URL.createObjectURL(file);
a.download = filename;
document.body.appendChild(a);
a.click();
$('a').last().remove();
if (callback !== undefined && callback !== null)
{
callback(button, text, filename);
}
}
});
}
function ClearDownloadOnClick(button)
{
button.off('click');
}
var jacksInstance;
var jacksInput;
var jacksOutput;
......@@ -269,6 +303,8 @@ return {
ShowWaitWait: ShowWaitWait,
HideWaitWait: HideWaitWait,
CallServerMethod: CallServerMethod,
DownloadOnClick: DownloadOnClick,
ClearDownloadOnClick: ClearDownloadOnClick,
maketopmap: maketopmap,
SpitOops: SpitOops,
StartGeniLogin: StartGeniLogin,
......
......@@ -115,8 +115,11 @@ $(function ()
var href = "show-profile.php?uuid=" + profile_uuid;
source = $.trim($('#profile_script_textarea').val());
$('#rspec_modal_download_button')
.attr("href", href + "&source=true");
sup.DownloadOnClick($('#rspec_modal_download_button'),
function () { return source; },
'profile.py');
/* $('#rspec_modal_download_button')
.attr("href", href + "&source=true");*/
if (! source || ! source.length) {
isScript = false;
}
......@@ -124,8 +127,11 @@ $(function ()
$(this).attr("id") != "show_source_modal_button") {
source = $.trim($('#profile_rspec_textarea').val());
$('#rspec_modal_download_button')
.attr("href", href + "&rspec=true");
sup.DownloadOnClick($('#rspec_modal_download_button'),
function () { return source; },
'profile.xml');
// $('#rspec_modal_download_button')
// .attr("href", href + "&rspec=true");
}
if ($(this).attr("id") == "show_source_modal_button" && isScript) {
openEditor();
......
......@@ -536,7 +536,7 @@ if (! $instance) {
if (!$geniflags) {
WRITESUBMENUBUTTON("Duplicate Experiment",
"beginexp.php?copyid=$expindex");
if (ISADMIN() || STUDLY()) {
if (1) {
$uuid = $experiment->uuid();
WRITESUBMENUBUTTON("Create Profile from Experiment",
"portal/manage_profile.php?fromexp=$uuid");
......
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