Merge lp:~michael.nelson/launchpad/487009-db-more-soyuz-extraction into lp:launchpad/db-devel
- 487009-db-more-soyuz-extraction
- Merge into db-devel
Proposed by
Michael Nelson
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Henning Eggers | ||||
Approved revision: | not available | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~michael.nelson/launchpad/487009-db-more-soyuz-extraction | ||||
Merge into: | lp:launchpad/db-devel | ||||
Prerequisite: | lp:~michael.nelson/launchpad/487009-db-generalise-ibuilder-1b | ||||
Diff against target: |
565 lines (+246/-191) 5 files modified
lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py (+19/-4) lib/lp/buildmaster/model/buildfarmjobbehavior.py (+14/-0) lib/lp/soyuz/interfaces/builder.py (+0/-13) lib/lp/soyuz/model/binarypackagebuildbehavior.py (+206/-0) lib/lp/soyuz/model/builder.py (+7/-174) |
||||
To merge this branch: | bzr merge lp:~michael.nelson/launchpad/487009-db-more-soyuz-extraction | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Henning Eggers (community) | code | Approve | |
Review via email: mp+15533@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Michael Nelson (michael.nelson) wrote : | # |
Revision history for this message
Henning Eggers (henninge) wrote : | # |
Thank you for doing this important groundwork for our bridging-the-gap strategy. It will benefit all of us and most importantly Ubuntu.
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py' |
2 | --- lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py 2009-12-02 08:50:30 +0000 |
3 | +++ lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py 2009-12-02 08:50:31 +0000 |
4 | @@ -11,7 +11,7 @@ |
5 | 'IBuildFarmJobBehavior', |
6 | ] |
7 | |
8 | -from zope.interface import Interface |
9 | +from zope.interface import Attribute, Interface |
10 | |
11 | |
12 | class BuildBehaviorMismatch(Exception): |
13 | @@ -23,6 +23,9 @@ |
14 | |
15 | class IBuildFarmJobBehavior(Interface): |
16 | |
17 | + status = Attribute( |
18 | + "Generated status information for this particular job.") |
19 | + |
20 | def setBuilder(builder): |
21 | """Sets the associated builder reference for this instance.""" |
22 | |
23 | @@ -33,6 +36,18 @@ |
24 | :param build_queue_item: A BuildQueueItem to build. |
25 | :param logger: A logger to be used to log diagnostic information. |
26 | """ |
27 | - # A number of other methods to go here that can be customised for each of |
28 | - # the different build types (branch build, recipe build, translation |
29 | - # build etc.) |
30 | + |
31 | + def dispatchBuildToSlave(build_queue_item, logger): |
32 | + """Dispatch a specific build to the slave. |
33 | + |
34 | + :param build_queue_item: The `BuildQueueItem` that will be built. |
35 | + :logger: A logger to be used to log diagnostic information. |
36 | + """ |
37 | + |
38 | + def verifyBuildRequest(build_queue_item, logger): |
39 | + """Carry out any pre-build checks. |
40 | + |
41 | + :param build_queue_item: The `BuildQueueItem` that is to be built. |
42 | + :logger: A logger to be used to log diagnostic information. |
43 | + """ |
44 | + |
45 | |
46 | === modified file 'lib/lp/buildmaster/model/buildfarmjobbehavior.py' |
47 | --- lib/lp/buildmaster/model/buildfarmjobbehavior.py 2009-12-02 08:50:30 +0000 |
48 | +++ lib/lp/buildmaster/model/buildfarmjobbehavior.py 2009-12-02 08:50:31 +0000 |
49 | @@ -33,6 +33,10 @@ |
50 | """The builder should be set once and not changed.""" |
51 | self._builder = builder |
52 | |
53 | + def verifyBuildRequest(self, build_queue_item, logger): |
54 | + """The default behavior is a no-op.""" |
55 | + pass |
56 | + |
57 | |
58 | class IdleBuildBehavior(BuildFarmJobBehaviorBase): |
59 | |
60 | @@ -48,3 +52,13 @@ |
61 | """See `IBuildFarmJobBehavior`.""" |
62 | raise BuildBehaviorMismatch( |
63 | "Builder was idle when asked to log the start of a build.") |
64 | + |
65 | + def dispatchBuildToSlave(self, build_queue_item, logger): |
66 | + """See `IBuildFarmJobBehavior`.""" |
67 | + raise BuildBehaviorMismatch( |
68 | + "Builder was idle when asked to dispatch a build to the slave.") |
69 | + |
70 | + @property |
71 | + def status(self): |
72 | + """See `IBuildFarmJobBehavior`.""" |
73 | + return "Idle" |
74 | |
75 | === modified file 'lib/lp/soyuz/interfaces/builder.py' |
76 | --- lib/lp/soyuz/interfaces/builder.py 2009-12-02 08:50:30 +0000 |
77 | +++ lib/lp/soyuz/interfaces/builder.py 2009-12-02 08:50:31 +0000 |
78 | @@ -154,19 +154,6 @@ |
79 | file. |
80 | """ |
81 | |
82 | - def cachePrivateSourceOnSlave(logger, build_queue_item): |
83 | - """Ask the slave to download source files for a private build. |
84 | - |
85 | - The slave will cache the files for the source in build_queue_item |
86 | - to its local disk in preparation for a private build. Private builds |
87 | - will always take the source files from the archive rather than the |
88 | - librarian since the archive has more granular access to each |
89 | - archive's files. |
90 | - |
91 | - :param logger: A logger used for providing debug information. |
92 | - :param build_queue_item: The `IBuildQueue` being built. |
93 | - """ |
94 | - |
95 | def checkCanBuildForDistroArchSeries(distro_arch_series): |
96 | """Check that the slave can compile for the given distro_arch_release. |
97 | |
98 | |
99 | === modified file 'lib/lp/soyuz/model/binarypackagebuildbehavior.py' |
100 | --- lib/lp/soyuz/model/binarypackagebuildbehavior.py 2009-12-02 08:50:30 +0000 |
101 | +++ lib/lp/soyuz/model/binarypackagebuildbehavior.py 2009-12-02 08:50:31 +0000 |
102 | @@ -11,11 +11,20 @@ |
103 | 'BinaryPackageBuildBehavior', |
104 | ] |
105 | |
106 | +import socket |
107 | +import xmlrpclib |
108 | + |
109 | +from canonical.launchpad.webapp import urlappend |
110 | from lp.buildmaster.interfaces.buildfarmjobbehavior import ( |
111 | IBuildFarmJobBehavior) |
112 | from lp.buildmaster.model.buildfarmjobbehavior import ( |
113 | BuildFarmJobBehaviorBase) |
114 | +from lp.registry.interfaces.pocket import PackagePublishingPocket |
115 | +from lp.soyuz.adapters.archivedependencies import ( |
116 | + get_primary_current_component, get_sources_list_for_building) |
117 | +from lp.soyuz.interfaces.archive import ArchivePurpose |
118 | from lp.soyuz.interfaces.build import IBuildSet |
119 | +from lp.soyuz.interfaces.builder import BuildSlaveFailure, CannotBuild |
120 | |
121 | from zope.component import getUtility |
122 | from zope.interface import implements |
123 | @@ -33,3 +42,200 @@ |
124 | |
125 | logger.info("startBuild(%s, %s, %s, %s)", self._builder.url, |
126 | spr.name, spr.version, build.pocket.title) |
127 | + |
128 | + @property |
129 | + def status(self): |
130 | + """See `IBuildFarmJobBehavior`.""" |
131 | + build = getUtility(IBuildSet).getByQueueEntry( |
132 | + self._builder.currentjob) |
133 | + msg = 'Building %s' % build.title |
134 | + archive = build.archive |
135 | + if not archive.owner.private and (archive.is_ppa or archive.is_copy): |
136 | + return '%s [%s/%s]' % (msg, archive.owner.name, archive.name) |
137 | + else: |
138 | + return msg |
139 | + |
140 | + def dispatchBuildToSlave(self, build_queue_item, logger): |
141 | + """See `IBuildFarmJobBehavior`.""" |
142 | + |
143 | + # Start the binary package build on the slave builder. First |
144 | + # we send the chroot. |
145 | + build = getUtility(IBuildSet).getByQueueEntry(build_queue_item) |
146 | + chroot = build.distroarchseries.getChroot() |
147 | + self._builder.cacheFileOnSlave(logger, chroot) |
148 | + |
149 | + # Build filemap structure with the files required in this build |
150 | + # and send them to the slave. |
151 | + # If the build is private we tell the slave to get the files from the |
152 | + # archive instead of the librarian because the slaves cannot |
153 | + # access the restricted librarian. |
154 | + private = build.archive.private |
155 | + if private: |
156 | + self._cachePrivateSourceOnSlave(build_queue_item, logger) |
157 | + filemap = {} |
158 | + for source_file in build.sourcepackagerelease.files: |
159 | + lfa = source_file.libraryfile |
160 | + filemap[lfa.filename] = lfa.content.sha1 |
161 | + if not private: |
162 | + self._builder.cacheFileOnSlave( |
163 | + logger, source_file.libraryfile) |
164 | + |
165 | + # Generate a string which can be used to cross-check when obtaining |
166 | + # results so we know we are referring to the right database object in |
167 | + # subsequent runs. |
168 | + buildid = "%s-%s" % (build.id, build_queue_item.id) |
169 | + chroot_sha1 = chroot.content.sha1 |
170 | + logger.debug( |
171 | + "Initiating build %s on %s" % (buildid, self._builder.url)) |
172 | + |
173 | + try: |
174 | + args = self._extraBuildArgs(build) |
175 | + status, info = self._builder.slave.build( |
176 | + buildid, "debian", chroot_sha1, filemap, args) |
177 | + message = """%s (%s): |
178 | + ***** RESULT ***** |
179 | + %s |
180 | + %s |
181 | + %s: %s |
182 | + ****************** |
183 | + """ % ( |
184 | + self._builder.name, |
185 | + self._builder.url, |
186 | + filemap, |
187 | + args, |
188 | + status, |
189 | + info, |
190 | + ) |
191 | + logger.info(message) |
192 | + except xmlrpclib.Fault, info: |
193 | + # Mark builder as 'failed'. |
194 | + logger.debug( |
195 | + "Disabling builder: %s" % self._builder.url, exc_info=1) |
196 | + self._builder.failbuilder( |
197 | + "Exception (%s) when setting up to new job" % info) |
198 | + raise BuildSlaveFailure |
199 | + except socket.error, info: |
200 | + error_message = "Exception (%s) when setting up new job" % info |
201 | + self._builder.handleTimeout(logger, error_message) |
202 | + raise BuildSlaveFailure |
203 | + |
204 | + def verifyBuildRequest(self, build_queue_item, logger): |
205 | + """Assert some pre-build checks. |
206 | + |
207 | + The build request is checked: |
208 | + * Virtualized builds can't build on a non-virtual builder |
209 | + * Ensure that we have a chroot |
210 | + * Ensure that the build pocket allows builds for the current |
211 | + distroseries state. |
212 | + """ |
213 | + build = getUtility(IBuildSet).getByQueueEntry(build_queue_item) |
214 | + assert not (not self._builder.virtualized and build.is_virtualized), ( |
215 | + "Attempt to build non-virtual item on a virtual builder.") |
216 | + |
217 | + # Assert that we are not silently building SECURITY jobs. |
218 | + # See findBuildCandidates. Once we start building SECURITY |
219 | + # correctly from EMBARGOED archive this assertion can be removed. |
220 | + # XXX Julian 2007-12-18 spec=security-in-soyuz: This is being |
221 | + # addressed in the work on the blueprint: |
222 | + # https://blueprints.launchpad.net/soyuz/+spec/security-in-soyuz |
223 | + target_pocket = build.pocket |
224 | + assert target_pocket != PackagePublishingPocket.SECURITY, ( |
225 | + "Soyuz is not yet capable of building SECURITY uploads.") |
226 | + |
227 | + # Ensure build has the needed chroot |
228 | + chroot = build.distroarchseries.getChroot() |
229 | + if chroot is None: |
230 | + raise CannotBuild( |
231 | + "Missing CHROOT for %s/%s/%s" % ( |
232 | + build.distroseries.distribution.name, |
233 | + build.distroseries.name, |
234 | + build.distroarchseries.architecturetag) |
235 | + ) |
236 | + |
237 | + # The main distribution has policies to prevent uploads to some |
238 | + # pockets (e.g. security) during different parts of the distribution |
239 | + # series lifecycle. These do not apply to PPA builds nor any archive |
240 | + # that allows release pocket updates. |
241 | + if (build.archive.purpose != ArchivePurpose.PPA and |
242 | + not build.archive.allowUpdatesToReleasePocket()): |
243 | + # XXX Robert Collins 2007-05-26: not an explicit CannotBuild |
244 | + # exception yet because the callers have not been audited |
245 | + assert build.distroseries.canUploadToPocket(build.pocket), ( |
246 | + "%s (%s) can not be built for pocket %s: invalid pocket due " |
247 | + "to the series status of %s." |
248 | + % (build.title, build.id, build.pocket.name, |
249 | + build.distroseries.name)) |
250 | + |
251 | + def _cachePrivateSourceOnSlave(self, build_queue_item, logger): |
252 | + """Ask the slave to download source files for a private build. |
253 | + |
254 | + The slave will cache the files for the source in build_queue_item |
255 | + to its local disk in preparation for a private build. Private builds |
256 | + will always take the source files from the archive rather than the |
257 | + librarian since the archive has more granular access to each |
258 | + archive's files. |
259 | + |
260 | + :param build_queue_item: The `IBuildQueue` being built. |
261 | + :param logger: A logger used for providing debug information. |
262 | + """ |
263 | + # The URL to the file in the archive consists of these parts: |
264 | + # archive_url / makePoolPath() / filename |
265 | + # Once this is constructed we add the http basic auth info. |
266 | + |
267 | + # Avoid circular imports. |
268 | + from lp.soyuz.model.publishing import makePoolPath |
269 | + |
270 | + build = getUtility(IBuildSet).getByQueueEntry(build_queue_item) |
271 | + archive = build.archive |
272 | + archive_url = archive.archive_url |
273 | + component_name = build.current_component.name |
274 | + for source_file in build.sourcepackagerelease.files: |
275 | + file_name = source_file.libraryfile.filename |
276 | + sha1 = source_file.libraryfile.content.sha1 |
277 | + source_name = build.sourcepackagerelease.sourcepackagename.name |
278 | + poolpath = makePoolPath(source_name, component_name) |
279 | + url = urlappend(archive_url, poolpath) |
280 | + url = urlappend(url, file_name) |
281 | + logger.debug("Asking builder on %s to ensure it has file %s " |
282 | + "(%s, %s)" % ( |
283 | + self._builder.url, file_name, url, sha1)) |
284 | + self._builder._sendFileToSlave( |
285 | + url, sha1, "buildd", archive.buildd_secret) |
286 | + |
287 | + def _extraBuildArgs(self, build): |
288 | + """ |
289 | + Return the extra arguments required by the slave for the given build. |
290 | + """ |
291 | + # Build extra arguments. |
292 | + args = {} |
293 | + # turn 'arch_indep' ON only if build is archindep or if |
294 | + # the specific architecture is the nominatedarchindep for |
295 | + # this distroseries (in case it requires any archindep source) |
296 | + args['arch_indep'] = build.distroarchseries.isNominatedArchIndep |
297 | + |
298 | + suite = build.distroarchseries.distroseries.name |
299 | + if build.pocket != PackagePublishingPocket.RELEASE: |
300 | + suite += "-%s" % (build.pocket.name.lower()) |
301 | + args['suite'] = suite |
302 | + |
303 | + archive_purpose = build.archive.purpose |
304 | + if (archive_purpose == ArchivePurpose.PPA and |
305 | + not build.archive.require_virtualized): |
306 | + # If we're building a non-virtual PPA, override the purpose |
307 | + # to PRIMARY and use the primary component override. |
308 | + # This ensures that the package mangling tools will run over |
309 | + # the built packages. |
310 | + args['archive_purpose'] = ArchivePurpose.PRIMARY.name |
311 | + args["ogrecomponent"] = ( |
312 | + get_primary_current_component(build)) |
313 | + else: |
314 | + args['archive_purpose'] = archive_purpose.name |
315 | + args["ogrecomponent"] = ( |
316 | + build.current_component.name) |
317 | + |
318 | + args['archives'] = get_sources_list_for_building(build) |
319 | + |
320 | + # Let the build slave know whether this is a build in a private |
321 | + # archive. |
322 | + args['archive_private'] = build.archive.private |
323 | + return args |
324 | |
325 | === modified file 'lib/lp/soyuz/model/builder.py' |
326 | --- lib/lp/soyuz/model/builder.py 2009-12-02 08:50:30 +0000 |
327 | +++ lib/lp/soyuz/model/builder.py 2009-12-02 08:50:31 +0000 |
328 | @@ -38,8 +38,6 @@ |
329 | from lp.buildmaster.master import BuilddMaster |
330 | from lp.buildmaster.model.buildfarmjobbehavior import IdleBuildBehavior |
331 | from canonical.database.sqlbase import SQLBase, sqlvalues |
332 | -from lp.soyuz.adapters.archivedependencies import ( |
333 | - get_primary_current_component, get_sources_list_for_building) |
334 | from lp.soyuz.model.buildqueue import BuildQueue |
335 | from lp.registry.interfaces.person import validate_public_person |
336 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
337 | @@ -117,6 +115,7 @@ |
338 | |
339 | return (stdout, stderr, resume_process.returncode) |
340 | |
341 | + |
342 | class Builder(SQLBase): |
343 | |
344 | implements(IBuilder, IHasBuildRecords) |
345 | @@ -195,30 +194,6 @@ |
346 | url, libraryfilealias.content.sha1)) |
347 | self._sendFileToSlave(url, libraryfilealias.content.sha1) |
348 | |
349 | - def cachePrivateSourceOnSlave(self, logger, build_queue_item): |
350 | - """See `IBuilder`.""" |
351 | - # The URL to the file in the archive consists of these parts: |
352 | - # archive_url / makePoolPath() / filename |
353 | - # Once this is constructed we add the http basic auth info. |
354 | - |
355 | - # Avoid circular imports. |
356 | - from lp.soyuz.model.publishing import makePoolPath |
357 | - |
358 | - build = getUtility(IBuildSet).getByQueueEntry(build_queue_item) |
359 | - archive = build.archive |
360 | - archive_url = archive.archive_url |
361 | - component_name = build.current_component.name |
362 | - for source_file in build.sourcepackagerelease.files: |
363 | - file_name = source_file.libraryfile.filename |
364 | - sha1 = source_file.libraryfile.content.sha1 |
365 | - source_name = build.sourcepackagerelease.sourcepackagename.name |
366 | - poolpath = makePoolPath(source_name, component_name) |
367 | - url = urlappend(archive_url, poolpath) |
368 | - url = urlappend(url, file_name) |
369 | - logger.debug("Asking builder on %s to ensure it has file %s " |
370 | - "(%s, %s)" % (self.url, file_name, url, sha1)) |
371 | - self._sendFileToSlave(url, sha1, "buildd", archive.buildd_secret) |
372 | - |
373 | def _sendFileToSlave(self, url, sha1, username="", password=""): |
374 | """Helper to send the file at 'url' with 'sha1' to this builder.""" |
375 | if not self.builderok: |
376 | @@ -308,99 +283,6 @@ |
377 | """See IBuilder.""" |
378 | self.slave = proxy |
379 | |
380 | - def _verifyBuildRequest(self, build_queue_item, logger): |
381 | - """Assert some pre-build checks. |
382 | - |
383 | - The build request is checked: |
384 | - * Virtualized builds can't build on a non-virtual builder |
385 | - * Ensure that we have a chroot |
386 | - * Ensure that the build pocket allows builds for the current |
387 | - distroseries state. |
388 | - """ |
389 | - build = getUtility(IBuildSet).getByQueueEntry(build_queue_item) |
390 | - assert not (not self.virtualized and build.is_virtualized), ( |
391 | - "Attempt to build non-virtual item on a virtual builder.") |
392 | - |
393 | - # Assert that we are not silently building SECURITY jobs. |
394 | - # See findBuildCandidates. Once we start building SECURITY |
395 | - # correctly from EMBARGOED archive this assertion can be removed. |
396 | - # XXX Julian 2007-12-18 spec=security-in-soyuz: This is being |
397 | - # addressed in the work on the blueprint: |
398 | - # https://blueprints.launchpad.net/soyuz/+spec/security-in-soyuz |
399 | - target_pocket = build.pocket |
400 | - assert target_pocket != PackagePublishingPocket.SECURITY, ( |
401 | - "Soyuz is not yet capable of building SECURITY uploads.") |
402 | - |
403 | - # Ensure build has the needed chroot |
404 | - build = getUtility(IBuildSet).getByQueueEntry(build_queue_item) |
405 | - chroot = build.distroarchseries.getChroot() |
406 | - if chroot is None: |
407 | - raise CannotBuild( |
408 | - "Missing CHROOT for %s/%s/%s" % ( |
409 | - build.distroseries.distribution.name, |
410 | - build.distroseries.name, |
411 | - build.distroarchseries.architecturetag) |
412 | - ) |
413 | - |
414 | - # The main distribution has policies to prevent uploads to some |
415 | - # pockets (e.g. security) during different parts of the distribution |
416 | - # series lifecycle. These do not apply to PPA builds nor any archive |
417 | - # that allows release pocket updates. |
418 | - if (build.archive.purpose != ArchivePurpose.PPA and |
419 | - not build.archive.allowUpdatesToReleasePocket()): |
420 | - # XXX Robert Collins 2007-05-26: not an explicit CannotBuild |
421 | - # exception yet because the callers have not been audited |
422 | - assert build.distroseries.canUploadToPocket(build.pocket), ( |
423 | - "%s (%s) can not be built for pocket %s: invalid pocket due " |
424 | - "to the series status of %s." |
425 | - % (build.title, build.id, build.pocket.name, |
426 | - build.distroseries.name)) |
427 | - |
428 | - def _dispatchBuildToSlave(self, build_queue_item, args, buildid, logger): |
429 | - """Start the build on the slave builder.""" |
430 | - # Send chroot. |
431 | - build = getUtility(IBuildSet).getByQueueEntry(build_queue_item) |
432 | - chroot = build.distroarchseries.getChroot() |
433 | - self.cacheFileOnSlave(logger, chroot) |
434 | - |
435 | - # Build filemap structure with the files required in this build |
436 | - # and send them to the slave. |
437 | - # If the build is private we tell the slave to get the files from the |
438 | - # archive instead of the librarian because the slaves cannot |
439 | - # access the restricted librarian. |
440 | - private = build.archive.private |
441 | - if private: |
442 | - self.cachePrivateSourceOnSlave(logger, build_queue_item) |
443 | - filemap = {} |
444 | - for source_file in build.sourcepackagerelease.files: |
445 | - lfa = source_file.libraryfile |
446 | - filemap[lfa.filename] = lfa.content.sha1 |
447 | - if not private: |
448 | - self.cacheFileOnSlave(logger, source_file.libraryfile) |
449 | - |
450 | - chroot_sha1 = chroot.content.sha1 |
451 | - try: |
452 | - status, info = self.slave.build( |
453 | - buildid, "debian", chroot_sha1, filemap, args) |
454 | - message = """%s (%s): |
455 | - ***** RESULT ***** |
456 | - %s |
457 | - %s |
458 | - %s: %s |
459 | - ****************** |
460 | - """ % (self.name, self.url, filemap, args, status, info) |
461 | - logger.info(message) |
462 | - except xmlrpclib.Fault, info: |
463 | - # Mark builder as 'failed'. |
464 | - logger.debug("Disabling builder: %s" % self.url, exc_info=1) |
465 | - self.failbuilder( |
466 | - "Exception (%s) when setting up to new job" % info) |
467 | - raise BuildSlaveFailure |
468 | - except socket.error, info: |
469 | - error_message = "Exception (%s) when setting up new job" % info |
470 | - self.handleTimeout(logger, error_message) |
471 | - raise BuildSlaveFailure |
472 | - |
473 | def startBuild(self, build_queue_item, logger): |
474 | """See IBuilder.""" |
475 | # Set the build behavior depending on the provided build queue item. |
476 | @@ -408,55 +290,15 @@ |
477 | self.logStartBuild(build_queue_item, logger) |
478 | |
479 | # Make sure the request is valid; an exception is raised if it's not. |
480 | - self._verifyBuildRequest(build_queue_item, logger) |
481 | + self.verifyBuildRequest(build_queue_item, logger) |
482 | |
483 | # If we are building a virtual build, resume the virtual machine. |
484 | if self.virtualized: |
485 | self.resumeSlaveHost() |
486 | |
487 | - # Build extra arguments. |
488 | - args = {} |
489 | - # turn 'arch_indep' ON only if build is archindep or if |
490 | - # the specific architecture is the nominatedarchindep for |
491 | - # this distroseries (in case it requires any archindep source) |
492 | - build = getUtility(IBuildSet).getByQueueEntry(build_queue_item) |
493 | - args['arch_indep'] = build.distroarchseries.isNominatedArchIndep |
494 | - |
495 | - suite = build.distroarchseries.distroseries.name |
496 | - if build.pocket != PackagePublishingPocket.RELEASE: |
497 | - suite += "-%s" % (build.pocket.name.lower()) |
498 | - args['suite'] = suite |
499 | - |
500 | - archive_purpose = build.archive.purpose |
501 | - if (archive_purpose == ArchivePurpose.PPA and |
502 | - not build.archive.require_virtualized): |
503 | - # If we're building a non-virtual PPA, override the purpose |
504 | - # to PRIMARY and use the primary component override. |
505 | - # This ensures that the package mangling tools will run over |
506 | - # the built packages. |
507 | - args['archive_purpose'] = ArchivePurpose.PRIMARY.name |
508 | - args["ogrecomponent"] = ( |
509 | - get_primary_current_component(build)) |
510 | - else: |
511 | - args['archive_purpose'] = archive_purpose.name |
512 | - args["ogrecomponent"] = ( |
513 | - build.current_component.name) |
514 | - |
515 | - args['archives'] = get_sources_list_for_building(build) |
516 | - |
517 | - # Let the build slave know whether this is a build in a private |
518 | - # archive. |
519 | - args['archive_private'] = build.archive.private |
520 | - |
521 | - # Generate a string which can be used to cross-check when obtaining |
522 | - # results so we know we are referring to the right database object in |
523 | - # subsequent runs. |
524 | - buildid = "%s-%s" % (build.id, build_queue_item.id) |
525 | - logger.debug("Initiating build %s on %s" % (buildid, self.url)) |
526 | - |
527 | # Do it. |
528 | build_queue_item.markAsBuilding(self) |
529 | - self._dispatchBuildToSlave(build_queue_item, args, buildid, logger) |
530 | + self.dispatchBuildToSlave(build_queue_item, logger) |
531 | |
532 | # XXX cprov 2009-06-24: This code does not belong to the content |
533 | # class domain. Here we cannot make sensible decisions about what |
534 | @@ -469,19 +311,10 @@ |
535 | if self.failnotes is not None: |
536 | return self.failnotes |
537 | return 'Disabled' |
538 | - # Cache the 'currentjob', so we don't have to hit the database |
539 | - # more than once. |
540 | - currentjob = self.currentjob |
541 | - if currentjob is None: |
542 | - return 'Idle' |
543 | |
544 | - build = getUtility(IBuildSet).getByQueueEntry(currentjob) |
545 | - msg = 'Building %s' % build.title |
546 | - archive = build.archive |
547 | - if not archive.owner.private and (archive.is_ppa or archive.is_copy): |
548 | - return '%s [%s/%s]' % (msg, archive.owner.name, archive.name) |
549 | - else: |
550 | - return msg |
551 | + # If the builder is OK then we delegate the status |
552 | + # to our current behavior. |
553 | + return self.current_build_behavior.status |
554 | |
555 | def failbuilder(self, reason): |
556 | """See IBuilder""" |
557 | @@ -722,7 +555,7 @@ |
558 | logger = self._getSlaveScannerLogger() |
559 | try: |
560 | self.startBuild(candidate, logger) |
561 | - except (BuildSlaveFailure, CannotBuild), err: |
562 | + except (BuildSlaveFailure, CannotBuild, BuildBehaviorMismatch), err: |
563 | logger.warn('Could not build: %s' % err) |
564 | |
565 | def handleTimeout(self, logger, error_message): |
= Summary =
This branch continues on from the prerequisite at:
https:/ /code.edge. launchpad. net/~michael. nelson/ launchpad/ 487009- db-generalise- ibuilder- 1b/+merge/ 15477
and extracts most of the remaining soyuz-specific binary build logic from IBuilder and into the custom BinaryPackageBu ildBehavior to which IBuilder delegates for binary builds, in particular leaving the IBuilder. startBuild( ) method looking like:
http:// pastebin. ubuntu. com/332947/
with verifyBuildRequ est() and dispatchBuildTo Slave() now being delegated to the current build behavior.
I will have one further branch that: getBuildRecords () slaveStatus( ) havior with examples for adding further behaviors.
* extracts IBuilder.
* extracts IBuilder.
* adds documentation for the IBuildFarmJobBe
== Pre-implementation notes ==
See the pre-implementation notes on bug 487009.
== Implementation details ==
== Tests ==
bin/test -vv -t doc/builder.txt -t doc/buildd- dispatching. txt
== Demo and Q/A ==
We will need to Q/A this on dogfood.
= Launchpad lint =
lib/lp/ soyuz/model/ builder. py
23: [F0401] Unable to import 'lazr.delegates' (No module named delegates)