All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 7700c6cf authored by Mike Hibler's avatar Mike Hibler

Respect the uploader_path field in image_versions.

The "Emulab configuration" of the mserver will now use uploader_path
if set rather than path.

A slight semantic change goes along with this. If the uploader_path is
set, we assume that it is a temporary file to upload to and we (the mserver)
do not do the dance of uploading to our own temporary and moving it into place.
parent 1782fc9b
......@@ -434,6 +434,7 @@ set_put_values(struct config_host_authinfo *ai, int ix)
ii->put_itimeout = put_maxiwait;
/* put_oldversion */
#if 0
/*
* For standard images, we keep ALL old versions as:
* <path>.<timestamp>, just because we are extra paranoid about those.
......@@ -449,7 +450,12 @@ set_put_values(struct config_host_authinfo *ai, int ix)
snprintf(str, len, "%s.%09u", ii->path, (unsigned)curtime);
ii->put_oldversion = str;
} else
ii->put_oldversion = NULL;
#endif
{
int len = strlen(ii->path) + 5;
ii->put_oldversion = mymalloc(len);
snprintf(ii->put_oldversion, len, "%s.bak", ii->path);
}
/* put_options */
ii->put_options = NULL;
......@@ -1480,7 +1486,8 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
if (wantvers) {
res = mydb_query("SELECT i.pid,i.gid,"
"i.imagename,v.path,"
"i.imageid,v.version"
"i.imageid,v.version,"
"v.uploader_path"
" FROM images as i "
" LEFT JOIN image_versions "
" as v on "
......@@ -1488,12 +1495,13 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
" v.version='%s' "
"WHERE i.pid='%s'"
" AND i.imagename='%s'",
6, wantvers, wantpid, wantname);
7, wantvers, wantpid, wantname);
}
else {
res = mydb_query("SELECT i.pid,i.gid,"
"i.imagename,v.path,"
"i.imageid,v.version"
"i.imageid,v.version,"
"v.uploader_path"
" FROM images as i "
" LEFT JOIN image_versions "
" as v on "
......@@ -1501,7 +1509,7 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
" v.version=i.version "
"WHERE i.pid='%s'"
" AND i.imagename='%s'",
6, wantpid, wantname);
7, wantpid, wantname);
}
} else {
/*
......@@ -1511,7 +1519,8 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
if (wantvers) {
res = mydb_query("SELECT i.pid,i.gid,"
"i.imagename,v.path,"
"i.imageid,v.version"
"i.imageid,v.version,"
"v.uploader_path"
" FROM images as i"
" LEFT JOIN image_versions "
" as v on "
......@@ -1523,13 +1532,14 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
" AND (i.gid='%s' OR"
" (i.gid=i.pid AND "
" v.shared=1))",
6, wantvers, wantpid, wantname,
7, wantvers, wantpid, wantname,
ei->pid, ei->gid);
}
else {
res = mydb_query("SELECT i.pid,i.gid,"
"i.imagename,v.path,"
"i.imageid,v.version"
"i.imageid,v.version,"
"v.uploader_path"
" FROM images as i"
" LEFT JOIN image_versions "
" as v on "
......@@ -1572,11 +1582,12 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
struct emulab_ii_extra_info *ii;
struct config_imageinfo *ci;
struct stat sb;
char *iid;
int iidx;
char *iid, *targetpath;
int iidx, hasuploadpath = 0;
row = mysql_fetch_row(res);
/* XXX ignore rows with null or empty info */
/* XXX row[6] (uploader_path) can be NULL */
if (!row[0] || !row[0][0] ||
!row[1] || !row[1][0] ||
!row[2] || !row[2][0] ||
......@@ -1585,6 +1596,16 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
!row[5] || !row[5][0])
continue;
/*
* If an uploader_path was specified, use that.
* Otherwise use the path.
*/
if (row[6] && row[6][0]) {
targetpath = row[6];
hasuploadpath = 1;
} else
targetpath = row[3];
/*
* XXX if image is in the standard image directory,
* disallow PUTs.
......@@ -1597,9 +1618,9 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
* hwdown and other special experiments possibly
* without revoking the access of the previous user.
*/
if (isindir(STDIMAGEDIR, row[3])) {
FrisError("%s: cannot update standard images "
"right now", row[3]);
if (isindir(STDIMAGEDIR, targetpath)) {
FrisError("%s: cannot update image using "
"path '%s'", targetpath);
continue;
}
......@@ -1608,12 +1629,12 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
ci->imageid = iid;
ci->dir = NULL;
if (wantmeta && strcmp(wantmeta, "sig") == 0) {
ci->path = mymalloc(strlen(row[3]) + 4);
strcpy(ci->path, row[3]);
ci->path = mymalloc(strlen(targetpath) + 4);
strcpy(ci->path, targetpath);
strcat(ci->path, ".sig");
ci->flags = CONFIG_PATH_ISSIGFILE;
} else {
ci->path = mystrdup(row[3]);
ci->path = mystrdup(targetpath);
ci->flags = CONFIG_PATH_ISFILE;
}
if (stat(ci->path, &sb) == 0) {
......@@ -1646,6 +1667,16 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
}
set_put_values(put, put->numimages);
/*
* XXX if we have an explict uploader path we are
* under control of image_create and don't need to
* worry about backups.
*/
if (hasuploadpath && ci->put_oldversion) {
free(ci->put_oldversion);
ci->put_oldversion = NULL;
}
ii = mymalloc(sizeof *ii);
ii->DB_imageid = iidx;
ci->extra = ii;
......
......@@ -187,23 +187,28 @@ set_get_values(struct config_host_authinfo *ai, int ix)
static void
set_put_values(struct config_host_authinfo *ai, int ix)
{
struct config_imageinfo *ii = &ai->imageinfo[ix];
int len;
/* put_maxsize */
ai->imageinfo[ix].put_maxsize = 10000000000ULL; /* XXX 10GB */
ii->put_maxsize = 20000000000ULL; /* XXX 20GB */
/* put_timeout */
ai->imageinfo[ix].put_timeout = 900;
ai->imageinfo[ix].put_itimeout = 120;
ii->put_timeout = 1200;
ii->put_itimeout = 120;
/* put_oldversion */
ai->imageinfo[ix].put_oldversion = NULL;
/* put_oldversion -- setting to NULL means no tmpfile during upload */
len = strlen(ii->path) + 5;
ii->put_oldversion = mymalloc(len);
snprintf(ii->put_oldversion, len, "%s.bak", ii->path);
/* put_options */
ai->imageinfo[ix].put_options = NULL;
ii->put_options = NULL;
/* and whack the get_* fields */
ai->imageinfo[ix].get_methods = 0;
ai->imageinfo[ix].get_timeout = 0;
ai->imageinfo[ix].get_options = NULL;
ii->get_methods = 0;
ii->get_timeout = 0;
ii->get_options = NULL;
}
#define FREE(p) { if (p) free(p); }
......
......@@ -2009,7 +2009,7 @@ static void
finishupload(struct childinfo *ci, int status)
{
char *bakname, *tmpname, *realname;
int len, didbackup;
int didbackup;
struct uploadextra *ue;
time_t mtime;
......@@ -2019,14 +2019,28 @@ finishupload(struct childinfo *ci, int status)
mtime = (time_t)ue->mtime;
free(ci->extra);
ci->extra = NULL;
tmpname = ci->imageinfo->path;
ci->imageinfo->path = realname;
if (realname) {
tmpname = ci->imageinfo->path;
assert(tmpname != NULL);
ci->imageinfo->path = realname;
bakname = ci->imageinfo->put_oldversion;
assert(bakname != NULL);
} else {
tmpname = bakname = NULL;
realname = ci->imageinfo->path;
}
if (status != 0) {
FrisError("%s: upload failed, removing tmpfile %s",
realname, tmpname);
unlink(tmpname);
free(tmpname);
if (tmpname) {
FrisError("%s: upload failed, removing tmpfile %s",
realname, tmpname);
unlink(tmpname);
free(tmpname);
} else {
FrisError("%s: upload failed, removing", realname);
unlink(realname);
}
return;
}
......@@ -2035,35 +2049,30 @@ finishupload(struct childinfo *ci, int status)
gettimeofday(&tv[0], NULL);
tv[1].tv_sec = mtime;
tv[1].tv_usec = 0;
if (utimes(tmpname, tv) < 0)
FrisWarning("%s: failed to set mtime", tmpname);
if (utimes(tmpname ? tmpname : realname, tv) < 0)
FrisWarning("%s: failed to set mtime",
tmpname ? tmpname : realname);
}
/*
* If the configuration specified an explicit place for the
* old version, move it there now. Otherwise just save it as
* <realname>.bak
* old version, move it there now. Otherwise, we were saving
* directly to the specified path and there is nothing to backup.
*/
if (ci->imageinfo->put_oldversion)
bakname = ci->imageinfo->put_oldversion;
else {
len = strlen(realname) + 5;
bakname = malloc(len);
snprintf(bakname, len, "%s.bak", realname);
}
didbackup = 1;
if (rename(realname, bakname) < 0)
didbackup = 0;
if ((!didbackup && errno != ENOENT) || rename(tmpname, realname) < 0) {
FrisError("%s: failed to install new version (%d), leaving as %s",
realname, errno, tmpname);
if (didbackup)
rename(bakname, realname);
if (bakname) {
didbackup = 1;
if (rename(realname, bakname) < 0)
didbackup = 0;
if ((!didbackup && errno != ENOENT) ||
rename(tmpname, realname) < 0) {
FrisError("%s: failed to install new version (%d),"
"leaving as %s", realname, errno, tmpname);
if (didbackup)
rename(bakname, realname);
}
free(tmpname);
}
free(tmpname);
if (ci->imageinfo->put_oldversion == NULL)
free(bakname);
FrisLog("%s: upload complete", realname);
}
......@@ -2076,8 +2085,7 @@ startuploader(struct config_imageinfo *ii, in_addr_t meaddr, in_addr_t youaddr,
{
struct childinfo *ci;
struct uploadextra *ue;
char *tmpname;
int len, itimo = 0;
int itimo = 0;
assert(findchild(ii->imageid, PTYPE_UPLOADER, MS_METHOD_ANY) == NULL);
assert(errorp != NULL);
......@@ -2158,14 +2166,21 @@ startuploader(struct config_imageinfo *ii, in_addr_t meaddr, in_addr_t youaddr,
/*
* Arrange to upload the image as <path>.tmp and then
* rename it into place when done.
*
* XXX if put_oldversion is NULL, we assume that we are
* uploading to a temporary file in the first place.
* See config_emulab.c.
*/
len = strlen(ci->imageinfo->path) + 5;
if ((tmpname = malloc(len)) != NULL) {
ue->realname = ci->imageinfo->path;
snprintf(tmpname, len, "%s.tmp", ci->imageinfo->path);
ci->imageinfo->path = tmpname;
ci->done = finishupload;
if (ci->imageinfo->put_oldversion) {
int len = strlen(ci->imageinfo->path) + 5;
char *tmpname = malloc(len);
if (tmpname != NULL) {
ue->realname = ci->imageinfo->path;
snprintf(tmpname, len, "%s.tmp", ci->imageinfo->path);
ci->imageinfo->path = tmpname;
}
}
ci->done = finishupload;
if ((*errorp = startchild(ci)) != 0) {
free_imageinfo(ci->imageinfo);
......
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