launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #01965
[Merge] lp:~mbp/launchpad/mbp-trivial into lp:launchpad
Martin Pool has proposed merging lp:~mbp/launchpad/mbp-trivial into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
#615740 test_on_merge.py doesn't handle eintr
https://bugs.launchpad.net/bugs/615740
This tweaks Jeroen and Benji's recent work in "Faster builds" so that the makefile dependencies are more precise, to avoid unnecessary rebuilds.
--
https://code.launchpad.net/~mbp/launchpad/mbp-trivial/+merge/41268
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~mbp/launchpad/mbp-trivial into lp:launchpad.
=== modified file 'Makefile'
--- Makefile 2010-11-02 01:34:05 +0000
+++ Makefile 2010-11-19 07:58:04 +0000
@@ -34,6 +34,9 @@
# Do not add bin/buildout to this list.
# It is impossible to get buildout to tell us all the files it would
# build, since each egg's setup.py doesn't tell us that information.
+#
+# NB: It's important BUILDOUT_BIN only mentions things genuinely produced by
+# buildout.
BUILDOUT_BIN = \
$(PY) bin/apiindex bin/combine-css bin/fl-build-report \
bin/fl-credential-ctl bin/fl-install-demo bin/fl-monitor-ctl \
@@ -45,6 +48,8 @@
bin/start_librarian bin/stxdocs bin/tags bin/test bin/tracereport \
bin/twistd bin/update-download-cache bin/windmill
+BUILDOUT_TEMPLATES = buildout-templates/_pythonpath.py.in
+
# DO NOT ALTER : this should just build by default
default: inplace
@@ -58,7 +63,7 @@
hosted_branches: $(PY)
$(PY) ./utilities/make-dummy-hosted-branches
-$(API_INDEX): $(BZR_VERSION_INFO)
+$(API_INDEX): $(BZR_VERSION_INFO) $(PY)
mkdir -p $(APIDOC_DIR).tmp
LPCONFIG=$(LPCONFIG) $(PY) ./utilities/create-lp-wadl-and-apidoc.py --force "$(WADL_TEMPLATE)"
mv $(APIDOC_DIR).tmp $(APIDOC_DIR)
@@ -66,7 +71,7 @@
apidoc: compile $(API_INDEX)
# Run by PQM.
-check_merge: $(PY)
+check_merge: $(BUILDOUT_BIN)
[ `PYTHONPATH= bzr status -S database/schema/ | \
grep -v "\(^P\|pending\|security.cfg\|Makefile\|unautovacuumable\|_pythonpath.py\)" | wc -l` -eq 0 ]
${PY} lib/canonical/tests/test_no_conflict_marker.py
@@ -140,12 +145,14 @@
${SHHH} bin/sprite-util create-image
jsbuild_lazr: bin/jsbuild
- # We absolutely do not want to include the lazr.testing module and its
- # jsTestDriver test harness modifications in the lazr.js and launchpad.js
- # roll-up files. They fiddle with built-in functions! See Bug 482340.
- ${SHHH} bin/jsbuild $(JSFLAGS) -b $(LAZR_BUILT_JS_ROOT) -x testing/ -c $(LAZR_BUILT_JS_ROOT)/yui
+ # We absolutely do not want to include the lazr.testing module and
+ # its jsTestDriver test harness modifications in the lazr.js and
+ # launchpad.js roll-up files. They fiddle with built-in functions!
+ # See Bug 482340.
+ ${SHHH} bin/jsbuild $(JSFLAGS) -b $(LAZR_BUILT_JS_ROOT) -x testing/ \
+ -c $(LAZR_BUILT_JS_ROOT)/yui
-jsbuild: jsbuild_lazr bin/jsbuild bin/jssize
+jsbuild: jsbuild_lazr bin/jsbuild bin/jssize $(BUILDOUT_BIN)
${SHHH} bin/jsbuild \
$(JSFLAGS) \
-n launchpad \
@@ -177,30 +184,45 @@
find eggs -name '*.pyc' -exec rm {} \;
# The download-cache dependency comes *before* eggs so that developers get the
-# warning before the eggs directory is made. The target for the eggs directory
-# is only there for deployment convenience.
+# warning before the eggs directory is made. The target for the eggs
+# directory is only there for deployment convenience.
# Note that the buildout version must be maintained here and in versions.cfg
# to make sure that the build does not go over the network.
+#
+# buildout won't touch files that would have the same contents, but for Make's
+# sake we need them to get fresh timestamps, so we touch them after building.
bin/buildout: download-cache eggs
$(SHHH) PYTHONPATH= $(PYTHON) bootstrap.py\
--setup-source=ez_setup.py \
--download-base=download-cache/dist --eggs=eggs \
--version=1.5.1
+ touch --no-create $@
# This target is used by LOSAs to prepare a build to be pushed out to
# destination machines. We only want eggs: they are the expensive bits,
# and the other bits might run into problems like bug 575037. This
# target runs buildout, and then removes everything created except for
# the eggs.
-build_eggs: $(BUILDOUT_BIN) clean_buildout
+build_eggs: $(BUILDOUT_BIN)
# This builds bin/py and all the other bin files except bin/buildout.
# Remove the target before calling buildout to ensure that buildout
# updates the timestamp.
-$(BUILDOUT_BIN): bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py
- $(RM) $@
+buildout_bin: $(BUILDOUT_BIN)
+
+# buildout won't touch files that would have the same contents, but for Make's
+# sake we need them to get fresh timestamps, so we touch them after building.
+#
+# If we listed every target on the left-hand side, a parallel make would try
+# multiple copies of this rule to build them all. Instead, we nominally build
+# just $(PY), and everything else is implicitly updated by that.
+$(PY): bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py \
+ $(BUILDOUT_TEMPLATES)
$(SHHH) PYTHONPATH= ./bin/buildout \
configuration:instance_name=${LPCONFIG} -c $(BUILDOUT_CFG)
+ touch $@
+
+$(subst $(PY),,$(BUILDOUT_BIN)): $(PY)
# bin/compile_templates is responsible for building all chameleon templates,
# of which there is currently one, but of which many more are coming.
@@ -405,7 +427,8 @@
# We insert the absolute path to the branch-rewrite script
# into the Apache config as we copy the file into position.
sed -e 's,%BRANCH_REWRITE%,$(shell pwd)/scripts/branch-rewrite.py,' configs/development/local-launchpad-apache > /etc/apache2/sites-available/local-launchpad
- cp configs/development/local-vostok-apache /etc/apache2/sites-available/local-vostok
+ cp configs/development/local-vostok-apache \
+ /etc/apache2/sites-available/local-vostok
touch /var/tmp/bazaar.launchpad.dev/rewrite.log
chown $(SUDO_UID):$(SUDO_GID) /var/tmp/bazaar.launchpad.dev/rewrite.log
@@ -430,8 +453,9 @@
lp.sfood:
# Generate import dependency graph
- sfood -i -u -I lib/sqlobject -I lib/schoolbell -I lib/devscripts -I lib/contrib \
- -I lib/canonical/not-used lib/canonical lib/lp 2>/dev/null | grep -v contrib/ \
+ sfood -i -u -I lib/sqlobject -I lib/schoolbell -I lib/devscripts \
+ -I lib/contrib -I lib/canonical/not-used lib/canonical \
+ lib/lp 2>/dev/null | grep -v contrib/ \
| grep -v sqlobject | grep -v BeautifulSoup | grep -v psycopg \
| grep -v schoolbell > lp.sfood.tmp
mv lp.sfood.tmp lp.sfood
@@ -463,10 +487,10 @@
--docformat restructuredtext --verbose-about epytext-summary \
$(PYDOCTOR_OPTIONS)
-.PHONY: apidoc check tags TAGS zcmldocs realclean clean debug stop\
- start run ftest_build ftest_inplace test_build test_inplace pagetests\
- check check_merge \
- schema default launchpad.pot check_merge_ui pull scan sync_branches\
- reload-apache hosted_branches check_db_merge check_mailman check_config\
- jsbuild jsbuild_lazr clean_js clean_buildout buildonce_eggs build_eggs\
- sprite_css sprite_image css_combine compile check_schema pydoctor
+.PHONY: apidoc buildout_bin check tags TAGS zcmldocs realclean clean debug \
+ stop start run ftest_build ftest_inplace test_build test_inplace \
+ pagetests check check_merge schema default launchpad.pot \
+ check_merge_ui pull scan sync_branches reload-apache hosted_branches \
+ check_db_merge check_mailman check_config jsbuild jsbuild_lazr \
+ clean_js clean_buildout buildonce_eggs build_eggs sprite_css \
+ sprite_image css_combine compile check_schema pydoctor
=== modified file 'cronscripts/publishing/cron.publish-copy-archives'
--- cronscripts/publishing/cron.publish-copy-archives 2010-06-25 14:36:11 +0000
+++ cronscripts/publishing/cron.publish-copy-archives 2010-11-19 07:58:04 +0000
@@ -10,7 +10,6 @@
exit 1
fi
-set -x
set -e
set -u
@@ -20,24 +19,23 @@
# Informational -- this *MUST* match the database.
-ARCHIVEROOT=/srv/launchpad.net/ubuntu-archive/ubuntu
+ARCHIVEROOT=/srv/launchpad.net/rebuild-test/ubuntu
DISTSROOT=$ARCHIVEROOT/dists
OVERRIDEROOT=$ARCHIVEROOT/../ubuntu-overrides
INDICES=$ARCHIVEROOT/indices
PRODUCTION_CONFIG=ftpmaster-publish
if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
- GNUPGHOME=/srv/launchpad.net/ubuntu-archive/gnupg-home
+ GNUPGHOME=/srv/launchpad.net/rebuild-test/gnupg-home
else
echo GPG keys will come from ~/.gnupg
# GNUPGHOME does not need to be set, keys can come from ~/.gnupg.
fi
# Configuration options.
-LAUNCHPADROOT=/srv/launchpad.net/codelines/current
-LOCKFILE=/srv/launchpad.net/ubuntu-archive/cron.daily.lock
+LAUNCHPADROOT=/srv/launchpad.net/production/launchpad
+LOCKFILE=/srv/launchpad.net/rebuild-test/cron.daily.lock
DISTRONAME=ubuntu
-TRACEFILE=$ARCHIVEROOT/project/trace/$(hostname --fqdn)
# Manipulate the environment.
export GNUPGHOME
@@ -64,20 +62,5 @@
# Publish the packages to disk.
publish-distro.py -v -v --copy-archive -d $DISTRONAME
-set +x
-
echo Removing uncompressed Packages and Sources files
find ${DISTSROOT} \( -name "Packages" -o -name "Sources" \) -exec rm "{}" \;
-
-# Copy in the indices.
-if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
- echo Copying the indices into place.
- rm -f $INDICES/override.*
- cp $OVERRIDEROOT/override.* $INDICES
-fi
-
-# Timestamp our trace file to track when the last archive publisher run took
-# place.
-if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
- date -u > "$TRACEFILE"
-fi
=== modified file 'lib/canonical/buildd/binarypackage.py'
--- lib/canonical/buildd/binarypackage.py 2010-07-13 09:13:41 +0000
+++ lib/canonical/buildd/binarypackage.py 2010-11-19 07:58:04 +0000
@@ -19,9 +19,7 @@
class BuildLogRegexes:
"""Build log regexes for performing actions based on regexes, and extracting dependencies for auto dep-waits"""
GIVENBACK = [
- (" terminated by signal 4"),
("^E: There are problems and -y was used without --force-yes"),
- ("^make.* Illegal instruction"),
]
DEPFAIL = [
("(?P<pk>[\-+.\w]+)\(inst [^ ]+ ! >> wanted (?P<v>[\-.+\w:~]+)\)","\g<pk> (>> \g<v>)"),
=== modified file 'lib/canonical/buildd/buildrecipe'
--- lib/canonical/buildd/buildrecipe 2010-09-30 20:22:15 +0000
+++ lib/canonical/buildd/buildrecipe 2010-11-19 07:58:04 +0000
@@ -11,6 +11,7 @@
import os
import pwd
import re
+from resource import RLIMIT_AS, setrlimit
import socket
from subprocess import call, Popen, PIPE
import sys
@@ -206,6 +207,7 @@
if __name__ == '__main__':
+ setrlimit(RLIMIT_AS, (1000000000, -1))
builder = RecipeBuilder(*sys.argv[1:])
if builder.buildTree() != 0:
sys.exit(RETCODE_FAILURE_BUILD_TREE)
=== renamed file 'lib/canonical/launchpad/doc/emailaddress.txt.disabled' => 'lib/canonical/launchpad/doc/emailaddress.txt'
--- lib/canonical/launchpad/doc/emailaddress.txt.disabled 2009-08-13 19:03:36 +0000
+++ lib/canonical/launchpad/doc/emailaddress.txt 2010-11-19 07:58:04 +0000
@@ -1,4 +1,5 @@
-= Email Addresses =
+Email Addresses
+===============
In Launchpad we use email addresses to uniquely identify a person. This is why
email addresses must be unique.
@@ -22,7 +23,7 @@
Email addresses provide both IEmailAddress and IHasOwner.
- >>> from canonical.launchpad.interfaces.launchpad import IHasOwner
+ >>> from lp.registry.interfaces.role import IHasOwner
>>> verifyObject(IEmailAddress, email)
True
>>> verifyObject(IHasOwner, email)
@@ -66,11 +67,12 @@
[u'celso.providelo@xxxxxxxxxxxxx', u'colin.watson@xxxxxxxxxxxxxxx',
u'daniel.silverstone@xxxxxxxxxxxxx', u'edgar@xxxxxxxxxxxxxxxx',
u'foo.bar@xxxxxxxxxxxxx', u'jeff.waugh@xxxxxxxxxxxxxxx',
- u'limi@xxxxxxxxx', u'mark@xxxxxxxxxxx', u'steve.alexander@xxxxxxxxxxxxxxx',
- u'support@xxxxxxxxxx']
-
-
-== Deleting email addresses ==
+ u'limi@xxxxxxxxx', u'mark@xxxxxxxxxxx',
+ u'steve.alexander@xxxxxxxxxxxxxxx', u'support@xxxxxxxxxx']
+
+
+Deleting email addresses
+------------------------
Email addresses may be deleted if they're not a person's preferred one
or the address of a team's mailing list.
=== modified file 'lib/lp/app/javascript/tests/test_lp_collapsibles.html'
--- lib/lp/app/javascript/tests/test_lp_collapsibles.html 2010-07-26 13:42:32 +0000
+++ lib/lp/app/javascript/tests/test_lp_collapsibles.html 2010-11-19 07:58:04 +0000
@@ -4,14 +4,14 @@
<title>Launchpad Collapsibles</title>
<!-- YUI 3.0 Setup -->
- <script type="text/javascript" src="../../../icing/yui/yui/yui.js"></script>
- <link rel="stylesheet" href="../../../icing/yui/cssreset/reset.css"/>
- <link rel="stylesheet" href="../../../icing/yui/cssfonts/fonts.css"/>
- <link rel="stylesheet" href="../../../icing/yui/cssbase/base.css"/>
- <link rel="stylesheet" href="../../test.css" />
+ <script type="text/javascript" src="../../../../canonical/launchpad/icing/yui/yui/yui.js"></script>
+ <script type="text/javascript" src="../../../../canonical/launchpad/icing/lazr/build/lazr.js"></script>
+ <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssreset/reset.css"/>
+ <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssfonts/fonts.css"/>
+ <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssbase/base.css"/>
+ <link rel="stylesheet" href="../../../../canonical/launchpad/javascript/test.css" />
<!-- The module under test -->
- <script type="text/javascript" src="../../../icing/lazr/build/effects/effects.js"></script>
<script type="text/javascript" src="../lp.js"></script>
<!-- The test suite -->
=== modified file 'lib/lp/app/javascript/tests/test_lp_collapsibles.js'
--- lib/lp/app/javascript/tests/test_lp_collapsibles.js 2010-07-26 13:42:32 +0000
+++ lib/lp/app/javascript/tests/test_lp_collapsibles.js 2010-11-19 07:58:04 +0000
@@ -1,21 +1,21 @@
/* Copyright (c) 2009, Canonical Ltd. All rights reserved. */
YUI({
- base: '../../../icing/yui/',
+ base: '../../../../canonical/launchpad/icing/yui/',
filter: 'raw',
combine: false
}).use('test', 'console', 'lp', function(Y) {
var Assert = Y.Assert; // For easy access to isTrue(), etc.
-Y.Test.Runner.add(new Y.Test.Case({
+var suite = new Y.Test.Suite("Collapsibles Tests");
+suite.add(new Y.Test.Case({
name: "activate_collapsibles",
_should: {
- error: {
+ fail: {
test_toggle_collapsible_fails_on_wrapperless_collapsible: true,
test_toggle_collapsible_fails_on_iconless_collapsible: true,
- test_activate_collapsibles_handles_no_collapsibles: false
}
},
@@ -149,17 +149,16 @@
test_toggle_collapsible_opens_collapsed_collapsible: function() {
// Calling toggle_collapsible() on a collapsed collapsible will
// toggle its state to open.
+ Y.lp.activate_collapsibles();
var collapsible = this.container.one('.collapsible');
- collapsible.addClass('collapsed');
+ var wrapper_div = collapsible.one('.collapseWrapper');
+ wrapper_div.addClass('lazr-closed');
- Y.lp.activate_collapsibles();
Y.lp.toggle_collapsible(collapsible);
this.wait(function() {
-
// The collapsible's wrapper div will now be open.
var icon = collapsible.one('img');
- var wrapper_div = collapsible.one('.collapseWrapper');
- Assert.isTrue(wrapper_div.hasClass('lazr-open'));
+ Assert.isFalse(wrapper_div.hasClass('lazr-closed'));
Assert.areNotEqual(
-1, icon.get('src').indexOf('/@@/treeExpanded'));
}, 500);
@@ -321,6 +320,15 @@
}
}));
+// Lock, stock, and two smoking barrels.
+var handle_complete = function(data) {
+ status_node = Y.Node.create(
+ '<p id="complete">Test status: complete</p>');
+ Y.get('body').appendChild(status_node);
+ };
+Y.Test.Runner.on('complete', handle_complete);
+Y.Test.Runner.add(suite);
+
var yui_console = new Y.Console({
newestOnTop: false
});
=== added directory 'lib/lp/app/windmill'
=== added file 'lib/lp/app/windmill/__init__.py'
=== added file 'lib/lp/app/windmill/testing.py'
--- lib/lp/app/windmill/testing.py 1970-01-01 00:00:00 +0000
+++ lib/lp/app/windmill/testing.py 2010-11-19 07:58:04 +0000
@@ -0,0 +1,21 @@
+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Launchpad app specific testing infrastructure for Windmill."""
+
+__metaclass__ = type
+__all__ = [
+ 'AppWindmillLayer',
+ ]
+
+
+from canonical.testing.layers import BaseWindmillLayer
+
+
+class AppWindmillLayer(BaseWindmillLayer):
+ """Layer for App Windmill tests."""
+
+ @classmethod
+ def setUp(cls):
+ cls.base_url = cls.appserver_root_url()
+ super(AppWindmillLayer, cls).setUp()
=== added directory 'lib/lp/app/windmill/tests'
=== added file 'lib/lp/app/windmill/tests/__init__.py'
=== added file 'lib/lp/app/windmill/tests/test_yuitests.py'
--- lib/lp/app/windmill/tests/test_yuitests.py 1970-01-01 00:00:00 +0000
+++ lib/lp/app/windmill/tests/test_yuitests.py 2010-11-19 07:58:04 +0000
@@ -0,0 +1,24 @@
+# Copyright 2010 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Run YUI.test tests."""
+
+__metaclass__ = type
+__all__ = []
+
+from lp.app.windmill.testing import AppWindmillLayer
+from lp.testing import (
+ build_yui_unittest_suite,
+ YUIUnitTestCase,
+ )
+
+
+class AppYUIUnitTestCase(YUIUnitTestCase):
+
+ layer = AppWindmillLayer
+ suite_name = 'AppYUIUnitTests'
+
+
+def test_suite():
+ app_testing_path = 'lp/app/javascript/tests'
+ return build_yui_unittest_suite(app_testing_path, AppYUIUnitTestCase)
=== modified file 'lib/lp/buildmaster/manager.py'
--- lib/lp/buildmaster/manager.py 2010-10-28 15:04:15 +0000
+++ lib/lp/buildmaster/manager.py 2010-11-19 07:58:04 +0000
@@ -151,10 +151,12 @@
if failure.check(
BuildSlaveFailure, CannotBuild, BuildBehaviorMismatch,
CannotResumeHost, BuildDaemonError, CannotFetchFile):
- self.logger.info("Scanning failed with: %s" % error_message)
+ self.logger.info("Scanning %s failed with: %s" % (
+ self.builder_name, error_message))
else:
- self.logger.info("Scanning failed with: %s\n%s" %
- (failure.getErrorMessage(), failure.getTraceback()))
+ self.logger.info("Scanning %s failed with: %s\n%s" % (
+ self.builder_name, failure.getErrorMessage(),
+ failure.getTraceback()))
# Decide if we need to terminate the job or fail the
# builder.
=== modified file 'lib/lp/buildmaster/model/builder.py'
--- lib/lp/buildmaster/model/builder.py 2010-11-10 13:06:05 +0000
+++ lib/lp/buildmaster/model/builder.py 2010-11-19 07:58:04 +0000
@@ -8,6 +8,7 @@
__all__ = [
'Builder',
'BuilderSet',
+ 'ProxyWithConnectionTimeout',
'rescueBuilderIfLost',
'updateBuilderStatus',
]
@@ -99,6 +100,41 @@
noisy = False
+class ProxyWithConnectionTimeout(xmlrpc.Proxy):
+ """Extend Twisted's Proxy to provide a configurable connection timeout."""
+
+ def __init__(self, url, user=None, password=None, allowNone=False,
+ useDateTime=False, timeout=None):
+ xmlrpc.Proxy.__init__(
+ self, url, user, password, allowNone, useDateTime)
+ if timeout is None:
+ self.timeout = config.builddmaster.socket_timeout
+ else:
+ self.timeout = timeout
+
+ def callRemote(self, method, *args):
+ """Basically a carbon copy of the parent but passes the timeout
+ to connectTCP."""
+
+ def cancel(d):
+ factory.deferred = None
+ connector.disconnect()
+ factory = self.queryFactory(
+ self.path, self.host, method, self.user,
+ self.password, self.allowNone, args, cancel, self.useDateTime)
+ if self.secure:
+ from twisted.internet import ssl
+ connector = default_reactor.connectSSL(
+ self.host, self.port or 443, factory,
+ ssl.ClientContextFactory(),
+ timeout=self.timeout)
+ else:
+ connector = default_reactor.connectTCP(
+ self.host, self.port or 80, factory,
+ timeout=self.timeout)
+ return factory.deferred
+
+
class BuilderSlave(object):
"""Add in a few useful methods for the XMLRPC slave.
@@ -141,7 +177,7 @@
"""
rpc_url = urlappend(builder_url.encode('utf-8'), 'rpc')
if proxy is None:
- server_proxy = xmlrpc.Proxy(rpc_url, allowNone=True)
+ server_proxy = ProxyWithConnectionTimeout(rpc_url, allowNone=True)
server_proxy.queryFactory = QuietQueryFactory
else:
server_proxy = proxy
@@ -213,7 +249,7 @@
:param libraryfilealias: An `ILibraryFileAlias`.
"""
url = libraryfilealias.http_url
- logger.debug(
+ logger.info(
"Asking builder on %s to ensure it has file %s (%s, %s)" % (
self._file_cache_url, libraryfilealias.filename, url,
libraryfilealias.content.sha1))
@@ -432,7 +468,7 @@
return defer.fail(CannotResumeHost('Undefined vm_host.'))
logger = self._getSlaveScannerLogger()
- logger.debug("Resuming %s (%s)" % (self.name, self.url))
+ logger.info("Resuming %s (%s)" % (self.name, self.url))
d = self.slave.resume()
def got_resume_ok((stdout, stderr, returncode)):
=== modified file 'lib/lp/buildmaster/tests/test_builder.py'
--- lib/lp/buildmaster/tests/test_builder.py 2010-11-10 22:40:05 +0000
+++ lib/lp/buildmaster/tests/test_builder.py 2010-11-19 07:58:04 +0000
@@ -43,6 +43,10 @@
)
from lp.buildmaster.interfaces.buildqueue import IBuildQueueSet
from lp.buildmaster.interfaces.builder import CannotResumeHost
+from lp.buildmaster.model.builder import (
+ BuilderSlave,
+ ProxyWithConnectionTimeout,
+ )
from lp.buildmaster.model.buildfarmjobbehavior import IdleBuildBehavior
from lp.buildmaster.model.buildqueue import BuildQueue
from lp.buildmaster.tests.mock_slaves import (
@@ -1059,6 +1063,56 @@
self.slave.build(None, None, None, None, None))
+class TestSlaveConnectionTimeouts(TrialTestCase):
+ # Testing that we can override the default 30 second connection
+ # timeout.
+
+ layer = TwistedLayer
+
+ def setUp(self):
+ super(TestSlaveConnectionTimeouts, self).setUp()
+ self.slave_helper = SlaveTestHelpers()
+ self.slave_helper.setUp()
+ self.addCleanup(self.slave_helper.cleanUp)
+ self.clock = Clock()
+ self.proxy = ProxyWithConnectionTimeout("fake_url")
+ self.slave = self.slave_helper.getClientSlave(
+ reactor=self.clock, proxy=self.proxy)
+
+ def test_connection_timeout(self):
+ # The default timeout of 30 seconds should not cause a timeout,
+ # only the config value should.
+ timeout_config = """
+ [builddmaster]
+ socket_timeout: 180
+ """
+ config.push('timeout', timeout_config)
+ self.addCleanup(config.pop, 'timeout')
+
+ d = self.slave.echo()
+ # Advance past the 30 second timeout. The real reactor will
+ # never call connectTCP() since we're not spinning it up. This
+ # avoids "connection refused" errors and simulates an
+ # environment where the endpoint doesn't respond.
+ self.clock.advance(31)
+ self.assertFalse(d.called)
+
+ # Now advance past the real socket timeout and expect a
+ # Failure.
+
+ def got_timeout(failure):
+ self.assertIsInstance(failure.value, CancelledError)
+
+ d.addBoth(got_timeout)
+ self.clock.advance(config.builddmaster.socket_timeout + 1)
+ self.assertTrue(d.called)
+
+ def test_BuilderSlave_uses_ProxyWithConnectionTimeout(self):
+ # Make sure that BuilderSlaves use the custom proxy class.
+ slave = BuilderSlave.makeBuilderSlave("url", "host")
+ self.assertIsInstance(slave._server, ProxyWithConnectionTimeout)
+
+
class TestSlaveWithLibrarian(TrialTestCase):
"""Tests that need more of Launchpad to run."""
=== modified file 'lib/lp/code/model/recipebuilder.py'
--- lib/lp/code/model/recipebuilder.py 2010-10-27 14:25:19 +0000
+++ lib/lp/code/model/recipebuilder.py 2010-11-19 07:58:04 +0000
@@ -122,6 +122,8 @@
if chroot is None:
raise CannotBuild("Unable to find a chroot for %s" %
distroarchseries.displayname)
+ logger.info(
+ "Sending chroot file for recipe build to %s" % self._builder.name)
d = self._builder.slave.cacheFile(logger, chroot)
def got_cache_file(ignored):
@@ -131,7 +133,7 @@
buildid = "%s-%s" % (self.build.id, build_queue_id)
cookie = self.buildfarmjob.generateSlaveBuildCookie()
chroot_sha1 = chroot.content.sha1
- logger.debug(
+ logger.info(
"Initiating build %s on %s" % (buildid, self._builder.url))
return self._builder.slave.build(
=== modified file 'lib/lp/code/model/tests/test_recipebuilder.py'
--- lib/lp/code/model/tests/test_recipebuilder.py 2010-10-26 15:47:24 +0000
+++ lib/lp/code/model/tests/test_recipebuilder.py 2010-11-19 07:58:04 +0000
@@ -282,8 +282,13 @@
d = defer.maybeDeferred(job.dispatchBuildToSlave, "someid", logger)
def check_dispatch(ignored):
logger.buffer.seek(0)
- self.assertEquals(
- "DEBUG: Initiating build 1-someid on http://fake:0000\n",
+
+ self.assertEquals(
+ "INFO: Sending chroot file for recipe build to "
+ "bob-de-bouwer\n",
+ logger.buffer.readline())
+ self.assertEquals(
+ "INFO: Initiating build 1-someid on http://fake:0000\n",
logger.buffer.readline())
self.assertEquals(["ensurepresent", "build"],
[call[0] for call in slave.call_log])
@@ -293,7 +298,8 @@
self.assertEquals(build_args[1], "sourcepackagerecipe")
self.assertEquals(build_args[3], [])
distroarchseries = job.build.distroseries.architectures[0]
- self.assertEqual(build_args[4], job._extraBuildArgs(distroarchseries))
+ self.assertEqual(
+ build_args[4], job._extraBuildArgs(distroarchseries))
return d.addCallback(check_dispatch)
def test_dispatchBuildToSlave_nochroot(self):
=== modified file 'lib/lp/registry/javascript/tests/test_milestone_table.html'
--- lib/lp/registry/javascript/tests/test_milestone_table.html 2010-04-28 18:43:25 +0000
+++ lib/lp/registry/javascript/tests/test_milestone_table.html 2010-11-19 07:58:04 +0000
@@ -9,7 +9,7 @@
<link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssreset/reset.css"/>
<link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssfonts/fonts.css"/>
<link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssbase/base.css"/>
- <link rel="stylesheet" href="../../../canonical/launchpad/javascript/test.css" />
+ <link rel="stylesheet" href="../../../../canonical/launchpad/javascript/test.css" />
<!-- The module under test -->
<script type="text/javascript" src="../milestonetable.js"></script>
=== modified file 'lib/lp/services/mailman/doc/postings.txt'
--- lib/lp/services/mailman/doc/postings.txt 2010-10-25 12:11:43 +0000
+++ lib/lp/services/mailman/doc/postings.txt 2010-11-19 07:58:04 +0000
@@ -177,25 +177,6 @@
From: itest-one-...@xxxxxxxxxxxxxxxxxxx
To: anne.person@xxxxxxxxxxx
...
- Sender: itest-one-bounces+anne.person=example.com@xxxxxxxxxxxxxxxxxxx
- Errors-To: itest-one-bounces+anne.person=example.com@xxxxxxxxxxxxxxxxxxx
- ...
- X-MailFrom: itest-one-bounces+anne.person=example.com@xxxxxxxxxxxxxxxxxxx
- X-RcptTo: anne.person@xxxxxxxxxxx
- <BLANKLINE>
- Your request to the Itest-one mailing list
- <BLANKLINE>
- Posting of your message titled "An unsubscribed post"
- <BLANKLINE>
- has been rejected by the list moderator. The moderator gave the
- following reason for rejecting your request:
- <BLANKLINE>
- "[No reason given]"
- <BLANKLINE>
- Any questions or comments should be directed to the list administrator
- at:
- <BLANKLINE>
- itest-one-owner@xxxxxxxxxxxxxxxxxxx
Anne posts another message to the mailing list, but she is still not
subscribed to it. The team administrator deems this message to be spam and
=== modified file 'lib/lp/translations/windmill/tests/test_languages.py'
--- lib/lp/translations/windmill/tests/test_languages.py 2010-10-18 12:56:47 +0000
+++ lib/lp/translations/windmill/tests/test_languages.py 2010-11-19 07:58:04 +0000
@@ -7,6 +7,7 @@
__all__ = []
from canonical.launchpad.windmill.testing.constants import (
+ FOR_ELEMENT,
PAGE_LOAD,
SLEEP,
)
@@ -61,7 +62,8 @@
# "Not-matching" message is hidden and languages are visible.
self.client.asserts.assertProperty(
id=u'no_filter_matches',
- validator='className|unseen')
+ validator='className|unseen',
+ timeout=FOR_ELEMENT)
self._assert_languages_visible({
u'German': True,
u'Mende': True,
Follow ups