summaryrefslogtreecommitdiff
blob: 1f05d6fc62d5758ee1dfd5945cd9414e2e7a1649 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/php
<?php
$pidfile='/var/run/ingenue.pid'; // Doesn't work when not run as root
$opts=getopt('fk');
if (isset($opts['f'])) {
	$f=pcntl_fork();
	switch($f) {
	case -1:
		die("Failed to fork");
	case 0:
		$conf['debug']=false;
		break;
	default:
		die();
	}
}
if (isset($opts['k'])) {
	if (is_file($pidfile)) {
		$pid=trim(file_get_contents($pidfile));
		if (posix_kill($pid, 0)) {
			fputs(STDERR, "Sending SIGTERM to $pid");
			if (!posix_kill($pid, SIGTERM)) {
				fputs(STDERR, "Failed to send SIGTERM to $pid");
				die(1);
			} else {
				// TODO wait for $pid to exit
			}
		} else {
			fputs(STDERR, "Couldn't send signal 0 to $pid");
			die(0);
		}
	} else {
		fputs(STDERR, 'No PID file found');
	}
	die();
}
if (is_file($pidfile)) {
	$pid=trim(file_get_contents($pidfile));
	if (posix_kill($pid, 0))
		die("Found already running backend PID=$pid.\n");
}
if (posix_geteuid() !== 0)
	fputs(STDERR, "Not running as root... this is not going to accomplish much.");
if (file_put_contents($pidfile, posix_getpid()))
	$unlinkpidfile=true;
require_once(dirname(__FILE__).'/../shared/include/includes.php'); // USE __DIR__ once 5.3.0 is out (and 2 lines down)
require_once(BACKEND.'/include/signals.php');
declare(ticks=1);
require_once(SHARED.'/include/dbinit.php');
while (true) {
	// TODO check first for builds that need to be resumed (and figure out how to resume things)
	$S['pdo']->query('LOCK TABLES `builds` WRITE');
	$r=$S['pdo']->query('SELECT * FROM `builds` WHERE `status`="build/ready" ORDER BY `ctime` ASC LIMIT 1');
	if ($r->rowCount()) {
		$build=new sql_build($r->fetch(PDO::FETCH_ASSOC));
		$build->start=time();
		$build->status='build/running';
		$build->write();
		$S['pdo']->query('UNLOCK TABLES');
		log_msg('Starting build id='.$build->id);
		$file=null;
		try {
			if ($conf['split_setup']) {
				$opt=new sql_buildopt($build->id, 'backend', $conf['backend_id']);
				$opt->write();
				unset($opt);
			}
			$opts=$build->get_opts();
			$build_proc=$build->module.'_build';
			require_once(BACKEND."/modules/$build->module/build.php");
			// TODO check that build_proc exists
			$workdir=WORK.'/build-'.$build->id;
			fatal(log_status('Creating work directory '.$workdir, mkdir($workdir, 0700)));
			$image=$build_proc($build, $opts, $workdir);
			require_once(BACKEND."/bundlers/{$opts['bundler']}.php");
			$proc='bundle_'.$opts['bundler'];
			$file=$proc($image, $workdir, $opts);
			if (!$conf['debug']) {
				execute_command('Delete work directory', 'rm -rf "'.$workdir.'"');
			}
		} catch (Exception $e) {
			log_msg('Caught exception: '.$e->getMessage());
			$build->status='finished/failed: '.$e->getMessage();
			$owner=$build->get_owner();
			xhtmlemail('"'.$owner->name.'" <'.$owner->email.'>', null, $conf['title'].' build failed', 'Your build has failed.  You can find more information at <a href="'.url('logs/'.$build->id).'">'.url('logs/'.$build->id).'</a>');
		}
		$build->finish=time();
		log_msg('Finished with build id='.$build->id);
		if (isset($file)) {
			log_msg("Completed build successfully");
			if ($conf['split_setup']) {
				$build->status='finished/uploading';
				$build->write();
				$key=randstring(30);
				$opt=new sql_buildopt($build->id, 'uploadkey', $key);
				$opt->write();
				$c=curl_init($conf['frontend_location'].'/backend/upload_image');
				curl_setopt($c, CURLOPT_POST, 1);
				curl_setopt($c, CURLOPT_POSTFIELDS, array(
					'build' => $build->id,
					'key' => $key,
					'file' => "@$file"
				));
				curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
				$result=curl_exec($c);
				if ($conf['debug'] && is_string($result)) {
					debug($result);
				}
				if ($result === false || strpos($result, 'Upload successful') === false) {
					$build->status='finished/failed: upload failed'.($result === false?' - '.curl_error($c):'');
				} else {
					debug("Transferred $file... unlinking it");
					unlink($file);
					$build->status='finished/success';
				}
			} else {
				$build->status='finished/success';
				$base=basename($file);
				$ext=substr($base, strpos($base, '.'));
				rename($file, COMPLETED.'/build-'.$build->id.$ext);
			}
			xhtmlemail('"'.$owner->name.'" <'.$owner->email.'>', null, $conf['title'].' build finished', 'Your build has completed successfully.  You can find more information and download the completed image at <a href="'.url('logs/'.$build->id).'">'.url('logs/'.$build->id).'</a>');
		}
		$build->write();
		unset($build);
	} else {
		$S['pdo']->query('UNLOCK TABLES');
	}
	//	log_msg('Sleeping...', false);
	sleep(5);
	//	log_msg("done");
}
?>