summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEudyptula <eitan@mosenkis.net>2009-07-01 17:46:53 -0400
committerEudyptula <eitan@mosenkis.net>2009-07-01 17:46:53 -0400
commite77f28c56eef5feae20bfc7716e6c11b2195ada0 (patch)
treeb675457e790b107f776e6e26e0255811d24facf7 /backend
parentMany fixes to CD building and some to command execution/logging (diff)
downloadingenue-e77f28c56eef5feae20bfc7716e6c11b2195ada0.tar.gz
ingenue-e77f28c56eef5feae20bfc7716e6c11b2195ada0.tar.bz2
ingenue-e77f28c56eef5feae20bfc7716e6c11b2195ada0.zip
Update both parts for proper modularity, start catalyst-based backend, code cleanup, especially on backend
Diffstat (limited to 'backend')
-rwxr-xr-xbackend/backend.php34
-rw-r--r--backend/functions/build.php90
-rw-r--r--backend/functions/execution.php40
-rw-r--r--backend/functions/makedirs.php18
-rw-r--r--backend/modules/gentoo_catalyst/build.php71
-rw-r--r--backend/modules/gentoo_catalyst/catalyst.conf79
-rw-r--r--backend/modules/gentoo_catalyst/catalystrc6
-rw-r--r--backend/modules/gentoo_portage/build.php78
8 files changed, 315 insertions, 101 deletions
diff --git a/backend/backend.php b/backend/backend.php
index 4e2209a..cde76f0 100755
--- a/backend/backend.php
+++ b/backend/backend.php
@@ -1,8 +1,5 @@
#!/usr/bin/php
<?php
-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);
$pidfile='/var/run/ingenue.pid'; // Doesn't work when not run as root
$opts=getopt('fk');
if (isset($opts['f'])) {
@@ -21,19 +18,19 @@ if (isset($opts['k'])) {
if (is_file($pidfile)) {
$pid=trim(file_get_contents($pidfile));
if (posix_kill($pid, 0)) {
- debug("Sending SIGTERM to $pid");
+ fputs(STDERR, "Sending SIGTERM to $pid");
if (!posix_kill($pid, SIGTERM)) {
- debug("Failed to send SIGTERM to $pid");
+ fputs(STDERR, "Failed to send SIGTERM to $pid");
die(1);
} else {
// TODO wait for $pid to exit
}
} else {
- debug("Couldn't send signal 0 to $pid");
+ fputs(STDERR, "Couldn't send signal 0 to $pid");
die(0);
}
} else {
- debug('No PID file found');
+ fputs(STDERR, 'No PID file found');
}
die();
}
@@ -43,9 +40,12 @@ if (is_file($pidfile)) {
die("Found already running backend PID=$pid.\n");
}
if (posix_geteuid() !== 0)
- debug("Not running as root... this is not going to accomplish much.");
+ 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)
@@ -58,7 +58,19 @@ while (true) {
log_msg('Starting build id='.$build->id);
$success=null;
try {
- $success=build($build);
+ $opts=$build->get_buildopts();
+ $module=$opts['backend_module'];
+ $build_proc=$module.'_build';
+ foreach (glob(BACKEND."/modules/$module/*.php") as $inc) {
+ require_once($inc);
+ }
+ // TODO check that build_proc exists
+ $workdir=WORK.'/build-'.$build->id;
+ fatal(log_status('Creating work directory '.$workdir, mkdir($workdir, 0700)));
+ $success=$build_proc($build, $opts, $workdir);
+ 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();
@@ -75,8 +87,8 @@ while (true) {
$build->write();
unset($build);
}
- log_msg('Sleeping...', false);
+// log_msg('Sleeping...', false);
sleep(5);
- log_msg("done");
+// log_msg("done");
}
?>
diff --git a/backend/functions/build.php b/backend/functions/build.php
deleted file mode 100644
index a5e2058..0000000
--- a/backend/functions/build.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-// This is the main function that carries out a build from start to finish
-function build(&$build) {
- global $conf, $profile;
- $opts=$build->get_buildopts();
- $profile=new sql_profile($opts['profile']);
- $headers=$profile->get_headers();
- $makeconf['pkgdir']=$conf['pkgdir_root'].'/'.$profile->pkgdir;
- $makeconf['chost']=$headers['chost'];
- $makeconf['accept_keywords']=$headers['accept_keywords'];
- $build->write();
- $W=WORK.'/build-'.$build->id;
- fatal(log_status('Creating work directory '.$W, mkdir($W, 0700)));
- $I=$W.'/image';
- fatal(log_status('Creating '.$I, mkdir($I, 0700)));
- $makeconf['root']=$I;
- $C=$W.'/config_root';
- fatal(log_status('Creating '.$C, mkdir($C, 0700)));
- fatal(log_status("Making symlink $C/etc -> $C", symlink('.', "$C/etc")));
- fatal(log_status('Creating '.$W.'/log', mkdir($W.'/log', 0700)));
- $makeconf['port_logdir']=$W.'/log';
- $makeconf['emerge_log_dir']=$conf['port_logdir'];
- fatal(log_status('Creating '.$W.'/tmp', mkdir($W.'/tmp', 0700)));
- $makeconf['portage_tmpdir']=$W.'/tmp';
- $makeconf['emerge_default_opts']=$conf['emerge_default_opts'];
- $contents='';
- foreach ($makeconf as $name => $val) {
- $contents.=strtoupper($name).'='.escapeshellarg($val)."\n";
- }
- unset($makeconf);
- fatal(log_status('Writing '.$C.'/make.conf', file_put_contents($C.'/etc/make.conf', $contents)));
- unset($contents);
- fatal(log_status('Making make.profile symlink to '.$conf['portdir'].'/profiles/'.$headers['profile'], symlink($conf['portdir'].'/profiles/'.$headers['profile'], $C.'/etc/make.profile')));
- $env=array(
- 'PORTAGE_CONFIGROOT' => $C,
- 'PATH' => $_ENV['PATH']
- );
- sql_task::execute_command('Log portage setup', 'emerge --info', $build, true, null, $env);
-// sql_task::execute_command('Pre-installing baselayout', 'emerge baselayout', $build, true, null, array_merge($env, array('USE' => 'build')));
- // TODO create make.conf, make.profile in target /etc
- sql_task::execute_command('Install base system', 'emerge system', $build, true, null, $env);
- if (isset($opts['image_type']) && $opts['image_type'] == 'livecd')
- sql_task::execute_command('Install LiveCD utilities', 'emerge livecd-tools', $build, true, null, $env);
- if (isset($opts['install_packages'])) {
- $pkgs=array();
- foreach (explode(' ', $opts['install_packages']) as $atom) {
- $pkgs[]=escapeshellarg($atom);
- }
- if (count($pkgs) > 1)
- sql_task::execute_command('Check that extra packages will install', 'emerge -p '.implode(' ', $pkgs), $build, true, null, $env);
- foreach ($pkgs as $atom)
- sql_task::execute_command('Install extra package '.$atom, 'emerge '.$atom, $build, true, null, $env);
- }
- $imgtype=isset($opts['image_type'])?$opts['image_type']:'tbz2';
- if ($imgtype == 'tbz2') {
- sql_task::execute_command('Compress finished image to tar/bzip2', "tar -p --same-owner -cjvf '$W/image.tar.bz2' -C '$W/image' .", $build, true, null, $env);
- rename($W.'/image.tar.bz2', COMPLETED.'/build-'.$build->id.'.tar.bz2') || throw_exception('rename failed');
- } elseif ($imgtype == 'tgz') {
- sql_task::execute_command('Compress finished image to tar/gz', "tar -p --same-owner -czvf '$W/image.tar.gz' -C '$W/image' .", $build, true, null, $env);
- rename($W.'/image.tar.gz', COMPLETED.'/build-'.$build->id.'.tar.gz') || throw_exception('rename failed');
- } elseif ($imgtype == 'livecd' || $imgtype == 'installcd') {
- if (strpos($headers['chost'], 'x86_64') === false)
- $minimaliso='/home/eitan/soc/install-x86-minimal-20090623.iso';
- else
- $minimaliso='/home/eitan/soc/install-amd64-minimal-20090625.iso';
- sql_task::execute_command('Mount minimal CD image', "mount -o loop -t iso9660 '$minimaliso' '$W/tmp'", $build, true, null, $env);
- sql_task::execute_command('Copy CD image to writable temp directory', "cp -va '$W/tmp' '$W/cd'", $build, true, null, $env);
- sql_task::execute_command('Unmount CD image', "umount '$W/tmp'", $build, true, null, $env);
- sql_task::execute_command('Copy kernel and initrd from CD to image', "cp -va '$W/cd/isolinux/gentoo' '$W/cd/isolinux/gentoo.igz' '$W/image/boot/'", $build, true, null, $env);
- file_put_contents("$W/unsquashfs-files", "/lib64/modules\n\lib\modules\n");
- sql_task::execute_command('Copy kernel modules from SquashFS to image', "unsquashfs -i -d '$W/image' -e '$W/unsquashfs-files' '$W/cd/image.squashfs'", $build, true, null, $env);
- if ($imgtype == 'livecd') {
- rename("$W/cd/image.squashfs", "$W/image.squashfs.old") || debug('Failed to move old SquashFS');
- sql_task::execute_command('Compress finished image to squashfs', "mksquashfs '$W/image' '$W/cd/image.squashfs' -noappend -info", $build, true, null, $env);
- } else // Install CD
- sql_task::execute_command('Compress finished image to tar/bzip2', "tar -p --same-owner -cjvf '$W/cd/image.tar.bz2' -C '$W/image' .", $build, true, null, $env);
- // TODO port the rest of /usr/lib/catalyst/targets/support/create-iso.sh to support other bootloaders
- // ISOLINUX bootloader
- // mkisofs -J -R -l ${mkisofs_zisofs_opts} -V "${clst_iso_volume_id}" -o ${1} -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table ${clst_target_path}
- sql_task::execute_command('Create ISO image', "mkisofs -J -R -l -V 'Ingenue Build $build->id' -o '$W/image.iso' -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table '$W/cd'", $build, true, null, $env);
- rename("$W/image.iso", COMPLETED.'/build-'.$build->id.'.iso') || throw_exception('rename failed');
- } else {
- throw_exception('invalid image type: '.$imgtype);
- }
- if (!$conf['debug']) {
- sql_task::execute_command('Delete work directory', 'rm -rf "'.$W.'"', $build, true, null, $env);
- }
- return true;
-}
-?>
diff --git a/backend/functions/execution.php b/backend/functions/execution.php
new file mode 100644
index 0000000..dd6dd88
--- /dev/null
+++ b/backend/functions/execution.php
@@ -0,0 +1,40 @@
+<?php
+function execute_command_with_all($description, $command, $fatal=true, $path=null, $env=null) {
+ global $build, $task;
+ $default_env=array(
+ 'PATH' => $_ENV['PATH']
+ );
+ $env=is_array($env)?array_merge($default_env, $env):$default_env;
+ // TODO this won't work once we have internal tasks too - we need to use a common function for tracking order
+ static $buildid=null;
+ static $order=0;
+ if ($build->id !== $buildid) {
+ $buildid=$build->id;
+ $order=0;
+ }
+ $task=new sql_task($build->id, $order++, null, $description, $command);
+ $result=$task->execute($path, $env);
+ unset($task);
+ if ($result != 0 && $fatal) {
+ if ($result > 0)
+ throw_exception($command.' returned with exit status '.$result);
+ elseif ($result == -128)
+ throw_exception($command.' received an unknown signal');
+ else
+ throw_exception($command.' received signal '.-$result);
+ }
+ return $result;
+}
+function execute_command($desc, $cmd) {
+ return execute_command_with_all($desc, $cmd, true, null, null);
+}
+function execute_command_with_env($desc, $cmd, $env) {
+ return execute_command_with_all($desc, $cmd, true, null, $env);
+}
+function execute_command_with_path($desc, $cmd, $path) {
+ return execute_command_with_all($desc, $cmd, true, $path, null);
+}
+function execute_non_fatal_command($desc, $cmd, $path=null, $env=null) {
+ return execute_command_with_all($desc, $cmd, false, $path, $env);
+}
+?>
diff --git a/backend/functions/makedirs.php b/backend/functions/makedirs.php
new file mode 100644
index 0000000..eb572c9
--- /dev/null
+++ b/backend/functions/makedirs.php
@@ -0,0 +1,18 @@
+<?php
+function makedirs() {
+ for ($i=0; $i<func_num_args(); $i++) {
+ $dir=func_get_arg($i);
+ if (is_array($dir)) {
+ call_user_func('makedirs', $dir);
+ } else {
+ makedir($dir);
+ }
+ }
+}
+function makedir($dir) {
+ global $workdir;
+ if (substr($dir, 0, 1) != '/')
+ $dir="$workdir/$dir";
+ fatal(log_status('Creating '.$dir, mkdir($dir, 0700, true)));
+}
+?>
diff --git a/backend/modules/gentoo_catalyst/build.php b/backend/modules/gentoo_catalyst/build.php
new file mode 100644
index 0000000..45b2b6e
--- /dev/null
+++ b/backend/modules/gentoo_catalyst/build.php
@@ -0,0 +1,71 @@
+<?php
+function gentoo_catalyst_build(&$build, &$opts, &$W) {
+ global $conf, $profile;
+ $profile=new sql_profile($opts['profile']);
+ $headers=$profile->get_headers();
+ $arch=explode(' ', $headers['accept_keywords']);
+ $arch=$arch[0];
+ if (substr($arch, 0, 1) == '~')
+ $arch=substr($arch, 1);
+// $C=$W.'/config_root';
+ makedirs('catalyst_tmp', 'snapshot_cache');
+ $catalyst=array(
+ 'digests' => '',
+ 'contents' => '',
+ 'distdir' => '',
+ // 'envscript' => '',
+ 'hash_function' => 'crc32',
+ 'options' => 'pkgcache metadata_overlay seedcache snapcache',
+ 'portdir' => $conf['portdir'],
+ 'sharedir' => '/usr/lib/catalyst', // This may not work on all systems
+ 'snapshotcache' => "$W/snapshot_cache",
+ 'storedir' => "$W/catalyst_tmp"
+ );
+ $ctc=fopen("$W/catalyst.conf", 'w');
+ foreach ($catalyst as $name => $val) {
+ fputs($ctc, "$name=\"$val\"\n");
+ }
+ fclose($ctc);
+ // TODO - stages 1-3 first, only do stage4 if we have extra packages to install
+ $spec=array(
+ 'subarch' => $arch,
+ 'version_stamp' => gmdate('Ymd-His'),
+ 'target' => 'stage4',
+ 'rel_type' => 'default',
+ 'profile' => $headers['profile'],
+ 'snapshot' => gmdate('Ymd'),
+ 'source_subpath' => 'default', // FIXME
+ 'portage_confdir' => '',
+ 'portage_overlay' => '',
+ 'pkgcache_path' => "$W/pkgcache",
+ 'kerncache_path' => '',
+ 'stage4/use' => $headers['use'],
+ 'stage4/packages' => $opts['install_packages'],
+ 'stage4/fsscript' => '',
+ 'stage4/splash_theme' => '',
+ 'stage4/gk_mainargs' => '',
+ 'stage4/linuxrc' => '',
+ 'stage4/motd' => '',
+// 'stage4/modblacklist' => '8139cp', // Not recognized by catalyst
+ 'stage4/rcadd' => '',
+ 'stage4/rcdel' => '',
+ 'stage4/root_overlay' => '',
+ 'stage4/xinitrc' => '',
+ 'stage4/users' => '',
+ 'boot/kernel' => '',
+ 'stage4/unmerge' => '',
+ 'stage4/empty' => '/var/tmp /var/cache /var/db /var/empty /var/lock /var/log /var/run /var/spool /var/state /tmp /usr/portage /usr/share/man /usr/share/info /usr/share/unimaps /usr/include /usr/share/zoneinfo /usr/share/dict /usr/share/doc /usr/share/ss /usr/share/state /usr/share/texinfo /usr/lib/python2.2 /usr/lib/portage /usr/share/gettext /usr/share/i18n /usr/share/rfc /usr/lib/X11/config /usr/lib/X11/etc /usr/lib/X11/doc /usr/src /usr/share/doc /usr/share/man /root/.ccache /etc/cron.daily /etc/cron.hourly /etc/cron.monthly /etc/cron.weekly /etc/logrotate.d /etc/rsync /usr/lib/awk /usr/lib/ccache /usr/lib/gcc-config /usr/lib/nfs /usr/local /usr/diet/include /usr/diet/man /usr/share/consolefonts/partialfonts /usr/share/consoletrans /usr/share/emacs /usr/share/gcc-data /usr/share/genkernel /etc/splash/gentoo /etc/splash/emergence /usr/share/gnuconfig /usr/share/lcms /usr/share/locale /etc/skel',
+ 'stage4/rm' => '/lib/*.a /usr/lib/*.a /usr/lib/gcc-lib/*/*/libgcj* /etc/dispatch-conf.conf /etc/etc-update.conf /etc/*- /etc/issue* /etc/make.conf /etc/man.conf /etc/*.old /root/.viminfo /usr/sbin/fb* /usr/sbin/fsck.cramfs /usr/sbin/fsck.minix /usr/sbin/mkfs.minix /usr/sbin/mkfs.bfs /usr/sbin/mkfs.cramfs /lib/security/pam_access.so /lib/security/pam_chroot.so /lib/security/pam_debug.so /lib/security/pam_ftp.so /lib/security/pam_issue.so /lib/security/pam_mail.so /lib/security/pam_motd.so /lib/security/pam_mkhomedir.so /lib/security/pam_postgresok.so /lib/security/pam_rhosts_auth.so /lib/security/pam_userdb.so /usr/share/consolefonts/1* /usr/share/consolefonts/7* /usr/share/consolefonts/8* /usr/share/consolefonts/9* /usr/share/consolefonts/A* /usr/share/consolefonts/C* /usr/share/consolefonts/E* /usr/share/consolefonts/G* /usr/share/consolefonts/L* /usr/share/consolefonts/M* /usr/share/consolefonts/R* /usr/share/consolefonts/a* /usr/share/consolefonts/c* /usr/share/consolefonts/dr* /usr/share/consolefonts/g* /usr/share/consolefonts/i* /usr/share/consolefonts/k* /usr/share/consolefonts/l* /usr/share/consolefonts/r* /usr/share/consolefonts/s* /usr/share/consolefonts/t* /usr/share/consolefonts/v* /etc/splash/livecd-2006.1/16* /etc/splash/livecd-2006.1/12* /etc/splash/livecd-2006.1/6* /etc/splash/livecd-2006.1/8* /etc/splash/livecd-2006.1/images/silent-16* /etc/splash/livecd-2006.1/images/silent-12* /etc/splash/livecd-2006.1/images/silent-6* /etc/splash/livecd-2006.1/images/silent-8* /etc/splash/livecd-2006.1/images/verbose-16* /etc/splash/livecd-2006.1/images/verbose-12* /etc/splash/livecd-2006.1/images/verbose-6* /etc/splash/livecd-2006.1/images/verbose-8* /etc/make.conf.example /etc/make.globals /etc/resolv.conf'
+ );
+ $specfile=fopen("$W/stage4.spec", 'w');
+ foreach ($spec as $name => $val) {
+ if (strlen($val))
+ fputs($specfile, "$name: $val\n");
+ }
+ fclose($specfile);
+ $pkgdir=$spec['pkgcache_path'].'/'.$spec['rel_type'].'/'.$spec['target'].'-'.$spec['version_stamp'];
+ makedir(dirname($pkgdir));
+ symlink($pkgdir, $profile->pkgdir);
+ execute_command('Running Catalyst for build stage 4', "catalyst -c '$W/catalyst.conf' -f '$W/stage4.spec'");
+}
+?>
diff --git a/backend/modules/gentoo_catalyst/catalyst.conf b/backend/modules/gentoo_catalyst/catalyst.conf
new file mode 100644
index 0000000..ba5505b
--- /dev/null
+++ b/backend/modules/gentoo_catalyst/catalyst.conf
@@ -0,0 +1,79 @@
+# /etc/catalyst/catalyst.conf
+
+# Simple desriptions of catalyst settings. Please refer to the online
+# documentation for more information.
+
+# Creates a .DIGESTS file containing the hash output from any of the supported
+# options below. Adding them all may take a long time.
+# Supported options: sha1, sha224, ripemd128, ripemd320, sha384, crc32,
+# ripemd256, sha256, sha512, ripemd160, md5
+digests="md5 sha1"
+
+# Creates a .CONTENTS file listing the contents of the file. Pick from any of
+# the supported options below:
+# auto - strongly recommended
+# tar-tv - does 'tar tvf FILE'
+# tar-tvz - does 'tar tvzf FILE'
+# tar-tvy - does 'tar tvyf FILE'
+# isoinfo-l - does 'isoinfo -l -i FILE'
+# isoinfo-f - does 'isoinfo -f -i FILE'
+# 'isoinfo-f' is the only option not chosen by the automatic algorithm.
+# If this variable is empty, no .CONTENTS will be generated at all.
+contents="auto"
+
+# distdir specifies where your distfiles are located. This setting should
+# work fine for most default installations.
+distdir="/usr/portage/distfiles"
+
+# envscript allows users to set options such as http proxies, MAKEOPTS,
+# GENTOO_MIRRORS, or any other environment variables needed for building.
+# The envscript file sets environment variables like so:
+# export FOO="bar"
+envscript="/etc/catalyst/catalystrc"
+
+# Internal hash function catalyst should use for things like autoresume,
+# seedcache, etc. The default and fastest is crc32. You should not ever need
+# to change this unless your OS does not support it.
+# Supported options: sha1, sha224, ripemd128, ripemd320, sha384, crc32,
+# ripemd256, sha256, sha512, ripemd160, md5
+hash_function="crc32"
+
+# options set different build-time options for catalyst. Some examples are:
+# autoresume = Attempt to resume a failed build, clear the autoresume flags with
+# the -a option to the catalyst cmdline. -p will clear the autoresume flags
+# as well as your pkgcache and kerncache
+# ( This option is not fully tested, bug reports welcome )
+# ccache = enables build time ccache support (highly recommended)
+# distcc = enable distcc support for building. You have to set distcc_hosts in
+# your spec file.
+# icecream = enables icecream compiler cluster support for building
+# kerncache = keeps a tbz2 of your built kernel and modules (useful if your
+# build stops in livecd-stage2)
+# metadata_overlay = enabled the metadata_overlay cache module in portage, which
+# uses the in-tree metadata
+# pkgcache = keeps a tbz2 of every built package (useful if your build stops
+# prematurely)
+# seedcache = use the build output of a previous target if it exists to speed up
+# the copy
+# snapcache = cache the snapshot so that it can be bind-mounted into the chroot.
+# WARNING: moving parts of the portage tree from within fsscript *will* break
+# your cache. The cache is unlinked before any empty or rm processing, though.
+#
+# (These options can be used together)
+options="autoresume kerncache metadata_overlay pkgcache seedcache snapcache"
+
+# portdir specifies the source portage tree used by the snapshot target.
+portdir="/usr/portage"
+
+# sharedir specifies where all of the catalyst runtime executables are. Most
+# users do not need to change this.
+sharedir="/usr/lib64/catalyst"
+
+# snapshot_cache specifies where the snapshots will be cached to if snapcache is
+# enabled in the options.
+snapshot_cache="/var/tmp/catalyst/snapshot_cache"
+
+# storedir specifies where catalyst will store everything that it builds, and
+# also where it will put its temporary files and caches.
+storedir="/var/tmp/catalyst"
+
diff --git a/backend/modules/gentoo_catalyst/catalystrc b/backend/modules/gentoo_catalyst/catalystrc
new file mode 100644
index 0000000..581772d
--- /dev/null
+++ b/backend/modules/gentoo_catalyst/catalystrc
@@ -0,0 +1,6 @@
+#!/bin/bash
+# This is an example catalystrc. As such, it doesn't actually *do* anything.
+
+# Uncomment the following to increase the number of threads used to compile.
+# export MAKEOPTS="-j16"
+
diff --git a/backend/modules/gentoo_portage/build.php b/backend/modules/gentoo_portage/build.php
new file mode 100644
index 0000000..693a85c
--- /dev/null
+++ b/backend/modules/gentoo_portage/build.php
@@ -0,0 +1,78 @@
+<?php
+// This is the main function that carries out a build from start to finish
+function gentoo_portage_build(&$build, &$opts, &$W) {
+ global $conf;
+ $profile=new sql_profile($opts['profile']);
+ $headers=$profile->get_headers();
+ $I=$W.'/image';
+ $C=$W.'/config_root';
+ makedirs($I, $C, "$W/log", "$W/tmp");
+ fatal(log_status("Making symlink $C/etc -> .", symlink('.', "$C/etc")));
+ $makeconf=array(
+ 'pkgdir' => $conf['pkgdir_root'].'/'.$profile->pkgdir,
+ 'chost' => $headers['chost'],
+ 'accept_keywords' => $headers['accept_keywords'],
+ 'root' => $I,
+ 'port_logdir' => "$W/log",
+ 'emerge_log_dir' => "$W/log",
+ 'portage_tmpdir' => "$W/tmp",
+ 'emerge_default_opts' => $conf['emerge_default_opts']
+ );
+ $contents='';
+ foreach ($makeconf as $name => $val)
+ $contents.=strtoupper($name).'='.escapeshellarg($val)."\n";
+ unset($makeconf);
+ fatal(log_status('Writing '.$C.'/make.conf', file_put_contents($C.'/etc/make.conf', $contents)));
+ unset($contents);
+ fatal(log_status('Making make.profile symlink to '.$conf['portdir'].'/profiles/'.$headers['profile'], symlink($conf['portdir'].'/profiles/'.$headers['profile'], $C.'/etc/make.profile')));
+ $prtg_cfgrt=array('PORTAGE_CONFIGROOT' => $C);
+ execute_command_with_env('Log portage setup', 'emerge --info', $prtg_cfgrt);
+// execute_command_with_env('Pre-installing baselayout', 'emerge baselayout', array_merge($prtg_cfgrt, array('USE' => 'build')));
+ // TODO create make.conf, make.profile in target /etc
+ execute_command_with_env('Install base system', 'emerge system', $prtg_cfgrt);
+ if (isset($opts['image_type']) && $opts['image_type'] == 'livecd')
+ execute_command_with_env('Install LiveCD utilities', 'emerge -1 livecd-tools', $prtg_cfgrt);
+ if (isset($opts['install_packages'])) {
+ $pkgs=array();
+ foreach (explode(' ', $opts['install_packages']) as $atom) {
+ $pkgs[]=escapeshellarg($atom);
+ }
+ if (count($pkgs) > 1)
+ execute_command_with_env('Check that extra packages will install', 'emerge -p '.implode(' ', $pkgs), $prtg_cfgrt);
+ foreach ($pkgs as $atom)
+ execute_command_with_env('Install extra package '.$atom, 'emerge '.$atom, $prtg_cfgrt);
+ }
+ $imgtype=isset($opts['image_type'])?$opts['image_type']:'tbz2';
+ if ($imgtype == 'tbz2') {
+ execute_command('Compress finished image to tar/bzip2', "tar -p --same-owner -cjvf '$W/image.tar.bz2' -C '$W/image' .");
+ rename($W.'/image.tar.bz2', COMPLETED.'/build-'.$build->id.'.tar.bz2') || throw_exception('rename failed');
+ } elseif ($imgtype == 'tgz') {
+ execute_command('Compress finished image to tar/gz', "tar -p --same-owner -czvf '$W/image.tar.gz' -C '$W/image' .");
+ rename($W.'/image.tar.gz', COMPLETED.'/build-'.$build->id.'.tar.gz') || throw_exception('rename failed');
+ } elseif ($imgtype == 'livecd' || $imgtype == 'installcd') {
+ if (strpos($headers['chost'], 'x86_64') === false)
+ $minimaliso='/home/eitan/soc/install-x86-minimal-20090623.iso';
+ else
+ $minimaliso='/home/eitan/soc/install-amd64-minimal-20090625.iso';
+ execute_command_with_env('Mount minimal CD image', "mount -o loop -t iso9660 '$minimaliso' '$W/tmp'", $prtg_cfgrt); // TODO check if env is necessary (and for umount)
+ execute_command('Copy CD image to writable temp directory', "cp -va '$W/tmp' '$W/cd'");
+ execute_command_with_env('Unmount CD image', "umount '$W/tmp'", $prtg_cfgrt);
+ execute_command('Copy kernel and initrd from CD to image', "cp -va '$W/cd/isolinux/gentoo' '$W/cd/isolinux/gentoo.igz' '$W/image/boot/'");
+ file_put_contents("$W/unsquashfs-files", "/lib64/modules\n\lib\modules\n");
+ execute_command('Copy kernel modules from SquashFS to image', "unsquashfs -i -d '$W/image' -e '$W/unsquashfs-files' '$W/cd/image.squashfs'");
+ if ($imgtype == 'livecd') {
+ rename("$W/cd/image.squashfs", "$W/image.squashfs.old") || debug('Failed to move old SquashFS');
+ execute_command('Compress finished image to squashfs', "mksquashfs '$W/image' '$W/cd/image.squashfs' -noappend -info");
+ } else // Install CD
+ execute_command('Compress finished image to tar/bzip2', "tar -p --same-owner -cjvf '$W/cd/image.tar.bz2' -C '$W/image' .");
+ // TODO port the rest of /usr/lib/catalyst/targets/support/create-iso.sh to support other bootloaders
+ // ISOLINUX bootloader
+ // mkisofs -J -R -l ${mkisofs_zisofs_opts} -V "${clst_iso_volume_id}" -o ${1} -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table ${clst_target_path}
+ execute_command('Create ISO image', "mkisofs -J -R -l -V 'Ingenue Build $build->id' -o '$W/image.iso' -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table '$W/cd'");
+ rename("$W/image.iso", COMPLETED.'/build-'.$build->id.'.iso') || throw_exception('rename failed');
+ } else {
+ throw_exception('invalid image type: '.$imgtype);
+ }
+ return true;
+}
+?>