summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJannis Pohlmann <jannis.pohlmann@codethink.co.uk>2012-12-17 14:16:53 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2013-02-21 15:06:18 +0000
commit6d901c09f611b3cb98d6b88bf99810782610c617 (patch)
tree23bc641a9aa0cd2be4ec0e79ec03e7aae100ad13
parente2a99f9bb762e61053cd3ee788390d0b2bb5e72d (diff)
downloadmorph-6d901c09f611b3cb98d6b88bf99810782610c617.tar.gz
Add ExtractedTarball class and method to extract/mount an artifact
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.
-rw-r--r--morphlib/__init__.py1
-rw-r--r--morphlib/bins.py29
-rw-r--r--morphlib/extractedtarball.py61
-rw-r--r--without-test-modules1
4 files changed, 91 insertions, 1 deletions
diff --git a/morphlib/__init__.py b/morphlib/__init__.py
index 3cf60171..b20c3f01 100644
--- a/morphlib/__init__.py
+++ b/morphlib/__init__.py
@@ -53,6 +53,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 622aa165..ba5f713f 100644
--- a/morphlib/bins.py
+++ b/morphlib/bins.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2011-2012 Codethink Limited
+# Copyright (C) 2011-2013 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
@@ -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 00000000..e435b1ef
--- /dev/null
+++ b/morphlib/extractedtarball.py
@@ -0,0 +1,61 @@
+# Copyright (C) 2012-2013 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 bd82963f..7ba80129 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