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 3f5e4ef8 authored by Russ Fish's avatar Russ Fish

Move newimageid page form logic to a backend Perl script.

     www/newimageid.php3 - The reworked PHP page.
     www/imageid_defs.php - Add an Image::NewImageId class method
                            bridging to the script via XML.
     backend/{newimageid,GNUmakefile}.in configure configure.in - New backend script.
     db/Image.pm.in - Add a Create class method for script arg checking.
     sql/database-fill.sql - Add to the table_regex 'images' checking patterns.
parent 978c891a
......@@ -13,9 +13,9 @@ UNIFIED = @UNIFIED_BOSS_AND_OPS@
include $(OBJDIR)/Makeconf
BIN_SCRIPTS = moduserinfo newgroup newmmlist editexp editimageid \
editnodetype editsitevars
editnodetype editsitevars newimageid
WEB_BIN_SCRIPTS = webmoduserinfo webnewgroup webnewmmlist webeditimageid \
webeditnodetype webeditsitevars
webeditnodetype webeditsitevars webnewimageid
WEB_SBIN_SCRIPTS=
LIBEXEC_SCRIPTS = $(WEB_BIN_SCRIPTS) $(WEB_SBIN_SCRIPTS)
......
This diff is collapsed.
......@@ -2429,7 +2429,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
account/quotamail account/mkusercert account/newproj account/newuser \
backend/GNUmakefile backend/moduserinfo backend/newgroup \
backend/newmmlist backend/editexp backend/editimageid backend/editnodetype \
backend/editsitevars \
backend/editsitevars backend/newimageid \
tbsetup/GNUmakefile tbsetup/console_setup tbsetup/spewlogfile \
tbsetup/spewrpmtar tbsetup/gentopofile tbsetup/power_sgmote.pm \
tbsetup/console_reset tbsetup/bwconfig tbsetup/power_rpc27.pm \
......
......@@ -809,7 +809,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
account/quotamail account/mkusercert account/newproj account/newuser \
backend/GNUmakefile backend/moduserinfo backend/newgroup \
backend/newmmlist backend/editexp backend/editimageid backend/editnodetype \
backend/editsitevars \
backend/editsitevars backend/newimageid \
tbsetup/GNUmakefile tbsetup/console_setup tbsetup/spewlogfile \
tbsetup/spewrpmtar tbsetup/gentopofile tbsetup/power_sgmote.pm \
tbsetup/console_reset tbsetup/bwconfig tbsetup/power_rpc27.pm \
......
......@@ -164,6 +164,163 @@ sub Refresh($)
return 0;
}
#
# Create a new os_info. This installs the new record in the DB,
# and returns an instance. There is some bookkeeping along the way.
#
sub Create($$$$)
{
my ($class, $project, $group, $creator, $imagename, $argref, $usrerr_ref) = @_;
my $idx;
my $now = time();
return undef
if (ref($class) || !ref($project));
my $isadmin = $creator->IsAdmin();
# We may ignore particular partN_osid's by deleting them.
my @arg_slots = grep(/^part[1-4]_osid$/, keys(%{$argref}));
# Pass-through a bunch of required slots, ignoring any extras
# and stuff we handle explicitly.
foreach my $key ("loadpart", "loadlength", "default_osid") {
if (!exists($argref->{$key})) {
$$usrerr_ref = "Error: $key missing in Image->Create!";
return undef;
}
push(@arg_slots, $key);
}
# Pass-through optional slots, otherwise the DB default is used.
foreach my $key ("path", "shared", "global") {
if (exists($argref->{$key})) {
push(@arg_slots, $key);
}
}
my $pid = $project->pid();
my $pid_idx = $project->pid_idx();
my $gid = $group->gid();
my $gid_idx = $group->gid_idx();
my $uid = $creator->uid();
my $uid_idx = $creator->uid_idx();
#
# The pid/imageid has to be unique, so lock the table for the check/insert.
#
DBQueryWarn("lock tables images write, emulab_indicies write")
or return undef;
my $query_result =
DBQueryWarn("select imagename from images ".
"where pid_idx='$pid_idx' and imagename='$imagename'");
if ($query_result->numrows) {
DBQueryWarn("unlock tables");
$$usrerr_ref = "Error: IMAGE $imagename in project $pid already exists!";
return undef;
}
#
# Grab unique ID. Table already locked.
#
my $imageid = TBGetUniqueIndex("next_imageid", undef, 1);
my $uuid = NewUUID();
my $desc = "''";
# Some fields special cause of quoting.
#
if (exists($argref->{'description'})) {
$desc = DBQuoteSpecial($argref->{'description'});
}
my $query = "insert into images set ".
join(",", map("$_='" . $argref->{$_} . "'", @arg_slots));
# Append the rest
$query .= ",imagename='$imagename'";
$query .= ",imageid='$imageid'";
$query .= ",uuid='$uuid'";
$query .= ",pid='$pid',pid_idx='$pid_idx'";
$query .= ",gid='$gid',gid_idx='$gid_idx'";
$query .= ",creator='$uid',creator_idx='$uid_idx'";
$query .= ",created=now()";
$query .= ",description=$desc";
if (! DBQueryWarn($query)) {
DBQueryWarn("unlock tables");
tberror("Error inserting new images record for $pid/$imagename!");
return undef;
}
my $image = Image->Lookup($imageid);
# Create the osidtoimageid mapping. Admins have an option to do it or not.
my $makedefault = exists($argref->{"makedefault"}) &&
$argref->{"makedefault"} eq "1";
if (!$isadmin || $makedefault) {
# Lock tables unlocks previous locks as a side-effect.
DBQueryWarn("lock tables osidtoimageid write, images write, ".
"nodes as n write, node_type_attributes as a write");
#
# Need a list of node types. We join this over the nodes table so that
# we get a list of just the nodes that are currently in the testbed, not
# just in the node_types table.
#
my $types_result =
DBQueryWarn("select distinct n.type from nodes as n ".
"left join node_type_attributes as a on a.type=n.type ".
"where a.attrkey='imageable' and ".
" a.attrvalue!='0'");
my @mtypes_array;
my @map_updates;
while (my ($type) = $types_result->fetchrow_array()) {
push(@mtypes_array, $type);
# Remember when we get one of the mtype_$type args. These aren't DB
# columns to update, but instead control re-creating the rows in the
# osidtoimageid table for this imageid, below.
my $mtype = "mtype_$type";
if (exists($argref->{$mtype})) {
my $value = $argref->{$mtype};
##printf "argref->{$mtype} %s\n", $value;
if ($value eq "1") {
push(@map_updates, $type);
}
}
}
my @osid_array;
for (my $i = 1; $i <= 4; $i++) {
my $foo = $image->field("part${i}_osid");
if (defined($foo)) {
push(@osid_array, $foo);
}
}
for (my $i = 0; $i <= $#map_updates; $i++) {
for (my $j = 0; $j <= $#osid_array; $j++) {
my $query = "INSERT INTO osidtoimageid ".
" (osid, type, imageid) ".
"VALUES ('$osid_array[$j]', ".
" '$map_updates[$i]', ".
" '$imageid')";
##print "$query\n";
if (! DBQueryWarn($query)) {
DBQueryWarn("unlock tables");
tberror("Error inserting new ostoimageid mapping for ".
"$pid/$imagename!");
return undef;
}
}
}
}
DBQueryWarn("unlock tables");
return $image;
}
#
# Worker class method to edit image descriptor.
# Assumes most argument checking was done elsewhere.
......@@ -196,7 +353,7 @@ sub EditImageid($$$$)
# just in the node_types table.
#
my $types_result =
DBQueryFatal("select distinct n.type from nodes as n ".
DBQueryWarn("select distinct n.type from nodes as n ".
"left join node_type_attributes as a on a.type=n.type ".
"where a.attrkey='imageable' and ".
" a.attrvalue!='0'");
......@@ -230,13 +387,13 @@ sub EditImageid($$$$)
}
if (keys %updates || $redo_map) {
DBQueryFatal("lock tables images write, os_info write, ".
DBQueryWarn("lock tables images write, os_info write, ".
"osidtoimageid write");
}
if (keys %updates) {
if ($image->Update(\%updates)) {
$$usrerr_ref = "DB: Error updating the images table";
DBQueryFatal("unlock tables");
DBQueryWarn("unlock tables");
return undef;
}
}
......@@ -245,7 +402,7 @@ sub EditImageid($$$$)
# Update the osidtoimageid table too.
#
# Must delete old entries first.
DBQueryFatal("delete from osidtoimageid ".
DBQueryWarn("delete from osidtoimageid ".
"where imageid='$imageid'");
my @osid_array;
......@@ -263,12 +420,12 @@ sub EditImageid($$$$)
" '$map_updates[$i]', ".
" '$imageid')";
##print "$query\n";
DBQueryFatal($query);
DBQueryWarn($query);
}
}
}
if (keys %updates || $redo_map) {
DBQueryFatal("unlock tables");
DBQueryWarn("unlock tables");
}
return 1;
......
......@@ -789,12 +789,24 @@ REPLACE INTO table_regex VALUES ('experiments','elab_in_elab','int','redirect','
REPLACE INTO table_regex VALUES ('experiments','elabinelab_singlenet','int','redirect','default:boolean',0,0,NULL);
REPLACE INTO table_regex VALUES ('experiments','elabinelab_cvstag','text','regex','^[-\\w\\@\\/\\.]+$',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','imageid','text','redirect','default:int',0,100000000,NULL);
REPLACE INTO table_regex VALUES ('images','imagename','text','regex','^[a-zA-Z0-9][-\\w\\.+]+$',2,30,NULL);
REPLACE INTO table_regex VALUES ('images','imageid','text','redirect','default:int',0,100000000,NULL);
REPLACE INTO table_regex VALUES ('images','pid','text','redirect','projects:pid',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','gid','text','redirect','groups:gid',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','description','text','regex','^[\\040-\\176\\012\\015\\011]*$',1,256,NULL);
REPLACE INTO table_regex VALUES ('images','loadpart','text','redirect','default:tinyint',0,4,NULL);
REPLACE INTO table_regex VALUES ('images','loadlength','text','redirect','default:tinyint',1,4,NULL);
REPLACE INTO table_regex VALUES ('images','part1_osid','text','redirect','os_info:osid',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','part2_osid','text','redirect','os_info:osid',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','part3_osid','text','redirect','os_info:osid',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','part4_osid','text','redirect','os_info:osid',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','default_osid','text','redirect','os_info:osid',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','path','text','regex','^[-_\\w\\.\\/:+]*$',1,256,NULL);
REPLACE INTO table_regex VALUES ('images','shared','text','redirect','default:boolean',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','global','text','redirect','default:boolean',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','makedefault','text','redirect','default:boolean',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','mtype','text','redirect','default:boolean',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','osid','text','redirect','os_info:osid',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','node_id','text','redirect','nodes:node_id',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','load_address','text','redirect','default:text',0,0,NULL);
REPLACE INTO table_regex VALUES ('images','frisbee_pid','text','redirect','default:int',0,0,NULL);
......
......@@ -115,7 +115,94 @@ class Image
}
#
# Class function to edit image descriptor.
# Class function to create a new image descriptor.
#
function NewImageId($imagename, $args, &$errors) {
global $suexec_output, $suexec_output_array;
#
# Generate a temporary file and write in the XML goo.
#
$xmlname = tempnam("/tmp", "newimageid");
if (! $xmlname) {
TBERROR("Could not create temporary filename", 0);
$errors[] = "Transient error(1); please try again later.";
return null;
}
if (! ($fp = fopen($xmlname, "w"))) {
TBERROR("Could not open temp file $xmlname", 0);
$errors[] = "Transient error(2); please try again later.";
return null;
}
# Add these. Maybe caller should do this?
$args["imagename"] = $imagename;
fwrite($fp, "<image>\n");
foreach ($args as $name => $value) {
fwrite($fp, "<attribute name=\"$name\">");
fwrite($fp, " <value>" . htmlspecialchars($value) . "</value>");
fwrite($fp, "</attribute>\n");
}
fwrite($fp, "</image>\n");
fclose($fp);
chmod($xmlname, 0666);
$retval = SUEXEC("nobody", "nobody", "webnewimageid $xmlname",
SUEXEC_ACTION_IGNORE);
if ($retval) {
if ($retval < 0) {
$errors[] = "Transient error(3); please try again later.";
SUEXECERROR(SUEXEC_ACTION_CONTINUE);
}
else {
# unlink($xmlname);
if (count($suexec_output_array)) {
for ($i = 0; $i < count($suexec_output_array); $i++) {
$line = $suexec_output_array[$i];
if (preg_match("/^([-\w]+):\s*(.*)$/",
$line, $matches)) {
$errors[$matches[1]] = $matches[2];
}
else
$errors[] = $line;
}
}
else
$errors[] = "Transient error(4); please try again later.";
}
return null;
}
#
# Parse the last line of output. Ick.
#
unset($matches);
if (!preg_match("/^IMAGE\s+([^\/]+)\/(\d+)\s+/",
$suexec_output_array[count($suexec_output_array)-1],
$matches)) {
$errors[] = "Transient error; please try again later.";
SUEXECERROR(SUEXEC_ACTION_CONTINUE);
return null;
}
$image = $matches[2];
$newimage = image::Lookup($image);
if (! $newimage) {
$errors[] = "Transient error; please try again later.";
TBERROR("Could not lookup new image $image", 0);
return null;
}
# Unlink this here, so that the file is left behind in case of error.
# We can then create the image by hand from the xmlfile, if desired.
unlink($xmlname);
return $newimage;
}
#
# Class function to edit an image descriptor.
#
function EditImageid($image, $args, &$errors) {
global $suexec_output, $suexec_output_array;
......
This diff is collapsed.
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