summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEudyptula <eitan@mosenkis.net>2009-07-03 14:04:10 -0400
committerEudyptula <eitan@mosenkis.net>2009-07-03 14:04:10 -0400
commitb38ffa446425cad5bd1f7bedffb311903c58c823 (patch)
treed5ec561a722c5e1fae079f0a647836de23704826
parentBackend can upload finished images; caches state after emerge system completes (diff)
downloadingenue-b38ffa446425cad5bd1f7bedffb311903c58c823.tar.gz
ingenue-b38ffa446425cad5bd1f7bedffb311903c58c823.tar.bz2
ingenue-b38ffa446425cad5bd1f7bedffb311903c58c823.zip
Separated configurations from builds of those configurations, added configurations manager to frontend
-rw-r--r--frontend/css/configsummary.css15
-rw-r--r--frontend/include/header.php3
-rw-r--r--frontend/modules/gentoo/step1.php6
-rw-r--r--frontend/modules/gentoo/step2.php6
-rw-r--r--frontend/modules/gentoo/step3.php2
-rw-r--r--frontend/pages/configurations/manager.php42
-rw-r--r--frontend/pages/configurations/wizard.php (renamed from frontend/pages/wizard.php)61
-rw-r--r--frontend/routing.csv9
-rw-r--r--shared/classes/configopt.php22
-rw-r--r--shared/classes/configuration.php106
-rw-r--r--todo6
11 files changed, 231 insertions, 47 deletions
diff --git a/frontend/css/configsummary.css b/frontend/css/configsummary.css
new file mode 100644
index 0000000..af62488
--- /dev/null
+++ b/frontend/css/configsummary.css
@@ -0,0 +1,15 @@
+table.configsummary {
+ font-size: 80%;
+ font-family: monospace;
+}
+table.configsummary td {
+ padding-bottom: 3px;
+ border-bottom: 1px solid black;
+}
+table.configsummary td.name {
+ font-style: italic;
+ border-right: 1px dashed blue;
+}
+table.configsummary td.val {
+ border-left: 1px dashed green;
+}
diff --git a/frontend/include/header.php b/frontend/include/header.php
index 4a60969..c88028c 100644
--- a/frontend/include/header.php
+++ b/frontend/include/header.php
@@ -30,7 +30,8 @@ if (isset($S['head'])) {
<ul>
<?php
echo '<li><a href="'.url().'">Home</a></li>';
-echo '<li><a href="'.url('create').'">Create an image</a></li>';
+echo '<li><a href="'.url('create').'">New configuration</a></li>';
+echo '<li><a href="'.url('configurations').'">Manage configurations</a></li>';
echo '<li><a href="'.url('logs').'">Log viewer</a></li>';
if (isset($S['user']) && $S['user']->hasflag('a')) {
echo '<li><a href="'.url('invite').'">Invite</a></li>';
diff --git a/frontend/modules/gentoo/step1.php b/frontend/modules/gentoo/step1.php
index 16f04d9..aeb0a9e 100644
--- a/frontend/modules/gentoo/step1.php
+++ b/frontend/modules/gentoo/step1.php
@@ -4,8 +4,8 @@ function gentoo_init_step1() {
}
function gentoo_body_step1() {
global $S;
- $build=&$S['wizard.build'];
- //$opts=$build->get_buildopts(); // TODO use this to set selected="selected" on the current profile
+ $configuration=&$S['wizard.configuration'];
+ //$opts=$configuration->get_configopts(); // TODO use this to set selected="selected" on the current profile
echo 'Profile: <select name="pkgdir">';
$r=$S['pdo']->query('SELECT * FROM `profiles` WHERE `flags` NOT LIKE "%d%"'); // d for disabled
while ($profile=$r->fetch(PDO::FETCH_ASSOC)) {
@@ -18,7 +18,7 @@ function gentoo_body_step1() {
function gentoo_process_step1() {
global $S, $request;
$profile=new sql_profile($request['pkgdir']);
- $profileopt=new sql_buildopt($S['wizard.build']->id, 'profile', $profile->id);
+ $profileopt=new sql_configopt($S['wizard.configuration']->id, 'profile', $profile->id);
$profileopt->write();
}
?>
diff --git a/frontend/modules/gentoo/step2.php b/frontend/modules/gentoo/step2.php
index 4e2907c..564dd4d 100644
--- a/frontend/modules/gentoo/step2.php
+++ b/frontend/modules/gentoo/step2.php
@@ -4,8 +4,8 @@ function gentoo_init_step2() {
}
function gentoo_body_step2() {
global $S;
- $build=&$S['wizard.build'];
- $opts=$build->get_buildopts();
+ $configuration=&$S['wizard.configuration'];
+ $opts=$configuration->get_configopts();
$profile=new sql_profile($opts['profile']);
$categories=$profile->get_packages();
echo '<ul>';
@@ -30,7 +30,7 @@ function gentoo_process_step2() {
$packages[]=$name;
}
$packages=implode(' ', $packages);
- $opt=new sql_buildopt($S['wizard.build']->id, 'install_packages', $packages);
+ $opt=new sql_configopt($S['wizard.configuration']->id, 'install_packages', $packages);
$opt->write();
}
}
diff --git a/frontend/modules/gentoo/step3.php b/frontend/modules/gentoo/step3.php
index d1d152d..2f66325 100644
--- a/frontend/modules/gentoo/step3.php
+++ b/frontend/modules/gentoo/step3.php
@@ -9,7 +9,7 @@ function gentoo_process_step3() {
global $S, $request;
if (isset($request['image_type'])) {
debug('wizard', 'step3: image type='.$request['image_type']);
- $opt=new sql_buildopt($S['wizard.build']->id, 'image_type', $request['image_type']);
+ $opt=new sql_configopt($S['wizard.configuration']->id, 'image_type', $request['image_type']);
$opt->write();
} else {
debug('wizard', 'step3: no image_type variable');
diff --git a/frontend/pages/configurations/manager.php b/frontend/pages/configurations/manager.php
new file mode 100644
index 0000000..dfadf4a
--- /dev/null
+++ b/frontend/pages/configurations/manager.php
@@ -0,0 +1,42 @@
+<?php
+function init_configurations_manage() {
+ global $S;
+ if (!isset($S['user'])) {
+ return 'login';
+ }
+ return array('title' => 'Manage Configurations');
+}
+function body_configurations_manager() {
+ global $S, $request;
+ echo '<h3>Configurations Manager</h3>';
+ $r=$S['pdo']->query('SELECT * FROM `configurations` WHERE `owner`='.$S['user']->id);
+ if ($r->rowCount() == 0) {
+ echo print_warning('You have no configurations.').'<a href="'.url('create').'">Create a configuration</a>';
+ return;
+ } elseif (isset($request['build']) && isset($request['configuration'])) {
+ $c=new sql_configuration($request['configuration']);
+ if ($c->owner!=$S['user']->id) {
+ echo print_error('You do not have permission to build this configuration.');
+ } else {
+ $name=isset($request['name'])?$request['name']:null;
+ $build=$c->build($name);
+ echo print_success('Submitted for build - <a href="'.url('logs/'.$build->id).'">Logs</a>');
+ }
+ }
+ echo '<form action="'.url('configurations').'" method="post"><table><tr><th>ID</th><th>Name</th><th>Status</th><th>Options</th><th>Builds</th></tr>'."\n";
+ while($c=$r->fetch(PDO::FETCH_ASSOC)) {
+ $c=new sql_configuration($c);
+ echo "<tr><td><input id=\"radio-$c->id\" type=\"radio\" name=\"configuration\" value=\"$c->id\" /> <label for=\"radio-$c->id\">$c->id</label></td><td>".(isset($c->name) && strlen($c->name)?htmlentities($c->name):'<i>Unnamed</i>')."</td><td>$c->status</td><td>".$c->summary().'</td><td>';
+ $builds=$c->get_builds();
+ if ($builds) {
+ foreach ($builds as $build) {
+ echo '<a href="'.url('logs/'.$build).'">'.$build.'</a> ';
+ }
+ } else {
+ echo '<i>None</i>';
+ }
+ echo "</td></tr>\n";
+ }
+ echo '</table>Name (optional): <input name="name" /> <input type="submit" name="build" value="Build" /></form>';
+}
+?>
diff --git a/frontend/pages/wizard.php b/frontend/pages/configurations/wizard.php
index d8fc9e8..3931363 100644
--- a/frontend/pages/wizard.php
+++ b/frontend/pages/configurations/wizard.php
@@ -1,25 +1,25 @@
<?php
-function init_wizard() {
+function init_configurations_wizard() {
global $S, $request, $conf;
if (!isset($S['user'])) {
return 'login';
}
- // Make it so you can just pop over to config build=x and it will go to the right step
- if (isset($request['build']) && preg_match('/^[a-zA-Z0-9]{6}$/', $request['build'])) {
- $r=$S['pdo']->query('SELECT * FROM `builds` WHERE `owner`='.$S['user']->id.' AND `id`="'.$request['build'].'"');
+ // Make it so you can just pop over to config configuration=x and it will go to the right step
+ if (isset($request['configuration']) && preg_match('/^[a-zA-Z0-9]{6}$/', $request['configuration'])) {
+ $r=$S['pdo']->query('SELECT * FROM `configurations` WHERE `owner`='.$S['user']->id.' AND `id`="'.$request['configuration'].'"');
if ($r->rowCount()) {
- $S['wizard.build']=new sql_build($r->fetch(PDO::FETCH_ASSOC));
- $build=&$S['wizard.build'];
- $opts=$build->get_buildopts();
+ $S['wizard.configuration']=new sql_configuration($r->fetch(PDO::FETCH_ASSOC));
+ $configuration=&$S['wizard.configuration'];
+ $opts=$configuration->get_configopts();
$S['wizard.module']=$opts['frontend_module'];
$module=&$S['wizard.module'];
- if (!preg_match('#^config/step([0-9]+)$#', $build->status, $match)) {
- debug('wizard', 'build not in config stage (status '.$build->status.') - PANIC!');
+ if (!preg_match('#^config/step([0-9]+)$#', $configuration->status, $match)) {
+ debug('wizard', 'configuration not in config stage (status '.$configuration->status.') - PANIC!');
throw_exception('We haven\'t implemented this yet.');
}
$S['wizard.step']=$match[1];
$step=&$S['wizard.step'];
- debug('wizard', 'Build '.$build->id." is at step $step");
+ debug('wizard', 'Build '.$configuration->id." is at step $step");
if (isset($request['wizard_submit'])) {
debug('wizard', "Processing step $step");
if (!is_file(FRONTEND."/modules/$module/step$step.php")) {
@@ -30,17 +30,16 @@ function init_wizard() {
if (function_exists($proc)) {
if ($proc() === true) {
debug('wizard', "Step $step returned <i>true</i> - config finished!");
- $build->status='build/ready';
- $build->ctime=time();
- $build->write();
+ $configuration->status='config/done';
+ $configuration->write();
$S['wizard.done']=true;
return array('title' => 'Config Finished');
}
} else {
debug('wizard', "No processing function for $wizard step $step");
}
- $build->status='config/step'.++$step;
- $build->write();
+ $configuration->status='config/step'.++$step;
+ $configuration->write();
debug('wizard', "Continuing to step $step");
} else {
debug('wizard', "Not ready for processing... staying at step $step");
@@ -49,22 +48,22 @@ function init_wizard() {
throw_exception('Build not found');
}
} elseif (isset($request['init'])) {
- $r=$S['pdo']->query('SELECT * FROM `builds` WHERE `owner`='.$S['user']->id.' AND `status`="config/step1"');
+ $r=$S['pdo']->query('SELECT * FROM `configurations` WHERE `owner`='.$S['user']->id.' AND `status`="config/step1"');
if ($r->rowCount()) {
- $S['wizard.build']=new sql_build($r->fetch(PDO::FETCH_ASSOC));
+ $S['wizard.configuration']=new sql_configuration($r->fetch(PDO::FETCH_ASSOC));
} else {
- $S['wizard.build']=new sql_build();
- $S['wizard.build']->init();
+ $S['wizard.configuration']=new sql_configuration();
+ $S['wizard.configuration']->init();
}
- $build=&$S['wizard.build'];
- $S['wizard.build']->name=$request['name'];
- $S['wizard.build']->write();
+ $configuration=&$S['wizard.configuration'];
+ $S['wizard.configuration']->name=$request['name'];
+ $S['wizard.configuration']->write();
$femods=explode(' ', $conf['frontend_modules']);
$bemods=explode(' ', $conf['backend_modules']);
$femod=isset($request['femod']) && isset($femods[$request['femod']])?$femods[$request['femod']]:$femods[0];
$bemod=isset($request['bemod']) && isset($bemods[$request['bemod']])?$bemods[$request['bemod']]:$bemods[0];
- $beopt=new sql_buildopt($build->id, 'backend_module', $bemod);
- $feopt=new sql_buildopt($build->id, 'frontend_module', $femod);
+ $beopt=new sql_configopt($configuration->id, 'backend_module', $bemod);
+ $feopt=new sql_configopt($configuration->id, 'frontend_module', $femod);
debug('wizard', "Backend: $bemod; Frontend: $femod");
$beopt->write();
$feopt->write();
@@ -72,7 +71,7 @@ function init_wizard() {
$module=&$S['wizard.module'];
$S['wizard.step']=1;
}
- if (isset($S['wizard.build'], $S['wizard.step'])) {
+ if (isset($S['wizard.configuration'], $S['wizard.step'])) {
$step=&$S['wizard.step'];
if (is_file(FRONTEND."/modules/$module/step$step.php")) {
require_once(FRONTEND."/modules/$module/step$step.php");
@@ -90,17 +89,17 @@ function init_wizard() {
}
return array('title' => 'Create');
}
-function body_wizard() {
+function body_configurations_wizard() {
global $S, $conf;
- if (isset($S['wizard.build'])) {
+ if (isset($S['wizard.configuration'])) {
if (isset($S['wizard.done'])) {
- echo '<h3>Config finished!</h3><p>Check your build\'s status <a href="'.url('logs/'.$S['wizard.build']->id).'">here</a></p>';
+ echo print_success('Config finished!', '<form action="'.url('configurations').'" method="post"><input type="hidden" name="configuration" value="'.$S['wizard.configuration']->id.'" />Name (optional): <input name="name" value="'.($S['wizard.configuration']->name?htmlentities($S['wizard.configuration']->name):'').'" /> <input type="submit" name="build" value="Build" /></form>');
} else {
- $build=&$S['wizard.build'];
+ $configuration=&$S['wizard.configuration'];
$module=&$S['wizard.module'];
$step=&$S['wizard.step'];
echo '<h3>'.$S['title'].'</h3>';
- echo '<form action="'.url('create/'.$build->id).'" method="post">';
+ echo '<form action="'.url('config/'.$configuration->id).'" method="post">';
require_once(FRONTEND."/modules/$module/step$step.php");
$proc=$module.'_body_step'.$step;
if (!function_exists($proc)) {
@@ -110,7 +109,7 @@ function body_wizard() {
echo '<input type="submit" name="wizard_submit" value="Continue" /></form>';
}
} else {
- echo '<form action="'.url('create').'" method="post"><h3>Request an image built</h3>Name of your build (optional): <input name="name" /><br/>';
+ echo '<form action="'.url('create').'" method="post"><h3>Request an image built</h3>Name of your configuration (optional): <input name="name" /><br/>';
$femods=explode(' ', $conf['frontend_modules']);
$bemods=explode(' ', $conf['backend_modules']);
if (count($femods) > 1) {
diff --git a/frontend/routing.csv b/frontend/routing.csv
index 4b77f29..7b9ea0f 100644
--- a/frontend/routing.csv
+++ b/frontend/routing.csv
@@ -17,10 +17,11 @@
^logs/([a-z0-9]{6})/([0-9]+)$ logview build task
^logs/([a-z0-9]{6})/([0-9]+)/([0-9]+)$ logview build task page
#^logs/([a-z0-9]{6})/live$ livelog build
-# Build creation
-^create$ wizard
-^create/([a-zA-Z0-9]{6})$ wizard build
-^create/([a-zA-Z0-9]{6})/([0-9]+)$ wizard build step
+# Configurations
+^create$ configurations/wizard
+^config/([a-zA-Z0-9]{6})$ configurations/wizard configuration
+^config/([a-zA-Z0-9]{6})/([0-9]+)$ configurations/wizard configuration step
+^configurations$ configurations/manager
# Download finished image
^download/([a-zA-Z0-9]{6})$ downloadimage build
# Session
diff --git a/shared/classes/configopt.php b/shared/classes/configopt.php
new file mode 100644
index 0000000..178d0bb
--- /dev/null
+++ b/shared/classes/configopt.php
@@ -0,0 +1,22 @@
+<?php
+class sql_configopt extends sql_row_obj {
+ protected $table='configopts', $primary_key=array('configuration', 'name'), $columns=array(
+ 'configuration' => array (
+ 'type' => 'CHAR',
+ 'length' => 6,
+ 'not_null' => true,
+ 'refers_to' => 'configurations.id'
+ ),
+ 'name' => array (
+ 'type' => 'VARCHAR',
+ 'length' => 255,
+ 'not_null' => true,
+ 'default' => ''
+ ),
+ 'value' => array (
+ 'type' => 'TEXT'
+ )
+
+ );
+}
+?>
diff --git a/shared/classes/configuration.php b/shared/classes/configuration.php
new file mode 100644
index 0000000..088908f
--- /dev/null
+++ b/shared/classes/configuration.php
@@ -0,0 +1,106 @@
+<?php
+class sql_configuration extends sql_row_obj {
+ protected $table='configurations', $primary_key=array('id'), $columns=array(
+ 'id' => array (
+ 'type' => 'CHAR',
+ 'length' => 6,
+ 'not_null' => true,
+ 'default' => ''
+ ),
+ 'owner' => array (
+ 'type' => 'INT',
+ 'length' => 10,
+ 'unsigned' => true,
+ 'not_null' => true,
+ 'default' => 0,
+ 'refers_to' => 'users.id'
+ ),
+ 'name' => array (
+ 'type' => 'VARCHAR',
+ 'length' => 255
+ ),
+ 'status' => array (
+ 'type' => 'VARCHAR',
+ 'length' => 255,
+ 'not_null' => true,
+ 'default' => ''
+ )
+
+ );
+ // Generates a unique id and sets status to config/step0, writes self to db and returns id
+ public function init() {
+ global $S;
+ $this->owner=$S['user']->id;
+ $this->status='config/step1';
+ $fails=0;
+ while (true) {
+ $id=randstring(6);
+ debug("Trying id=$id...");
+ $r=$S['pdo']->query('SELECT `id` FROM `configurations` WHERE `id`="'.$id.'"');
+ if ($r->rowCount() == 0) {
+ break;
+ }
+ if (++$fails == 10) {
+ throw_exception('Failed 10 times to find a unique configuration id... this shouldn\'t happen.');
+ }
+ }
+ $this->id=$id;
+ $this->write();
+ return $this->id;
+ }
+ // Fetches all available configopts pertaining to this configuration in a nice array
+ function &get_configopts() {
+ global $S;
+ $r=$S['pdo']->query('SELECT * FROM `configopts` WHERE `configuration`="'.$this->id.'"');
+ $opts=array();
+ while ($opt=$r->fetch(PDO::FETCH_ASSOC)) {
+ $opt=new sql_configopt($opt);
+ $opts[$opt->name]=$opt->value; // TODO maybe we should return the actual objects
+ }
+ return $opts;
+ }
+ function build($name=null) {
+ $build=new sql_build();
+ $build->init();
+ $build->name=$name;
+ $opts=$this->get_configopts();
+ $opts['configuration']=$this->id;
+ foreach ($opts as $name => $val) {
+ $opt=new sql_buildopt($build->id, $name, $val);
+ $opt->write();
+ }
+ $build->ctime=time();
+ $build->status='build/ready';
+ $build->write();
+ return $build;
+ }
+ function summary() {
+ $opts=$this->get_configopts();
+ $r=array();
+ foreach($opts as $name => $val) {
+ $name=htmlentities($name);
+ $val=htmlentities($val);
+ $r[]="$name</td><td class=\"val\">$val";
+ }
+ if ($r) {
+ return '<table class="configsummary"><tr><td class="name">'.implode('</td></tr><tr><td class="name">', $r).'</td></tr></table>';
+ } else {
+ return '<i>No options set</i>';
+ }
+ }
+ // Returns an array of the IDs of all the builds that report this configuration as their source
+ function get_builds() {
+ global $S;
+ $r=$S['pdo']->query('SELECT `build` FROM `buildopts` WHERE `name`="configuration" AND `value`="'.$this->id.'"');
+ if ($r->rowCount()) {
+ $builds=array();
+ while ($b=$r->fetch(PDO::FETCH_COLUMN)) {
+ $builds[]=$b;
+ }
+ return $builds;
+ } else {
+ return null;
+ }
+ }
+}
+?>
diff --git a/todo b/todo
index 74d6493..b536ae1 100644
--- a/todo
+++ b/todo
@@ -16,10 +16,8 @@ Separate variables we got from the URL from the rest, stop using $request, inste
Get rid of backend use of echo, debug, etc. and do all logging in the db
Support ~arch installation or remove it from listings
Completely plan out how frontend modules should function - each step needs to report if it finished successfully (required values)
-*** Change over wizard to work on configurations, not actual builds ***
See if I can figure any way to use classes instead of funny named functions (namespaces in 5.3.0 perhaps) - also needs to have a depend of some sort so we can make a quick-config page that doesn't show things that we don't have enough info for yet (use AJAX to show them when we're ready)
Allow backend to define bail-out functions to call when it dies (things like unmounting the ISO it was copying)
Add STDERR (maybe STDOUT) only option to log viewer
-*** Make frontend/backend split possible ***
- Stop directly accessing PKGDIR from the frontend - put whatever info we need in the database and write a script for updating it from the backend
-Add options viewer - part of config process should be read-only version
+*** Make frontend/backend split possible *** - Stop directly accessing PKGDIR from the frontend - put whatever info we need in the database and write a script for updating it from the backend; track which backend is doing which build
+Simplify status to numeric on builds, configurations - varchar isn't necessary