summaryrefslogtreecommitdiff
blob: 2874b1a1c1e2b8a675e7d4ffe1903762bddc88e8 (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
134
135
#!/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:
		$S['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.\n");
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
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)
	while (true) {
		$r=query('SELECT * FROM `builds` WHERE `backend`="'.$S['conf']['backend_id'].'" AND `status` IN ("queued","cancel","uploading","upload_failed","building","got_signal") ORDER BY `ctime` ASC LIMIT 1');
		if ($r->rowCount())
			break;
		else {
			$r=query('UPDATE `builds` SET `backend`="'.$S['conf']['backend_id'].'" WHERE `status`="queued" AND `backend` IS NULL ORDER BY `ctime` ASC LIMIT 1');
			if ($r->rowCount() == 0)
				sleep(5);
		}
	}
	$build=new sql_build($r->fetch(PDO::FETCH_ASSOC));
	if (!isset($build->start)) {
		$build->start=time();
		$build->write();
	}
	debug('Starting build id='.$build->id);
	$file=null;
	$owner=$build->get_owner();
	$workdir=WORK."/build-$build->id";
	if (($image=$build->build($workdir)) !== false) {
		try {
			$bundler=$build->get_opt('bundler');
			$bundle_proc="bundle_$bundler";
			if (!function_exists($bundle_proc))
				throw_exception("No bundler function defined for bundler $bundler");
			$opts=$build->get_opts();
			$file=$bundle_proc($image, $workdir, $opts);
			end_internal_task(0); // Just in case
		} catch (Exception $e) {
			log_msg('Caught exception: '.$e->getMessage());
			end_internal_task(1);
			$build->status='failed';
			$build->write();
			xhtmlemail('"'.$owner->name.'" <'.$owner->email.'>', null, $S['conf']['title'].' build failed', 'Your build has failed in bundling stage.  You can find more information at <a href="'.url("build/$build->id").'">'.url("build/$build->id").'</a>');
		}
		$build->finish=time();
		debug('Finished with build id='.$build->id);
		if (isset($file)) {
			debug("Completed build successfully");
			if ($S['conf']['split_setup']) {
				$build->status='uploading';
				$build->write();
				$key=randstring(30);
				$build->set_opt('uploadkey', $key);
				$c=curl_init(url('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 ($S['conf']['debug'] && is_string($result)) {
					debug($result);
				}
				if ($result === false || strpos($result, 'Upload successful') === false) {
					$build->status='upload_failed';
					$build->write();
				} else {
					debug("Transferred $file... unlinking it");
					unlink($file);
					$build->status='complete';
					$build->write();
					shell_exec('rm -rf '.escapeshellarg($workdir));
				}
			} else {
				$build->status='complete';
				$base=basename($file);
				$ext=substr($base, strpos($base, '.'));
				rename($file, COMPLETED.'/build-'.$build->id.$ext);
				$build->write();
				shell_exec('rm -rf '.escapeshellarg($workdir));
			}
			xhtmlemail('"'.$owner->name.'" <'.$owner->email.'>', null, $S['conf']['title'].' build finished', 'Your build has completed successfully.  You can find more information and download the completed image at <a href="'.url("build/$build->id").'">'.url("build/$build->id").'</a>');
		}
	} else {
		$build->status='failed';
		$build->write();
		xhtmlemail('"'.$owner->name.'" <'.$owner->email.'>', null, $S['conf']['title'].' build failed', 'Your build has failed.  You can find more information at <a href="'.url("build/$build->id").'">'.url("build/$build->id").'</a>');
	}
	unset($build);
}
?>