summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Coldrick <adam.coldrick@codethink.co.uk>2015-04-10 13:28:39 +0000
committerAdam Coldrick <adam.coldrick@codethink.co.uk>2015-04-10 13:52:27 +0000
commitf16a5206ec97e1c99231968f96f298379bb8a033 (patch)
tree7f7e56e6225d4d7268e16e78ecff9bd58ec615e7
parenta09fea8f54e36a5269d2ae0e69e17651c484d040 (diff)
downloadmorph-f16a5206ec97e1c99231968f96f298379bb8a033.tar.gz
fixup: tidy up deployment
-rw-r--r--morphlib/plugins/deploy_plugin.py103
1 files changed, 79 insertions, 24 deletions
diff --git a/morphlib/plugins/deploy_plugin.py b/morphlib/plugins/deploy_plugin.py
index f68d004a..9c2782e6 100644
--- a/morphlib/plugins/deploy_plugin.py
+++ b/morphlib/plugins/deploy_plugin.py
@@ -27,6 +27,14 @@ import morphlib
from morphlib.artifactcachereference import ArtifactCacheReference
+class NotYetBuiltError(morphlib.Error):
+
+ def __init__(self, name):
+ self.msg = ('Deployment failed as %s is not yet built.\n'
+ 'Please ensure the system is built before deployment.'
+ % name)
+
+
class DeployPlugin(cliapp.Plugin):
def enable(self):
@@ -542,6 +550,20 @@ class DeployPlugin(cliapp.Plugin):
pass
def checkout_stratum(self, path, artifact, lac, rac):
+ """Pull the chunks in a stratum, and checkout them into `path`.
+
+ This reads a stratum artifact and pulls the chunks it contains from
+ the remote into the local artifact cache if they are not already
+ cached locally. Each of these chunks is then checked out into `path`.
+
+ Also download the stratum metadata into the local cache, then place
+ it in the /baserock directory of the system checkout indicated by
+ `path`.
+
+ If any of the chunks have not been cached either locally or remotely,
+ a morphlib.remoteartifactcache.GetError is raised.
+
+ """
with open(lac.get(artifact), 'r') as stratum:
chunks = [ArtifactCacheReference(c) for c in json.load(stratum)]
morphlib.builder.download_depends(chunks, lac, rac)
@@ -556,14 +578,69 @@ class DeployPlugin(cliapp.Plugin):
shutil.copyfileobj(meta_src, meta_dst)
def checkout_strata(self, path, artifact, lac, rac):
+ """Pull the dependencies of `artifact` and checkout them into `path`.
+
+ This assumes that `artifact` is a system artifact. If any of the
+ dependencies aren't cached remotely or locally, this raises a
+ morphlib.remoteartifactcache.GetError.
+
+ """
deps = artifact.source.dependencies
morphlib.builder.download_depends(deps, lac, rac)
for stratum in deps:
self.checkout_stratum(path, stratum, lac, rac)
morphlib.builder.ldconfig(self.app.runcmd, path)
+ def checkout_system(self, build_command, artifact, path):
+ """Checkout a system into `path`.
+
+ This checks out each of the strata into the directory given by `path`,
+ then checks out the system artifact into the same directory. This uses
+ OSTree's `union` checkout mode to overwrite duplicate files but not
+ need an empty directory. Artifacts which aren't cached locally are
+ fetched from the remote cache.
+
+ Raises a NotYetBuiltError if either the system artifact or any of the
+ chunk artifacts in the strata which make up the system aren't cached
+ either locally or remotely.
+
+ """
+ # Check if the system artifact is in the local or remote cache.
+ # If it isn't, we don't need to bother checking out strata before
+ # we fail.
+ if not (build_command.lac.has(artifact)
+ or build_command.rac.has(artifact)):
+ raise NotYetBuiltError(artifact.name)
+
+ # Checkout the strata involved in the artifact into a tempdir
+ self.app.status(msg='Checking out strata in system')
+ try:
+ self.checkout_strata(path, artifact,
+ build_command.lac, build_command.rac)
+
+ self.app.status(msg='Checking out system for configuration')
+ build_command.cache_artifacts_locally([artifact])
+ build_command.lac.get(artifact, path)
+ except (morphlib.ostreeartifactcache.NotCachedError,
+ morphlib.remoteartifactcache.GetError):
+ raise NotYetBuiltError(artifact.name)
+
+ self.app.status(
+ msg='System checked out at %(system_tree)s',
+ system_tree=path)
+
def setup_deploy(self, build_command, deploy_tempdir, root_repo_dir, ref,
artifact, deployment_type, location, env):
+ """Checkout the artifact, create metadata and return the location.
+
+ This checks out the system into a temporary directory, and then mounts
+ this temporary directory alongside a different temporary directory
+ using a union filesystem. This allows changes to be made without
+ touching the checked out artifacts. The deployment metadata file is
+ created and then the directory at which the two temporary directories
+ are mounted is returned.
+
+ """
# deployment_type, location and env are only used for saving metadata
deployment_dir = tempfile.mkdtemp(dir=deploy_tempdir)
@@ -583,26 +660,7 @@ class DeployPlugin(cliapp.Plugin):
deploy_tree = os.path.join(deployment_dir,
'overlay-deploy-%s' % artifact.name)
try:
- # Checkout the strata involved in the artifact into a tempdir
- self.app.status(msg='Checking out strata in system')
- self.checkout_strata(system_tree, artifact,
- build_command.lac, build_command.rac)
-
- self.app.status(msg='Checking out system for configuration')
- if build_command.lac.has(artifact):
- build_command.lac.get(artifact, system_tree)
- elif build_command.rac.has(artifact):
- build_command.cache_artifacts_locally([artifact])
- build_command.lac.get(artifact, system_tree)
- else:
- raise cliapp.AppException('Deployment failed as system is'
- ' not yet built.\nPlease ensure'
- ' the system is built before'
- ' deployment.')
-
- self.app.status(
- msg='System checked out at %(system_tree)s',
- system_tree=system_tree)
+ self.checkout_system(build_command, artifact, system_tree)
union_filesystem = self.app.settings['union-filesystem']
morphlib.fsutils.overlay_mount(self.app.runcmd,
@@ -625,10 +683,7 @@ class DeployPlugin(cliapp.Plugin):
except Exception:
if deploy_tree and os.path.exists(deploy_tree):
morphlib.fsutils.unmount(self.app.runcmd, deploy_tree)
- shutil.rmtree(deploy_tree)
- shutil.rmtree(system_tree)
- shutil.rmtree(overlay_dir)
- shutil.rmtree(work_dir)
+ shutil.rmtree(deployment_dir)
raise
def run_deploy_commands(self, deploy_tempdir, env, artifact, root_repo_dir,