summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorJonathan Maw <jonathan.maw@codethink.co.uk>2012-11-28 12:43:24 +0000
committerJonathan Maw <jonathan.maw@codethink.co.uk>2012-12-10 15:16:32 +0000
commit5b3eb6cac0a70ce4fcbc0123d29034936f194271 (patch)
treeb595f86c7a95e90b5ffffa1548e59336930d3612 /scripts
parent8cd95022df4a01a9ffa2f36a4118d0ace8ddbdc0 (diff)
downloadmorph-5b3eb6cac0a70ce4fcbc0123d29034936f194271.tar.gz
Add find-artifacts script
This script reads a built baserock system and finds all the chunks used to build it in the artifact cache
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/find-artifacts123
1 files changed, 123 insertions, 0 deletions
diff --git a/scripts/find-artifacts b/scripts/find-artifacts
new file mode 100755
index 00000000..bd2c02c8
--- /dev/null
+++ b/scripts/find-artifacts
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011-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.
+
+# This is a program to read the metadata of a baserock image to produce a list
+# of all the chunks needed to build said image.
+
+import json
+import os
+import tempfile
+import gzip
+import sys
+import glob
+
+import cliapp
+
+path = os.path.dirname(os.path.dirname(__file__))
+sys.path.append(path)
+import morphlib
+
+# MountableImage yanked from the TrebuchetPlugin and modified slightly
+class MountableImage(object):
+ '''Mountable image (deals with decompression).
+
+ Note, this is a read-only mount in the sense that the decompressed
+ image is not then recompressed after, instead any changes are discarded.
+
+ '''
+ def __init__(self, app, artifact_path):
+ self.app = app
+ self.artifact_path = artifact_path
+
+ def setup(self, path):
+ (tempfd, self.temp_path) = \
+ tempfile.mkstemp(dir=self.app.settings['tempdir'])
+
+ try:
+ with os.fdopen(tempfd, "wb") as outfh:
+ infh = gzip.open(path, "rb")
+ morphlib.util.copyfileobj(infh, outfh)
+ infh.close()
+ except:
+ os.unlink(self.temp_path)
+ raise
+ part = morphlib.fsutils.setup_device_mapping(self.app.runcmd,
+ self.temp_path)
+ mount_point = tempfile.mkdtemp(dir=self.app.settings['tempdir'])
+ morphlib.fsutils.mount(self.app.runcmd, part, mount_point)
+ self.mount_point = mount_point
+ return mount_point
+
+ def cleanup(self, path, mount_point):
+ try:
+ morphlib.fsutils.unmount(self.app.runcmd, mount_point)
+ except:
+ pass
+ try:
+ morphlib.fsutils.undo_device_mapping(self.app.runcmd, path)
+ except:
+ pass
+ try:
+ os.rmdir(mount_point)
+ os.unlink(path)
+ except:
+ pass
+
+ def __enter__(self):
+ return self.setup(self.artifact_path)
+
+ def __exit__(self, exctype, excvalue, exctraceback):
+ self.cleanup(self.temp_path, self.mount_point)
+
+
+class FindArtifacts(cliapp.Application):
+
+ def add_settings(self):
+ self.settings.string(['cachedir'], 'The directory morph writes its '
+ 'cache to')
+ self.settings.string(['tempdir'], 'A temporary directory to mount the '
+ 'system image in')
+
+ def process_args(self, args):
+ artifacts_dir = os.path.join(self.settings['cachedir'], 'artifacts')
+
+ # args[0] is the path to the built image.
+ # Mount the image
+ mount_point = None
+ with MountableImage(self, args[0]) as mount_point:
+ # For each meta file:
+ metadir = os.path.join(mount_point, 'factory-run', 'baserock')
+ metaglob = os.path.join(metadir, '*.meta')
+ for metafile in glob.iglob(metaglob):
+ metafilepath = os.path.join(metadir, metafile)
+ # Read the file as JSON and extract the kind and cache-key
+ with open(metafilepath) as openedmetafile:
+ metajson = json.load(openedmetafile)
+ cache_key = metajson['cache-key']
+
+ # Grab every file in the artifact cache which matches the
+ # cache-key
+ artifact_glob = os.path.join(artifacts_dir, cache_key) + '*'
+ found_artifacts = glob.glob(artifact_glob)
+ if not found_artifacts:
+ raise cliapp.AppException('Could not find cache-key '
+ + cache_key + ' for artifact '
+ + metajson['artifact-name'])
+ for cached_file in found_artifacts:
+ self.output.write(cached_file + "\n")
+
+FindArtifacts().run()