Commit 545e32cf authored by Leigh Stoller's avatar Leigh Stoller

Another checkpoint; frisbee (loading) now supports image versions.

parent 5acdd9ce
......@@ -1017,7 +1017,7 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
MYSQL_ROW row;
char *node, *proxy, *role = NULL;
int i, j, nrows;
char *wantpid = NULL, *wantname = NULL;
char *wantpid = NULL, *wantname = NULL, *wantvers = NULL;
struct config_host_authinfo *get = NULL, *put = NULL;
struct emulab_ha_extra_info *ei = NULL;
int imageidx = 0, ngids, igids[2];
......@@ -1297,6 +1297,11 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
*wantname = '\0';
wantname = mystrdup(wantname+1);
}
wantvers = index(wantname, ':');
if (wantvers) {
*wantvers = '\0';
wantvers = wantvers+1;
}
imageidx = emulab_imageid(wantpid, wantname);
if (imageidx == 0)
goto done;
......@@ -1308,7 +1313,20 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
if (imageid != NULL) {
/* Interested in a specific image */
if (can_access(imageidx, ei, 1)) {
res = mydb_query("SELECT i.pid,i.gid,"
if (wantvers) {
res = mydb_query("SELECT i.pid,i.gid,"
" i.imagename,v.path,i.imageid"
" FROM images as i "
" LEFT JOIN image_versions "
" as v on "
" v.imageid=i.imageid and "
" v.version='%s' "
" WHERE i.pid='%s'"
" AND i.imagename='%s'",
5, wantvers, wantpid, wantname);
}
else {
res = mydb_query("SELECT i.pid,i.gid,"
" i.imagename,v.path,i.imageid"
" FROM images as i "
" LEFT JOIN image_versions "
......@@ -1318,12 +1336,31 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
" WHERE i.pid='%s'"
" AND i.imagename='%s'",
5, wantpid, wantname);
}
} else {
/*
* Pid of expt must be same as pid of image
* and gid the same or image "shared".
*/
res = mydb_query("SELECT i.pid,i.gid,"
if (wantvers) {
res = mydb_query("SELECT i.pid,i.gid,"
" i.imagename,v.path,i.imageid"
" FROM images as i "
" LEFT JOIN image_versions "
" as v on "
" v.imageid=i.imageid and "
" v.version='%s' "
" WHERE i.pid='%s' "
" AND i.imagename='%s'"
" AND i.pid='%s'"
" AND (i.gid='%s' OR"
" (i.gid=i.pid AND "
" v.shared=1))",
5, wantvers, wantpid, wantname,
ei->pid, ei->gid);
}
else {
res = mydb_query("SELECT i.pid,i.gid,"
" i.imagename,v.path,i.imageid"
" FROM images as i "
" LEFT JOIN image_versions "
......@@ -1338,6 +1375,7 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
" v.shared=1))",
5, wantpid, wantname,
ei->pid, ei->gid);
}
}
} else {
/* Find all images that this pid/gid can PUT */
......@@ -1449,7 +1487,20 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
if (imageid != NULL) {
/* Interested in a specific image */
if (can_access(imageidx, ei, 0)) {
res = mydb_query("SELECT i.pid,i.gid,"
if (wantvers) {
res = mydb_query("SELECT i.pid,i.gid,"
"i.imagename,v.path,i.imageid"
" FROM images as i "
" LEFT JOIN image_versions "
" as v on "
" v.imageid=i.imageid and "
" v.version='%s' "
"WHERE i.pid='%s'"
" AND i.imagename='%s'",
5, wantvers, wantpid, wantname);
}
else {
res = mydb_query("SELECT i.pid,i.gid,"
"i.imagename,v.path,i.imageid"
" FROM images as i "
" LEFT JOIN image_versions "
......@@ -1459,8 +1510,28 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
"WHERE i.pid='%s'"
" AND i.imagename='%s'",
5, wantpid, wantname);
}
} else {
res = mydb_query("SELECT i.pid,i.gid,"
if (wantvers) {
res = mydb_query("SELECT i.pid,i.gid,"
"i.imagename,v.path,i.imageid"
" FROM images as i"
" LEFT JOIN image_versions "
" as v on "
" v.imageid=i.imageid and "
" v.version='%s' "
" WHERE i.pid='%s' "
" AND i.imagename='%s' "
" AND (v.global=1"
" OR (i.pid='%s'"
" AND (i.gid='%s'"
" OR v.shared=1)))"
" ORDER BY pid,gid,imagename",
5, wantvers, wantpid, wantname,
ei->pid, ei->gid);
}
else {
res = mydb_query("SELECT i.pid,i.gid,"
"i.imagename,v.path,i.imageid"
" FROM images as i"
" LEFT JOIN image_versions "
......@@ -1476,6 +1547,7 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
" ORDER BY pid,gid,imagename",
5, wantpid, wantname,
ei->pid, ei->gid);
}
}
} else {
/* Find all images that this pid/gid can GET */
......
......@@ -618,7 +618,7 @@ sub NewVersion($$$$$)
or goto bad;
DBQueryWarn("update $imtablename set ".
" uuid=uuid(),ready=0,path='$path', ".
" uuid=uuid(),ready=0,released=1,path='$path', ".
" $part_vers, default_vers='$clone_vers', ".
" version='$clone_vers',".
" parent_imageid='$parent_imageid',".
......@@ -846,7 +846,7 @@ sub Update($$)
}
#
# Delete a descriptor.
# Delete an image,
#
sub Delete($;$)
{
......@@ -916,6 +916,54 @@ sub Delete($;$)
return -1;
}
#
# Delete a version of an image. This is not to be used, except when there
# is an error during clone, and we want to undo the creation of a new version.
#
sub DeleteVersion($)
{
my ($self) = @_;
my $imageid = $self->imageid();
my $version = $self->version();
DBQueryWarn("lock tables images write, image_versions write, ".
" os_info write, os_info_versions write")
or return -1;
#
# We do not allow the deletion if it is not the "head" version of the
# image. Maybe later.
#
my $query_result =
DBQueryWarn("select version from images ".
"where imageid='$imageid' and version='$version'");
goto bad
if (!$query_result);
if (!$query_result->numrows) {
print STDERR "Image::DeleteVersion: not the head version of $self\n";
goto bad;
}
goto bad
if (! (DBQueryWarn("delete from image_versions ".
"where imageid='$imageid' and version='$version'") &&
DBQueryWarn("update images set version=version-1 ".
"where imageid='$imageid'") &&
DBQueryWarn("delete from os_info_versions ".
"where osid='$imageid' and vers='$version'") &&
DBQueryWarn("update os_info set version=version-1 ".
"where osid='$imageid'")));
DBQueryWarn("unlock tables")
or return -1;
return 0;
bad:
DBQueryWarn("unlock tables");
return -1;
}
#
# Load the project object for an image
#
......@@ -1606,6 +1654,17 @@ sub MarkReady($)
return 0;
}
# Released bit.
sub MarkReleased($)
{
my ($self) = @_;
return -1
if (! $self->Update({'released' => 1}));
return 0;
}
#
# Get the logfile.
#
......
......@@ -501,7 +501,7 @@ sub osload ($$) {
'node_id' => $node,
'partition' => $i,
'osid' => $osid,
'osid_version' => $osinfo->vers(),
'osid_vers' => $osinfo->vers(),
'imageid' => $image->imageid(),
'imageid_version' => $image->version(),
'imagepid' => $imagepid,
......@@ -525,7 +525,7 @@ sub osload ($$) {
if (exists($partitions{$i})) {
my $href = $partitions{$i};
my $osid = $href->{'osid'};
my $osvers = $href->{'osid_version'};
my $osvers = $href->{'osid_vers'};
my $imid = $href->{'imageid'};
my $imvers = $href->{'imageid_version'};
my $impid = $href->{'imagepid'};
......
......@@ -5199,11 +5199,12 @@ COMMAND_PROTOTYPE(doloadinfo)
" i.imageid,prepare,i.imagename,p.pid,g.gid,iv.path,"
" ov.version,pa.partition,iv.size,"
" iv.lba_low,iv.lba_high,iv.lba_size,iv.relocatable,"
" UNIX_TIMESTAMP(iv.updated) "
" UNIX_TIMESTAMP(iv.updated),r.imageid_version "
"from current_reloads as r "
"left join images as i on i.imageid=r.image_id "
"left join image_versions as iv on "
" iv.imageid=i.imageid and iv.version=i.version "
" iv.imageid=i.imageid and "
" iv.version=r.imageid_version "
"left join frisbee_blobs as f on f.imageid=i.imageid "
"left join os_info_versions as ov on "
" ov.osid=iv.default_osid and "
......@@ -5214,7 +5215,7 @@ COMMAND_PROTOTYPE(doloadinfo)
" pa.node_id=r.node_id and "
" pa.osid=iv.default_osid and loadpart=0 "
"where r.node_id='%s' order by r.idx",
19, reqp->nodeid);
20, reqp->nodeid);
if (!res) {
error("doloadinfo: %s: DB Error getting loading address!\n",
......@@ -5547,8 +5548,8 @@ COMMAND_PROTOTYPE(doloadinfo)
return 1;
}
bufp += OUTPUT(bufp, ebufp - bufp, " IMAGEID=%s,%s,%s",
row[8], row[9], row[7]);
bufp += OUTPUT(bufp, ebufp - bufp, " IMAGEID=%s,%s,%s:%s",
row[8], row[9], row[7], row[19]);
/*
* All images version 38 and above, or just vnodes
......
......@@ -27,6 +27,7 @@ use Getopt::Std;
use Data::Dumper;
use File::Temp qw(tempfile);
use CGI;
use File::Basename;
#
# Clone an image (descriptor) from a node and then snapshot
......@@ -177,6 +178,8 @@ print "$node_id is running $base_osinfo,$base_image\n"
# a simple snapshot to the image file.
#
if (defined($image)) {
my $needdelete = 0;
#
# Only EZ images via this interface.
#
......@@ -216,15 +219,48 @@ if (defined($image)) {
fatal("Image is locked, please try again later!\n");
}
if ($DOPROVENANCE) {
my $clone_error;
my $clone = $image->NewVersion($this_user,
$base_image, undef, \$clone_error);
if (!defined($clone)) {
$image->Unlock();
fatal("Could not clone image descriptor" .
(defined($clone_error) ? ": $clone_error" : "") . "\n");
#
# Is the ready bit set? If not, it means something went wrong with
# a previous image creation. Lets reset the provenance.
#
if (!$image->ready()) {
my $osinfo = OSinfo->Lookup($image->imageid());
if (!defined($osinfo)) {
$image->Unlock();
fatal("Cannot lookup osinfo for $image");
}
$image->SetProvenance($base_image);
$osinfo->SetProvenance($base_osinfo);
}
else {
my $clone_error;
my $clone = $image->NewVersion($this_user,
$base_image, undef, \$clone_error);
if (!defined($clone)) {
$image->Unlock();
fatal("Could not clone image descriptor" .
(defined($clone_error) ? ": $clone_error" : "") . "\n");
}
$image = $clone;
$needdelete = 1;
#
# Watch for a system image that is saved elsewhere; see equiv code
# in create_image. We change the path to point over to the /proj
# directory so that we do not burn up space on boss until it is
# officially "released". We can also use this version of the image
# by explicitly using its version number, before it is released.
#
if ($image->path() =~ /^\/usr\/testbed/) {
my $path = $PROJROOT . "/" . $image->pid() . "/images/" .
basename($image->path()) . ":" . $image->version();
if ($image->Update({"path" => $path, "released" => 0})) {
$image->DeleteVersion();
fatal("Could not update path and ready bit");
}
}
}
$image = $clone;
}
$image->Unlock();
......@@ -237,8 +273,8 @@ if (defined($image)) {
my $output = emutil::ExecQuiet("$CREATEIMAGE -p $pid $imagename $node_id");
if ($?) {
if ($DOPROVENANCE) {
# Delete with Purge.
$image->Delete(1);
$image->DeleteVersion()
if ($needdelete);
}
print STDERR $output;
fatal("Failed to create image");
......@@ -246,6 +282,7 @@ if (defined($image)) {
print "Image is being created. This can take 15-30 minutes.\n";
exit(0);
}
DoNew:
#
# Only EZ images via this interface.
......
......@@ -209,7 +209,7 @@ $EUID = $UID;
#
# Untaint the arguments.
#
if ($imagename =~ /^([-\w\.\+]+)$/) {
if ($imagename =~ /^([-\w\.\+:]+)$/) {
$imagename = $1;
}
else {
......@@ -367,10 +367,11 @@ else {
#
my $filename = $image->path();
my $isglobal = $image->global();
my $usepath = 0;
# Temporary until frisbee path can handle versions?
my $usepath = $image->released() ? 0 : 1;
#
# Redirect pathname for global images.
# Redirect pathname for global images. See equiv code in clone_image.
#
if ($isglobal && ($filename =~ /^\/usr\/testbed/)) {
$filename = PROJROOT() . "/$pid/images/" . basename($filename);
......@@ -425,7 +426,7 @@ if ($image->Lock()) {
}
$needunlock = 1;
if (!$usepath && $image->ready()) {
if ($image->ready()) {
$image->Unlock();
die("*** $0:\n".
" $image ready flag is set, this is inconsistent!\n");
......
......@@ -57,8 +57,10 @@ SUBMENUSTART("More Options");
$fooid = rawurlencode($imageid);
WRITESUBMENUBUTTON("Edit this Image Descriptor",
"editimageid.php3?imageid=$fooid");
WRITESUBMENUBUTTON("Snapshot Node Disk into Image",
"loadimage.php3?imageid=$fooid");
if ($image->AccessCheck($this_user, $TB_IMAGEID_MODIFYINFO )) {
WRITESUBMENUBUTTON("Snapshot Node Disk into Image",
"loadimage.php3?imageid=$fooid");
}
WRITESUBMENUBUTTON("Clone this Image Descriptor",
"newimageid_ez.php3?baseimage=$fooid");
WRITESUBMENUBUTTON("Delete this Image Descriptor",
......
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