summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEudyptula <eitan@mosenkis.net>2009-06-19 01:00:34 -0400
committerEudyptula <eitan@mosenkis.net>2009-06-19 01:00:34 -0400
commit28b33c0c19620780290c978cf7df14ef36109916 (patch)
tree5a5bad2f466024b58584abf656b76e20d5795b59
parentRemoved extraneous line from routing.csv (diff)
downloadingenue-28b33c0c19620780290c978cf7df14ef36109916.tar.gz
ingenue-28b33c0c19620780290c978cf7df14ef36109916.tar.bz2
ingenue-28b33c0c19620780290c978cf7df14ef36109916.zip
Added sessions, login, build request on frontend; changed backend to use build queue from db (generated by frontend)
-rwxr-xr-xbackend/backend.php40
-rw-r--r--backend/functions/build.php15
-rw-r--r--backend/functions/error_handling.php2
-rw-r--r--backend/functions/execution.php4
-rw-r--r--frontend/include/header.php37
-rw-r--r--frontend/include/setup.php27
-rw-r--r--frontend/index.php3
-rw-r--r--frontend/pages/login.php55
-rw-r--r--frontend/pages/logview.php10
-rw-r--r--frontend/pages/wizard.php44
-rw-r--r--frontend/routing.csv4
-rwxr-xr-xnewclass.php15
-rw-r--r--shared/classes/session.php30
-rw-r--r--todo2
14 files changed, 232 insertions, 56 deletions
diff --git a/backend/backend.php b/backend/backend.php
index 5e7d657..1cb1cdb 100755
--- a/backend/backend.php
+++ b/backend/backend.php
@@ -3,6 +3,7 @@
require_once(dirname(__FILE__).'/../shared/include/includes.php'); // USE __DIR__ once 5.3.0 is out
require_once(SHARED.'/config.php');
require_once(SHARED.'/include/dbinit.php');
+$pdo=&$S['pdo'];
$opts=getopt('f');
if (isset($opts['f'])) {
$f=pcntl_fork();
@@ -16,34 +17,21 @@ if (isset($opts['f'])) {
echo "I am the child!\n";
}
}
-// TODO this should be in the frontend
-$fails=0;
while (true) {
- $id=randstring(6);
- log_msg("Trying id=$id...", false);
- // Maybe we should query the DB, not see if insert fails?
- $build=new sql_build($id, 0, 'Test build', 'pre-build', null, null);
- try {
- if ($build->write()) {
- if (is_dir(WORK.'/build-'.$id)) {
- log_msg('failed... directory already exists (this is bad - it should be in the database)');
- $build->delete();
- } else {
- break;
- }
+ // TODO check first for builds that need to be resumed
+ $r=$pdo->query('SELECT * FROM `builds` WHERE `status`="build/ready" LIMIT 1'); // TODO ORDER BY `ctime` ASC
+ if ($r->rowCount()) {
+ $build=new sql_build($r->fetch(PDO::FETCH_ASSOC));
+ echo 'Starting build id='.$build->id."\n";
+ try {
+ build($build);
+ } catch (Exception $e) {
+ echo 'Caught exception: '.$e->getMessage()."\n";
}
- } catch (Exception $e) {
- if (get_class($e) != 'PDOException' || !isset($e->errorInfo) || !isset($e->errorInfo[0]) || $e->errorInfo[0] != 23000) {
- log_msg(''); // For \n
- throw ($e);
- } else {
- log_msg('already taken in the database');
- }
- }
- if (++$fails >= 10) {
- log_msg('Something is wrong - failed 10 times to choose a unique build id');
- die;
+ echo 'Finished with build id='.$build->id."\n";
}
+ echo 'Sleeping...';
+ sleep(5);
+ echo "done\n";
}
-build($id);
?>
diff --git a/backend/functions/build.php b/backend/functions/build.php
index 13bacbb..9859020 100644
--- a/backend/functions/build.php
+++ b/backend/functions/build.php
@@ -6,14 +6,15 @@ $conf['pkgdir']='/home/eitan/soc/tinderbox/default-linux-amd64';
$conf['chost']='x86_64-pc-linux-gnu';
$conf['port_logdir']='$W/log';
$conf['emerge_log_dir']=$conf['port_logdir'];
-$conf['emerge_default_opts']='-t -K --color=n';
+$conf['emerge_default_opts']='-t -K --color=n --root-deps=rdeps';
$conf['portage_tmpdir']='$W/tmp';
$profile='/etc/make.profile';
// This is the main function that carries out a build from start to finish
-function build($id) {
+function build(&$build) {
global $conf, $profile;
- $build=new sql_build($id);
- define('W', WORK.'/build-'.$id);
+ $build->status='build/started';
+ $build->write();
+ define('W', WORK.'/build-'.$build->id);
fatal(log_status('Creating work directory '.W, mkdir(W, 0700)));
fatal(log_status('Creating '.W.'/image', mkdir(W.'/image', 0700)));
define('I', W.'/image');
@@ -34,8 +35,8 @@ function build($id) {
'PORTAGE_CONFIGROOT' => C,
'ROOT' => I
);
- fatal(!log_command($id, 'emerge --info', null, $env)!=0);
- fatal(!log_command($id, 'emerge -pv system', null, $env)!=0);
- fatal(!log_command($id, 'emerge -v system', null, $env)!=0);
+ fatal(!log_command($build, 'emerge --info', null, $env)!=0);
+ fatal(!log_command($build, 'emerge -pv system', null, $env)!=0);
+ fatal(!log_command($build, 'emerge -v system', null, $env)!=0);
}
?>
diff --git a/backend/functions/error_handling.php b/backend/functions/error_handling.php
index 4439509..945f556 100644
--- a/backend/functions/error_handling.php
+++ b/backend/functions/error_handling.php
@@ -1,7 +1,7 @@
<?php
function fatal($status) {
if ($status === false) {
- exit(1);
+ throw new Exception('Failed');
} else {
return $status;
}
diff --git a/backend/functions/execution.php b/backend/functions/execution.php
index a06e962..c201adf 100644
--- a/backend/functions/execution.php
+++ b/backend/functions/execution.php
@@ -1,11 +1,11 @@
<?php
-function log_command($id, $command, $path=null, $env=null) {
+function log_command(&$build, $command, $path=null, $env=null) {
$descriptorspec=array(
0 => array('pipe', 'r'), // STDIN
1 => array('pipe', 'w'), // STDOUT
2 => array('pipe', 'w') // STDERR
);
- $task=new sql_task(null, $id, $command, null);
+ $task=new sql_task(null, $build->id, $command, null);
$task->write();
$p=proc_open($command, $descriptorspec, $pipes, $path, $env);
foreach ($pipes as $pipe) {
diff --git a/frontend/include/header.php b/frontend/include/header.php
index ae6f118..578605a 100644
--- a/frontend/include/header.php
+++ b/frontend/include/header.php
@@ -1,6 +1,6 @@
<?php
- ob_start();
- echo xmlheader();
+ob_start();
+echo xmlheader();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
@@ -9,27 +9,36 @@
<link rel="shortcut icon" href="<?php echo url('images/favicon.ico'); ?>" />
<link rel="icon" href="<?php echo url('images/icon.gif'); ?>" type="image/gif" />
<title><?php
- echo ($S['title'] != null?$S['title'].' | ':'').$conf['title'];
+echo ($S['title'] != null?$S['title'].' | ':'').$conf['title'];
?></title>
<?php
- $scripts=array('GetXmlHttpObject', 'url', 'ajax');
- if ($conf['debug']) {
- array_unshift($scripts, 'debug');
- }
- foreach (array_merge($S['scripts'], $scripts) as $script) {
- echo '<script type="text/javascript" src="'.url('js/'.$script.'.js').'"></script>'."\n";
- }
- if (isset($S['head'])) {
- echo $S['head'];
- }
+$scripts=array('GetXmlHttpObject', 'url', 'ajax');
+if ($conf['debug']) {
+ array_unshift($scripts, 'debug');
+}
+foreach (array_merge($S['scripts'], $scripts) as $script) {
+ echo '<script type="text/javascript" src="'.url('js/'.$script.'.js').'"></script>'."\n";
+}
+if (isset($S['head'])) {
+ echo $S['head'];
+}
?>
</head>
<body>
<div id="left" class="box">
<h1>Ingenue</h1>
+<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('logs').'">Log viewer</a></li>';
+?>
+</ul>
</div>
<div id="top" class="box">
-Top stuff
+<?php
+ echo (isset($S['user'])?'<a href="'.url('logout').'">Logout</a>':'<a href="'.url('login').'">Login</a>');
+?>
</div>
<div id="main" class="box">
<?php
diff --git a/frontend/include/setup.php b/frontend/include/setup.php
index df288c4..dbdc3fa 100644
--- a/frontend/include/setup.php
+++ b/frontend/include/setup.php
@@ -25,5 +25,30 @@ if (isset($conf['rootDir'])) { // What on Earth is going on here?
$S['root']=rtrim('http://'.$_SERVER['HTTP_HOST'].($_SERVER['SERVER_PORT']==(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']?443:80)?'':':'.$_SERVER['SERVER_PORT']).$cDir, '/');
}
require_once(SHARED.'/include/dbinit.php');
-// TODO DB init and sql_row_obj::set_pdo_obj
+if (isset($_COOKIE[$conf['cookiename']])) {
+ $cookie=$_COOKIE[$conf['cookiename']];
+ debug('session', 'cookie received '.$conf['cookiename'].'='.htmlentities($cookie));
+ if (preg_match('/[a-z0-9]{30}/', $cookie)) {
+ $r=$S['pdo']->query('SELECT * FROM `sessions` WHERE `id`="'.$cookie.'"');
+ if ($r->rowCount()) {
+ $S['session']=new sql_session($r->fetch(PDO::FETCH_ASSOC));
+ if ($S['session']->atime+$S['session']->expire < time()) {
+ setcookie($conf['cookiename'], '', 1, $S['cookie_dir'], '', false, true);
+ $S['sesion']->delete();
+ unset($S['session']);
+ } else {
+ $S['session']->atime=time();
+ $S['session']->write();
+ $S['user']=new sql_user($S['session']->user);
+ debug('session', 'sessionid='.$S['session']->id.', email='.$S['user']->email);
+ setcookie($conf['cookiename'], $S['session']->id, time()+$conf['sessionlength'], $S['cookie_dir'], '', false, true);
+ }
+ } else {
+ debug('session', 'session not found');
+ setcookie($conf['cookiename'], '', 1, $S['cookie_dir'], '', false, true);
+ }
+ } else {
+ debug('session', 'session id invalid');
+ }
+}
?>
diff --git a/frontend/index.php b/frontend/index.php
index 149bee8..846a3f9 100644
--- a/frontend/index.php
+++ b/frontend/index.php
@@ -42,6 +42,9 @@ for ($line=fgets($routing, 32768); !feof($routing); $line=fgets($routing, 32768)
}
while ($dest != null) {
debug('routing','Routing to '.$dest);
+ if (!is_file('pages/'.$dest.'.php')) {
+ throw new Exception('Routing to '.$dest.' but pages/'.$dest.'.php doesn\'t exist.');
+ }
require_once('pages/'.$dest.'.php');
$dest=str_replace(array('/', '-'), '_', $dest);
$initfunc='init_'.$dest;
diff --git a/frontend/pages/login.php b/frontend/pages/login.php
new file mode 100644
index 0000000..881a821
--- /dev/null
+++ b/frontend/pages/login.php
@@ -0,0 +1,55 @@
+<?php
+function init_login() {
+ global $S, $request, $conf;
+ if (isset($S['user'])) {
+ return 'welcome';
+ } else {
+ if (isset($request['email']) && isset($request['password'])) {
+ $r=$S['pdo']->query('SELECT * FROM `users` WHERE `email`='.$S['pdo']->quote($request['email']).' AND `passhash`="'.sha1($request['password']).'"');
+ if ($r->rowCount()) {
+ $S['user']=new sql_user($r->fetch(PDO::FETCH_ASSOC));
+ $id=null;
+ while (!$id) {
+ $id=randstring(30);
+ $r=$S['pdo']->query('SELECT * FROM `sessions` WHERE `id`="'.$id.'"');
+ if ($r->rowCount()) {
+ $id=null;
+ }
+ }
+ $session=new sql_session($id, $S['user']->id, time(), $conf['sessionlength']);
+ debug('setcookie', $conf['cookiename'].'='.$id);
+ if (setcookie($conf['cookiename'], $session->id, time()+$conf['sessionlength'], $S['cookie_dir'], '', false, true)) {
+ $session->write();
+ $S['login_result']=true;
+ }
+ } else {
+ $S['login_result']=false;
+ }
+ }
+ return array('title' => 'Login');
+ }
+}
+function body_login() {
+ global $request, $S;
+ if (substr($S['request'], 0, 5) != 'login') {
+ $request['go']=$S['request'];
+ echo print_warning('Please sign in to access this page.');
+ }
+ if (isset($S['login_result'])) {
+ if ($S['login_result'] === 'error') {
+ echo print_error('An error occurred while signing you in.');
+ } elseif ($S['login_result']) {
+ echo print_success('Welcome, '.$S['user']->name);
+ echo '<a href="'.url(isset($request['go'])?$request['go']:'').'">Continue</a>';
+die;
+ } else {
+ echo print_error('Your email and password combination was not recognized.');
+ }
+ }
+ echo '<h3>Login</h3><form action="'.url('login').'" method="post">';
+ if (isset($request['go'])) {
+ echo '<input type="hidden" name="go" value="'.htmlentities($request['go']).'" />';
+ }
+ echo 'Email: <input name="email" /><br/>Password: <input type="password" name="password" /><br/><input type="submit" value="Submit" /></form>';
+}
+?>
diff --git a/frontend/pages/logview.php b/frontend/pages/logview.php
index 9ef4ecd..bb4900b 100644
--- a/frontend/pages/logview.php
+++ b/frontend/pages/logview.php
@@ -27,20 +27,24 @@ function body_logview() {
if (isset($request['task']) && is_numeric($request['task'])) {
$s=$S['pdo']->query('SELECT * FROM `buildlogs` WHERE `task`='.$task->id.' ORDER BY `order` ASC');
if ($s->rowCount()) {
- echo '<code>';
+ echo '<div style="font-family: monospace">';
while ($entry=$s->fetch(PDO::FETCH_ASSOC)) {
$entry=new sql_buildlog_entry($entry);
- $text=str_replace("\n", "<br/>\n", htmlentities($entry->text));
+ $text=str_replace(array("\n", "\t"), array("<hr/>\n", str_repeat('&nbsp;', 4)), htmlentities($entry->text));
echo '<a name="entry_'.$task->id.'_'.$entry->order.'"'.($entry->stream=='stderr'?' style="color: red" ':'').' title="'.strtoupper($entry->stream).', entry #'.$entry->order.' @ '.date('D j M Y @ H:i:s', $entry->timestamp).' UTC">'.$text.'</a>';
}
echo '<a name="end">&nbsp;</a>';
- echo '</code>';
+ echo '</div>';
} else {
echo '<b>No output</b>';
}
}
} elseif (isset($request['build']) && preg_match('/[a-z0-9]{6}/', $request['build'])) {
+ echo '<h3>Build '.$request['build'].'</h3>';
$r=$S['pdo']->query('SELECT * FROM `tasks` WHERE `build`="'.$request['build'].'" ORDER BY `id` ASC');
+ if ($r->rowCount() == 0) {
+ echo '<b>No tasks found.</b>';
+ }
$i=0;
while ($task=$r->fetch(PDO::FETCH_ASSOC)) {
$task=new sql_task($task);
diff --git a/frontend/pages/wizard.php b/frontend/pages/wizard.php
new file mode 100644
index 0000000..2e0066c
--- /dev/null
+++ b/frontend/pages/wizard.php
@@ -0,0 +1,44 @@
+<?php
+function init_wizard() {
+ if (isset($GLOBALS['S']['user'])) {
+ return array('title' => 'Image Creator');
+ } else {
+ return 'login';
+ }
+}
+function body_wizard() {
+ global $request, $S;
+ if (isset($request['submit'])) {
+ $fails=0;
+ while (true) {
+ $id=randstring(6);
+ debug("Trying id=$id...");
+ // Maybe we should query the DB, not see if insert fails?
+ $build=new sql_build($id, $S['user']->id, $request['name'], 'build/ready', null, null);
+ try {
+ if ($build->write()) {
+ if (is_dir(WORK.'/build-'.$id)) {
+ debug('failed... directory already exists (this is bad - it should be in the database)');
+ $build->delete();
+ } else {
+ break;
+ }
+ }
+ } catch (Exception $e) {
+ if (get_class($e) != 'PDOException' || !isset($e->errorInfo) || !isset($e->errorInfo[0]) || $e->errorInfo[0] != 23000) {
+ throw ($e);
+ } else {
+ debug('already taken in the database');
+ }
+ }
+ if (++$fails >= 10) {
+ die(print_error('Something is wrong - failed 10 times to choose a unique build id'));
+die;
+ }
+ }
+ echo '<h3>Build submitted</h3><p><b>ID: '.$id.'</b></p><p>Check your build\'s status <a href="'.url('logs/build'.$id).'">here</a>.</p>';
+ } else {
+ echo '<form action="'.url('create').'" method="post"><h3>Request an image built</h3>Name of your build (optional): <input name="name" /><br/><input type="submit" name="submit" value="Submit" /></form>';
+ }
+}
+?>
diff --git a/frontend/routing.csv b/frontend/routing.csv
index 232daef..ba0f7c1 100644
--- a/frontend/routing.csv
+++ b/frontend/routing.csv
@@ -11,9 +11,13 @@
# Home
^$ welcome
+# Logs
^logs$ logview
^logs/build([a-z0-9]{6})$ logview build
^logs/task([0-9]+)$ logview task
+# Build creation
+^create$ wizard
+^create/[0-9]+$ wizard stage
# Session
^login$ login
^logout$ logout
diff --git a/newclass.php b/newclass.php
index f942416..75d20df 100755
--- a/newclass.php
+++ b/newclass.php
@@ -57,9 +57,20 @@ if (!$tables) {
}
echo 'Generating classes for table(s): '.implode(', ', $tables)."\n";
foreach ($tables as $table) {
- $default=rtrim($table, 's');
+ $default='sql_';
+ if (substr($table, -1) == 's') {
+ $default.=substr($table, 0, strlen($table)-1);
+ } else {
+ $default.=$table;
+ }
$class=prompt_string('Class name for table '.$table.':', $default);
- $file=SHARED.'/classes/'.prompt_string('Filename for class '.$class.': '.SHARED.'/classes/', $class.'.php');
+ if (substr($class, 0, 4) == 'sql_') {
+ $default=substr($class, 4);
+ } else {
+ $default=$class;
+ }
+ $default.='.php';
+ $file=SHARED.'/classes/'.prompt_string('Filename for class '.$class.': '.SHARED.'/classes/', $default);
if (is_file($file)) {
if (!prompt_bool($file.' exists. Overwrite?', false)) {
echo 'Skipping table '.$table."\n";
diff --git a/shared/classes/session.php b/shared/classes/session.php
new file mode 100644
index 0000000..9b8a0a2
--- /dev/null
+++ b/shared/classes/session.php
@@ -0,0 +1,30 @@
+<?php
+class sql_session extends sql_row_obj {
+ protected $table='sessions', $primary_key='id', $columns=array(
+ 'id' => array (
+ 'type' => 'VARCHAR',
+ 'length' => 30,
+ 'not_null' => true
+ ),
+ 'user' => array (
+ 'type' => 'INT',
+ 'length' => 10,
+ 'unsigned' => true,
+ 'not_null' => true
+ ),
+ 'atime' => array (
+ 'type' => 'INT',
+ 'length' => 10,
+ 'unsigned' => true,
+ 'not_null' => true
+ ),
+ 'expire' => array (
+ 'type' => 'INT',
+ 'length' => 10,
+ 'unsigned' => true,
+ 'not_null' => true
+ )
+
+ );
+}
+?>
diff --git a/todo b/todo
index b5c6d95..6964cf1 100644
--- a/todo
+++ b/todo
@@ -4,3 +4,5 @@ Investigate using testing branch of portage (2.2)
Add a builds table and class, integrate it in backend
Add signal handling to the backend so when you hit Ctrl-C, it doesn't leave the logs saying "running" for the current task
Find kernels
+Add a 'requested' column to builds so we know which ones to start first
+Add status column of builds to log viewer