diff options
author | Lars Wirzenius <liw@liw.fi> | 2011-10-05 12:20:38 +0100 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2011-10-05 12:20:38 +0100 |
commit | 1c2c62bf836b0b178aec42688a6489d31a876fc5 (patch) | |
tree | 9a14ba24568f8cab58a1f4922e572cf4beb652f1 | |
parent | cc412bb982172afcf0e618ea8de5f718f2b13cf4 (diff) | |
download | morph-1c2c62bf836b0b178aec42688a6489d31a876fc5.tar.gz |
Build system morphologies.
-rw-r--r-- | morphlib/builder.py | 86 |
1 files changed, 84 insertions, 2 deletions
diff --git a/morphlib/builder.py b/morphlib/builder.py index d687fefb..1c6e0cf6 100644 --- a/morphlib/builder.py +++ b/morphlib/builder.py @@ -17,6 +17,7 @@ import json import logging import os +import shutil import StringIO import urlparse @@ -62,6 +63,8 @@ class Builder(object): self.settings['chunk-ref']) elif morph.kind == 'stratum': self.build_stratum(morph) + elif morph.kind == 'system': + self.build_system(morph) else: raise Exception('Unknown kind of morphology: %s' % morph.kind) @@ -81,7 +84,7 @@ class Builder(object): self.ex.run(morph.build_commands) self.ex.run(morph.test_commands) os.mkdir(self._inst) - self.ex.run(morph.install_commands, as_root=True) + self.ex.run(morph.install_commands, as_fakeroot=True) self.prepare_binary_metadata(morph, repo=repo, ref=self.get_git_commit_id(repo, ref)) @@ -132,8 +135,9 @@ class Builder(object): filename = self.get_cached_name('chunk', chunk_repo, chunk_ref) self.unpack_chunk(filename) self.prepare_binary_metadata(morph) - self.create_stratum(morph) + stratum_filename = self.create_stratum(morph) self.tempdir.clear() + return stratum_filename def unpack_chunk(self, filename): self.ex.runv(['tar', '-C', self._inst, '-xf', filename]) @@ -149,6 +153,7 @@ class Builder(object): filename = self.get_cached_name('stratum', '', '') logging.debug('Creating stratum %s at %s' % (morph.name, filename)) self.ex.runv(['tar', '-C', self._inst, '-czf', filename, '.']) + return filename @property def _build(self): @@ -223,3 +228,80 @@ class Builder(object): json.dump(meta, f, indent=4) f.write('\n') + def build_system(self, morph): + '''Build a system image.''' + + # Build strata. + stratum_filenames = [] + for stratum in morph.strata: + with open('%s.morph' % stratum) as f: + stratum_morph = morphlib.morphology.Morphology(f, + baseurl=self.settings['git-base-url']) + filename = self.build_stratum(stratum_morph) + stratum_filenames.append(filename) + + self.tempdir.clear() + self.msg('Building system image %s' % morph.name) + self.ex = morphlib.execute.Execute(self.tempdir.dirname, self.msg) + + image_name = self.tempdir.join('%s.img' % morph.name) + + # Create image. + self.ex.runv(['qemu-img', 'create', '-f', 'raw', image_name, + morph.disk_size]) + + # Partition it. + self.ex.runv(['parted', '-s', image_name, 'mklabel', 'msdos'], + as_root=True) + self.ex.runv(['parted', '-s', image_name, 'mkpart', 'primary', + '0%', '100%'], as_root=True) + self.ex.runv(['parted', '-s', image_name, 'set', '1', 'boot', 'on'], + as_root=True) + + # Install first stage boot loader into MBR. + self.ex.runv(['install-mbr', image_name], as_root=True) + + # Setup device mapper to access the partition. + out = self.ex.runv(['kpartx', '-av', image_name], as_root=True) + devices = [line.split()[2] + for line in out.splitlines() + if line.startswith('add map ')] + partition = '/dev/mapper/%s' % devices[0] + + try: + # Create filesystem. + self.ex.runv(['mkfs', '-t', 'ext2', partition], as_root=True) + + # Mount it. + mount_point = self.tempdir.join('mnt') + os.mkdir(mount_point) + self.ex.runv(['mount', partition, mount_point], as_root=True) + + # Unpack all strata into filesystem. + for filename in stratum_filenames: + self.ex.runv(['tar', '-C', mount_point, '-xf', filename], + as_root=True) + + # Unmount. + self.ex.runv(['umount', mount_point], as_root=True) + except BaseException, e: + # Unmount. + try: + self.ex.runv(['umount', mount_point], as_root=True) + except Exception: + pass + + # Undo device mapping. + try: + self.ex.runv(['kpartx', '-d', image_name], as_root=True) + except Exception: + pass + raise + + # Undo device mapping. + self.ex.runv(['kpartx', '-d', image_name], as_root=True) + + # Copy image file to cache. + filename = self.get_cached_name('system', '', '') + self.ex.runv(['cp', '-a', image_name, filename]) + |