[PATCH 03/17] Add ExtractedTarball class and method to extract/mount an artifact

Jonathan Maw jonathan.maw at codethink.co.uk
Thu Jan 24 18:45:08 GMT 2013


From: Jannis Pohlmann <jannis.pohlmann at codethink.co.uk>

ExtractedTarball is more or less the equivalent to MountableImage for
artifacts that are not mountable images. So in order to inspect root
file system tarballs, ExtractedTarball can be used, for disk images,
MountableImage can be used.

The morphlib.bins.call_in_artifact_directory() method combines these
two classes and provides a way to extract/mount an artifact and call
a callback with the temporary directory / mount point as its first
argument. Using this, a plugin that runs a command relative to an
artifact's root directory can be written easily.
---
 morphlib/__init__.py         |  1 +
 morphlib/bins.py             | 27 ++++++++++++++++++++
 morphlib/extractedtarball.py | 61 ++++++++++++++++++++++++++++++++++++++++++++
 without-test-modules         |  1 +
 4 files changed, 90 insertions(+)
 create mode 100644 morphlib/extractedtarball.py

diff --git a/morphlib/__init__.py b/morphlib/__init__.py
index ec44903..a3a277b 100644
--- a/morphlib/__init__.py
+++ b/morphlib/__init__.py
@@ -40,6 +40,7 @@ import builder2
 import cachedir
 import cachedrepo
 import cachekeycomputer
+import extractedtarball
 import fsutils
 import git
 import localartifactcache
diff --git a/morphlib/bins.py b/morphlib/bins.py
index 622aa16..d77abcd 100644
--- a/morphlib/bins.py
+++ b/morphlib/bins.py
@@ -21,6 +21,7 @@ Binaries are chunks, strata, and system images.
 '''
 
 
+import cliapp
 import logging
 import os
 import re
@@ -29,6 +30,11 @@ import stat
 import shutil
 import tarfile
 
+import morphlib
+
+from morphlib.extractedtarball import ExtractedTarball
+from morphlib.mountableimage import MountableImage
+
 
 # Work around http://bugs.python.org/issue16477
 def safe_makefile(self, tarinfo, targetpath):
@@ -211,3 +217,24 @@ def unpack_binary_from_file(f, dirname):  # pragma: no cover
 def unpack_binary(filename, dirname):
     with open(filename, "rb") as f:
         unpack_binary_from_file(f, dirname)
+
+
+class ArtifactNotMountableError(cliapp.AppException): # pragma: no cover
+
+    def __init__(self, filename):
+        cliapp.AppException.__init__(
+                self, 'Artifact %s cannot be extracted or mounted' % filename)
+
+
+def call_in_artifact_directory(app, filename, callback): # pragma: no cover
+    '''Call a function in a directory the artifact is extracted/mounted in.'''
+
+    try:
+        with ExtractedTarball(app, filename) as dirname:
+            callback(dirname)
+    except tarfile.TarError:
+        try:
+            with MountableImage(app, filename) as dirname:
+                callback(dirname)
+        except (IOError, OSError):
+            raise ArtifactNotMountableError(filename)
diff --git a/morphlib/extractedtarball.py b/morphlib/extractedtarball.py
new file mode 100644
index 0000000..afd4f1f
--- /dev/null
+++ b/morphlib/extractedtarball.py
@@ -0,0 +1,61 @@
+# Copyright (C) 2012  Codethink Limited
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+import cliapp
+import gzip
+import os
+import tempfile
+import shutil
+
+import morphlib
+
+
+class ExtractedTarball(object): # pragma: no cover
+
+    '''Tarball extracted in a temporary directory.
+
+    This can be used e.g. to inspect the contents of a rootfs tarball.
+
+    '''
+    def __init__(self, app, tarball):
+        self.app = app
+        self.tarball = tarball
+
+    def setup(self):
+        self.app.status(msg='Preparing tarball %(tarball)s',
+                        tarball=os.path.basename(self.tarball), chatty=True)
+        self.app.status(msg='  Extracting...', chatty=True)
+        self.tempdir = tempfile.mkdtemp(dir=self.app.settings['tempdir'])
+        try:
+            morphlib.bins.unpack_binary(self.tarball, self.tempdir)
+        except:
+            shutil.rmtree(self.tempdir)
+            raise
+        return self.tempdir
+
+    def cleanup(self):
+        self.app.status(msg='Cleanup extracted tarball %(tarball)s',
+                        tarball=os.path.basename(self.tarball), chatty=True)
+        try:
+            shutil.rmtree(self.tempdir)
+        except:
+            pass
+
+    def __enter__(self):
+        return self.setup()
+
+    def __exit__(self, exctype, excvalue, exctraceback):
+        self.cleanup()
diff --git a/without-test-modules b/without-test-modules
index 9666628..d1c68f0 100644
--- a/without-test-modules
+++ b/without-test-modules
@@ -6,6 +6,7 @@ morphlib/git.py
 morphlib/fsutils.py
 morphlib/app.py
 morphlib/mountableimage.py
+morphlib/extractedtarball.py
 morphlib/plugins/hello_plugin.py
 morphlib/plugins/graphing_plugin.py
 morphlib/plugins/syslinux-disk-systembuilder_plugin.py
-- 
1.7.11.7





More information about the baserock-dev mailing list