forked from planetlab/build
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun-nightlies.py
executable file
·159 lines (127 loc) · 5.88 KB
/
run-nightlies.py
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/python
# This script makes the declaration of builds declarative. In the past, our build system involved constructing a set of command lines
# that would get executed with parameters such as the name of the distribution, the kernel version and so on. Unfortunately, the code
# that went into creating these command lines was shared between people and often when someone modified his build, other builds would
# break. With this script, each build is declared as a Python dict, such as in the following example:
#
# caglars_k32_build = {
# 'tags':'planetlab-k32-tags.mk',
# 'fcdistro':['centos5', 'f12','f8'],
# 'personality':['linux32','linux64'],
# 'test':0,
# 'release':'k32'
# }
#
# This declaration corresponds to 6 builds - with static values of 'tags', 'test' and 'release' and every combination of the values provided for
# 'fcdistro' and 'personality', i.e. 3x2.
#
# More complex dependencies can be added, e.g. to build linux64 only for f12, you can set the values of the options to functions:
#
# caglars_k32_build = {
# 'tags':'planetlab-k32-tags.mk',
# 'fcdistro':['centos5', 'f12','f8'],
# 'personality': lambda build: if (build['fcdistro']=='f12') then return ['linux32', 'linux64'] else return ['linux32']
# 'test':0,
# 'release':'k32'
# }
#
# Naturally, you can achieve the same result by breaking the above declaration into two dicts, rather than using only one
import os
import re
import shlex
import subprocess
import time
from optparse import OptionParser
PARALLEL_BUILD = False
# Assemble a list of builds from a single build spec
def interpret_build(build, param_names, current_concrete_build={}, concrete_build_list=[]):
if (param_names==[]):
concrete_build_list.extend([current_concrete_build])
else:
(cur_param_name,remaining_param_names)=(param_names[0],param_names[1:])
cur_param = build[cur_param_name]
# If it's a list, produce a concrete build for each element of the list
if (type(cur_param)==type([])):
for value in cur_param:
new_concrete_build = current_concrete_build.copy()
new_concrete_build[cur_param_name] = value
concrete_build_list = interpret_build(build, remaining_param_names, new_concrete_build, concrete_build_list)
# If not, just tack on the value and move on
else:
current_concrete_build[cur_param_name] = cur_param
concrete_build_list = interpret_build(build, remaining_param_names, current_concrete_build,concrete_build_list)
return concrete_build_list
# Fill in parameters that are not defined in __default_build__
def complete_build_spec_with_defaults (build, default_build):
for default_param in default_build.keys():
if (not build.has_key(default_param)):
build[default_param]=default_build[default_param]
return build
# Turn a concrete build into a commandline
def concrete_build_to_commandline(concrete_build):
cmdline = '''%(sh)s
%(vbuildnightly)s
-b pl-%(fcdistro)s-%(arch)s-%(myplcversion)s-%(release)s-%(date)s
-f %(fcdistro)s
-m %(mailto)s
-p %(personality)s
-d %(pldistro)s
-r %(webpath)s
-s %(scmpath)s
-t %(tags)s
-w %(webpath)s/%(pldistro)s/%(fcdistro)s
%(runtests)s'''.replace('\n','')
cmdline = cmdline % concrete_build
purge_spaces = re.compile('\s+')
return purge_spaces.sub(' ', cmdline)
# reduce dependencies in a build
def reduce_dependencies(concrete_build):
for b in concrete_build.keys():
val = concrete_build[b]
if (type(val)==type(lambda x:x)):
concrete_build[b] = val(concrete_build)
return concrete_build
# Turn build parameter dicts into commandlines and execute them
def process_builds (builds, build_names, default_build, options):
for build_name in build_names:
build = complete_build_spec_with_defaults (builds[build_name], default_build)
concrete_builds_without_deps = interpret_build (build, build.keys(), {}, [])
concrete_builds = map(reduce_dependencies, concrete_builds_without_deps)
commandlines = map(concrete_build_to_commandline, concrete_builds)
for commandline in commandlines:
if PARALLEL_BUILD == True:
args = shlex.split(commandline)
subprocess.Popen(args)
# work around the vserver race
time.sleep(60)
else:
if (build_name.startswith(options.prefix) and not options.pretend):
os.system(commandline)
else:
print "### Skipping the following build###\n"
print commandline
def main():
parser = OptionParser()
parser.add_option("-c", "--config-file", dest="config_file",
help="Config file with build declarations", metavar="FILE", default = '/etc/build-conf-planetlab.py')
parser.add_option("-p", "--pretend",
dest="pretend", default=False, action="store_true",
help="don't run only print")
parser.add_option("-o", "--only-build", dest="prefix",
help="Only build declarations starting with this prefix", metavar="PREFIX", default = '')
(options, args) = parser.parse_args ()
config_file = options.config_file
builds = {}
try:
execfile(config_file, builds)
except IOError, e:
raise IOError, "Could not open %s\n" % config_file
config_file_attributes = builds.keys()
build_names = [e for e in config_file_attributes if not e.startswith('__')]
try:
default_build = builds['__default_build__']
except KeyError:
raise KeyError, "Please define the default build config in %s\n" % config_file
process_builds(builds, build_names, default_build, options)
if __name__ == "__main__":
main()