From a2c69fb20002f679698c8774f61c7f186f23100d Mon Sep 17 00:00:00 2001 From: Adam Coldrick Date: Tue, 24 Feb 2015 08:55:57 +0000 Subject: Create device nodes in staging area We can't store devices nodes in OSTree, so we can't create them at artifact build time and store them in the chunk artifacts anymore. Instead, we should create them in the staging area when installing an artifact with a source which has a morphology which defines them into the staging area. Change-Id: I423c5e4b8d6595b95894935329c3bf3517cfa475 --- morphlib/builder.py | 23 ----------------------- morphlib/stagingarea.py | 26 +++++++++++++++++++++++++- morphlib/stagingarea_tests.py | 25 ++++++++++++++----------- 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/morphlib/builder.py b/morphlib/builder.py index 524e85a3..735e70aa 100644 --- a/morphlib/builder.py +++ b/morphlib/builder.py @@ -246,28 +246,6 @@ class ChunkBuilder(BuilderBase): '''Build chunk artifacts.''' - def create_devices(self, destdir): # pragma: no cover - '''Creates device nodes if the morphology specifies them''' - morphology = self.source.morphology - perms_mask = stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO - if 'devices' in morphology and morphology['devices'] is not None: - for dev in morphology['devices']: - destfile = os.path.join(destdir, './' + dev['filename']) - mode = int(dev['permissions'], 8) & perms_mask - if dev['type'] == 'c': - mode = mode | stat.S_IFCHR - elif dev['type'] == 'b': - mode = mode | stat.S_IFBLK - else: - raise IOError('Cannot create device node %s,' - 'unrecognized device type "%s"' - % (destfile, dev['type'])) - self.app.status(msg="Creating device node %s" - % destfile) - os.mknod(destfile, mode, - os.makedev(dev['major'], dev['minor'])) - os.chown(destfile, dev['uid'], dev['gid']) - def build_and_cache(self): # pragma: no cover with self.build_watch('overall-build'): @@ -286,7 +264,6 @@ class ChunkBuilder(BuilderBase): try: self.get_sources(builddir) self.run_commands(builddir, destdir, temppath, stdout) - self.create_devices(destdir) os.rename(temppath, logpath) except BaseException as e: diff --git a/morphlib/stagingarea.py b/morphlib/stagingarea.py index ae11dea7..28b22031 100644 --- a/morphlib/stagingarea.py +++ b/morphlib/stagingarea.py @@ -154,7 +154,31 @@ class StagingArea(object): raise IOError('Cannot extract %s into staging-area. Unsupported' ' type.' % srcpath) - def install_artifact(self, handle): + def create_devices(self, morphology): # pragma: no cover + '''Creates device nodes if the morphology specifies them''' + perms_mask = stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO + if 'devices' in morphology and morphology['devices'] is not None: + for dev in morphology['devices']: + destfile = os.path.join(self.dirname, './' + dev['filename']) + mode = int(dev['permissions'], 8) & perms_mask + if dev['type'] == 'c': + mode = mode | stat.S_IFCHR + elif dev['type'] == 'b': + mode = mode | stat.S_IFBLK + else: + raise IOError('Cannot create device node %s,' + 'unrecognized device type "%s"' + % (destfile, dev['type'])) + parent = os.path.dirname(destfile) + if not os.path.exists(parent): + os.makedirs(parent) + if not os.path.exists(destfile): + logging.debug("Creating device node %s" % destfile) + os.mknod(destfile, mode, + os.makedev(dev['major'], dev['minor'])) + os.chown(destfile, dev['uid'], dev['gid']) + + def install_artifact(self, artifact, artifact_checkout): '''Install a build artifact into the staging area. We access the artifact via an open file handle. For now, we assume diff --git a/morphlib/stagingarea_tests.py b/morphlib/stagingarea_tests.py index 4b772e1e..ffdf5eaa 100644 --- a/morphlib/stagingarea_tests.py +++ b/morphlib/stagingarea_tests.py @@ -30,6 +30,7 @@ class FakeBuildEnvironment(object): } self.extra_path = ['/extra-path'] + class FakeSource(object): def __init__(self): @@ -39,6 +40,12 @@ class FakeSource(object): self.name = 'le-name' +class FakeArtifact(object): + + def __init__(self): + self.source = FakeSource() + + class FakeApplication(object): def __init__(self, cachedir, tempdir): @@ -83,12 +90,8 @@ class StagingAreaTests(unittest.TestCase): os.mkdir(chunkdir) with open(os.path.join(chunkdir, 'file.txt'), 'w'): pass - chunk_tar = os.path.join(self.tempdir, 'chunk.tar') - tf = tarfile.TarFile(name=chunk_tar, mode='w') - tf.add(chunkdir, arcname='.') - tf.close() - return chunk_tar + return chunkdir def list_tree(self, root): files = [] @@ -137,15 +140,15 @@ class StagingAreaTests(unittest.TestCase): self.assertEqual(self.sa.relative(filename), '/foobar') def test_installs_artifact(self): - chunk_tar = self.create_chunk() - with open(chunk_tar, 'rb') as f: - self.sa.install_artifact(f) + artifact = FakeArtifact() + chunkdir = self.create_chunk() + self.sa.install_artifact(artifact, chunkdir) self.assertEqual(self.list_tree(self.staging), ['/', '/file.txt']) def test_removes_everything(self): - chunk_tar = self.create_chunk() - with open(chunk_tar, 'rb') as f: - self.sa.install_artifact(f) + artifact = FakeArtifact() + chunkdir = self.create_chunk() + self.sa.install_artifact(artifact, chunkdir) self.sa.remove() self.assertFalse(os.path.exists(self.staging)) -- cgit v1.2.1