Merge lp:~mbp/launchpad/mbp-trivial into lp:launchpad/db-devel

Proposed by Martin Pool
Status: Superseded
Proposed branch: lp:~mbp/launchpad/mbp-trivial
Merge into: lp:launchpad/db-devel
Diff against target: 728 lines (+243/-98)
17 files modified
Makefile (+46/-22)
cronscripts/publishing/cron.publish-copy-archives (+4/-21)
lib/canonical/buildd/binarypackage.py (+0/-2)
lib/canonical/buildd/buildrecipe (+2/-0)
lib/canonical/launchpad/doc/emailaddress.txt (+9/-7)
lib/lp/app/javascript/tests/test_lp_collapsibles.html (+6/-6)
lib/lp/app/javascript/tests/test_lp_collapsibles.js (+17/-9)
lib/lp/app/windmill/testing.py (+21/-0)
lib/lp/app/windmill/tests/test_yuitests.py (+24/-0)
lib/lp/buildmaster/manager.py (+5/-3)
lib/lp/buildmaster/model/builder.py (+39/-3)
lib/lp/buildmaster/tests/test_builder.py (+54/-0)
lib/lp/code/model/recipebuilder.py (+3/-1)
lib/lp/code/model/tests/test_recipebuilder.py (+9/-3)
lib/lp/registry/javascript/tests/test_milestone_table.html (+1/-1)
lib/lp/services/mailman/doc/postings.txt (+0/-19)
lib/lp/translations/windmill/tests/test_languages.py (+3/-1)
To merge this branch: bzr merge lp:~mbp/launchpad/mbp-trivial
Reviewer Review Type Date Requested Status
Jeroen T. Vermeulen (community) code Needs Resubmitting
Launchpad code reviewers Pending
Review via email: mp+41268@code.launchpad.net

This proposal has been superseded by a proposal from 2010-11-21.

Description of the change

This tweaks Jeroen and Benji's recent work in "Faster builds" so that the makefile dependencies are more precise, to avoid unnecessary rebuilds.

To post a comment you must log in.
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

The Makefile changes look good—and thanks again for making them!—but I think you accidentally submitted this for db-devel (after branching off devel) so the diff contains a lot of unrelated material.

review: Needs Resubmitting (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2010-11-02 01:34:05 +0000
3+++ Makefile 2010-11-19 08:04:58 +0000
4@@ -34,6 +34,9 @@
5 # Do not add bin/buildout to this list.
6 # It is impossible to get buildout to tell us all the files it would
7 # build, since each egg's setup.py doesn't tell us that information.
8+#
9+# NB: It's important BUILDOUT_BIN only mentions things genuinely produced by
10+# buildout.
11 BUILDOUT_BIN = \
12 $(PY) bin/apiindex bin/combine-css bin/fl-build-report \
13 bin/fl-credential-ctl bin/fl-install-demo bin/fl-monitor-ctl \
14@@ -45,6 +48,8 @@
15 bin/start_librarian bin/stxdocs bin/tags bin/test bin/tracereport \
16 bin/twistd bin/update-download-cache bin/windmill
17
18+BUILDOUT_TEMPLATES = buildout-templates/_pythonpath.py.in
19+
20 # DO NOT ALTER : this should just build by default
21 default: inplace
22
23@@ -58,7 +63,7 @@
24 hosted_branches: $(PY)
25 $(PY) ./utilities/make-dummy-hosted-branches
26
27-$(API_INDEX): $(BZR_VERSION_INFO)
28+$(API_INDEX): $(BZR_VERSION_INFO) $(PY)
29 mkdir -p $(APIDOC_DIR).tmp
30 LPCONFIG=$(LPCONFIG) $(PY) ./utilities/create-lp-wadl-and-apidoc.py --force "$(WADL_TEMPLATE)"
31 mv $(APIDOC_DIR).tmp $(APIDOC_DIR)
32@@ -66,7 +71,7 @@
33 apidoc: compile $(API_INDEX)
34
35 # Run by PQM.
36-check_merge: $(PY)
37+check_merge: $(BUILDOUT_BIN)
38 [ `PYTHONPATH= bzr status -S database/schema/ | \
39 grep -v "\(^P\|pending\|security.cfg\|Makefile\|unautovacuumable\|_pythonpath.py\)" | wc -l` -eq 0 ]
40 ${PY} lib/canonical/tests/test_no_conflict_marker.py
41@@ -139,13 +144,15 @@
42 sprite_image:
43 ${SHHH} bin/sprite-util create-image
44
45+# We absolutely do not want to include the lazr.testing module and
46+# its jsTestDriver test harness modifications in the lazr.js and
47+# launchpad.js roll-up files. They fiddle with built-in functions!
48+# See Bug 482340.
49 jsbuild_lazr: bin/jsbuild
50- # We absolutely do not want to include the lazr.testing module and its
51- # jsTestDriver test harness modifications in the lazr.js and launchpad.js
52- # roll-up files. They fiddle with built-in functions! See Bug 482340.
53- ${SHHH} bin/jsbuild $(JSFLAGS) -b $(LAZR_BUILT_JS_ROOT) -x testing/ -c $(LAZR_BUILT_JS_ROOT)/yui
54+ ${SHHH} bin/jsbuild $(JSFLAGS) -b $(LAZR_BUILT_JS_ROOT) -x testing/ \
55+ -c $(LAZR_BUILT_JS_ROOT)/yui
56
57-jsbuild: jsbuild_lazr bin/jsbuild bin/jssize
58+jsbuild: jsbuild_lazr bin/jsbuild bin/jssize $(BUILDOUT_BIN)
59 ${SHHH} bin/jsbuild \
60 $(JSFLAGS) \
61 -n launchpad \
62@@ -177,30 +184,45 @@
63 find eggs -name '*.pyc' -exec rm {} \;
64
65 # The download-cache dependency comes *before* eggs so that developers get the
66-# warning before the eggs directory is made. The target for the eggs directory
67-# is only there for deployment convenience.
68+# warning before the eggs directory is made. The target for the eggs
69+# directory is only there for deployment convenience.
70 # Note that the buildout version must be maintained here and in versions.cfg
71 # to make sure that the build does not go over the network.
72+#
73+# buildout won't touch files that would have the same contents, but for Make's
74+# sake we need them to get fresh timestamps, so we touch them after building.
75 bin/buildout: download-cache eggs
76 $(SHHH) PYTHONPATH= $(PYTHON) bootstrap.py\
77 --setup-source=ez_setup.py \
78 --download-base=download-cache/dist --eggs=eggs \
79 --version=1.5.1
80+ touch --no-create $@
81
82 # This target is used by LOSAs to prepare a build to be pushed out to
83 # destination machines. We only want eggs: they are the expensive bits,
84 # and the other bits might run into problems like bug 575037. This
85 # target runs buildout, and then removes everything created except for
86 # the eggs.
87-build_eggs: $(BUILDOUT_BIN) clean_buildout
88+build_eggs: $(BUILDOUT_BIN)
89
90 # This builds bin/py and all the other bin files except bin/buildout.
91 # Remove the target before calling buildout to ensure that buildout
92 # updates the timestamp.
93-$(BUILDOUT_BIN): bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py
94- $(RM) $@
95+buildout_bin: $(BUILDOUT_BIN)
96+
97+# buildout won't touch files that would have the same contents, but for Make's
98+# sake we need them to get fresh timestamps, so we touch them after building.
99+#
100+# If we listed every target on the left-hand side, a parallel make would try
101+# multiple copies of this rule to build them all. Instead, we nominally build
102+# just $(PY), and everything else is implicitly updated by that.
103+$(PY): bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py \
104+ $(BUILDOUT_TEMPLATES)
105 $(SHHH) PYTHONPATH= ./bin/buildout \
106 configuration:instance_name=${LPCONFIG} -c $(BUILDOUT_CFG)
107+ touch $@
108+
109+$(subst $(PY),,$(BUILDOUT_BIN)): $(PY)
110
111 # bin/compile_templates is responsible for building all chameleon templates,
112 # of which there is currently one, but of which many more are coming.
113@@ -405,7 +427,8 @@
114 # We insert the absolute path to the branch-rewrite script
115 # into the Apache config as we copy the file into position.
116 sed -e 's,%BRANCH_REWRITE%,$(shell pwd)/scripts/branch-rewrite.py,' configs/development/local-launchpad-apache > /etc/apache2/sites-available/local-launchpad
117- cp configs/development/local-vostok-apache /etc/apache2/sites-available/local-vostok
118+ cp configs/development/local-vostok-apache \
119+ /etc/apache2/sites-available/local-vostok
120 touch /var/tmp/bazaar.launchpad.dev/rewrite.log
121 chown $(SUDO_UID):$(SUDO_GID) /var/tmp/bazaar.launchpad.dev/rewrite.log
122
123@@ -430,8 +453,9 @@
124
125 lp.sfood:
126 # Generate import dependency graph
127- sfood -i -u -I lib/sqlobject -I lib/schoolbell -I lib/devscripts -I lib/contrib \
128- -I lib/canonical/not-used lib/canonical lib/lp 2>/dev/null | grep -v contrib/ \
129+ sfood -i -u -I lib/sqlobject -I lib/schoolbell -I lib/devscripts \
130+ -I lib/contrib -I lib/canonical/not-used lib/canonical \
131+ lib/lp 2>/dev/null | grep -v contrib/ \
132 | grep -v sqlobject | grep -v BeautifulSoup | grep -v psycopg \
133 | grep -v schoolbell > lp.sfood.tmp
134 mv lp.sfood.tmp lp.sfood
135@@ -463,10 +487,10 @@
136 --docformat restructuredtext --verbose-about epytext-summary \
137 $(PYDOCTOR_OPTIONS)
138
139-.PHONY: apidoc check tags TAGS zcmldocs realclean clean debug stop\
140- start run ftest_build ftest_inplace test_build test_inplace pagetests\
141- check check_merge \
142- schema default launchpad.pot check_merge_ui pull scan sync_branches\
143- reload-apache hosted_branches check_db_merge check_mailman check_config\
144- jsbuild jsbuild_lazr clean_js clean_buildout buildonce_eggs build_eggs\
145- sprite_css sprite_image css_combine compile check_schema pydoctor
146+.PHONY: apidoc buildout_bin check tags TAGS zcmldocs realclean clean debug \
147+ stop start run ftest_build ftest_inplace test_build test_inplace \
148+ pagetests check check_merge schema default launchpad.pot \
149+ check_merge_ui pull scan sync_branches reload-apache hosted_branches \
150+ check_db_merge check_mailman check_config jsbuild jsbuild_lazr \
151+ clean_js clean_buildout buildonce_eggs build_eggs sprite_css \
152+ sprite_image css_combine compile check_schema pydoctor
153
154=== modified file 'cronscripts/publishing/cron.publish-copy-archives'
155--- cronscripts/publishing/cron.publish-copy-archives 2010-06-25 14:36:11 +0000
156+++ cronscripts/publishing/cron.publish-copy-archives 2010-11-19 08:04:58 +0000
157@@ -10,7 +10,6 @@
158 exit 1
159 fi
160
161-set -x
162 set -e
163 set -u
164
165@@ -20,24 +19,23 @@
166
167
168 # Informational -- this *MUST* match the database.
169-ARCHIVEROOT=/srv/launchpad.net/ubuntu-archive/ubuntu
170+ARCHIVEROOT=/srv/launchpad.net/rebuild-test/ubuntu
171 DISTSROOT=$ARCHIVEROOT/dists
172 OVERRIDEROOT=$ARCHIVEROOT/../ubuntu-overrides
173 INDICES=$ARCHIVEROOT/indices
174 PRODUCTION_CONFIG=ftpmaster-publish
175
176 if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
177- GNUPGHOME=/srv/launchpad.net/ubuntu-archive/gnupg-home
178+ GNUPGHOME=/srv/launchpad.net/rebuild-test/gnupg-home
179 else
180 echo GPG keys will come from ~/.gnupg
181 # GNUPGHOME does not need to be set, keys can come from ~/.gnupg.
182 fi
183
184 # Configuration options.
185-LAUNCHPADROOT=/srv/launchpad.net/codelines/current
186-LOCKFILE=/srv/launchpad.net/ubuntu-archive/cron.daily.lock
187+LAUNCHPADROOT=/srv/launchpad.net/production/launchpad
188+LOCKFILE=/srv/launchpad.net/rebuild-test/cron.daily.lock
189 DISTRONAME=ubuntu
190-TRACEFILE=$ARCHIVEROOT/project/trace/$(hostname --fqdn)
191
192 # Manipulate the environment.
193 export GNUPGHOME
194@@ -64,20 +62,5 @@
195 # Publish the packages to disk.
196 publish-distro.py -v -v --copy-archive -d $DISTRONAME
197
198-set +x
199-
200 echo Removing uncompressed Packages and Sources files
201 find ${DISTSROOT} \( -name "Packages" -o -name "Sources" \) -exec rm "{}" \;
202-
203-# Copy in the indices.
204-if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
205- echo Copying the indices into place.
206- rm -f $INDICES/override.*
207- cp $OVERRIDEROOT/override.* $INDICES
208-fi
209-
210-# Timestamp our trace file to track when the last archive publisher run took
211-# place.
212-if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
213- date -u > "$TRACEFILE"
214-fi
215
216=== modified file 'lib/canonical/buildd/binarypackage.py'
217--- lib/canonical/buildd/binarypackage.py 2010-07-13 09:13:41 +0000
218+++ lib/canonical/buildd/binarypackage.py 2010-11-19 08:04:58 +0000
219@@ -19,9 +19,7 @@
220 class BuildLogRegexes:
221 """Build log regexes for performing actions based on regexes, and extracting dependencies for auto dep-waits"""
222 GIVENBACK = [
223- (" terminated by signal 4"),
224 ("^E: There are problems and -y was used without --force-yes"),
225- ("^make.* Illegal instruction"),
226 ]
227 DEPFAIL = [
228 ("(?P<pk>[\-+.\w]+)\(inst [^ ]+ ! >> wanted (?P<v>[\-.+\w:~]+)\)","\g<pk> (>> \g<v>)"),
229
230=== modified file 'lib/canonical/buildd/buildrecipe'
231--- lib/canonical/buildd/buildrecipe 2010-09-30 20:22:15 +0000
232+++ lib/canonical/buildd/buildrecipe 2010-11-19 08:04:58 +0000
233@@ -11,6 +11,7 @@
234 import os
235 import pwd
236 import re
237+from resource import RLIMIT_AS, setrlimit
238 import socket
239 from subprocess import call, Popen, PIPE
240 import sys
241@@ -206,6 +207,7 @@
242
243
244 if __name__ == '__main__':
245+ setrlimit(RLIMIT_AS, (1000000000, -1))
246 builder = RecipeBuilder(*sys.argv[1:])
247 if builder.buildTree() != 0:
248 sys.exit(RETCODE_FAILURE_BUILD_TREE)
249
250=== renamed file 'lib/canonical/launchpad/doc/emailaddress.txt.disabled' => 'lib/canonical/launchpad/doc/emailaddress.txt'
251--- lib/canonical/launchpad/doc/emailaddress.txt.disabled 2009-08-13 19:03:36 +0000
252+++ lib/canonical/launchpad/doc/emailaddress.txt 2010-11-19 08:04:58 +0000
253@@ -1,4 +1,5 @@
254-= Email Addresses =
255+Email Addresses
256+===============
257
258 In Launchpad we use email addresses to uniquely identify a person. This is why
259 email addresses must be unique.
260@@ -22,7 +23,7 @@
261
262 Email addresses provide both IEmailAddress and IHasOwner.
263
264- >>> from canonical.launchpad.interfaces.launchpad import IHasOwner
265+ >>> from lp.registry.interfaces.role import IHasOwner
266 >>> verifyObject(IEmailAddress, email)
267 True
268 >>> verifyObject(IHasOwner, email)
269@@ -66,11 +67,12 @@
270 [u'celso.providelo@canonical.com', u'colin.watson@ubuntulinux.com',
271 u'daniel.silverstone@canonical.com', u'edgar@monteparadiso.hr',
272 u'foo.bar@canonical.com', u'jeff.waugh@ubuntulinux.com',
273- u'limi@plone.org', u'mark@example.com', u'steve.alexander@ubuntulinux.com',
274- u'support@ubuntu.com']
275-
276-
277-== Deleting email addresses ==
278+ u'limi@plone.org', u'mark@example.com',
279+ u'steve.alexander@ubuntulinux.com', u'support@ubuntu.com']
280+
281+
282+Deleting email addresses
283+------------------------
284
285 Email addresses may be deleted if they're not a person's preferred one
286 or the address of a team's mailing list.
287
288=== modified file 'lib/lp/app/javascript/tests/test_lp_collapsibles.html'
289--- lib/lp/app/javascript/tests/test_lp_collapsibles.html 2010-07-26 13:42:32 +0000
290+++ lib/lp/app/javascript/tests/test_lp_collapsibles.html 2010-11-19 08:04:58 +0000
291@@ -4,14 +4,14 @@
292 <title>Launchpad Collapsibles</title>
293
294 <!-- YUI 3.0 Setup -->
295- <script type="text/javascript" src="../../../icing/yui/yui/yui.js"></script>
296- <link rel="stylesheet" href="../../../icing/yui/cssreset/reset.css"/>
297- <link rel="stylesheet" href="../../../icing/yui/cssfonts/fonts.css"/>
298- <link rel="stylesheet" href="../../../icing/yui/cssbase/base.css"/>
299- <link rel="stylesheet" href="../../test.css" />
300+ <script type="text/javascript" src="../../../../canonical/launchpad/icing/yui/yui/yui.js"></script>
301+ <script type="text/javascript" src="../../../../canonical/launchpad/icing/lazr/build/lazr.js"></script>
302+ <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssreset/reset.css"/>
303+ <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssfonts/fonts.css"/>
304+ <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssbase/base.css"/>
305+ <link rel="stylesheet" href="../../../../canonical/launchpad/javascript/test.css" />
306
307 <!-- The module under test -->
308- <script type="text/javascript" src="../../../icing/lazr/build/effects/effects.js"></script>
309 <script type="text/javascript" src="../lp.js"></script>
310
311 <!-- The test suite -->
312
313=== modified file 'lib/lp/app/javascript/tests/test_lp_collapsibles.js'
314--- lib/lp/app/javascript/tests/test_lp_collapsibles.js 2010-07-26 13:42:32 +0000
315+++ lib/lp/app/javascript/tests/test_lp_collapsibles.js 2010-11-19 08:04:58 +0000
316@@ -1,21 +1,21 @@
317 /* Copyright (c) 2009, Canonical Ltd. All rights reserved. */
318
319 YUI({
320- base: '../../../icing/yui/',
321+ base: '../../../../canonical/launchpad/icing/yui/',
322 filter: 'raw',
323 combine: false
324 }).use('test', 'console', 'lp', function(Y) {
325
326 var Assert = Y.Assert; // For easy access to isTrue(), etc.
327
328-Y.Test.Runner.add(new Y.Test.Case({
329+var suite = new Y.Test.Suite("Collapsibles Tests");
330+suite.add(new Y.Test.Case({
331 name: "activate_collapsibles",
332
333 _should: {
334- error: {
335+ fail: {
336 test_toggle_collapsible_fails_on_wrapperless_collapsible: true,
337 test_toggle_collapsible_fails_on_iconless_collapsible: true,
338- test_activate_collapsibles_handles_no_collapsibles: false
339 }
340 },
341
342@@ -149,17 +149,16 @@
343 test_toggle_collapsible_opens_collapsed_collapsible: function() {
344 // Calling toggle_collapsible() on a collapsed collapsible will
345 // toggle its state to open.
346+ Y.lp.activate_collapsibles();
347 var collapsible = this.container.one('.collapsible');
348- collapsible.addClass('collapsed');
349+ var wrapper_div = collapsible.one('.collapseWrapper');
350+ wrapper_div.addClass('lazr-closed');
351
352- Y.lp.activate_collapsibles();
353 Y.lp.toggle_collapsible(collapsible);
354 this.wait(function() {
355-
356 // The collapsible's wrapper div will now be open.
357 var icon = collapsible.one('img');
358- var wrapper_div = collapsible.one('.collapseWrapper');
359- Assert.isTrue(wrapper_div.hasClass('lazr-open'));
360+ Assert.isFalse(wrapper_div.hasClass('lazr-closed'));
361 Assert.areNotEqual(
362 -1, icon.get('src').indexOf('/@@/treeExpanded'));
363 }, 500);
364@@ -321,6 +320,15 @@
365 }
366 }));
367
368+// Lock, stock, and two smoking barrels.
369+var handle_complete = function(data) {
370+ status_node = Y.Node.create(
371+ '<p id="complete">Test status: complete</p>');
372+ Y.get('body').appendChild(status_node);
373+ };
374+Y.Test.Runner.on('complete', handle_complete);
375+Y.Test.Runner.add(suite);
376+
377 var yui_console = new Y.Console({
378 newestOnTop: false
379 });
380
381=== added directory 'lib/lp/app/windmill'
382=== added file 'lib/lp/app/windmill/__init__.py'
383=== added file 'lib/lp/app/windmill/testing.py'
384--- lib/lp/app/windmill/testing.py 1970-01-01 00:00:00 +0000
385+++ lib/lp/app/windmill/testing.py 2010-11-19 08:04:58 +0000
386@@ -0,0 +1,21 @@
387+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
388+# GNU Affero General Public License version 3 (see the file LICENSE).
389+
390+"""Launchpad app specific testing infrastructure for Windmill."""
391+
392+__metaclass__ = type
393+__all__ = [
394+ 'AppWindmillLayer',
395+ ]
396+
397+
398+from canonical.testing.layers import BaseWindmillLayer
399+
400+
401+class AppWindmillLayer(BaseWindmillLayer):
402+ """Layer for App Windmill tests."""
403+
404+ @classmethod
405+ def setUp(cls):
406+ cls.base_url = cls.appserver_root_url()
407+ super(AppWindmillLayer, cls).setUp()
408
409=== added directory 'lib/lp/app/windmill/tests'
410=== added file 'lib/lp/app/windmill/tests/__init__.py'
411=== added file 'lib/lp/app/windmill/tests/test_yuitests.py'
412--- lib/lp/app/windmill/tests/test_yuitests.py 1970-01-01 00:00:00 +0000
413+++ lib/lp/app/windmill/tests/test_yuitests.py 2010-11-19 08:04:58 +0000
414@@ -0,0 +1,24 @@
415+# Copyright 2010 Canonical Ltd. This software is licensed under the
416+# GNU Affero General Public License version 3 (see the file LICENSE).
417+
418+"""Run YUI.test tests."""
419+
420+__metaclass__ = type
421+__all__ = []
422+
423+from lp.app.windmill.testing import AppWindmillLayer
424+from lp.testing import (
425+ build_yui_unittest_suite,
426+ YUIUnitTestCase,
427+ )
428+
429+
430+class AppYUIUnitTestCase(YUIUnitTestCase):
431+
432+ layer = AppWindmillLayer
433+ suite_name = 'AppYUIUnitTests'
434+
435+
436+def test_suite():
437+ app_testing_path = 'lp/app/javascript/tests'
438+ return build_yui_unittest_suite(app_testing_path, AppYUIUnitTestCase)
439
440=== modified file 'lib/lp/buildmaster/manager.py'
441--- lib/lp/buildmaster/manager.py 2010-10-28 15:04:15 +0000
442+++ lib/lp/buildmaster/manager.py 2010-11-19 08:04:58 +0000
443@@ -151,10 +151,12 @@
444 if failure.check(
445 BuildSlaveFailure, CannotBuild, BuildBehaviorMismatch,
446 CannotResumeHost, BuildDaemonError, CannotFetchFile):
447- self.logger.info("Scanning failed with: %s" % error_message)
448+ self.logger.info("Scanning %s failed with: %s" % (
449+ self.builder_name, error_message))
450 else:
451- self.logger.info("Scanning failed with: %s\n%s" %
452- (failure.getErrorMessage(), failure.getTraceback()))
453+ self.logger.info("Scanning %s failed with: %s\n%s" % (
454+ self.builder_name, failure.getErrorMessage(),
455+ failure.getTraceback()))
456
457 # Decide if we need to terminate the job or fail the
458 # builder.
459
460=== modified file 'lib/lp/buildmaster/model/builder.py'
461--- lib/lp/buildmaster/model/builder.py 2010-11-10 13:06:05 +0000
462+++ lib/lp/buildmaster/model/builder.py 2010-11-19 08:04:58 +0000
463@@ -8,6 +8,7 @@
464 __all__ = [
465 'Builder',
466 'BuilderSet',
467+ 'ProxyWithConnectionTimeout',
468 'rescueBuilderIfLost',
469 'updateBuilderStatus',
470 ]
471@@ -99,6 +100,41 @@
472 noisy = False
473
474
475+class ProxyWithConnectionTimeout(xmlrpc.Proxy):
476+ """Extend Twisted's Proxy to provide a configurable connection timeout."""
477+
478+ def __init__(self, url, user=None, password=None, allowNone=False,
479+ useDateTime=False, timeout=None):
480+ xmlrpc.Proxy.__init__(
481+ self, url, user, password, allowNone, useDateTime)
482+ if timeout is None:
483+ self.timeout = config.builddmaster.socket_timeout
484+ else:
485+ self.timeout = timeout
486+
487+ def callRemote(self, method, *args):
488+ """Basically a carbon copy of the parent but passes the timeout
489+ to connectTCP."""
490+
491+ def cancel(d):
492+ factory.deferred = None
493+ connector.disconnect()
494+ factory = self.queryFactory(
495+ self.path, self.host, method, self.user,
496+ self.password, self.allowNone, args, cancel, self.useDateTime)
497+ if self.secure:
498+ from twisted.internet import ssl
499+ connector = default_reactor.connectSSL(
500+ self.host, self.port or 443, factory,
501+ ssl.ClientContextFactory(),
502+ timeout=self.timeout)
503+ else:
504+ connector = default_reactor.connectTCP(
505+ self.host, self.port or 80, factory,
506+ timeout=self.timeout)
507+ return factory.deferred
508+
509+
510 class BuilderSlave(object):
511 """Add in a few useful methods for the XMLRPC slave.
512
513@@ -141,7 +177,7 @@
514 """
515 rpc_url = urlappend(builder_url.encode('utf-8'), 'rpc')
516 if proxy is None:
517- server_proxy = xmlrpc.Proxy(rpc_url, allowNone=True)
518+ server_proxy = ProxyWithConnectionTimeout(rpc_url, allowNone=True)
519 server_proxy.queryFactory = QuietQueryFactory
520 else:
521 server_proxy = proxy
522@@ -213,7 +249,7 @@
523 :param libraryfilealias: An `ILibraryFileAlias`.
524 """
525 url = libraryfilealias.http_url
526- logger.debug(
527+ logger.info(
528 "Asking builder on %s to ensure it has file %s (%s, %s)" % (
529 self._file_cache_url, libraryfilealias.filename, url,
530 libraryfilealias.content.sha1))
531@@ -432,7 +468,7 @@
532 return defer.fail(CannotResumeHost('Undefined vm_host.'))
533
534 logger = self._getSlaveScannerLogger()
535- logger.debug("Resuming %s (%s)" % (self.name, self.url))
536+ logger.info("Resuming %s (%s)" % (self.name, self.url))
537
538 d = self.slave.resume()
539 def got_resume_ok((stdout, stderr, returncode)):
540
541=== modified file 'lib/lp/buildmaster/tests/test_builder.py'
542--- lib/lp/buildmaster/tests/test_builder.py 2010-11-10 22:40:05 +0000
543+++ lib/lp/buildmaster/tests/test_builder.py 2010-11-19 08:04:58 +0000
544@@ -43,6 +43,10 @@
545 )
546 from lp.buildmaster.interfaces.buildqueue import IBuildQueueSet
547 from lp.buildmaster.interfaces.builder import CannotResumeHost
548+from lp.buildmaster.model.builder import (
549+ BuilderSlave,
550+ ProxyWithConnectionTimeout,
551+ )
552 from lp.buildmaster.model.buildfarmjobbehavior import IdleBuildBehavior
553 from lp.buildmaster.model.buildqueue import BuildQueue
554 from lp.buildmaster.tests.mock_slaves import (
555@@ -1059,6 +1063,56 @@
556 self.slave.build(None, None, None, None, None))
557
558
559+class TestSlaveConnectionTimeouts(TrialTestCase):
560+ # Testing that we can override the default 30 second connection
561+ # timeout.
562+
563+ layer = TwistedLayer
564+
565+ def setUp(self):
566+ super(TestSlaveConnectionTimeouts, self).setUp()
567+ self.slave_helper = SlaveTestHelpers()
568+ self.slave_helper.setUp()
569+ self.addCleanup(self.slave_helper.cleanUp)
570+ self.clock = Clock()
571+ self.proxy = ProxyWithConnectionTimeout("fake_url")
572+ self.slave = self.slave_helper.getClientSlave(
573+ reactor=self.clock, proxy=self.proxy)
574+
575+ def test_connection_timeout(self):
576+ # The default timeout of 30 seconds should not cause a timeout,
577+ # only the config value should.
578+ timeout_config = """
579+ [builddmaster]
580+ socket_timeout: 180
581+ """
582+ config.push('timeout', timeout_config)
583+ self.addCleanup(config.pop, 'timeout')
584+
585+ d = self.slave.echo()
586+ # Advance past the 30 second timeout. The real reactor will
587+ # never call connectTCP() since we're not spinning it up. This
588+ # avoids "connection refused" errors and simulates an
589+ # environment where the endpoint doesn't respond.
590+ self.clock.advance(31)
591+ self.assertFalse(d.called)
592+
593+ # Now advance past the real socket timeout and expect a
594+ # Failure.
595+
596+ def got_timeout(failure):
597+ self.assertIsInstance(failure.value, CancelledError)
598+
599+ d.addBoth(got_timeout)
600+ self.clock.advance(config.builddmaster.socket_timeout + 1)
601+ self.assertTrue(d.called)
602+
603+ def test_BuilderSlave_uses_ProxyWithConnectionTimeout(self):
604+ # Make sure that BuilderSlaves use the custom proxy class.
605+ slave = BuilderSlave.makeBuilderSlave("url", "host")
606+ self.assertIsInstance(slave._server, ProxyWithConnectionTimeout)
607+
608+
609 class TestSlaveWithLibrarian(TrialTestCase):
610 """Tests that need more of Launchpad to run."""
611
612
613=== modified file 'lib/lp/code/model/recipebuilder.py'
614--- lib/lp/code/model/recipebuilder.py 2010-10-27 14:25:19 +0000
615+++ lib/lp/code/model/recipebuilder.py 2010-11-19 08:04:58 +0000
616@@ -122,6 +122,8 @@
617 if chroot is None:
618 raise CannotBuild("Unable to find a chroot for %s" %
619 distroarchseries.displayname)
620+ logger.info(
621+ "Sending chroot file for recipe build to %s" % self._builder.name)
622 d = self._builder.slave.cacheFile(logger, chroot)
623
624 def got_cache_file(ignored):
625@@ -131,7 +133,7 @@
626 buildid = "%s-%s" % (self.build.id, build_queue_id)
627 cookie = self.buildfarmjob.generateSlaveBuildCookie()
628 chroot_sha1 = chroot.content.sha1
629- logger.debug(
630+ logger.info(
631 "Initiating build %s on %s" % (buildid, self._builder.url))
632
633 return self._builder.slave.build(
634
635=== modified file 'lib/lp/code/model/tests/test_recipebuilder.py'
636--- lib/lp/code/model/tests/test_recipebuilder.py 2010-10-26 15:47:24 +0000
637+++ lib/lp/code/model/tests/test_recipebuilder.py 2010-11-19 08:04:58 +0000
638@@ -282,8 +282,13 @@
639 d = defer.maybeDeferred(job.dispatchBuildToSlave, "someid", logger)
640 def check_dispatch(ignored):
641 logger.buffer.seek(0)
642- self.assertEquals(
643- "DEBUG: Initiating build 1-someid on http://fake:0000\n",
644+
645+ self.assertEquals(
646+ "INFO: Sending chroot file for recipe build to "
647+ "bob-de-bouwer\n",
648+ logger.buffer.readline())
649+ self.assertEquals(
650+ "INFO: Initiating build 1-someid on http://fake:0000\n",
651 logger.buffer.readline())
652 self.assertEquals(["ensurepresent", "build"],
653 [call[0] for call in slave.call_log])
654@@ -293,7 +298,8 @@
655 self.assertEquals(build_args[1], "sourcepackagerecipe")
656 self.assertEquals(build_args[3], [])
657 distroarchseries = job.build.distroseries.architectures[0]
658- self.assertEqual(build_args[4], job._extraBuildArgs(distroarchseries))
659+ self.assertEqual(
660+ build_args[4], job._extraBuildArgs(distroarchseries))
661 return d.addCallback(check_dispatch)
662
663 def test_dispatchBuildToSlave_nochroot(self):
664
665=== modified file 'lib/lp/registry/javascript/tests/test_milestone_table.html'
666--- lib/lp/registry/javascript/tests/test_milestone_table.html 2010-04-28 18:43:25 +0000
667+++ lib/lp/registry/javascript/tests/test_milestone_table.html 2010-11-19 08:04:58 +0000
668@@ -9,7 +9,7 @@
669 <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssreset/reset.css"/>
670 <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssfonts/fonts.css"/>
671 <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssbase/base.css"/>
672- <link rel="stylesheet" href="../../../canonical/launchpad/javascript/test.css" />
673+ <link rel="stylesheet" href="../../../../canonical/launchpad/javascript/test.css" />
674
675 <!-- The module under test -->
676 <script type="text/javascript" src="../milestonetable.js"></script>
677
678=== modified file 'lib/lp/services/mailman/doc/postings.txt'
679--- lib/lp/services/mailman/doc/postings.txt 2010-10-25 12:11:43 +0000
680+++ lib/lp/services/mailman/doc/postings.txt 2010-11-19 08:04:58 +0000
681@@ -177,25 +177,6 @@
682 From: itest-one-...@lists.launchpad.dev
683 To: anne.person@example.com
684 ...
685- Sender: itest-one-bounces+anne.person=example.com@lists.launchpad.dev
686- Errors-To: itest-one-bounces+anne.person=example.com@lists.launchpad.dev
687- ...
688- X-MailFrom: itest-one-bounces+anne.person=example.com@lists.launchpad.dev
689- X-RcptTo: anne.person@example.com
690- <BLANKLINE>
691- Your request to the Itest-one mailing list
692- <BLANKLINE>
693- Posting of your message titled "An unsubscribed post"
694- <BLANKLINE>
695- has been rejected by the list moderator. The moderator gave the
696- following reason for rejecting your request:
697- <BLANKLINE>
698- "[No reason given]"
699- <BLANKLINE>
700- Any questions or comments should be directed to the list administrator
701- at:
702- <BLANKLINE>
703- itest-one-owner@lists.launchpad.dev
704
705 Anne posts another message to the mailing list, but she is still not
706 subscribed to it. The team administrator deems this message to be spam and
707
708=== modified file 'lib/lp/translations/windmill/tests/test_languages.py'
709--- lib/lp/translations/windmill/tests/test_languages.py 2010-10-18 12:56:47 +0000
710+++ lib/lp/translations/windmill/tests/test_languages.py 2010-11-19 08:04:58 +0000
711@@ -7,6 +7,7 @@
712 __all__ = []
713
714 from canonical.launchpad.windmill.testing.constants import (
715+ FOR_ELEMENT,
716 PAGE_LOAD,
717 SLEEP,
718 )
719@@ -61,7 +62,8 @@
720 # "Not-matching" message is hidden and languages are visible.
721 self.client.asserts.assertProperty(
722 id=u'no_filter_matches',
723- validator='className|unseen')
724+ validator='className|unseen',
725+ timeout=FOR_ELEMENT)
726 self._assert_languages_visible({
727 u'German': True,
728 u'Mende': True,

Subscribers

People subscribed via source and target branches

to status/vote changes: