summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Thomas <james.thomas@codethink.co.uk>2015-02-03 16:03:49 (GMT)
committerJames Thomas <james.thomas@codethink.co.uk>2015-02-04 12:09:48 (GMT)
commit28579b3f41688594b60b28e2e5f6ea98f0fdc71d (patch)
tree817e10b8ec749b589a8461ba182c5023f070979c
parenta85ef8ca229d26ff35787f53b30713fe774ee88a (diff)
downloadmorph-baserock/james/img-upgrade.tar.gz
Add support for deploying upgrades from rawdisk imagesbaserock/james/img-upgrade
This patch allows morph to upgrade a system from a pre-deployed rawdisk image. For this to work in your cluster, use "image:/path/to/image.img" instead of "morph: systems/foo.morph"
-rw-r--r--morphlib/plugins/deploy_plugin.py127
1 files changed, 82 insertions, 45 deletions
diff --git a/morphlib/plugins/deploy_plugin.py b/morphlib/plugins/deploy_plugin.py
index 6d506a2..3c074f2 100644
--- a/morphlib/plugins/deploy_plugin.py
+++ b/morphlib/plugins/deploy_plugin.py
@@ -437,14 +437,29 @@ class DeployPlugin(cliapp.Plugin):
any(sys_id in deployment_filter for sys_id in sys_ids):
return
old_status_prefix = self.app.status_prefix
- system_status_prefix = '%s[%s]' % (old_status_prefix, system['morph'])
+ source_type = 'morph'
+ image_path = None
+
+ if 'image' in system:
+ if self.app.settings['upgrade']:
+ source_type='rawdisk'
+ system_status_prefix = '%s[%s]' % (old_status_prefix, system['image'])
+ image_path = system['image']
+ else:
+ raise cliapp.AppException(
+ 'image type can only be used for upgrades')
+ else:
+ system_status_prefix = '%s[%s]' % (old_status_prefix, system['morph'])
+
self.app.status_prefix = system_status_prefix
try:
- # Find the artifact to build
- morph = morphlib.util.sanitise_morphology_path(system['morph'])
- srcpool = build_command.create_source_pool(build_repo, ref, morph)
+ artifact = None
+ if source_type == 'morph':
+ # Find the artifact to build
+ morph = morphlib.util.sanitise_morphology_path(system['morph'])
+ srcpool = build_command.create_source_pool(build_repo, ref, morph)
- artifact = build_command.resolve_artifacts(srcpool)
+ artifact = build_command.resolve_artifacts(srcpool)
deploy_defaults = system.get('deploy-defaults', {})
for system_id, deploy_params in system['deploy'].iteritems():
@@ -486,7 +501,8 @@ class DeployPlugin(cliapp.Plugin):
root_repo_dir,
ref, artifact,
deployment_type,
- location, final_env)
+ location, final_env,
+ source_type, image_path)
for subsystem in system.get('subsystems', []):
self.deploy_system(build_command, deploy_tempdir,
root_repo_dir, build_repo,
@@ -500,7 +516,8 @@ class DeployPlugin(cliapp.Plugin):
self.run_deploy_commands(deploy_tempdir, final_env,
artifact, root_repo_dir,
ref, deployment_type,
- system_tree, deploy_location)
+ system_tree, deploy_location,
+ source_type)
finally:
self.app.status_prefix = system_status_prefix
finally:
@@ -537,7 +554,8 @@ class DeployPlugin(cliapp.Plugin):
pass
def setup_deploy(self, build_command, deploy_tempdir, root_repo_dir, ref,
- artifact, deployment_type, location, env):
+ artifact, deployment_type, location, env, source_type,
+ image_path):
# deployment_type, location and env are only used for saving metadata
# Create a tempdir to extract the rootfs in
@@ -547,55 +565,72 @@ class DeployPlugin(cliapp.Plugin):
# Unpack the artifact (tarball) to a temporary directory.
self.app.status(msg='Unpacking system for configuration')
- if build_command.lac.has(artifact):
- f = build_command.lac.get(artifact)
- elif build_command.rac.has(artifact):
- build_command.cache_artifacts_locally([artifact])
- f = build_command.lac.get(artifact)
- else:
- raise cliapp.AppException('Deployment failed as system is'
- ' not yet built.\nPlease ensure'
- ' the system is built before'
- ' deployment.')
- tf = tarfile.open(fileobj=f)
- tf.extractall(path=system_tree)
-
- self.app.status(
- msg='System unpacked at %(system_tree)s',
- system_tree=system_tree)
-
- self.app.status(
- msg='Writing deployment metadata file')
- metadata = self.create_metadata(
- artifact, root_repo_dir, deployment_type, location, env)
- metadata_path = os.path.join(
- system_tree, 'baserock', 'deployment.meta')
- with morphlib.savefile.SaveFile(metadata_path, 'w') as f:
- json.dump(metadata, f, indent=4,
- sort_keys=True, encoding='unicode-escape')
+ if source_type == 'morph':
+ if build_command.lac.has(artifact):
+ f = build_command.lac.get(artifact)
+ elif build_command.rac.has(artifact):
+ build_command.cache_artifacts_locally([artifact])
+ f = build_command.lac.get(artifact)
+ else:
+ raise cliapp.AppException('Deployment failed as system is'
+ ' not yet built.\nPlease ensure'
+ ' the system is built before'
+ ' deployment.')
+ tf = tarfile.open(fileobj=f)
+ tf.extractall(path=system_tree)
+ self.app.status(
+ msg='System unpacked at %(system_tree)s',
+ system_tree=system_tree)
+
+ self.app.status(
+ msg='Writing deployment metadata file')
+ metadata = self.create_metadata(
+ artifact, root_repo_dir, deployment_type, location, env)
+ metadata_path = os.path.join(
+ system_tree, 'baserock', 'deployment.meta')
+ with morphlib.savefile.SaveFile(metadata_path, 'w') as f:
+ json.dump(metadata, f, indent=4,
+ sort_keys=True, encoding='unicode-escape')
+ elif source_type == 'rawdisk':
+ cliapp.runcmd(['mount', '-t', 'btrfs', '-o',
+ 'ro,subvol=/systems/default/run', image_path,
+ system_tree])
+ # Now that we've mounted the image, actually check to see if
+ # it's a baserock system
+ baserock_path = os.path.join(system_tree, 'baserock')
+ output = cliapp.runcmd(['sh', '-c',
+ 'test -d '+ baserock_path +' || echo -n dirnotfound'])
+ if output == 'dirnotfound':
+ raise cliapp.AppException('%s is not a baserock system!'
+ % image_path)
+
return system_tree
except Exception:
+ if source_type == 'rawdisk':
+ cliapp.runcmd(['umount', system_tree])
shutil.rmtree(system_tree)
raise
def run_deploy_commands(self, deploy_tempdir, env, artifact, root_repo_dir,
- ref, deployment_type, system_tree, location):
+ ref, deployment_type, system_tree, location,
+ source_type):
# Extensions get a private tempdir so we can more easily clean
# up any files an extension left behind
deploy_private_tempdir = tempfile.mkdtemp(dir=deploy_tempdir)
env['TMPDIR'] = deploy_private_tempdir
try:
- # Run configuration extensions.
- self.app.status(msg='Configure system')
- names = artifact.source.morphology['configuration-extensions']
- for name in names:
- self._run_extension(
- root_repo_dir,
- name,
- '.configure',
- [system_tree],
- env)
+ if source_type == 'morph':
+ # Run configuration extensions.
+ self.app.status(msg='Configure system')
+ names = artifact.source.morphology['configuration-extensions']
+ for name in names:
+ self._run_extension(
+ root_repo_dir,
+ name,
+ '.configure',
+ [system_tree],
+ env)
# Run write extension.
self.app.status(msg='Writing to device')
@@ -609,6 +644,8 @@ class DeployPlugin(cliapp.Plugin):
finally:
# Cleanup.
self.app.status(msg='Cleaning up')
+ if source_type == 'rawdisk':
+ cliapp.runcmd(['umount', system_tree])
shutil.rmtree(deploy_private_tempdir)
def _report_extension_stdout(self, line):