diff options
author | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2017-05-23 14:59:24 +0100 |
---|---|---|
committer | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2017-05-23 14:59:24 +0100 |
commit | 9b874110e45b9af3a3bb0a7481bec8918a1c3adb (patch) | |
tree | a619d13d5c3e0913a41c54d352049d7d2efa1385 /old/scripts/release-build | |
parent | 63224e2233280204626b58fcbe5224d3582c8627 (diff) | |
download | definitions-9b874110e45b9af3a3bb0a7481bec8918a1c3adb.tar.gz |
Move existing Baserock definitions into old/ subdirectory
This will be removed in due course.
Diffstat (limited to 'old/scripts/release-build')
-rwxr-xr-x | old/scripts/release-build | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/old/scripts/release-build b/old/scripts/release-build new file mode 100755 index 00000000..cb62f661 --- /dev/null +++ b/old/scripts/release-build @@ -0,0 +1,192 @@ +#!/usr/bin/env python +# Copyright (C) 2014 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. + + +import cliapp +import morphlib +import os +import subprocess +import sys +import time + + +class Build(object): + '''A single distbuild instance.''' + + def __init__(self, name, arch, app): + self.system_name = name + + controller_netloc = app.controllers[arch].split(':') + controller_args = [ + '--controller-initiator-address=%s' % controller_netloc[0], + ] + if len(controller_netloc) > 1: + controller_args.append( + '--controller-initiator-port=%s' % controller_netloc[1]) + + self.command = ['morph', 'distbuild', '--local-changes=ignore'] + self.command += controller_args + [self.system_name] + + def start(self): + self.process = subprocess.Popen(self.command) + + def completed(self): + return (self.process.poll() is not None) + + +class ReleaseApp(cliapp.Application): + + '''Cliapp app that handles distbuilding and deploying a cluster.''' + + def add_settings(self): + self.settings.string_list(['controllers'], + 'a list of distbuild controllers and their ' + 'architecture') + + self.settings.string(['trove-host'], + 'hostname of Trove instance') + + self.settings.string(['artifact-cache-server'], + 'server to fetch artifacts from', default=None) + + self.settings.string(['release-number'], + 'Baserock version of the systems being built', + default='yy.ww') + + def error(self, message): + raise cliapp.AppException(message) + + def check_args(self, args): + if len(args) == 0: + self.error( + "Please pass the name of the release cluster (e.g. " + "clusters/release.morph)") + + if len(args) > 1: + self.error("Too many arguments given.") + + def process_args(self, args): + '''Process the command line''' + self.controllers = {} + controllers_list = self.settings['controllers'] + + for item in controllers_list: + arch, controller = item.split(':', 1) + self.controllers[arch] = controller + + defs_repo = morphlib.definitions_repo.open( + '.', search_for_root=True) + self.loader = defs_repo.get_morphology_loader() + self.finder = morphlib.morphologyfinder.MorphologyFinder(defs_repo) + + self.check_args(args) + + cluster_name = args[0] + cluster, cluster_path = self.load_morphology(cluster_name) + + builds = self.prepare_builds(cluster) + for build in builds: + build.start() + + while not all(build.completed() for build in builds): + time.sleep(1) + + fail = False + for build in builds: + if build.process.returncode != 0: + fail = True + sys.stderr.write( + 'Building failed for %s\n' % build.system_name) + if fail: + raise cliapp.AppException('Building of systems failed') + + if not os.path.exists('release'): + os.mkdir('release') + self.deploy_images(cluster, cluster_path) + + def load_morphology(self, name, kind=None): + path = morphlib.util.sanitise_morphology_path(name) + morph = self.loader.load_from_string( + self.finder.read_file(path)) + if kind: + assert morph['kind'] == kind + return morph, path + + def iterate_systems(self, system_list): + for system in system_list: + yield system['morph'] + if 'subsystems' in system: + for subsystem in self.iterate_systems(system['subsystems']): + yield subsystem + + def prepare_builds(self, cluster): + '''Prepare a list of builds''' + systems = set(self.iterate_systems(cluster['systems'])) + builds = [] + for system_name in systems: + system, _ = self.load_morphology(system_name) + if system['arch'] in self.controllers: + builds.append(Build(system_name, system['arch'], self)) + else: + print("Unable to build %s: no %s distbuild available" % + (system_name, system['arch'])) + return builds + + def deploy_images(self, cluster, cluster_path): + version_label = 'baserock-%s' % self.settings['release-number'] + outputs = {} + + for system in cluster['systems']: + morphology_name = system['morph'] + morphology = self.load_morphology(morphology_name)[0] + if morphology['arch'] not in self.controllers: + continue + + for deployment_name, deployment_info in system['deploy'].iteritems(): + # The release.morph cluster must specify a basename for the file, + # of name and extension. This script knows about name, but it + # can't find out the appropriate file extension without second + # guessing the behaviour of write extensions. + basename = deployment_info['location'] + + if '/' in basename or basename.startswith(version_label): + raise cliapp.AppException( + 'In %s: system %s.location should be just the base name, ' + 'e.g. "%s.img"' % (cluster_path, deployment_name, deployment_name)) + + filename = os.path.join('release', '%s-%s' % (version_label, basename)) + if os.path.exists(filename): + self.output.write('Reusing existing deployment of %s\n' % filename) + else: + self.output.write('Creating %s from release.morph\n' % filename) + self.deploy_single_image(cluster_path, deployment_name, filename, version_label) + + def deploy_single_image(self, cluster_path, name, location, version_label): + deploy_command = [ + 'morph', 'deploy', cluster_path, name, + '--trove-host=%s' % self.settings['trove-host']] + artifact_server = self.settings['artifact-cache-server'] + if artifact_server is not None: + deploy_command.append('--artifact-cache-server=%s' % artifact_server) + deploy_command.extend(( + '%s.location=%s' % (name, location), + '%s.VERSION_LABEL=%s' % (name, version_label) + )) + + cliapp.runcmd(deploy_command, stdout=sys.stdout) + + +ReleaseApp().run() |