diff options
author | Richard Maw <richard.maw@codethink.co.uk> | 2012-12-10 15:41:18 +0000 |
---|---|---|
committer | Richard Maw <richard.maw@codethink.co.uk> | 2012-12-10 15:41:18 +0000 |
commit | d63c97a0bef1cd2f03ca266acda67cad065632df (patch) | |
tree | 6e096b8f53e12950ffd3c7f44ea43492d4f5ca3a | |
parent | 1a570efbcd31678ce04c39c080b66735d05a2781 (diff) | |
parent | 5b3eb6cac0a70ce4fcbc0123d29034936f194271 (diff) | |
download | morph-d63c97a0bef1cd2f03ca266acda67cad065632df.tar.gz |
Merge branch 'jonathanmaw/find-artifacts-rebase' of ssh://trove.baserock.org/baserock/baserock/morph
-rwxr-xr-x | scripts/find-artifacts | 123 |
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() |