1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
# Copyright 2014 Codethink Ltd
#
# 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 json
import logging
import morphlib
import os
import subprocess
import time
import urlparse
import mason
class Build(object):
"""A single build instance."""
def __init__(self, name, controller, logfile):
self.system_name = name
self.controller = controller
self.log_path = logfile
self.logfile = open(logfile, 'w+')
#TODO: use distbuild not local build
self.command = [
'morph', 'build', self.system_name]
def start(self):
self.process = subprocess.Popen(self.command, stdout=self.logfile, stderr=self.logfile)
def completed(self):
return (self.process.poll() is not None)
def close_log(self):
self.logfile.close()
class Runner(mason.runners.JobRunner):
"""Test that the built system will deploy and run
This handles running the build-deploy-build test, which
is used to ensure that Baserock can build Baserock.
"""
log = logging.getLogger("mason.tests.build.Runner")
def __init__(self, worker_server, plugin_config, job_name):
super(Runner, self).__init__(worker_server, plugin_config, job_name)
self.total_steps = 4
def run_job(self):
self.log.debug('Got job: %s', self.job_arguments)
self.log.info('Step 1: Creating a workspace')
self._create_workspace()
self.log.info('Step 2: Prepare build log directory')
self._prepare_build_log_dir()
self.log.info('Step 3: Building the systems')
try:
self._build_systems()
except Exception as e:
self._remove_workspace()
raise e
self.log.info('Step 4: Clean up')
self._clean_up()
@staticmethod
def _parse_controllers(conf):
return dict(item.split(':', 1) for item in conf['controllers'])
def _prepare_builds(self, conf):
cluster = self.morph_helper.load_morphology(conf['cluster-morphology'])
systems = set(self.morph_helper.iterate_systems(cluster['systems']))
controllers = self._parse_controllers(conf)
builds = []
for system_name in systems:
system = self.morph_helper.load_morphology(system_name)
print 'loaded %s' % system_name
if system['arch'] in controllers:
logfile = os.path.join(self.logdir, '%s.log' % system['name'])
builds.append(Build(system_name, controllers[system['arch']], logfile))
print 'prepared builds'
return builds
@mason.util.job_step
def _prepare_build_log_dir(self):
self.logdir = '/var/www/logs/%s-%s/build' % \
(self.project, self.commit[:7])
if not os.path.exists(self.logdir):
os.makedirs(self.logdir)
@mason.util.job_step
def _build_systems(self):
builds = self._prepare_builds(self.plugin_config['config'])
os.chdir(self.defs_checkout)
for build in builds:
build.start()
# TODO: Don't force serialisation when we change to distbuild.
while not build.completed():
time.sleep(1)
fail = False
for build in builds:
build.close_log()
if build.process.returncode != 0:
fail = True
logging.error('Building failed for %s. Log is at %s.' %
(build.system_name, build.log_path))
if fail:
raise cliapp.AppException('Building of systems failed.')
|