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); ...@@ -34,15 +34,16 @@ use Cwd qw(realpath);
# #
sub usage() sub usage()
{ {
print("Usage: newimageid [-v] [-a] [-s] <xmlfile>\n"); print("Usage: newimageid [-v] [-a] [-s] [-t target] <xmlfile>\n");
exit(-1); exit(-1);
} }
my $optlist = "dvfas"; my $optlist = "dvfast:";
my $debug = 0; my $debug = 0;
my $force = 0; my $force = 0;
my $verify = 0; # Check data and return status only. my $verify = 0; # Check data and return status only.
my $allpc = 0; # insert mappings for all pc types. my $allpc = 0; # insert mappings for all pc types.
my $skipadmin = 0; # Skip SLOT_ADMINONLY checks. my $skipadmin = 0; # Skip SLOT_ADMINONLY checks.
my $target;
# #
# Configure variables # Configure variables
...@@ -52,6 +53,8 @@ my $TBOPS = "@TBOPSEMAIL@"; ...@@ -52,6 +53,8 @@ my $TBOPS = "@TBOPSEMAIL@";
my $TBAUDIT = "@TBAUDITEMAIL@"; my $TBAUDIT = "@TBAUDITEMAIL@";
my $TBGROUP_DIR = "@GROUPSROOT_DIR@"; my $TBGROUP_DIR = "@GROUPSROOT_DIR@";
my $TBPROJ_DIR = "@PROJROOT_DIR@"; my $TBPROJ_DIR = "@PROJROOT_DIR@";
my $CREATEIMAGE = "$TB/bin/create_image";
my $CLONEIMAGE = "$TB/sbin/clone_image";
# #
# Untaint the path # Untaint the path
...@@ -107,6 +110,20 @@ if (defined($options{"s"})) { ...@@ -107,6 +110,20 @@ if (defined($options{"s"})) {
if (defined($options{"a"})) { if (defined($options{"a"})) {
$allpc = 1; $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) { if (@ARGV != 1) {
usage(); usage();
} }
...@@ -727,7 +744,8 @@ UserError($usrerr) ...@@ -727,7 +744,8 @@ UserError($usrerr)
fatal("Could not create new Image!") fatal("Could not create new Image!")
if (!defined($new_image)); if (!defined($new_image));
my $imageid = $new_image->imageid(); my $imageid = $new_image->imageid();
my $imagepid = $new_image->pid();
# #
# Insert a submap entry. # Insert a submap entry.
...@@ -748,6 +766,27 @@ if (defined($parentos)) { ...@@ -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. # The web interface requires this line to be printed.
print "IMAGE $imagename/$imageid has been created\n"; print "IMAGE $imagename/$imageid has been created\n";
......
...@@ -47,6 +47,7 @@ $TRACSUPPORT = @TRACSUPPORT@; ...@@ -47,6 +47,7 @@ $TRACSUPPORT = @TRACSUPPORT@;
$BUGDBSUPPORT = @BUGDBSUPPORT@; $BUGDBSUPPORT = @BUGDBSUPPORT@;
$CVSSUPPORT = @CVSSUPPORT@; $CVSSUPPORT = @CVSSUPPORT@;
$MAILMANSUPPORT = @MAILMANSUPPORT@; $MAILMANSUPPORT = @MAILMANSUPPORT@;
$DOPROVENANCE = @IMAGEPROVENANCE@;
$CHATSUPPORT = @CHATSUPPORT@; $CHATSUPPORT = @CHATSUPPORT@;
$PROTOGENI = @PROTOGENI_SUPPORT@; $PROTOGENI = @PROTOGENI_SUPPORT@;
$GENIRACK = @PROTOGENI_GENIRACK@; $GENIRACK = @PROTOGENI_GENIRACK@;
......
...@@ -108,6 +108,27 @@ class Image ...@@ -108,6 +108,27 @@ class Image
return Image::Lookup($row["imageid"]); 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) { function LookupByUUID($uuid) {
$safe_uuid = addslashes($uuid); $safe_uuid = addslashes($uuid);
...@@ -162,7 +183,8 @@ class Image ...@@ -162,7 +183,8 @@ class Image
# #
# Class function to create a new image descriptor. # 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; global $suexec_output, $suexec_output_array;
# #
...@@ -192,9 +214,12 @@ class Image ...@@ -192,9 +214,12 @@ class Image
fwrite($fp, "</image>\n"); fwrite($fp, "</image>\n");
fclose($fp); fclose($fp);
chmod($xmlname, 0666); chmod($xmlname, 0666);
$opt = ($target ? "-t " . escapeshellarg($target) : "");
$script = "webnewimageid" . ($ez ? "_ez" : ""); $script = "webnewimageid" . ($ez ? "_ez" : "");
$retval = SUEXEC("nobody", "nobody", "$script $xmlname", $retval = SUEXEC($creator->uid(),
$group->pid() . "," . $group->gid(),
"$script $opt $xmlname",
SUEXEC_ACTION_IGNORE); SUEXEC_ACTION_IGNORE);
if ($retval) { if ($retval) {
...@@ -384,6 +409,9 @@ class Image ...@@ -384,6 +409,9 @@ class Image
function imagefile_url() { return $this->field("imagefile_url"); } function imagefile_url() { return $this->field("imagefile_url"); }
function logfileid() { return $this->field("logfileid"); } function logfileid() { return $this->field("logfileid"); }
function noexport() { return $this->field("noexport"); } 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. # Return the DB data.
function DBData() { return $this->image; } function DBData() { return $this->image; }
...@@ -529,7 +557,7 @@ class Image ...@@ -529,7 +557,7 @@ class Image
} }
function Show($showperms = 0) { function Show($showperms = 0) {
global $TBBASE; global $TBBASE, $DOPROVENANCE;
$imageid = $this->imageid(); $imageid = $this->imageid();
$imagename = $this->imagename(); $imagename = $this->imagename();
...@@ -777,14 +805,38 @@ class Image ...@@ -777,14 +805,38 @@ class Image
if ($this->parent_imageid() != $this->imageid() && if ($this->parent_imageid() != $this->imageid() &&
$this->version() > 0) { $this->version() > 0) {
$p_version = $this->version() - 1;
$p_url = CreateURL("showimageid", $this, $p_url = CreateURL("showimageid", $this,
"version", $this->version() - 1); "version", $p_version);
echo "<tr> echo "<tr>
<td>Previous Vers: </td> <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"; </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> echo "<tr>
<td>MBR Version: </td> <td>MBR Version: </td>
...@@ -968,4 +1020,22 @@ class Image ...@@ -968,4 +1020,22 @@ class Image
} }
return 0; 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; ...@@ -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"; the node at all!<br>\n";
flush(); 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(); $logfile = $image->GetLogfile();
if ($logfile) { if ($logfile) {
STARTLOG($logfile); STARTLOG($logfile);
......
...@@ -788,9 +788,15 @@ if (mysql_num_rows($query_result)) { ...@@ -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. # Send to the backend for more checking, and eventually, to update the DB.
$imagename = $args["imagename"]; $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. # 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. # I just hate it when that happens so lets not be guilty of it ourselves.
SPITFORM($formfields, $errors); SPITFORM($formfields, $errors);
...@@ -798,12 +804,6 @@ if (! ($image = Image::NewImageId(0, $imagename, $args, $errors))) { ...@@ -798,12 +804,6 @@ if (! ($image = Image::NewImageId(0, $imagename, $args, $errors))) {
return; return;
} }
$pid = $image->pid();
$gid_idx = $image->gid_idx();
$group = Group::Lookup($gid_idx);
$project = $image->Project();
SUBPAGESTART(); SUBPAGESTART();
SUBMENUSTART("More Options"); SUBMENUSTART("More Options");
if (! isset($node_id)) { if (! isset($node_id)) {
......
...@@ -42,9 +42,6 @@ $uid = $this_user->uid(); ...@@ -42,9 +42,6 @@ $uid = $this_user->uid();
$dbid = $this_user->dbid(); $dbid = $this_user->dbid();
$isadmin = ISADMIN(); $isadmin = ISADMIN();
# This will not return if its a sajax request.
include("showlogfile_sup.php3");
# #
# Verify page arguments. # Verify page arguments.
# #
...@@ -1400,8 +1397,19 @@ if (!isset($confirmed) && 0 != strcmp($confirmationWarning,"")) { ...@@ -1400,8 +1397,19 @@ if (!isset($confirmed) && 0 != strcmp($confirmationWarning,"")) {
return; 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"]; $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. # 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. # I just hate it when that happens so lets not be guilty of it ourselves.
SPITFORM($formfields, $errors); SPITFORM($formfields, $errors);
...@@ -1413,11 +1421,14 @@ $imageid = $image->imageid(); ...@@ -1413,11 +1421,14 @@ $imageid = $image->imageid();
SUBPAGESTART(); SUBPAGESTART();
SUBMENUSTART("More Options"); SUBMENUSTART("More Options");
if (! isset($node)) { if (! isset($node)) {
$fooid = rawurlencode($imageid);
WRITESUBMENUBUTTON("Edit this Image Descriptor", WRITESUBMENUBUTTON("Edit this Image Descriptor",
"editimageid.php3?imageid=$fooid"); "editimageid.php3?imageid=$imageid");
WRITESUBMENUBUTTON("Delete this Image Descriptor", 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) { if ($isadmin) {
WRITESUBMENUBUTTON("Create a new Image Descriptor", WRITESUBMENUBUTTON("Create a new Image Descriptor",
...@@ -1439,19 +1450,8 @@ SUBPAGEEND(); ...@@ -1439,19 +1450,8 @@ SUBPAGEEND();
if (isset($node) || $ec2) { if (isset($node) || $ec2) {
# #
# Create the image. # The backend is creating the image. Patience please.
#
# 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.
# #
# Grab the unix GID for running script.
#
$unix_gid = $group->unix_gid();
$unix_pid = $project->unix_gid();
$safe_name = escapeshellarg($imagename);
echo "<br>"; echo "<br>";
if ($ec2) { if ($ec2) {
...@@ -1461,24 +1461,16 @@ if (isset($node) || $ec2) { ...@@ -1461,24 +1461,16 @@ if (isset($node) || $ec2) {
$target = $node_id; $target = $node_id;
} }
echo "Taking a snapshot of $target for image ..."; echo "Taking a snapshot of $target for image ...";
echo "<br><br>\n"; echo "<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 "This will take as little as 10 minutes or as much as an hour; echo "This will take as little as 10 minutes or as much as an hour;
you will receive email you will receive email
notification when the image is complete. In the meantime, notification when the image is complete. In the meantime,
<b>PLEASE DO NOT</b> delete the imageid or mess with <b>PLEASE DO NOT</b> delete the imageid or mess with
the node at all!<br>\n"; the node at all! ";
if ($image->GetLogfile()) {
$logfile = $image->GetLogfile(); echo "You can watch the
if ($logfile) { <a href='showimageid.php3?imageid=$imageid&showlog=1'>
STARTLOG($logfile); log file in realtime.</a>";
} }
} }
......
...@@ -32,10 +32,14 @@ $uid = $this_user->uid(); ...@@ -32,10 +32,14 @@ $uid = $this_user->uid();
$isadmin = ISADMIN(); $isadmin = ISADMIN();
$showperms = 1; $showperms = 1;
# This will not return if its a sajax request.
include("showlogfile_sup.php3");
# #
# Verify page arguments. # Verify page arguments.
# #
$reqargs = RequiredPageArguments("image", PAGEARG_IMAGE); $reqargs = RequiredPageArguments("image", PAGEARG_IMAGE);
$optargs = OptionalPageArguments("showlog", PAGEARG_BOOLEAN);
# #
# Standard Testbed Header # Standard Testbed Header
...@@ -44,6 +48,7 @@ PAGEHEADER("Image Descriptor"); ...@@ -44,6 +48,7 @@ PAGEHEADER("Image Descriptor");
# Need these below. # Need these below.
$imageid = $image->imageid(); $imageid = $image->imageid();
$version = $image->version();
# #
# Verify permission. # Verify permission.
...@@ -52,19 +57,33 @@ if (!$image->AccessCheck($this_user, $TB_IMAGEID_READINFO)) { ...@@ -52,19 +57,33 @@ if (!$image->AccessCheck($this_user, $TB_IMAGEID_READINFO)) {
USERERROR("You do not have permission to access ImageID $imageid.", 1); 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(); SUBPAGESTART();
SUBMENUSTART("More Options"); SUBMENUSTART("More Options");
$fooid = rawurlencode($imageid);
WRITESUBMENUBUTTON("Edit this Image Descriptor", 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 )) { if ($image->AccessCheck($this_user, $TB_IMAGEID_MODIFYINFO )) {
WRITESUBMENUBUTTON("Snapshot Node Disk into Image", WRITESUBMENUBUTTON("Snapshot Node Disk into Image",
"loadimage.php3?imageid=$fooid"); "loadimage.php3?imageid=$imageid");
} }
WRITESUBMENUBUTTON("Clone this Image Descriptor", WRITESUBMENUBUTTON("Clone this Image Descriptor",
"newimageid_ez.php3?baseimage=$fooid"); "newimageid_ez.php3?baseimage=$imageid");
WRITESUBMENUBUTTON("Delete this Image Descriptor", WRITESUBMENUBUTTON("Delete this Image Descriptor",
"deleteimageid.php3?imageid=$fooid"); "deleteimageid.php3?imageid=$imageid");
WRITESUBMENUBUTTON("Image Descriptor list", WRITESUBMENUBUTTON("Image Descriptor list",
"showimageid_list.php3"); "showimageid_list.php3");
if ($isadmin) { 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