diff options
author | 2009-08-10 16:48:30 -0400 | |
---|---|---|
committer | 2009-08-10 16:48:30 -0400 | |
commit | 3edcf564bc8f41a13a1ed9be4b1cc40976cf6527 (patch) | |
tree | c84d58996b9e8c07f6cf27f0761734a26cfa3d23 /shared | |
parent | Added a makefile for bkisofs-cli (diff) | |
download | ingenue-3edcf564bc8f41a13a1ed9be4b1cc40976cf6527.tar.gz ingenue-3edcf564bc8f41a13a1ed9be4b1cc40976cf6527.tar.bz2 ingenue-3edcf564bc8f41a13a1ed9be4b1cc40976cf6527.zip |
Major backend reorganization - moved much of backend.php into build class, reformated bundlers to be the same format as modules, fixed build status tracking to be properly resumable throughout the process (except stages that create files that get in their own way); etc.
Diffstat (limited to 'shared')
-rw-r--r-- | shared/classes/build.php | 168 | ||||
-rw-r--r-- | shared/classes/task.php | 37 | ||||
-rw-r--r-- | shared/config.php | 3 | ||||
-rw-r--r-- | shared/functions/load_config.php | 2 | ||||
-rw-r--r-- | shared/include/defaults.php | 7 | ||||
-rw-r--r-- | shared/include/includes.php | 5 |
6 files changed, 139 insertions, 83 deletions
diff --git a/shared/classes/build.php b/shared/classes/build.php index 64730fe..10b2043 100644 --- a/shared/classes/build.php +++ b/shared/classes/build.php @@ -36,18 +36,25 @@ class sql_build extends conf_build_common { ), 'status' => array ( 'type' => 'ENUM', - 'length' => '\'queued\',\'uploading\',\'cancel\',\'complete\',\'upload_failed\',\'canceled\',\'failed\',\'got_signal\',\'building\',\'bundling\'', + 'length' => '\'queued\',\'uploading\',\'cancel\',\'complete\',\'canceled\',\'building\',\'bundling\'', 'not_null' => true ), - 'details' => array ( + 'build_step' => array ( 'type' => 'TINYINT', - 'length' => 4 + 'length' => 4, + 'unsigned' => true ), - 'build_step' => array ( + 'num_steps' => array ( 'type' => 'TINYINT', - 'length' => 3, + 'length' => 4, 'unsigned' => true ), + 'failed' => array ( + 'type' => 'ENUM', + 'length' => '\'false\',\'true\'', + 'not_null' => true, + 'default' => 'false' + ), 'ctime' => array ( 'type' => 'INT', 'length' => 10, @@ -71,49 +78,52 @@ class sql_build extends conf_build_common { $perms=$this->visibility == 'public' || owner_or_admin($this->id); $html='<div class="build"><span class="name">'.(isset($this->name) && strlen($this->name)?htmlentities($this->name):'Unnamed Build').'</span> '; $links=array(); - if ($this->status == 'queued') { + switch ($this->status) { + case 'queued': $total=query('SELECT COUNT(*) FROM `builds` WHERE `status`="queued"')->fetch(PDO::FETCH_COLUMN); $num=query('SELECT COUNT(*) FROM `builds` WHERE `status`="queued" AND `ctime` <= '.$this->ctime)->fetch(PDO::FETCH_COLUMN); $html.="<span class=\"status queued\">[queued ($num/$total)]</span>"; - } elseif ($this->status == 'uploading') { + break; + case 'uploading': $html.='<span class="status successful">[uploading]</span>'; if ($perms) $links['Build log']="build/$this->id"; - } elseif ($this->status == 'cancel') { + break; + case 'cancel': $html.='<span class="status queued">[pending cancellation]</span>'; if ($perms) $links['Build log']="build/$this->id"; - } elseif ($this->status == 'building') { - // TODO stage x/y - $html.='<span class="status building">[building ('.$this->build_step.'/'.$this->details.')]</span>'; + break; + case 'building': + case 'bundling': + $html.='<span class="status building">['.$this->status.' ('.$this->build_step.'/'.$this->num_steps.')]</span>'; if ($perms) { //$links['Watch']="build/$this->id/live"; $links['Build Log']="build/$this->id"; } - } elseif ($this->status == 'complete') { - $r=query('SELECT COUNT(*) as `count`, MAX(`time`) as `time` FROM `downloads` WHERE `build`="'.$this->id.'"')->fetch(PDO::FETCH_ASSOC); - $d=($perms && $r['count']?'<a href="'.url("build/$this->id/history").'">':'').$r['count'].' download'.($r['count'] != 1?'s':'').($r['count']?($perms?'</a>':'').'<br/><span class="time">(last at '.date($format, $r['time']).')</span>':''); + break; + case 'complete': + $url="build/$this->id/history"; + if ($perms && $S['request'] != $url) { + $r=query('SELECT COUNT(*) as `count`, MAX(`time`) as `time` FROM `downloads` WHERE `build`="'.$this->id.'"')->fetch(PDO::FETCH_ASSOC); + $d=($r['count']?'<a href="'.url($url).'">':'').$r['count'].' download'.($r['count'] != 1?'s':'').($r['count']?($perms?'</a>':'').'<br/><span class="time">(last at '.date($format, $r['time']).')</span>':''); + } else + $d=''; $html.='<span class="downloads">'.$d.'</span><span class="status successful">[successful]</span>'; $links['Download image']="build/$this->id/download"; if ($perms) $links['Build log']="build/$this->id"; - } elseif ($this->status == 'upload_failed') { - $html.='<span class="status failed">[upload failed]</span>'; - if ($perms) $links['Build log']="build/$this->id"; - } elseif ($this->status == 'failed') { - $html.='<span class="status failed">[failed after step '.$this->build_step.']</span>'; - if ($perms) { - //$links['View output of failed command']="build/$this->id/failure"; - $links['Build log']="build/$this->id"; - } - } elseif ($this->status == 'canceled') { + break; + case 'canceled': $html.='<span class="status failed">[canceled]</span>'; if ($perms) $links['Build log']="build/$this->id"; - } elseif ($this->status == 'got_signal') { - $html.='<span class="status failed">[failed: got signal '.$this->details.' after step '.$this->build_step.']</span>'; - if ($perms) $links['Build log']="build/$this->id"; - } else { + break; + default: $html.='<span class="status failed">[UNKNOWN STATUS: '.$this->status.']</span>'; } - if ($perms && ($this->status == 'upload_failed' || $this->status == 'failed' || $this->status == 'canceled' || $this->status == 'queued' || $this->status == 'complete' || $this->status == 'got_signal')) - $links['Delete']="build/$this->id/delete"; + if ($perms) { + if ($this->status == 'canceled' || $this->status == 'queued' || $this->status == 'complete' || $this->failed == 'true') + $links['Delete']="build/$this->id/delete"; + elseif ($this->status != 'cancel') + $links['Cancel']="build/$this->id/cancel"; + } if ($links) { foreach ($links as $label => $url) { if ($S['request'] == $url) @@ -141,13 +151,6 @@ class sql_build extends conf_build_common { $html.='</div>'; return $html; } - public function queued_tasks() { - global $S; - static $cache; - if (!isset($cache)) - $cache=query('SELECT COUNT(`order`) FROM `tasks` WHERE `start` IS NULL AND `build`="'.$this->id.'"')->fetch(PDO::FETCH_COLUMN); - return $cache; - } public function delete() { global $S; query('DELETE FROM `buildlogs` WHERE `build`="'.$this->id.'"'); @@ -161,43 +164,108 @@ class sql_build extends conf_build_common { public function build($workdir) { global $S; try { - if (!is_dir($workdir)) - log_status('Create work directory '.$workdir, mkdir($workdir, 0700)); $opts=$this->get_opts(); $S['build_steps']=array(); if (!is_readable(BACKEND."/modules/$this->module/build.php")) throw_exception("No build script for module $this->module"); - $dir=require(BACKEND."/modules/$this->module/build.php"); + $imagedir=require(BACKEND."/modules/$this->module/build.php"); switch ($this->status) { case 'queued': - $this->build_step=0; - case 'got_signal': - case 'failed': $this->status='building'; - $this->details=count($S['build_steps']); + $this->build_step=0; + $this->num_steps=count($S['build_steps']); $this->write(); case 'building': $step=$this->build_step; break; - case 'uploading': - case 'upload_failed': - case 'cancel': - case 'bundling': default: - $step=count($S['build_steps']); + return $imagedir; } + if (!is_dir($workdir)) + log_status('Create work directory '.$workdir, mkdir($workdir, 0700)); while ($step < count($S['build_steps'])) { require(BACKEND."/modules/$this->module/{$S['build_steps'][$step]}.php"); $step++; $this->build_step=$step; $this->write(); + if ($this->is_canceled()) return false; } - return $dir; + return $imagedir; } catch(Exception $e) { log_msg('Caught exception: '.$e->getMessage()); end_internal_task(1); + $this->failed(); return false; } } + public function bundle($imagedir, $workdir) { + global $S; + try { + $opts=$this->get_opts(); + $bundler=$opts['bundler']; + if (!is_readable(BACKEND."/bundlers/$bundler/bundle.php")) + throw_exception("No bundle script for bundler $bundler"); + $S['build_steps']=array(); + $file=require(BACKEND."/bundlers/$bundler/bundle.php"); + switch($this->status) { + case 'building': + $this->status='bundling'; + $this->build_step=0; + $this->num_steps=count($S['build_steps']); + $this->write(); + case 'bundling': + $step=$this->build_step; + break; + default: + return $file; + } + print_r($S['build_steps']); + while ($step < count($S['build_steps'])) { + require(BACKEND."/bundlers/$bundler/{$S['build_steps'][$step]}.php"); + $step++; + $this->build_step=$step; + $this->write(); + if ($this->is_canceled()) return false; + } + return $file; + } catch (Exception $e) { + log_msg('Caught exception: '.$e->getMessage()); + end_internal_task(1); + $this->failed(); + return false; + } + } + public function upload($file) { + $this->status='uploading'; + $this->write(); + $key=randstring(30); + $this->set_opt('uploadkey', $key); + $c=curl_init(url('backend/upload_image')); + curl_setopt($c, CURLOPT_POST, 1); + curl_setopt($c, CURLOPT_POSTFIELDS, array( + 'build' => $this->id, + 'key' => $key, + 'file' => "@$file" + )); + curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); + $result=curl_exec($c); + $result($result !== false && strpos($result, 'Upload successful') !== false); + if ($result) { + $this->status='complete'; + $this->finish=time(); + $this->write(); + } else + $this->failed(); + return $result; + } + private function failed() { + $this->failed='true'; + $this->finish=time(); + $this->write(); + } + public function is_canceled() { + $this->load(); + return ($this->status == 'cancel'); + } } ?> diff --git a/shared/classes/task.php b/shared/classes/task.php index d763107..e249e0f 100644 --- a/shared/classes/task.php +++ b/shared/classes/task.php @@ -51,30 +51,25 @@ class sql_task extends sql_row_obj { global $S; $link="build/$this->build/$this->order"; $html='<div class="task"><div class="description">'.htmlentities($this->description).'</div><div class="info">'.($S['request'] == $link || strpos($S['request'], "$link/") === 0?'':'[<a href="'.url($link).'">log</a>] ').($this->command?'<span class="command"'.($this->env?' title="'.htmlentities(str_replace("\n", '; ', $this->env)).'"':'').'>'.htmlentities($this->command).'</span> ':''); - if (isset($this->start)) { - if (isset($this->finish)) { - $html.='<span class="status '; - if ($this->exit === '0') { - $html.='successful">[successful'; - } else { - $html.='failed">['; - if (isset($this->exit)) { - if ($this->exit > 0) - $html.='exit status '.$this->exit; - elseif ($this->exit == -128) - $html.='got unknown signal'; - else - $html.='got signal '.-$this->exit; - } else - $html.='failed to execute'; - } - $html.=']</span> <span class="time">Finished in <span class="time">'.display_time($this->finish-$this->start).'</span></span>'; + if (isset($this->finish)) { + $html.='<span class="status '; + if ($this->exit === '0') { + $html.='successful">[successful'; } else { - $html.='<span class="status running">[running]</span> <span class="time">Running for <span class="time">'.display_time(time()-$this->start).'</span></span>'; + $html.='failed">['; + if (isset($this->exit)) { + if ($this->exit > 0) + $html.='exit status '.$this->exit; + elseif ($this->exit == -128) + $html.='got unknown signal'; + else + $html.='got signal '.-$this->exit; + } else + $html.='failed to execute'; } + $html.=']</span> <span class="time">Finished in <span class="time">'.display_time($this->finish-$this->start).'</span></span>'; } else { - $num=query('SELECT COUNT(*) FROM `tasks` WHERE `builds`="'.$this->build.'" AND `start` IS NULL AND `order` <= '.$this->order)->fetch(PDO::FETCH_ASSOC); - $html.="<span class=\"status queued\">[queued $num/".$build->queued_tasks()."]</span>"; + $html.='<span class="status running">[running]</span> <span class="time">Running for <span class="time">'.display_time(time()-$this->start).'</span></span>'; } $html.='</div></div>'; return $html; diff --git a/shared/config.php b/shared/config.php index 9270d2d..8a93454 100644 --- a/shared/config.php +++ b/shared/config.php @@ -8,14 +8,13 @@ $sqlpass='socpassword'; // MySQL password $sqldb='soc'; // MySQL database $debug=true; // Whether to print debugging information // $modules='All non-hidden dirs in frontend/modules'; // Space-separated list of modules to offer the user -// $bundlers='All non-hidden <bundler>.php files in backend/bundlers'; // Space-separated list of bundlers to offer the user +// $bundlers='All non-hidden dirs in backend/bundlers' that contain a bundle.php; // Space-separated list of bundlers to offer the user // $cookiename='ingenueid'; // Name of the cookie to send for keeping sessions // $sessionlength=1814400; // Time in seconds before sessions are purged // $mod_rewrite=true; // Use mod_rewrite for pretty URLs // $timezone_root='/usr/share/zoneinfo'; // Directory to search for timezone data (sys-libs/timezone-data) $emailfrom='noreply@gentoo.org'; // Used as the From: field in emails $check_email_dns=true; // Use DNS to check the domain of submitted emails for validity -// $split_setup=true; // Whether the frontend and backend are running on different hosts // Frontend options: // $registration=false; // Whether users can create new accounts without an invite // $invite='admin'; // Who can use the invite function: true or 'user'=users; admin=admins; false=nobody diff --git a/shared/functions/load_config.php b/shared/functions/load_config.php index a212b16..d719fb9 100644 --- a/shared/functions/load_config.php +++ b/shared/functions/load_config.php @@ -3,7 +3,7 @@ function load_config() { require(SHARED.'/include/defaults.php'); require(SHARED.'/config.php'); $modules=explode(' ', $modules); - foreach (explode(' ', 'title url sqlhost sqluser sqlpass sqldb debug modules bundlers cookiename sessionlength mod_rewrite timezone_root emailfrom check_email_dns split_setup registration invite logview_max progressbar_width pkgdir_root emerge_default_opts portdir backend_id') as $var) { + foreach (explode(' ', 'title url sqlhost sqluser sqlpass sqldb debug modules bundlers cookiename sessionlength mod_rewrite timezone_root emailfrom check_email_dns registration invite logview_max progressbar_width pkgdir_root emerge_default_opts portdir backend_id') as $var) { if (isset($$var)) { $GLOBALS['S']['conf'][$var]=$$var; } diff --git a/shared/include/defaults.php b/shared/include/defaults.php index ced0e01..95cbfc2 100644 --- a/shared/include/defaults.php +++ b/shared/include/defaults.php @@ -14,10 +14,8 @@ foreach (glob(FRONTEND.'/modules/*.info') as $module) { } $modules=implode(' ', $modules); $bundlers=array(); -foreach (glob(BACKEND.'/bundlers/*.php') as $bundler) { - $bundler=basename($bundler); - $bundlers[]=substr($bundler, 0, strlen($bundler)-4); -} +foreach (glob(BACKEND.'/bundlers/*/bundle.php') as $bundler) + $bundlers[]=basename(dirname($bundler)); $bundlers=implode(' ', $bundlers); $cookiename='ingenueid'; $sessionlength=1814400; @@ -25,7 +23,6 @@ $mod_rewrite=true; $timezone_root='/usr/share/zoneinfo'; $emailfrom='noreply@noreply.net'; $check_email_dns=false; -$split_setup=true; $registration=false; $invite='admin'; $logview_max=1000; diff --git a/shared/include/includes.php b/shared/include/includes.php index 410177f..8a75b58 100644 --- a/shared/include/includes.php +++ b/shared/include/includes.php @@ -9,9 +9,6 @@ foreach (array('functions', 'classes') as $type) { } } } -$includes=($_SERVER['DOCUMENT_ROOT']?FRONTEND:BACKEND).'/include/includes.php'; -if (is_readable($includes)) - require_once($includes); -unset($dir, $file, $type, $includes); +unset($dir, $file, $type); load_config(); ?> |