Mercurial > bitten > bitten-test
annotate bitten/master.py @ 284:ddc93fe34cad
Fix a bug in the build master (introduced in [289]) where multiple slaves matching the same target platform would potentially start the same build. This is done by setting the build to `IN_PROGRESS` as soon as the build initiation is sent, as opposed to when the slave accepts the build request.
author | cmlenz |
---|---|
date | Fri, 14 Oct 2005 21:12:45 +0000 |
parents | 33625fa61d6c |
children | 6abd43d0cd8a |
rev | line source |
---|---|
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
1 # -*- coding: iso8859-1 -*- |
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
2 # |
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
3 # Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de> |
163 | 4 # All rights reserved. |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
5 # |
163 | 6 # This software is licensed as described in the file COPYING, which |
7 # you should have received as part of this distribution. The terms | |
8 # are also available at http://bitten.cmlenz.net/wiki/License. | |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
9 |
95
1984b2e01998
Make the repository poll interval configurable. It now defaults to 2 minutes instead of 10 seconds.
cmlenz
parents:
94
diff
changeset
|
10 from datetime import datetime, timedelta |
15
06207499c58c
* Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents:
14
diff
changeset
|
11 import logging |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
12 import os |
83
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
13 try: |
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
14 set |
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
15 except NameError: |
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
16 from sets import Set as set |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
17 import sys |
47
083e848088ee
* Improvements to the model classes, and a couple of unit tests.
cmlenz
parents:
45
diff
changeset
|
18 import time |
18
591a5a836ecc
* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents:
15
diff
changeset
|
19 |
591a5a836ecc
* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents:
15
diff
changeset
|
20 from trac.env import Environment |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
21 from bitten.model import BuildConfig, Build, BuildStep, BuildLog, Report |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
22 from bitten.queue import BuildQueue |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
23 from bitten.trac_ext.main import BuildSystem |
277 | 24 from bitten.util import beep, xmlio |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
25 |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
26 log = logging.getLogger('bitten.master') |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
27 |
95
1984b2e01998
Make the repository poll interval configurable. It now defaults to 2 minutes instead of 10 seconds.
cmlenz
parents:
94
diff
changeset
|
28 DEFAULT_CHECK_INTERVAL = 120 # 2 minutes |
1984b2e01998
Make the repository poll interval configurable. It now defaults to 2 minutes instead of 10 seconds.
cmlenz
parents:
94
diff
changeset
|
29 |
1984b2e01998
Make the repository poll interval configurable. It now defaults to 2 minutes instead of 10 seconds.
cmlenz
parents:
94
diff
changeset
|
30 |
18
591a5a836ecc
* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents:
15
diff
changeset
|
31 class Master(beep.Listener): |
591a5a836ecc
* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents:
15
diff
changeset
|
32 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
33 def __init__(self, envs, ip, port, adjust_timestamps=False, |
95
1984b2e01998
Make the repository poll interval configurable. It now defaults to 2 minutes instead of 10 seconds.
cmlenz
parents:
94
diff
changeset
|
34 check_interval=DEFAULT_CHECK_INTERVAL): |
18
591a5a836ecc
* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents:
15
diff
changeset
|
35 beep.Listener.__init__(self, ip, port) |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
36 self.profiles[OrchestrationProfileHandler.URI] = \ |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
37 OrchestrationProfileHandler |
130
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
38 self.adjust_timestamps = adjust_timestamps |
95
1984b2e01998
Make the repository poll interval configurable. It now defaults to 2 minutes instead of 10 seconds.
cmlenz
parents:
94
diff
changeset
|
39 self.check_interval = check_interval |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
40 self.handlers = {} # Map of connected slaves keyed by name |
47
083e848088ee
* Improvements to the model classes, and a couple of unit tests.
cmlenz
parents:
45
diff
changeset
|
41 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
42 self.queues = [] |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
43 for env in envs: |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
44 self.queues.append(BuildQueue(env)) |
47
083e848088ee
* Improvements to the model classes, and a couple of unit tests.
cmlenz
parents:
45
diff
changeset
|
45 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
46 self.schedule(self.check_interval, self._enqueue_builds) |
47
083e848088ee
* Improvements to the model classes, and a couple of unit tests.
cmlenz
parents:
45
diff
changeset
|
47 |
083e848088ee
* Improvements to the model classes, and a couple of unit tests.
cmlenz
parents:
45
diff
changeset
|
48 def close(self): |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
49 for queue in self.queues: |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
50 queue.reset_orphaned_builds() |
47
083e848088ee
* Improvements to the model classes, and a couple of unit tests.
cmlenz
parents:
45
diff
changeset
|
51 beep.Listener.close(self) |
18
591a5a836ecc
* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents:
15
diff
changeset
|
52 |
277 | 53 def _enqueue_builds(self): |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
54 self.schedule(self.check_interval, self._enqueue_builds) |
18
591a5a836ecc
* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents:
15
diff
changeset
|
55 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
56 for queue in self.queues: |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
57 queue.populate() |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
58 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
59 self.schedule(self.check_interval * 0.2, self._initiate_builds) |
92
2e090827c63a
Delete snapshots for builds that have been completed by all configured target platforms, and are thus no longer needed. Closes #20.
cmlenz
parents:
90
diff
changeset
|
60 |
277 | 61 def _initiate_builds(self): |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
62 available_slaves = set([name for name in self.handlers |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
63 if not self.handlers[name].building]) |
228
a8c9dd7e3f71
* Cleanup and documentation for the `BuildQueue` class added in [236].
cmlenz
parents:
227
diff
changeset
|
64 for idx, queue in enumerate(self.queues[:]): |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
65 build, slave = queue.get_next_pending_build(available_slaves) |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
66 if build: |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
67 self.handlers[slave].send_initiation(queue, build) |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
68 available_slaves.discard(slave) |
228
a8c9dd7e3f71
* Cleanup and documentation for the `BuildQueue` class added in [236].
cmlenz
parents:
227
diff
changeset
|
69 self.queues.append(self.queues.pop(idx)) # Round robin |
18
591a5a836ecc
* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents:
15
diff
changeset
|
70 |
83
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
71 def register(self, handler): |
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
72 any_match = False |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
73 for queue in self.queues: |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
74 if queue.register_slave(handler.name, handler.info): |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
75 any_match = True |
83
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
76 |
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
77 if not any_match: |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
78 log.warning('Slave %s does not match any of the configured target ' |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
79 'platforms', handler.name) |
83
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
80 return False |
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
81 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
82 self.handlers[handler.name] = handler |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
83 self.schedule(self.check_interval * 0.2, self._initiate_builds) |
95
1984b2e01998
Make the repository poll interval configurable. It now defaults to 2 minutes instead of 10 seconds.
cmlenz
parents:
94
diff
changeset
|
84 |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
85 log.info('Registered slave "%s"', handler.name) |
83
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
86 return True |
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
87 |
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
88 def unregister(self, handler): |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
89 if handler.name not in self.handlers: |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
90 return |
83
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
91 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
92 for queue in self.queues: |
253 | 93 if queue.unregister_slave(handler.name): |
94 for build in list(Build.select(queue.env, slave=handler.name, | |
95 status=Build.IN_PROGRESS)): | |
96 handler._build_aborted(queue, build) | |
97 | |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
98 del self.handlers[handler.name] |
184
fbf949f4c706
Allow invalidation of builds from the web interface. This results in the build being reset to ''PENDING'' status, and all build logs, slave information and reports deleted. Basically initiates a rebuild for a specific revision and target platform.
cmlenz
parents:
163
diff
changeset
|
99 |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
100 log.info('Unregistered slave "%s"', handler.name) |
83
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
101 |
56 | 102 |
19
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
103 class OrchestrationProfileHandler(beep.ProfileHandler): |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
104 """Handler for communication on the Bitten build orchestration profile from |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
105 the perspective of the build master. |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
106 """ |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
107 URI = 'http://bitten.cmlenz.net/beep/orchestration' |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
108 |
51
5caccd7b247e
Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents:
49
diff
changeset
|
109 def handle_connect(self): |
18
591a5a836ecc
* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents:
15
diff
changeset
|
110 self.master = self.session.listener |
591a5a836ecc
* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents:
15
diff
changeset
|
111 assert self.master |
47
083e848088ee
* Improvements to the model classes, and a couple of unit tests.
cmlenz
parents:
45
diff
changeset
|
112 self.name = None |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
113 self.building = False |
82
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
114 self.info = {} |
24
cad6d28b8975
* Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents:
19
diff
changeset
|
115 |
cad6d28b8975
* Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents:
19
diff
changeset
|
116 def handle_disconnect(self): |
83
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
117 self.master.unregister(self) |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
118 |
88 | 119 def handle_msg(self, msgno, payload): |
120 assert payload.content_type == beep.BEEP_XML | |
121 elem = xmlio.parse(payload.body) | |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
122 |
51
5caccd7b247e
Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents:
49
diff
changeset
|
123 if elem.name == 'register': |
69 | 124 self.name = elem.attr['name'] |
127
a9443f673344
Add option for specifying a [wiki:SlaveConfiguration configuration file] for the build slave. Closes #29.
cmlenz
parents:
119
diff
changeset
|
125 self.info[Build.IP_ADDRESS] = self.session.addr[0] |
51
5caccd7b247e
Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents:
49
diff
changeset
|
126 for child in elem.children(): |
5caccd7b247e
Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents:
49
diff
changeset
|
127 if child.name == 'platform': |
82
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
128 self.info[Build.MACHINE] = child.gettext() |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
129 self.info[Build.PROCESSOR] = child.attr.get('processor') |
51
5caccd7b247e
Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents:
49
diff
changeset
|
130 elif child.name == 'os': |
82
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
131 self.info[Build.OS_NAME] = child.gettext() |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
132 self.info[Build.OS_FAMILY] = child.attr.get('family') |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
133 self.info[Build.OS_VERSION] = child.attr.get('version') |
127
a9443f673344
Add option for specifying a [wiki:SlaveConfiguration configuration file] for the build slave. Closes #29.
cmlenz
parents:
119
diff
changeset
|
134 elif child.name == 'package': |
a9443f673344
Add option for specifying a [wiki:SlaveConfiguration configuration file] for the build slave. Closes #29.
cmlenz
parents:
119
diff
changeset
|
135 for name, value in child.attr.items(): |
a9443f673344
Add option for specifying a [wiki:SlaveConfiguration configuration file] for the build slave. Closes #29.
cmlenz
parents:
119
diff
changeset
|
136 if name == 'name': |
a9443f673344
Add option for specifying a [wiki:SlaveConfiguration configuration file] for the build slave. Closes #29.
cmlenz
parents:
119
diff
changeset
|
137 continue |
a9443f673344
Add option for specifying a [wiki:SlaveConfiguration configuration file] for the build slave. Closes #29.
cmlenz
parents:
119
diff
changeset
|
138 self.info[child.attr['name'] + '.' + name] = value |
14
1733c601d2f8
Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents:
13
diff
changeset
|
139 |
83
42970c14524a
Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents:
82
diff
changeset
|
140 if not self.master.register(self): |
277 | 141 raise beep.ProtocolError(550, 'Nothing for you to build here, ' |
142 'please move along') | |
18
591a5a836ecc
* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents:
15
diff
changeset
|
143 |
29 | 144 xml = xmlio.Element('ok') |
88 | 145 self.channel.send_rpy(msgno, beep.Payload(xml)) |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
146 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
147 def send_initiation(self, queue, build): |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
148 log.info('Initiating build of "%s" on slave %s', build.config, |
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
149 self.name) |
284
ddc93fe34cad
Fix a bug in the build master (introduced in [289]) where multiple slaves matching the same target platform would potentially start the same build. This is done by setting the build to `IN_PROGRESS` as soon as the build initiation is sent, as opposed to when the slave accepts the build request.
cmlenz
parents:
281
diff
changeset
|
150 |
ddc93fe34cad
Fix a bug in the build master (introduced in [289]) where multiple slaves matching the same target platform would potentially start the same build. This is done by setting the build to `IN_PROGRESS` as soon as the build initiation is sent, as opposed to when the slave accepts the build request.
cmlenz
parents:
281
diff
changeset
|
151 build.slave = self.name |
ddc93fe34cad
Fix a bug in the build master (introduced in [289]) where multiple slaves matching the same target platform would potentially start the same build. This is done by setting the build to `IN_PROGRESS` as soon as the build initiation is sent, as opposed to when the slave accepts the build request.
cmlenz
parents:
281
diff
changeset
|
152 build.slave_info.update(self.info) |
ddc93fe34cad
Fix a bug in the build master (introduced in [289]) where multiple slaves matching the same target platform would potentially start the same build. This is done by setting the build to `IN_PROGRESS` as soon as the build initiation is sent, as opposed to when the slave accepts the build request.
cmlenz
parents:
281
diff
changeset
|
153 build.status = Build.IN_PROGRESS |
ddc93fe34cad
Fix a bug in the build master (introduced in [289]) where multiple slaves matching the same target platform would potentially start the same build. This is done by setting the build to `IN_PROGRESS` as soon as the build initiation is sent, as opposed to when the slave accepts the build request.
cmlenz
parents:
281
diff
changeset
|
154 build.update() |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
155 self.building = True |
284
ddc93fe34cad
Fix a bug in the build master (introduced in [289]) where multiple slaves matching the same target platform would potentially start the same build. This is done by setting the build to `IN_PROGRESS` as soon as the build initiation is sent, as opposed to when the slave accepts the build request.
cmlenz
parents:
281
diff
changeset
|
156 |
277 | 157 config = BuildConfig.fetch(queue.env, build.config) |
42
efa525876b1e
Basic infrastructure for transmission of snapshot archives to build slaves. See #8.
cmlenz
parents:
34
diff
changeset
|
158 |
88 | 159 def handle_reply(cmd, msgno, ansno, payload): |
42
efa525876b1e
Basic infrastructure for transmission of snapshot archives to build slaves. See #8.
cmlenz
parents:
34
diff
changeset
|
160 if cmd == 'ERR': |
88 | 161 if payload.content_type == beep.BEEP_XML: |
162 elem = xmlio.parse(payload.body) | |
51
5caccd7b247e
Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents:
49
diff
changeset
|
163 if elem.name == 'error': |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
164 log.warning('Slave %s refused build request: %s (%d)', |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
165 self.name, elem.gettext(), |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
166 int(elem.attr['code'])) |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
167 self.building = False |
284
ddc93fe34cad
Fix a bug in the build master (introduced in [289]) where multiple slaves matching the same target platform would potentially start the same build. This is done by setting the build to `IN_PROGRESS` as soon as the build initiation is sent, as opposed to when the slave accepts the build request.
cmlenz
parents:
281
diff
changeset
|
168 self._build_aborted(queue, build) |
51
5caccd7b247e
Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents:
49
diff
changeset
|
169 return |
5caccd7b247e
Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents:
49
diff
changeset
|
170 |
88 | 171 elem = xmlio.parse(payload.body) |
277 | 172 if elem.name != 'proceed': |
173 raise beep.ProtocolError(500) | |
51
5caccd7b247e
Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents:
49
diff
changeset
|
174 |
277 | 175 snapshots = queue.snapshots[config.name] |
176 snapshot = snapshots.get(build.rev) | |
177 if not snapshot: | |
178 # Request a snapshot for this build, and schedule a poll | |
179 # function that kicks off the snapshot transmission once the | |
180 # archive has been completely built | |
181 worker = snapshots.create(build.rev) | |
182 def _check_snapshot(): | |
183 worker.join(.5) | |
184 if worker.isAlive(): | |
185 self.master.schedule(2, _check_snapshot) | |
186 else: | |
281
33625fa61d6c
* If a slave disconnects after the master has started to create a snapshot archive for it, just remain calm and keep the archive in place.
cmlenz
parents:
277
diff
changeset
|
187 if self.name not in self.master.handlers: |
33625fa61d6c
* If a slave disconnects after the master has started to create a snapshot archive for it, just remain calm and keep the archive in place.
cmlenz
parents:
277
diff
changeset
|
188 # The slave disconnected while we were building |
33625fa61d6c
* If a slave disconnects after the master has started to create a snapshot archive for it, just remain calm and keep the archive in place.
cmlenz
parents:
277
diff
changeset
|
189 # the archive |
33625fa61d6c
* If a slave disconnects after the master has started to create a snapshot archive for it, just remain calm and keep the archive in place.
cmlenz
parents:
277
diff
changeset
|
190 return |
277 | 191 snapshot = snapshots.get(build.rev) |
192 if snapshot is None: | |
193 log.error('Failed to create snapshot archive for ' | |
194 '%s@%s', config.path, build.rev) | |
195 return | |
196 self.send_snapshot(queue, build, snapshot) | |
197 _check_snapshot() | |
198 else: | |
199 self.send_snapshot(queue, build, snapshot) | |
200 | |
147
395b67aa072e
Build recipes are now stored in the database with the build configuration. This means that it is no longer necessary to store the recipe in the repository. Closes #41.
cmlenz
parents:
135
diff
changeset
|
201 self.channel.send_msg(beep.Payload(config.recipe), |
395b67aa072e
Build recipes are now stored in the database with the build configuration. This means that it is no longer necessary to store the recipe in the repository. Closes #41.
cmlenz
parents:
135
diff
changeset
|
202 handle_reply=handle_reply) |
51
5caccd7b247e
Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents:
49
diff
changeset
|
203 |
277 | 204 def send_snapshot(self, queue, build, snapshot): |
130
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
205 timestamp_delta = 0 |
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
206 if self.master.adjust_timestamps: |
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
207 d = datetime.now() - timedelta(seconds=self.master.check_interval) \ |
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
208 - datetime.fromtimestamp(build.rev_time) |
277 | 209 log.info('Warping timestamps by %s', d) |
130
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
210 timestamp_delta = d.days * 86400 + d.seconds |
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
211 |
88 | 212 def handle_reply(cmd, msgno, ansno, payload): |
51
5caccd7b247e
Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents:
49
diff
changeset
|
213 if cmd == 'ERR': |
277 | 214 if payload.content_type != beep.BEEP_XML: |
215 raise beep.ProtocolError(500) | |
88 | 216 elem = xmlio.parse(payload.body) |
63
2332aedba328
* Allow specifying a different name for a build slave (default is the host name).
cmlenz
parents:
61
diff
changeset
|
217 if elem.name == 'error': |
185
2c24d9a950ed
Add a `--dry-run` option to the build slave. This will result in the slave being registered and executing builds, but without submitting the progress and results of the build back to the server. Useful for getting the configuration of new slaves right without polluting the database with invalid builds.
cmlenz
parents:
184
diff
changeset
|
218 log.warning('Slave %s refused to start build: %s (%d)', |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
219 self.name, elem.gettext(), |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
220 int(elem.attr['code'])) |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
221 self.building = False |
284
ddc93fe34cad
Fix a bug in the build master (introduced in [289]) where multiple slaves matching the same target platform would potentially start the same build. This is done by setting the build to `IN_PROGRESS` as soon as the build initiation is sent, as opposed to when the slave accepts the build request.
cmlenz
parents:
281
diff
changeset
|
222 self._build_aborted(queue, build) |
80
dc1c7fc9b915
Record the output of build steps in the database. See #12. Still need to get better granularity in transmitting the log output from slave to master before #12 can be closed.
cmlenz
parents:
76
diff
changeset
|
223 |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
224 elif cmd == 'ANS': |
277 | 225 if payload.content_type != beep.BEEP_XML: |
226 raise beep.ProtocolError(500) | |
88 | 227 elem = xmlio.parse(payload.body) |
63
2332aedba328
* Allow specifying a different name for a build slave (default is the host name).
cmlenz
parents:
61
diff
changeset
|
228 if elem.name == 'started': |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
229 self._build_started(queue, build, elem, timestamp_delta) |
63
2332aedba328
* Allow specifying a different name for a build slave (default is the host name).
cmlenz
parents:
61
diff
changeset
|
230 elif elem.name == 'step': |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
231 self._build_step_completed(queue, build, elem, |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
232 timestamp_delta) |
82
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
233 elif elem.name == 'completed': |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
234 self._build_completed(queue, build, elem, timestamp_delta) |
70 | 235 elif elem.name == 'aborted': |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
236 self._build_aborted(queue, build) |
63
2332aedba328
* Allow specifying a different name for a build slave (default is the host name).
cmlenz
parents:
61
diff
changeset
|
237 elif elem.name == 'error': |
2332aedba328
* Allow specifying a different name for a build slave (default is the host name).
cmlenz
parents:
61
diff
changeset
|
238 build.status = Build.FAILURE |
80
dc1c7fc9b915
Record the output of build steps in the database. See #12. Still need to get better granularity in transmitting the log output from slave to master before #12 can be closed.
cmlenz
parents:
76
diff
changeset
|
239 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
240 elif cmd == 'NUL': |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
241 self.building = False |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
242 |
277 | 243 snapshot_name = os.path.basename(snapshot) |
244 message = beep.Payload(file(snapshot, 'rb'), | |
245 content_type='application/zip', | |
246 content_disposition=snapshot_name) | |
42
efa525876b1e
Basic infrastructure for transmission of snapshot archives to build slaves. See #8.
cmlenz
parents:
34
diff
changeset
|
247 self.channel.send_msg(message, handle_reply=handle_reply) |
efa525876b1e
Basic infrastructure for transmission of snapshot archives to build slaves. See #8.
cmlenz
parents:
34
diff
changeset
|
248 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
249 def _build_started(self, queue, build, elem, timestamp_delta=None): |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
250 build.started = int(_parse_iso_datetime(elem.attr['time'])) |
130
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
251 if timestamp_delta: |
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
252 build.started -= timestamp_delta |
253 | 253 build.update() |
254 | |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
255 log.info('Slave %s started build %d ("%s" as of [%s])', |
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
256 self.name, build.id, build.config, build.rev) |
253 | 257 for listener in BuildSystem(queue.env).listeners: |
258 listener.build_started(build) | |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
259 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
260 def _build_step_completed(self, queue, build, elem, timestamp_delta=None): |
204
e1a53e70b43f
* Make deletion of build steps compatible with PySQLite2: records cannot be deleted inside a `select()` loop.
cmlenz
parents:
203
diff
changeset
|
261 log.debug('Slave %s completed step "%s" with status %s', self.name, |
e1a53e70b43f
* Make deletion of build steps compatible with PySQLite2: records cannot be deleted inside a `select()` loop.
cmlenz
parents:
203
diff
changeset
|
262 elem.attr['id'], elem.attr['result']) |
200
692924ffed80
Changes to the BDB XML report store to support transactions. Closes #47.
cmlenz
parents:
197
diff
changeset
|
263 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
264 db = queue.env.get_db_cnx() |
200
692924ffed80
Changes to the BDB XML report store to support transactions. Closes #47.
cmlenz
parents:
197
diff
changeset
|
265 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
266 step = BuildStep(queue.env, build=build.id, name=elem.attr['id'], |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
267 description=elem.attr.get('description')) |
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
268 step.started = int(_parse_iso_datetime(elem.attr['time'])) |
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
269 step.stopped = step.started + int(elem.attr['duration']) |
130
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
270 if timestamp_delta: |
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
271 step.started -= timestamp_delta |
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
272 step.stopped -= timestamp_delta |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
273 if elem.attr['result'] == 'failure': |
135 | 274 log.warning('Step failed') |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
275 step.status = BuildStep.FAILURE |
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
276 else: |
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
277 step.status = BuildStep.SUCCESS |
277 | 278 step.errors += [error.gettext() for error in elem.children('error')] |
112
a38eabd4b6e1
* Store build logs in a structured way, for example to highlight messages on the error stream.
cmlenz
parents:
110
diff
changeset
|
279 step.insert(db=db) |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
280 |
203
e6ddca1e5712
Huge refactoring to remove dependency on BDB XML. Report data is now stored in the Trac database (SQLite/PostgreSQL).
cmlenz
parents:
202
diff
changeset
|
281 for idx, log_elem in enumerate(elem.children('log')): |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
282 build_log = BuildLog(queue.env, build=build.id, step=step.name, |
203
e6ddca1e5712
Huge refactoring to remove dependency on BDB XML. Report data is now stored in the Trac database (SQLite/PostgreSQL).
cmlenz
parents:
202
diff
changeset
|
283 generator=log_elem.attr.get('generator'), |
e6ddca1e5712
Huge refactoring to remove dependency on BDB XML. Report data is now stored in the Trac database (SQLite/PostgreSQL).
cmlenz
parents:
202
diff
changeset
|
284 orderno=idx) |
115
16d69eb6e047
Add support for XML fragments to the {{{xmlio}}} module, so that build output and reports don't need to be nested in a meaningless element (such as {{{<log type="distutils"><messages><message ...>}}}).
cmlenz
parents:
112
diff
changeset
|
285 for message_elem in log_elem.children('message'): |
16d69eb6e047
Add support for XML fragments to the {{{xmlio}}} module, so that build output and reports don't need to be nested in a meaningless element (such as {{{<log type="distutils"><messages><message ...>}}}).
cmlenz
parents:
112
diff
changeset
|
286 build_log.messages.append((message_elem.attr['level'], |
16d69eb6e047
Add support for XML fragments to the {{{xmlio}}} module, so that build output and reports don't need to be nested in a meaningless element (such as {{{<log type="distutils"><messages><message ...>}}}).
cmlenz
parents:
112
diff
changeset
|
287 message_elem.gettext())) |
112
a38eabd4b6e1
* Store build logs in a structured way, for example to highlight messages on the error stream.
cmlenz
parents:
110
diff
changeset
|
288 build_log.insert(db=db) |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
289 |
203
e6ddca1e5712
Huge refactoring to remove dependency on BDB XML. Report data is now stored in the Trac database (SQLite/PostgreSQL).
cmlenz
parents:
202
diff
changeset
|
290 for report_elem in elem.children('report'): |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
291 report = Report(queue.env, build=build.id, step=step.name, |
213
25f84dd9f159
* Refactoring of build recipes, the file format has changed slightly:
cmlenz
parents:
204
diff
changeset
|
292 category=report_elem.attr.get('category'), |
25f84dd9f159
* Refactoring of build recipes, the file format has changed slightly:
cmlenz
parents:
204
diff
changeset
|
293 generator=report_elem.attr.get('generator')) |
203
e6ddca1e5712
Huge refactoring to remove dependency on BDB XML. Report data is now stored in the Trac database (SQLite/PostgreSQL).
cmlenz
parents:
202
diff
changeset
|
294 for item_elem in report_elem.children(): |
e6ddca1e5712
Huge refactoring to remove dependency on BDB XML. Report data is now stored in the Trac database (SQLite/PostgreSQL).
cmlenz
parents:
202
diff
changeset
|
295 item = {'type': item_elem.name} |
e6ddca1e5712
Huge refactoring to remove dependency on BDB XML. Report data is now stored in the Trac database (SQLite/PostgreSQL).
cmlenz
parents:
202
diff
changeset
|
296 item.update(item_elem.attr) |
e6ddca1e5712
Huge refactoring to remove dependency on BDB XML. Report data is now stored in the Trac database (SQLite/PostgreSQL).
cmlenz
parents:
202
diff
changeset
|
297 for child_elem in item_elem.children(): |
e6ddca1e5712
Huge refactoring to remove dependency on BDB XML. Report data is now stored in the Trac database (SQLite/PostgreSQL).
cmlenz
parents:
202
diff
changeset
|
298 item[child_elem.name] = child_elem.gettext() |
e6ddca1e5712
Huge refactoring to remove dependency on BDB XML. Report data is now stored in the Trac database (SQLite/PostgreSQL).
cmlenz
parents:
202
diff
changeset
|
299 report.items.append(item) |
e6ddca1e5712
Huge refactoring to remove dependency on BDB XML. Report data is now stored in the Trac database (SQLite/PostgreSQL).
cmlenz
parents:
202
diff
changeset
|
300 report.insert(db=db) |
116 | 301 |
200
692924ffed80
Changes to the BDB XML report store to support transactions. Closes #47.
cmlenz
parents:
197
diff
changeset
|
302 db.commit() |
692924ffed80
Changes to the BDB XML report store to support transactions. Closes #47.
cmlenz
parents:
197
diff
changeset
|
303 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
304 def _build_completed(self, queue, build, elem, timestamp_delta=None): |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
305 build.stopped = int(_parse_iso_datetime(elem.attr['time'])) |
130
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
306 if timestamp_delta: |
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
307 build.stopped -= timestamp_delta |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
308 if elem.attr['result'] == 'failure': |
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
309 build.status = Build.FAILURE |
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
310 else: |
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
311 build.status = Build.SUCCESS |
200
692924ffed80
Changes to the BDB XML report store to support transactions. Closes #47.
cmlenz
parents:
197
diff
changeset
|
312 build.update() |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
313 |
253 | 314 log.info('Slave %s completed build %d ("%s" as of [%s]) with status %s', |
315 self.name, build.id, build.config, build.rev, | |
316 build.status == Build.FAILURE and 'FAILURE' or 'SUCCESS') | |
317 for listener in BuildSystem(queue.env).listeners: | |
318 listener.build_completed(build) | |
319 | |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
320 def _build_aborted(self, queue, build): |
204
e1a53e70b43f
* Make deletion of build steps compatible with PySQLite2: records cannot be deleted inside a `select()` loop.
cmlenz
parents:
203
diff
changeset
|
321 log.info('Slave %s aborted build %d ("%s" as of [%s])', |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
322 self.name, build.id, build.config, build.rev) |
253 | 323 for listener in BuildSystem(queue.env).listeners: |
324 listener.build_aborted(build) | |
184
fbf949f4c706
Allow invalidation of builds from the web interface. This results in the build being reset to ''PENDING'' status, and all build logs, slave information and reports deleted. Basically initiates a rebuild for a specific revision and target platform.
cmlenz
parents:
163
diff
changeset
|
325 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
326 db = queue.env.get_db_cnx() |
200
692924ffed80
Changes to the BDB XML report store to support transactions. Closes #47.
cmlenz
parents:
197
diff
changeset
|
327 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
328 for step in list(BuildStep.select(queue.env, build=build.id, db=db)): |
184
fbf949f4c706
Allow invalidation of builds from the web interface. This results in the build being reset to ''PENDING'' status, and all build logs, slave information and reports deleted. Basically initiates a rebuild for a specific revision and target platform.
cmlenz
parents:
163
diff
changeset
|
329 step.delete(db=db) |
fbf949f4c706
Allow invalidation of builds from the web interface. This results in the build being reset to ''PENDING'' status, and all build logs, slave information and reports deleted. Basically initiates a rebuild for a specific revision and target platform.
cmlenz
parents:
163
diff
changeset
|
330 |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
331 build.slave = None |
253 | 332 build.slave_info = {} |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
333 build.started = 0 |
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
334 build.status = Build.PENDING |
200
692924ffed80
Changes to the BDB XML report store to support transactions. Closes #47.
cmlenz
parents:
197
diff
changeset
|
335 build.update(db=db) |
692924ffed80
Changes to the BDB XML report store to support transactions. Closes #47.
cmlenz
parents:
197
diff
changeset
|
336 |
692924ffed80
Changes to the BDB XML report store to support transactions. Closes #47.
cmlenz
parents:
197
diff
changeset
|
337 db.commit() |
109
5bf22bb87915
Transmit build log and generated data back to the build master in XML format. Closes #23.
cmlenz
parents:
96
diff
changeset
|
338 |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
339 |
82
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
340 def _parse_iso_datetime(string): |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
341 """Minimal parser for ISO date-time strings. |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
342 |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
343 Return the time as floating point number. Only handles UTC timestamps |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
344 without time zone information.""" |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
345 try: |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
346 string = string.split('.', 1)[0] # strip out microseconds |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
347 secs = time.mktime(time.strptime(string, '%Y-%m-%dT%H:%M:%S')) |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
348 tzoffset = time.timezone |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
349 if time.daylight: |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
350 tzoffset = time.altzone |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
351 return secs - tzoffset |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
352 except ValueError, e: |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
353 raise ValueError, 'Invalid ISO date/time %s (%s)' % (string, e) |
01200c88ddb0
Include timing information in the build messages transmitted from slave to master for better accuracy.
cmlenz
parents:
80
diff
changeset
|
354 |
31 | 355 def main(): |
56 | 356 from bitten import __version__ as VERSION |
19
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
357 from optparse import OptionParser |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
358 |
112
a38eabd4b6e1
* Store build logs in a structured way, for example to highlight messages on the error stream.
cmlenz
parents:
110
diff
changeset
|
359 # Parse command-line arguments |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
360 parser = OptionParser(usage='usage: %prog [options] ENV_PATHS', |
19
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
361 version='%%prog %s' % VERSION) |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
362 parser.add_option('-p', '--port', action='store', type='int', dest='port', |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
363 help='port number to use') |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
364 parser.add_option('-H', '--host', action='store', dest='host', |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
365 metavar='HOSTNAME', |
33
d8d44216258a
Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents:
31
diff
changeset
|
366 help='the host name or IP address to bind to') |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
367 parser.add_option('-l', '--log', dest='logfile', metavar='FILENAME', |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
368 help='write log messages to FILENAME') |
95
1984b2e01998
Make the repository poll interval configurable. It now defaults to 2 minutes instead of 10 seconds.
cmlenz
parents:
94
diff
changeset
|
369 parser.add_option('-i', '--interval', dest='interval', metavar='SECONDS', |
1984b2e01998
Make the repository poll interval configurable. It now defaults to 2 minutes instead of 10 seconds.
cmlenz
parents:
94
diff
changeset
|
370 default=DEFAULT_CHECK_INTERVAL, type='int', |
1984b2e01998
Make the repository poll interval configurable. It now defaults to 2 minutes instead of 10 seconds.
cmlenz
parents:
94
diff
changeset
|
371 help='poll interval for changeset detection') |
242
372d1de2e3ec
* Fixes to the `<c:configure>` command added in [247]: Set current directory when invoking the script, and correctly pass `CFLAGS` and `CXXFLAGS`.
cmlenz
parents:
228
diff
changeset
|
372 parser.add_option('--timewarp', action='store_true', dest='timewarp', |
267 | 373 help='adjust timestamps of builds to be near the ' |
130
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
374 'timestamps of the corresponding changesets') |
19
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
375 parser.add_option('--debug', action='store_const', dest='loglevel', |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
376 const=logging.DEBUG, help='enable debugging output') |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
377 parser.add_option('-v', '--verbose', action='store_const', dest='loglevel', |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
378 const=logging.INFO, help='print as much as possible') |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
379 parser.add_option('-q', '--quiet', action='store_const', dest='loglevel', |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
380 const=logging.ERROR, help='print as little as possible') |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
381 parser.set_defaults(port=7633, loglevel=logging.WARNING) |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
382 options, args = parser.parse_args() |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
383 |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
384 if len(args) < 1: |
19
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
385 parser.error('incorrect number of arguments') |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
386 |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
387 # Configure logging |
157
2efdc69e63c3
Some style/documentation improvements to make Pylint happier.
cmlenz
parents:
152
diff
changeset
|
388 logger = logging.getLogger('bitten') |
2efdc69e63c3
Some style/documentation improvements to make Pylint happier.
cmlenz
parents:
152
diff
changeset
|
389 logger.setLevel(options.loglevel) |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
390 handler = logging.StreamHandler() |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
391 if options.logfile: |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
392 handler.setLevel(logging.WARNING) |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
393 else: |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
394 handler.setLevel(options.loglevel) |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
395 formatter = logging.Formatter('%(message)s') |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
396 handler.setFormatter(formatter) |
157
2efdc69e63c3
Some style/documentation improvements to make Pylint happier.
cmlenz
parents:
152
diff
changeset
|
397 logger.addHandler(handler) |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
398 if options.logfile: |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
399 handler = logging.FileHandler(options.logfile) |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
400 handler.setLevel(options.loglevel) |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
401 formatter = logging.Formatter('%(asctime)s [%(name)s] %(levelname)s: ' |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
402 '%(message)s') |
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
403 handler.setFormatter(formatter) |
157
2efdc69e63c3
Some style/documentation improvements to make Pylint happier.
cmlenz
parents:
152
diff
changeset
|
404 logger.addHandler(handler) |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
405 |
19
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
406 port = options.port |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
407 if not (1 <= port <= 65535): |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
408 parser.error('port must be an integer in the range 1-65535') |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
409 |
19
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
410 host = options.host |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
411 if not host: |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
412 import socket |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
413 ip = socket.gethostbyname(socket.gethostname()) |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
414 try: |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
415 host = socket.gethostbyaddr(ip)[0] |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
416 except socket.error, e: |
93
b289e572bc7e
Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents:
92
diff
changeset
|
417 log.warning('Reverse host name lookup failed (%s)', e) |
19
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
418 host = ip |
9db5f8eddb0d
Proper {{{optparse}}}-based command-line interface for master and slave.
cmlenz
parents:
18
diff
changeset
|
419 |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
420 envs = [] |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
421 for arg in args: |
228
a8c9dd7e3f71
* Cleanup and documentation for the `BuildQueue` class added in [236].
cmlenz
parents:
227
diff
changeset
|
422 if not os.path.isdir(arg): |
a8c9dd7e3f71
* Cleanup and documentation for the `BuildQueue` class added in [236].
cmlenz
parents:
227
diff
changeset
|
423 log.warning('Ignoring %s: not a directory', arg) |
a8c9dd7e3f71
* Cleanup and documentation for the `BuildQueue` class added in [236].
cmlenz
parents:
227
diff
changeset
|
424 continue |
227
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
425 env = Environment(arg) |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
426 if BuildSystem(env): |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
427 if env.needs_upgrade(): |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
428 log.warning('Environment at %s needs to be upgraded', env.path) |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
429 continue |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
430 envs.append(env) |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
431 if not envs: |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
432 log.error('None of the specified environments has support for Bitten') |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
433 sys.exit(2) |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
434 |
014bc6c29dff
* Factor build queue logic into a class separate from the build master.
cmlenz
parents:
213
diff
changeset
|
435 master = Master(envs, host, port, adjust_timestamps=options.timewarp, |
130
091ead7d2876
Add a {{{--timewarp}}} option to the build master. If provided, the build master will adjust the timestamps of all builds to shortly after the time of the corresponding changeset. This is mostly for building the history of a project while keeping a chronological association between changeset and build.
cmlenz
parents:
127
diff
changeset
|
436 check_interval=options.interval) |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
437 try: |
42
efa525876b1e
Basic infrastructure for transmission of snapshot archives to build slaves. See #8.
cmlenz
parents:
34
diff
changeset
|
438 master.run(timeout=5.0) |
13
21aa17f97522
Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents:
diff
changeset
|
439 except KeyboardInterrupt: |
34
6da9468a6879
The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents:
33
diff
changeset
|
440 master.quit() |
31 | 441 |
442 if __name__ == '__main__': | |
33
d8d44216258a
Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents:
31
diff
changeset
|
443 main() |