diff options
author | Eudyptula <eitan@mosenkis.net> | 2009-07-03 14:04:10 -0400 |
---|---|---|
committer | Eudyptula <eitan@mosenkis.net> | 2009-07-03 14:04:10 -0400 |
commit | b38ffa446425cad5bd1f7bedffb311903c58c823 (patch) | |
tree | d5ec561a722c5e1fae079f0a647836de23704826 | |
parent | Backend can upload finished images; caches state after emerge system completes (diff) | |
download | ingenue-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.css | 15 | ||||
-rw-r--r-- | frontend/include/header.php | 3 | ||||
-rw-r--r-- | frontend/modules/gentoo/step1.php | 6 | ||||
-rw-r--r-- | frontend/modules/gentoo/step2.php | 6 | ||||
-rw-r--r-- | frontend/modules/gentoo/step3.php | 2 | ||||
-rw-r--r-- | frontend/pages/configurations/manager.php | 42 | ||||
-rw-r--r-- | frontend/pages/configurations/wizard.php (renamed from frontend/pages/wizard.php) | 61 | ||||
-rw-r--r-- | frontend/routing.csv | 9 | ||||
-rw-r--r-- | shared/classes/configopt.php | 22 | ||||
-rw-r--r-- | shared/classes/configuration.php | 106 | ||||
-rw-r--r-- | todo | 6 |
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; + } + } +} +?> @@ -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 |