Commit 925d03c8 authored by Leigh Stoller's avatar Leigh Stoller

More tweaks to image versioning. Note that I moved the snapshot call from

php to the backend newimageid script so that the web interface does not
have to worry about provenance issues. Cleaner too. Also some cleanups to
log image spew.
parent 1ec31b36
......@@ -34,15 +34,16 @@ use Cwd qw(realpath);
#
sub usage()
{
print("Usage: newimageid [-v] [-a] [-s] <xmlfile>\n");
print("Usage: newimageid [-v] [-a] [-s] [-t target] <xmlfile>\n");
exit(-1);
}
my $optlist = "dvfas";
my $optlist = "dvfast:";
my $debug = 0;
my $force = 0;
my $verify = 0; # Check data and return status only.
my $allpc = 0; # insert mappings for all pc types.
my $skipadmin = 0; # Skip SLOT_ADMINONLY checks.
my $target;
#
# Configure variables
......@@ -52,6 +53,8 @@ my $TBOPS = "@TBOPSEMAIL@";
my $TBAUDIT = "@TBAUDITEMAIL@";
my $TBGROUP_DIR = "@GROUPSROOT_DIR@";
my $TBPROJ_DIR = "@PROJROOT_DIR@";
my $CREATEIMAGE = "$TB/bin/create_image";
my $CLONEIMAGE = "$TB/sbin/clone_image";
#
# Untaint the path
......@@ -107,6 +110,20 @@ if (defined($options{"s"})) {
if (defined($options{"a"})) {
$allpc = 1;
}
if (defined($options{"t"})) {
$target = $options{"t"};
# Might be an EC2 target. Also need to untaint for below.
if ($target =~ /^([-\w\@\.\+]+@[-\w\@\.\+]+)$/) {
$target = $1;
}
else {
my $node = Node->Lookup($target);
if (!defined($node)) {
fatal("No such node!");
}
$target = $node->node_id();
}
}
if (@ARGV != 1) {
usage();
}
......@@ -728,6 +745,7 @@ fatal("Could not create new Image!")
if (!defined($new_image));
my $imageid = $new_image->imageid();
my $imagepid = $new_image->pid();
#
# Insert a submap entry.
......@@ -748,6 +766,27 @@ if (defined($parentos)) {
}
}
#
# If a target was specified, fire off image creation. It will return
# quickly enough (going into the background) that we can wait here for
# it.
#
if (defined($target)) {
#
# Use clone_image for a node, create_image for an EC2 target. We use
# clone cause it will do the provenance, so we do not have to duplicate
# that stuff here. Then it just calls create_image.
#
if ($target =~ /^.*@.*$/) {
system("$CREATEIMAGE -p $imagepid $imageid '$target'"); }
else {
# Must be an imagename, not and imageid.
system("$CLONEIMAGE $imagename '$target'");
}
if ($?) {
fatal("Could not image capture from $target");
}
}
# The web interface requires this line to be printed.
print "IMAGE $imagename/$imageid has been created\n";
......
......@@ -47,6 +47,7 @@ $TRACSUPPORT = @TRACSUPPORT@;
$BUGDBSUPPORT = @BUGDBSUPPORT@;
$CVSSUPPORT = @CVSSUPPORT@;
$MAILMANSUPPORT = @MAILMANSUPPORT@;
$DOPROVENANCE = @IMAGEPROVENANCE@;
$CHATSUPPORT = @CHATSUPPORT@;
$PROTOGENI = @PROTOGENI_SUPPORT@;
$GENIRACK = @PROTOGENI_GENIRACK@;
......
......@@ -108,6 +108,27 @@ class Image
return Image::Lookup($row["imageid"]);
}
# Look for most recent unreleased version.
function LookupUnreleased() {
global $DOPROVENANCE;
if (!$DOPROVENANCE) {
return $this;
}
$imageid = $this->imageid();
$query_result =
DBQueryFatal("select version from image_versions ".
"where imageid='$imageid' and released=0 and ".
" deleted is null ".
"order by version desc limit 1");
if (mysql_num_rows($query_result) == 0) {
return null;
}
$row = mysql_fetch_array($query_result);
return Image::Lookup($imageid, $row["version"]);
}
function LookupByUUID($uuid) {
$safe_uuid = addslashes($uuid);
......@@ -162,7 +183,8 @@ class Image
#
# Class function to create a new image descriptor.
#
function NewImageId($ez, $imagename, $args, &$errors) {
function NewImageId($ez, $imagename, $args, $creator, $group,
$target, &$errors) {
global $suexec_output, $suexec_output_array;
#
......@@ -192,9 +214,12 @@ class Image
fwrite($fp, "</image>\n");
fclose($fp);
chmod($xmlname, 0666);
$opt = ($target ? "-t " . escapeshellarg($target) : "");
$script = "webnewimageid" . ($ez ? "_ez" : "");
$retval = SUEXEC("nobody", "nobody", "$script $xmlname",
$retval = SUEXEC($creator->uid(),
$group->pid() . "," . $group->gid(),
"$script $opt $xmlname",
SUEXEC_ACTION_IGNORE);
if ($retval) {
......@@ -384,6 +409,9 @@ class Image
function imagefile_url() { return $this->field("imagefile_url"); }
function logfileid() { return $this->field("logfileid"); }
function noexport() { return $this->field("noexport"); }
function ready() { return $this->field("ready"); }
function isdelta() { return $this->field("isdelta"); }
function released() { return $this->field("released"); }
# Return the DB data.
function DBData() { return $this->image; }
......@@ -529,7 +557,7 @@ class Image
}
function Show($showperms = 0) {
global $TBBASE;
global $TBBASE, $DOPROVENANCE;
$imageid = $this->imageid();
$imagename = $this->imagename();
......@@ -777,13 +805,37 @@ class Image
if ($this->parent_imageid() != $this->imageid() &&
$this->version() > 0) {
$p_version = $this->version() - 1;
$p_url = CreateURL("showimageid", $this,
"version", $this->version() - 1);
"version", $p_version);
echo "<tr>
<td>Previous Vers: </td>
<td class=left><a href='$p_url'>$imagename</a></td>
<td class=left>
<a href='$p_url'>$imagename ($p_version)</a></td>
</tr>\n";
}
}
# Look for an unreleased version of this image.
$unreleased = $this->LookupUnreleased();
if ($unreleased && $unreleased->version() != $this->version()) {
$u_version = $unreleased->version();
$u_url = CreateURL("showimageid", $this, "version", $u_version);
echo "<tr>
<td>Unreleased Vers: </td>
<td class=left>
<a href='$u_url'>$imagename ($u_version)</a></td>
</tr>\n";
}
if ($DOPROVENANCE) {
$released = $this->released();
$ready = $this->ready();
$isdelta = $this->isdelta();
echo "<tr>
<td>Rdy/Rel/Delta: </td>
<td class=left>$ready/$released/$isdelta</td>
</tr>\n";
}
echo "<tr>
......@@ -968,4 +1020,22 @@ class Image
}
return 0;
}
#
# Page header; spit back some html for the typical page header.
#
function PageHeader() {
$pid = $this->pid();
$imagename = $this->imagename();
$imageid = $this->imageid();
$version = $this->version();
$html = "<font size=+1>Image <b>".
"<a href='showproject.php3?pid=$pid'>$pid</a>/".
"<a href='showimageid.php3?imageid=$imageid&version=$version'>
$imagename</a>".
"</b></font>\n";
return $html;
}
}
......@@ -161,6 +161,14 @@ echo "This will take as little as 10 minutes or as much as an hour;
the node at all!<br>\n";
flush();
#
# When doing image provenance the most recent unreleased version is
# is what we are really working on.
#
if ($DOPROVENANCE) {
$image = $image->LookupUnreleased();
}
$logfile = $image->GetLogfile();
if ($logfile) {
STARTLOG($logfile);
......
......@@ -788,9 +788,15 @@ if (mysql_num_rows($query_result)) {
}
}
$pid = $image->pid();
$gid_idx = $image->gid_idx();
$group = Group::Lookup($gid_idx);
$project = $image->Project();
# Send to the backend for more checking, and eventually, to update the DB.
$imagename = $args["imagename"];
if (! ($image = Image::NewImageId(0, $imagename, $args, $errors))) {
if (! ($image = Image::NewImageId(0, $imagename, $args, $this_user, $group,
$node_id, $errors))) {
# Always respit the form so that the form fields are not lost.
# I just hate it when that happens so lets not be guilty of it ourselves.
SPITFORM($formfields, $errors);
......@@ -798,12 +804,6 @@ if (! ($image = Image::NewImageId(0, $imagename, $args, $errors))) {
return;
}
$pid = $image->pid();
$gid_idx = $image->gid_idx();
$group = Group::Lookup($gid_idx);
$project = $image->Project();
SUBPAGESTART();
SUBMENUSTART("More Options");
if (! isset($node_id)) {
......
......@@ -42,9 +42,6 @@ $uid = $this_user->uid();
$dbid = $this_user->dbid();
$isadmin = ISADMIN();
# This will not return if its a sajax request.
include("showlogfile_sup.php3");
#
# Verify page arguments.
#
......@@ -1400,8 +1397,19 @@ if (!isset($confirmed) && 0 != strcmp($confirmationWarning,"")) {
return;
}
# The target (a node or an ec2) to take a snapshot from.
if ($ec2) {
$target = $formfields["ec2_info"];
}
elseif (isset($node)) {
$target = $node_id;
}
else {
$target = null;
}
$imagename = $args["imagename"];
if (! ($image = Image::NewImageId(1, $imagename, $args, $errors))) {
if (! ($image = Image::NewImageId(1, $imagename, $args, $this_user, $group,
$target, $errors))) {
# Always respit the form so that the form fields are not lost.
# I just hate it when that happens so lets not be guilty of it ourselves.
SPITFORM($formfields, $errors);
......@@ -1413,11 +1421,14 @@ $imageid = $image->imageid();
SUBPAGESTART();
SUBMENUSTART("More Options");
if (! isset($node)) {
$fooid = rawurlencode($imageid);
WRITESUBMENUBUTTON("Edit this Image Descriptor",
"editimageid.php3?imageid=$fooid");
"editimageid.php3?imageid=$imageid");
WRITESUBMENUBUTTON("Delete this Image Descriptor",
"deleteimageid.php3?imageid=$fooid");
"deleteimageid.php3?imageid=$imageid");
}
if ($image->GetLogfile()) {
WRITESUBMENUBUTTON("View Log File",
"showimageid.php3?imageid=$imageid&showlog=1");
}
if ($isadmin) {
WRITESUBMENUBUTTON("Create a new Image Descriptor",
......@@ -1439,19 +1450,8 @@ SUBPAGEEND();
if (isset($node) || $ec2) {
#
# Create the image.
#
# XXX There is no locking of the descriptor or the node. Not really a
# problem for the descriptor; the script is done with it by the time
# it returns. However, if the node is freed up, things are going to go
# awry.
# The backend is creating the image. Patience please.
#
# Grab the unix GID for running script.
#
$unix_gid = $group->unix_gid();
$unix_pid = $project->unix_gid();
$safe_name = escapeshellarg($imagename);
echo "<br>";
if ($ec2) {
......@@ -1461,24 +1461,16 @@ if (isset($node) || $ec2) {
$target = $node_id;
}
echo "Taking a snapshot of $target for image ...";
echo "<br><br>\n";
$safe_target = escapeshellarg($target);
flush();
SUEXEC($uid, "$unix_pid,$unix_gid",
"webcreate_image -p $pid $safe_name $safe_target",
SUEXEC_ACTION_DUPDIE);
echo "<br>\n";
echo "This will take as little as 10 minutes or as much as an hour;
you will receive email
notification when the image is complete. In the meantime,
<b>PLEASE DO NOT</b> delete the imageid or mess with
the node at all!<br>\n";
$logfile = $image->GetLogfile();
if ($logfile) {
STARTLOG($logfile);
the node at all! ";
if ($image->GetLogfile()) {
echo "You can watch the
<a href='showimageid.php3?imageid=$imageid&showlog=1'>
log file in realtime.</a>";
}
}
......
......@@ -32,10 +32,14 @@ $uid = $this_user->uid();
$isadmin = ISADMIN();
$showperms = 1;
# This will not return if its a sajax request.
include("showlogfile_sup.php3");
#
# Verify page arguments.
#
$reqargs = RequiredPageArguments("image", PAGEARG_IMAGE);
$optargs = OptionalPageArguments("showlog", PAGEARG_BOOLEAN);
#
# Standard Testbed Header
......@@ -44,6 +48,7 @@ PAGEHEADER("Image Descriptor");
# Need these below.
$imageid = $image->imageid();
$version = $image->version();
#
# Verify permission.
......@@ -52,19 +57,33 @@ if (!$image->AccessCheck($this_user, $TB_IMAGEID_READINFO)) {
USERERROR("You do not have permission to access ImageID $imageid.", 1);
}
if (isset($showlog)) {
$logfile = $image->GetLogfile();
if ($logfile) {
echo $image->PageHeader();
STARTLOG($logfile);
PAGEFOOTER();
return;
}
}
SUBPAGESTART();
SUBMENUSTART("More Options");
$fooid = rawurlencode($imageid);
WRITESUBMENUBUTTON("Edit this Image Descriptor",
"editimageid.php3?imageid=$fooid");
"editimageid.php3?imageid=$imageid");
if ($image->GetLogfile()) {
WRITESUBMENUBUTTON("View Log File",
"showimageid.php3?imageid=$imageid&version=$version&showlog=1");
}
if ($image->AccessCheck($this_user, $TB_IMAGEID_MODIFYINFO )) {
WRITESUBMENUBUTTON("Snapshot Node Disk into Image",
"loadimage.php3?imageid=$fooid");
"loadimage.php3?imageid=$imageid");
}
WRITESUBMENUBUTTON("Clone this Image Descriptor",
"newimageid_ez.php3?baseimage=$fooid");
"newimageid_ez.php3?baseimage=$imageid");
WRITESUBMENUBUTTON("Delete this Image Descriptor",
"deleteimageid.php3?imageid=$fooid");
"deleteimageid.php3?imageid=$imageid");
WRITESUBMENUBUTTON("Image Descriptor list",
"showimageid_list.php3");
if ($isadmin) {
......
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