summaryrefslogtreecommitdiff
path: root/morphlib/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'morphlib/plugins')
-rw-r--r--morphlib/plugins/branch_and_merge_new_plugin.py11
-rw-r--r--morphlib/plugins/branch_and_merge_plugin.py2
-rw-r--r--morphlib/plugins/build_plugin.py92
-rw-r--r--morphlib/plugins/deploy_plugin.py155
4 files changed, 165 insertions, 95 deletions
diff --git a/morphlib/plugins/branch_and_merge_new_plugin.py b/morphlib/plugins/branch_and_merge_new_plugin.py
index 8ad9effd..3a3c1d1b 100644
--- a/morphlib/plugins/branch_and_merge_new_plugin.py
+++ b/morphlib/plugins/branch_and_merge_new_plugin.py
@@ -615,15 +615,8 @@ class SimpleBranchAndMergePlugin(cliapp.Plugin):
'''Read in all the morphologies in the root repository.'''
self.app.status(msg='Loading in all morphologies')
morphs = morphlib.morphset.MorphologySet()
- mf = morphlib.morphologyfinder.MorphologyFinder(
- morphlib.gitdir.GitDirectory(
- sb.get_git_directory_name(sb.root_repository_url)))
- for morph in mf.list_morphologies():
- text, filename = mf.read_morphology(morph)
- m = loader.load_from_string(text, filename=filename)
- m.repo_url = sb.root_repository_url
- m.ref = sb.system_branch_name
- morphs.add_morphology(m)
+ for morph in sb.load_all_morphologies(loader):
+ morphs.add_morphology(morph)
return morphs
def petrify(self, args):
diff --git a/morphlib/plugins/branch_and_merge_plugin.py b/morphlib/plugins/branch_and_merge_plugin.py
index 454caade..4666ea96 100644
--- a/morphlib/plugins/branch_and_merge_plugin.py
+++ b/morphlib/plugins/branch_and_merge_plugin.py
@@ -65,7 +65,7 @@ class BranchAndMergePlugin(cliapp.Plugin):
self.app.add_subcommand('old-unpetrify', self.unpetrify)
self.app.add_subcommand(
'tag', self.tag, arg_synopsis='TAG-NAME -- [GIT-COMMIT-ARG...]')
- self.app.add_subcommand('build', self.build,
+ self.app.add_subcommand('old-build', self.build,
arg_synopsis='SYSTEM')
self.app.add_subcommand('old-status', self.status)
self.app.add_subcommand('old-branch-from-image',
diff --git a/morphlib/plugins/build_plugin.py b/morphlib/plugins/build_plugin.py
index e9555888..8e04d0b3 100644
--- a/morphlib/plugins/build_plugin.py
+++ b/morphlib/plugins/build_plugin.py
@@ -15,6 +15,8 @@
import cliapp
+import contextlib
+import uuid
import morphlib
@@ -24,6 +26,8 @@ class BuildPlugin(cliapp.Plugin):
def enable(self):
self.app.add_subcommand('build-morphology', self.build_morphology,
arg_synopsis='(REPO REF FILENAME)...')
+ self.app.add_subcommand('build', self.build,
+ arg_synopsis='SYSTEM')
def disable(self):
pass
@@ -64,3 +68,91 @@ class BuildPlugin(cliapp.Plugin):
build_command = self.app.hookmgr.call('new-build-command',
build_command)
build_command.build(args)
+
+ def build(self, args):
+ '''Build a system image in the current system branch
+
+ Command line arguments:
+
+ * `SYSTEM` is the name of the system to build.
+
+ This builds a system image, and any of its components that
+ need building. The system name is the basename of the system
+ morphology, in the root repository of the current system branch,
+ without the `.morph` suffix in the filename.
+
+ The location of the resulting system image artifact is printed
+ at the end of the build output.
+
+ You do not need to commit your changes before building, Morph
+ does that for you, in a temporary branch for each build. However,
+ note that Morph does not untracked files to the temporary branch,
+ only uncommitted changes to files git already knows about. You
+ need to `git add` and commit each new file yourself.
+
+ Example:
+
+ morph build devel-system-x86_64-generic
+
+ '''
+
+ if len(args) != 1:
+ raise cliapp.AppException('morph build expects exactly one '
+ 'parameter: the system to build')
+
+ # Raise an exception if there is not enough space
+ morphlib.util.check_disk_available(
+ self.app.settings['tempdir'],
+ self.app.settings['tempdir-min-space'],
+ self.app.settings['cachedir'],
+ self.app.settings['cachedir-min-space'])
+
+ system_name = args[0]
+
+ ws = morphlib.workspace.open('.')
+ sb = morphlib.sysbranchdir.open_from_within('.')
+
+ build_uuid = uuid.uuid4().hex
+
+ build_command = morphlib.buildcommand.BuildCommand(self.app)
+ build_command = self.app.hookmgr.call('new-build-command',
+ build_command)
+ loader = morphlib.morphloader.MorphologyLoader()
+ push = self.app.settings['push-build-branches']
+ name = morphlib.git.get_user_name(self.app.runcmd)
+ email = morphlib.git.get_user_email(self.app.runcmd)
+ build_ref_prefix = self.app.settings['build-ref-prefix']
+
+ self.app.status(msg='Starting build %(uuid)s', uuid=build_uuid)
+ self.app.status(msg='Collecting morphologies involved in '
+ 'building %(system)s from %(branch)s',
+ system=system_name, branch=sb.system_branch_name)
+
+ bb = morphlib.buildbranch.BuildBranch(sb, build_ref_prefix,
+ push_temporary=push)
+ with contextlib.closing(bb) as bb:
+
+ for gd, build_ref in bb.add_uncommitted_changes():
+ self.app.status(msg='Adding uncommitted changes '\
+ 'in %(dirname)s to %(ref)s',
+ dirname=gd.dirname, ref=build_ref, chatty=True)
+
+ for gd in bb.inject_build_refs(loader):
+ self.app.status(msg='Injecting temporary build refs '\
+ 'into morphologies in %(dirname)s',
+ dirname=gd.dirname, chatty=True)
+
+ for gd, build_ref in bb.update_build_refs(name, email, build_uuid):
+ self.app.status(msg='Committing changes in %(dirname)s '\
+ 'to %(ref)s',
+ dirname=gd.dirname, ref=build_ref, chatty=True)
+
+ for gd, build_ref, remote in bb.push_build_branches():
+ self.app.status(msg='Pushing %(ref)s in %(dirname)s '\
+ 'to %(remote)s',
+ ref=build_ref, dirname=gd.dirname,
+ remote=remote.get_push_url(), chatty=True)
+
+ build_command.build([bb.root_repo_url,
+ bb.root_ref,
+ system_name])
diff --git a/morphlib/plugins/deploy_plugin.py b/morphlib/plugins/deploy_plugin.py
index 825b0124..09405aa4 100644
--- a/morphlib/plugins/deploy_plugin.py
+++ b/morphlib/plugins/deploy_plugin.py
@@ -15,13 +15,12 @@
import cliapp
-import gzip
+import contextlib
import os
import shutil
import stat
import tarfile
import tempfile
-import urlparse
import uuid
import morphlib
@@ -266,26 +265,74 @@ class DeployPlugin(cliapp.Plugin):
self.app.settings['tempdir-min-space'],
'/', 0)
- cluster = args[0]
+ cluster_name = args[0]
env_vars = args[1:]
- branch_dir = self.other.deduce_system_branch()[1]
- root_repo = self.other.get_branch_config(branch_dir, 'branch.root')
- root_repo_dir = self.other.find_repository(branch_dir, root_repo)
- data = self.other.load_morphology(root_repo_dir, cluster)
+ ws = morphlib.workspace.open('.')
+ sb = morphlib.sysbranchdir.open_from_within('.')
- if data['kind'] != 'cluster':
+ build_uuid = uuid.uuid4().hex
+
+ build_command = morphlib.buildcommand.BuildCommand(self.app)
+ build_command = self.app.hookmgr.call('new-build-command',
+ build_command)
+ loader = morphlib.morphloader.MorphologyLoader()
+ name = morphlib.git.get_user_name(self.app.runcmd)
+ email = morphlib.git.get_user_email(self.app.runcmd)
+ build_ref_prefix = self.app.settings['build-ref-prefix']
+
+ root_repo_dir = morphlib.gitdir.GitDirectory(
+ sb.get_git_directory_name(sb.root_repository_url))
+ mf = morphlib.morphologyfinder.MorphologyFinder(root_repo_dir)
+ cluster_text, cluster_filename = mf.read_morphology(cluster_name)
+ cluster_morphology = loader.load_from_string(cluster_text,
+ filename=cluster_filename)
+
+ if cluster_morphology['kind'] != 'cluster':
raise cliapp.AppException(
"Error: morph deploy is only supported for cluster"
" morphologies.")
- for system in data['systems']:
- self.deploy_system(system, env_vars)
- def deploy_system(self, system, env_vars):
+ bb = morphlib.buildbranch.BuildBranch(sb, build_ref_prefix,
+ push_temporary=False)
+ with contextlib.closing(bb) as bb:
+
+ for gd, build_ref in bb.add_uncommitted_changes():
+ self.app.status(msg='Adding uncommitted changes '\
+ 'in %(dirname)s to %(ref)s',
+ dirname=gd.dirname, ref=build_ref, chatty=True)
+
+ for gd in bb.inject_build_refs(loader):
+ self.app.status(msg='Injecting temporary build refs '\
+ 'into morphologies in %(dirname)s',
+ dirname=gd.dirname, chatty=True)
+
+ for gd, build_ref in bb.update_build_refs(name, email, build_uuid):
+ self.app.status(msg='Committing changes in %(dirname)s '\
+ 'to %(ref)s',
+ dirname=gd.dirname, ref=build_ref, chatty=True)
+
+ for gd, build_ref, remote in bb.push_build_branches():
+ self.app.status(msg='Pushing %(ref)s in %(dirname)s '\
+ 'to %(remote)s',
+ ref=build_ref, dirname=gd.dirname,
+ remote=remote.get_push_url(), chatty=True)
+
+ for system in cluster_morphology['systems']:
+ self.deploy_system(build_command, root_repo_dir,
+ bb.root_repo_url, bb.root_ref,
+ system, env_vars)
+
+ def deploy_system(self, build_command, root_repo_dir, build_repo, ref,
+ system, env_vars):
+ # Find the artifact to build
morph = system['morph']
+ srcpool = build_command.create_source_pool(build_repo, ref,
+ morph + '.morph')
+ artifact = build_command.resolve_artifacts(srcpool)
+
deploy_defaults = system['deploy-defaults']
deployments = system['deploy']
-
for system_id, deploy_params in deployments.iteritems():
user_env = morphlib.util.parse_environment_pairs(
os.environ,
@@ -308,64 +355,11 @@ class DeployPlugin(cliapp.Plugin):
'for system "%s"' % system_id)
morphlib.util.sanitize_environment(final_env)
- self.do_deploy(morph, deployment_type, location, final_env)
-
- def do_deploy(self, system_name, deployment_type, location, env):
- # Deduce workspace and system branch and branch root repository.
- workspace = self.other.deduce_workspace()
- branch, branch_dir = self.other.deduce_system_branch()
- branch_root = self.other.get_branch_config(branch_dir, 'branch.root')
- branch_uuid = self.other.get_branch_config(branch_dir, 'branch.uuid')
-
- # Generate a UUID for the build.
- build_uuid = uuid.uuid4().hex
-
- build_command = morphlib.buildcommand.BuildCommand(self.app)
- build_command = self.app.hookmgr.call('new-build-command',
- build_command)
- push = self.app.settings['push-build-branches']
-
- self.app.status(msg='Starting build %(uuid)s', uuid=build_uuid)
+ self.do_deploy(build_command, root_repo_dir, ref, artifact,
+ deployment_type, location, final_env)
- self.app.status(msg='Collecting morphologies involved in '
- 'building %(system)s from %(branch)s',
- system=system_name, branch=branch)
-
- # Find system branch root repository on the local disk.
- root_repo = self.other.get_branch_config(branch_dir, 'branch.root')
- root_repo_dir = self.other.find_repository(branch_dir, root_repo)
-
- # Get repositories of morphologies involved in building this system
- # from the current system branch.
- build_repos = self.other.get_system_build_repos(
- branch, branch_dir, branch_root, system_name)
-
- # Generate temporary build ref names for all these repositories.
- self.other.generate_build_ref_names(build_repos, branch_uuid)
-
- # Create the build refs for all these repositories and commit
- # all uncommitted changes to them, updating all references
- # to system branch refs to point to the build refs instead.
- self.other.update_build_refs(build_repos, branch, build_uuid, push)
-
- if push:
- self.other.push_build_refs(build_repos)
- build_branch_root = branch_root
- else:
- dirname = build_repos[branch_root]['dirname']
- build_branch_root = urlparse.urljoin('file://', dirname)
-
- # Run the build.
- build_ref = build_repos[branch_root]['build-ref']
- srcpool = build_command.create_source_pool(
- build_branch_root,
- build_ref,
- system_name + '.morph')
- artifact = build_command.resolve_artifacts(srcpool)
-
- if push:
- self.other.delete_remote_build_refs(build_repos)
-
+ def do_deploy(self, build_command, root_repo_dir, ref, artifact,
+ deployment_type, location, env):
# Create a tempdir for this deployment to work in
deploy_tempdir = tempfile.mkdtemp(
@@ -405,7 +399,7 @@ class DeployPlugin(cliapp.Plugin):
for name in names:
self._run_extension(
root_repo_dir,
- build_ref,
+ ref,
name,
'.configure',
[system_tree],
@@ -415,7 +409,7 @@ class DeployPlugin(cliapp.Plugin):
self.app.status(msg='Writing to device')
self._run_extension(
root_repo_dir,
- build_ref,
+ ref,
deployment_type,
'.write',
[system_tree, location],
@@ -428,7 +422,7 @@ class DeployPlugin(cliapp.Plugin):
self.app.status(msg='Finished deployment')
- def _run_extension(self, repo_dir, ref, name, kind, args, env):
+ def _run_extension(self, gd, ref, name, kind, args, env):
'''Run an extension.
The ``kind`` should be either ``.configure`` or ``.write``,
@@ -440,8 +434,9 @@ class DeployPlugin(cliapp.Plugin):
'''
# Look for extension in the system morphology's repository.
- ext = self._cat_file(repo_dir, ref, name + kind)
- if ext is None:
+ try:
+ ext = gd.get_file_from_ref(ref, name + kind)
+ except cliapp.AppException:
# Not found: look for it in the Morph code.
code_dir = os.path.dirname(morphlib.__file__)
ext_filename = os.path.join(code_dir, 'exts', name + kind)
@@ -465,7 +460,7 @@ class DeployPlugin(cliapp.Plugin):
self.app.runcmd(
[ext_filename] + args,
['sh', '-c', 'while read l; do echo `date "+%F %T"` $l; done'],
- cwd=repo_dir, env=env, stdout=None, stderr=None)
+ cwd=gd.dirname, env=env, stdout=None, stderr=None)
if delete_ext:
os.remove(ext_filename)
@@ -474,13 +469,3 @@ class DeployPlugin(cliapp.Plugin):
st = os.stat(filename)
mask = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
return (stat.S_IMODE(st.st_mode) & mask) != 0
-
- def _cat_file(self, repo_dir, ref, pathname):
- '''Retrieve contents of a file from a git repository.'''
-
- argv = ['git', 'cat-file', 'blob', '%s:%s' % (ref, pathname)]
- try:
- return self.app.runcmd(argv, cwd=repo_dir)
- except cliapp.AppException:
- return None
-