Merge lp:~mwhudson/launchpad/pull-mirror-branches-separately-bug-520107 into lp:launchpad

Proposed by Michael Hudson-Doyle
Status: Merged
Approved by: Michael Hudson-Doyle
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~mwhudson/launchpad/pull-mirror-branches-separately-bug-520107
Merge into: lp:launchpad
Prerequisite: lp:~mwhudson/launchpad/remove-old-puller-xmlrpc-methods
Diff against target: 527 lines (+144/-46)
14 files modified
cronscripts/supermirror-pull.py (+3/-1)
lib/lp/code/errors.py (+5/-0)
lib/lp/code/interfaces/branch.py (+0/-4)
lib/lp/code/interfaces/branchpuller.py (+3/-1)
lib/lp/code/interfaces/codehosting.py (+4/-1)
lib/lp/code/model/branchpuller.py (+5/-2)
lib/lp/code/model/tests/test_branchpuller.py (+47/-9)
lib/lp/code/xmlrpc/codehosting.py (+11/-2)
lib/lp/code/xmlrpc/tests/test_codehosting.py (+17/-9)
lib/lp/codehosting/inmemory.py (+12/-2)
lib/lp/codehosting/puller/scheduler.py (+3/-2)
lib/lp/codehosting/puller/tests/test_acceptance.py (+19/-2)
lib/lp/codehosting/puller/tests/test_scheduler.py (+14/-10)
lib/lp/testing/factory.py (+1/-1)
To merge this branch: bzr merge lp:~mwhudson/launchpad/pull-mirror-branches-separately-bug-520107
Reviewer Review Type Date Requested Status
Tim Penhey (community) Approve
Review via email: mp+20032@code.launchpad.net

Commit message

Allow an invocation of supermirror-pull.py to only pull certain branch types.

To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

Mirrored branches are inherently less reliable to access than hosted or imported branches, so it makes sense to be able to handle them in a separate process, and that's what this branch does.

The default behavior is kept the same, we can coordinate with the LOSAs after rollout to set up two different cronjobs.

Revision history for this message
Tim Penhey (thumper) wrote :

Good except test_type_filter_hosted_imported_returns_imported which creates a hosted branch instead of an imported one.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'cronscripts/supermirror-pull.py'
--- cronscripts/supermirror-pull.py 2009-10-13 14:38:07 +0000
+++ cronscripts/supermirror-pull.py 2010-02-24 19:04:21 +0000
@@ -38,12 +38,14 @@
38if __name__ == '__main__':38if __name__ == '__main__':
39 parser = OptionParser()39 parser = OptionParser()
40 logger_options(parser)40 logger_options(parser)
41 parser.add_option('--branch-type', action='append', default=[])
41 (options, arguments) = parser.parse_args()42 (options, arguments) = parser.parse_args()
42 if arguments:43 if arguments:
43 parser.error("Unhandled arguments %s" % repr(arguments))44 parser.error("Unhandled arguments %s" % repr(arguments))
44 log = set_up_logging_for_script(options, 'supermirror_puller')45 log = set_up_logging_for_script(options, 'supermirror_puller')
45 manager = scheduler.JobScheduler(46 manager = scheduler.JobScheduler(
46 LoggingProxy(config.codehosting.branch_puller_endpoint, log), log)47 LoggingProxy(config.codehosting.branch_puller_endpoint, log), log,
48 options.branch_type)
4749
48 reactor.callWhenRunning(run_mirror, log, manager)50 reactor.callWhenRunning(run_mirror, log, manager)
49 reactor.run()51 reactor.run()
5052
=== modified file 'lib/lp/code/errors.py'
--- lib/lp/code/errors.py 2009-12-14 06:41:18 +0000
+++ lib/lp/code/errors.py 2010-02-24 19:04:21 +0000
@@ -11,6 +11,7 @@
11 'ClaimReviewFailed',11 'ClaimReviewFailed',
12 'InvalidBranchMergeProposal',12 'InvalidBranchMergeProposal',
13 'ReviewNotPending',13 'ReviewNotPending',
14 'UnknownBranchTypeError',
14 'UserHasExistingReview',15 'UserHasExistingReview',
15 'UserNotBranchReviewer',16 'UserNotBranchReviewer',
16 'WrongBranchMergeProposal',17 'WrongBranchMergeProposal',
@@ -59,3 +60,7 @@
5960
60class WrongBranchMergeProposal(Exception):61class WrongBranchMergeProposal(Exception):
61 """The comment requested is not associated with this merge proposal."""62 """The comment requested is not associated with this merge proposal."""
63
64
65class UnknownBranchTypeError(Exception):
66 """Raised when the user specifies an unrecognized branch type."""
6267
=== modified file 'lib/lp/code/interfaces/branch.py'
--- lib/lp/code/interfaces/branch.py 2010-02-18 16:00:24 +0000
+++ lib/lp/code/interfaces/branch.py 2010-02-24 19:04:21 +0000
@@ -119,10 +119,6 @@
119 """The branch cannot be deleted at this time."""119 """The branch cannot be deleted at this time."""
120120
121121
122class UnknownBranchTypeError(Exception):
123 """Raised when the user specifies an unrecognized branch type."""
124
125
126class BranchCreationForbidden(BranchCreationException):122class BranchCreationForbidden(BranchCreationException):
127 """A Branch visibility policy forbids branch creation.123 """A Branch visibility policy forbids branch creation.
128124
129125
=== modified file 'lib/lp/code/interfaces/branchpuller.py'
--- lib/lp/code/interfaces/branchpuller.py 2010-02-24 01:22:28 +0000
+++ lib/lp/code/interfaces/branchpuller.py 2010-02-24 19:04:21 +0000
@@ -23,9 +23,11 @@
23 MIRROR_TIME_INCREMENT = Attribute(23 MIRROR_TIME_INCREMENT = Attribute(
24 "How frequently we mirror branches.")24 "How frequently we mirror branches.")
2525
26 def acquireBranchToPull():26 def acquireBranchToPull(*branch_types):
27 """Return a Branch to pull and mark it as mirror-started.27 """Return a Branch to pull and mark it as mirror-started.
2828
29 :param branch_types: Only return branches of these types. Passing no
30 types means consider all types (apart from REMOTE).
29 :return: The branch object to pull next, or ``None`` if there is no31 :return: The branch object to pull next, or ``None`` if there is no
30 branch to pull.32 branch to pull.
31 """33 """
3234
=== modified file 'lib/lp/code/interfaces/codehosting.py'
--- lib/lp/code/interfaces/codehosting.py 2010-02-24 01:57:35 +0000
+++ lib/lp/code/interfaces/codehosting.py 2010-02-24 19:04:21 +0000
@@ -58,9 +58,12 @@
58 Published at 'branch_puller' on the private XML-RPC server.58 Published at 'branch_puller' on the private XML-RPC server.
59 """59 """
6060
61 def acquireBranchToPull():61 def acquireBranchToPull(branch_type_names):
62 """Return a Branch to pull and mark it as mirror-started.62 """Return a Branch to pull and mark it as mirror-started.
6363
64 :param branch_type_names: Only consider branches of these type names.
65 An empty list means consider HOSTED, MIRRORED and IMPORTED
66 branches.
64 :return: A 5-tuple::67 :return: A 5-tuple::
6568
66 (branch_id, pull_url, unique_name, default_branch, branch_type)69 (branch_id, pull_url, unique_name, default_branch, branch_type)
6770
=== modified file 'lib/lp/code/model/branchpuller.py'
--- lib/lp/code/model/branchpuller.py 2010-02-24 01:22:28 +0000
+++ lib/lp/code/model/branchpuller.py 2010-02-24 19:04:21 +0000
@@ -28,13 +28,16 @@
28 MAXIMUM_MIRROR_FAILURES = 528 MAXIMUM_MIRROR_FAILURES = 5
29 MIRROR_TIME_INCREMENT = timedelta(hours=6)29 MIRROR_TIME_INCREMENT = timedelta(hours=6)
3030
31 def acquireBranchToPull(self):31 def acquireBranchToPull(self, *branch_types):
32 """See `IBranchPuller`."""32 """See `IBranchPuller`."""
33 if not branch_types:
34 branch_types = (
35 BranchType.HOSTED, BranchType.MIRRORED, BranchType.IMPORTED)
33 store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)36 store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
34 branch = store.find(37 branch = store.find(
35 Branch,38 Branch,
36 Branch.next_mirror_time <= UTC_NOW,39 Branch.next_mirror_time <= UTC_NOW,
37 Branch.branch_type != BranchType.REMOTE).order_by(40 Branch.branch_type.is_in(branch_types)).order_by(
38 Branch.next_mirror_time).first()41 Branch.next_mirror_time).first()
39 if branch is not None:42 if branch is not None:
40 branch.startMirroring()43 branch.startMirroring()
4144
=== modified file 'lib/lp/code/model/tests/test_branchpuller.py'
--- lib/lp/code/model/tests/test_branchpuller.py 2010-02-24 01:22:28 +0000
+++ lib/lp/code/model/tests/test_branchpuller.py 2010-02-24 19:04:21 +0000
@@ -169,12 +169,22 @@
169 and `startMirroring` as appropriate.169 and `startMirroring` as appropriate.
170 """170 """
171171
172 def assertNoBranchIsAquired(self):172 def assertNoBranchIsAquired(self, *branch_types):
173 """Assert that there is no branch to pull."""173 """Assert that there is no branch to pull.
174
175 :param branch_types: A list of branch types to pass to
176 acquireBranchToPull. Passing none means consider all types of
177 branch.
178 """
174 raise NotImplementedError(self.assertNoBranchIsAquired)179 raise NotImplementedError(self.assertNoBranchIsAquired)
175180
176 def assertBranchIsAquired(self, branch):181 def assertBranchIsAquired(self, branch, *branch_types):
177 """Assert that ``branch`` is the next branch to be pulled."""182 """Assert that ``branch`` is the next branch to be pulled.
183
184 :param branch_types: A list of branch types to pass to
185 acquireBranchToPull. Passing none means consider all types of
186 branch.
187 """
178 raise NotImplementedError(self.assertBranchIsAquired)188 raise NotImplementedError(self.assertBranchIsAquired)
179189
180 def startMirroring(self, branch):190 def startMirroring(self, branch):
@@ -202,7 +212,6 @@
202 removeSecurityProxy(branch).branch_type = BranchType.REMOTE212 removeSecurityProxy(branch).branch_type = BranchType.REMOTE
203 self.assertNoBranchIsAquired()213 self.assertNoBranchIsAquired()
204214
205
206 def test_private(self):215 def test_private(self):
207 # If there is a private branch that needs mirroring,216 # If there is a private branch that needs mirroring,
208 # acquireBranchToPull returns that.217 # acquireBranchToPull returns that.
@@ -232,6 +241,33 @@
232 naked_second_branch.next_mirror_time -= timedelta(seconds=50)241 naked_second_branch.next_mirror_time -= timedelta(seconds=50)
233 self.assertBranchIsAquired(naked_first_branch)242 self.assertBranchIsAquired(naked_first_branch)
234243
244 def test_type_filter_hosted_returns_hosted(self):
245 branch = self.factory.makeAnyBranch(branch_type=BranchType.HOSTED)
246 branch.requestMirror()
247 self.assertBranchIsAquired(branch, BranchType.HOSTED)
248
249 def test_type_filter_hosted_does_not_return_mirrored(self):
250 branch = self.factory.makeAnyBranch(branch_type=BranchType.MIRRORED)
251 branch.requestMirror()
252 self.assertNoBranchIsAquired(BranchType.HOSTED)
253
254 def test_type_filter_mirrored_does_not_return_hosted(self):
255 branch = self.factory.makeAnyBranch(branch_type=BranchType.HOSTED)
256 branch.requestMirror()
257 self.assertNoBranchIsAquired(BranchType.MIRRORED)
258
259 def test_type_filter_hosted_imported_returns_hosted(self):
260 branch = self.factory.makeAnyBranch(branch_type=BranchType.HOSTED)
261 branch.requestMirror()
262 self.assertBranchIsAquired(
263 branch, BranchType.HOSTED, BranchType.IMPORTED)
264
265 def test_type_filter_hosted_imported_returns_imported(self):
266 branch = self.factory.makeAnyBranch(branch_type=BranchType.IMPORTED)
267 branch.requestMirror()
268 self.assertBranchIsAquired(
269 branch, BranchType.HOSTED, BranchType.IMPORTED)
270
235271
236class TestAcquireBranchToPullDirectly(TestCaseWithFactory,272class TestAcquireBranchToPullDirectly(TestCaseWithFactory,
237 AcquireBranchToPullTests):273 AcquireBranchToPullTests):
@@ -239,14 +275,16 @@
239275
240 layer = DatabaseFunctionalLayer276 layer = DatabaseFunctionalLayer
241277
242 def assertNoBranchIsAquired(self):278 def assertNoBranchIsAquired(self, *branch_types):
243 """See `AcquireBranchToPullTests`."""279 """See `AcquireBranchToPullTests`."""
244 acquired_branch = getUtility(IBranchPuller).acquireBranchToPull()280 acquired_branch = getUtility(IBranchPuller).acquireBranchToPull(
281 *branch_types)
245 self.assertEqual(None, acquired_branch)282 self.assertEqual(None, acquired_branch)
246283
247 def assertBranchIsAquired(self, branch):284 def assertBranchIsAquired(self, branch, *branch_types):
248 """See `AcquireBranchToPullTests`."""285 """See `AcquireBranchToPullTests`."""
249 acquired_branch = getUtility(IBranchPuller).acquireBranchToPull()286 acquired_branch = getUtility(IBranchPuller).acquireBranchToPull(
287 *branch_types)
250 login_person(removeSecurityProxy(branch).owner)288 login_person(removeSecurityProxy(branch).owner)
251 self.assertEqual(branch, acquired_branch)289 self.assertEqual(branch, acquired_branch)
252 self.assertIsNot(None, acquired_branch.last_mirror_attempt)290 self.assertIsNot(None, acquired_branch.last_mirror_attempt)
253291
=== modified file 'lib/lp/code/xmlrpc/codehosting.py'
--- lib/lp/code/xmlrpc/codehosting.py 2010-02-24 01:22:28 +0000
+++ lib/lp/code/xmlrpc/codehosting.py 2010-02-24 19:04:21 +0000
@@ -23,6 +23,7 @@
23from zope.security.proxy import removeSecurityProxy23from zope.security.proxy import removeSecurityProxy
2424
25from canonical.launchpad.ftests import login_person, logout25from canonical.launchpad.ftests import login_person, logout
26from lp.code.errors import UnknownBranchTypeError
26from lp.code.enums import BranchType27from lp.code.enums import BranchType
27from lp.code.interfaces.branch import BranchCreationException28from lp.code.interfaces.branch import BranchCreationException
28from lp.code.interfaces.branchlookup import IBranchLookup29from lp.code.interfaces.branchlookup import IBranchLookup
@@ -54,9 +55,17 @@
5455
55 implements(IBranchPuller)56 implements(IBranchPuller)
5657
57 def acquireBranchToPull(self):58 def acquireBranchToPull(self, branch_type_names):
58 """See `IBranchPuller`."""59 """See `IBranchPuller`."""
59 branch = getUtility(branchpuller.IBranchPuller).acquireBranchToPull()60 branch_types = []
61 for branch_type_name in branch_type_names:
62 try:
63 branch_types.append(BranchType.items[branch_type_name])
64 except KeyError:
65 raise UnknownBranchTypeError(
66 'Unknown branch type: %r' % (branch_type_name,))
67 branch = getUtility(branchpuller.IBranchPuller).acquireBranchToPull(
68 *branch_types)
60 if branch is not None:69 if branch is not None:
61 branch = removeSecurityProxy(branch)70 branch = removeSecurityProxy(branch)
62 default_branch = branch.target.default_stacked_on_branch71 default_branch = branch.target.default_stacked_on_branch
6372
=== modified file 'lib/lp/code/xmlrpc/tests/test_codehosting.py'
--- lib/lp/code/xmlrpc/tests/test_codehosting.py 2010-02-24 01:57:35 +0000
+++ lib/lp/code/xmlrpc/tests/test_codehosting.py 2010-02-24 19:04:21 +0000
@@ -30,6 +30,7 @@
30from canonical.testing import DatabaseFunctionalLayer, FunctionalLayer30from canonical.testing import DatabaseFunctionalLayer, FunctionalLayer
3131
32from lp.code.enums import BranchType32from lp.code.enums import BranchType
33from lp.code.errors import UnknownBranchTypeError
33from lp.code.interfaces.branch import BRANCH_NAME_VALIDATION_ERROR_MESSAGE34from lp.code.interfaces.branch import BRANCH_NAME_VALIDATION_ERROR_MESSAGE
34from lp.code.interfaces.branchlookup import IBranchLookup35from lp.code.interfaces.branchlookup import IBranchLookup
35from lp.code.interfaces.branchtarget import IBranchTarget36from lp.code.interfaces.branchtarget import IBranchTarget
@@ -409,15 +410,17 @@
409 self.storage = frontend.getPullerEndpoint()410 self.storage = frontend.getPullerEndpoint()
410 self.factory = frontend.getLaunchpadObjectFactory()411 self.factory = frontend.getLaunchpadObjectFactory()
411412
412 def assertNoBranchIsAquired(self):413 def assertNoBranchIsAquired(self, *branch_types):
413 """See `AcquireBranchToPullTests`."""414 """See `AcquireBranchToPullTests`."""
414 pull_info = self.storage.acquireBranchToPull()415 branch_types = tuple(branch_type.name for branch_type in branch_types)
416 pull_info = self.storage.acquireBranchToPull(branch_types)
415 self.assertEqual((), pull_info)417 self.assertEqual((), pull_info)
416418
417 def assertBranchIsAquired(self, branch):419 def assertBranchIsAquired(self, branch, *branch_types):
418 """See `AcquireBranchToPullTests`."""420 """See `AcquireBranchToPullTests`."""
419 branch = removeSecurityProxy(branch)421 branch = removeSecurityProxy(branch)
420 pull_info = self.storage.acquireBranchToPull()422 branch_types = tuple(branch_type.name for branch_type in branch_types)
423 pull_info = self.storage.acquireBranchToPull(branch_types)
421 default_branch = branch.target.default_stacked_on_branch424 default_branch = branch.target.default_stacked_on_branch
422 if default_branch:425 if default_branch:
423 default_branch_name = default_branch426 default_branch_name = default_branch
@@ -437,21 +440,21 @@
437 def test_branch_type_returned_hosted(self):440 def test_branch_type_returned_hosted(self):
438 branch = self.factory.makeAnyBranch(branch_type=BranchType.HOSTED)441 branch = self.factory.makeAnyBranch(branch_type=BranchType.HOSTED)
439 branch.requestMirror()442 branch.requestMirror()
440 pull_info = self.storage.acquireBranchToPull()443 pull_info = self.storage.acquireBranchToPull(())
441 _, _, _, _, branch_type = pull_info444 _, _, _, _, branch_type = pull_info
442 self.assertEqual('HOSTED', branch_type)445 self.assertEqual('HOSTED', branch_type)
443446
444 def test_branch_type_returned_mirrored(self):447 def test_branch_type_returned_mirrored(self):
445 branch = self.factory.makeAnyBranch(branch_type=BranchType.MIRRORED)448 branch = self.factory.makeAnyBranch(branch_type=BranchType.MIRRORED)
446 branch.requestMirror()449 branch.requestMirror()
447 pull_info = self.storage.acquireBranchToPull()450 pull_info = self.storage.acquireBranchToPull(())
448 _, _, _, _, branch_type = pull_info451 _, _, _, _, branch_type = pull_info
449 self.assertEqual('MIRRORED', branch_type)452 self.assertEqual('MIRRORED', branch_type)
450453
451 def test_branch_type_returned_import(self):454 def test_branch_type_returned_import(self):
452 branch = self.factory.makeAnyBranch(branch_type=BranchType.IMPORTED)455 branch = self.factory.makeAnyBranch(branch_type=BranchType.IMPORTED)
453 branch.requestMirror()456 branch.requestMirror()
454 pull_info = self.storage.acquireBranchToPull()457 pull_info = self.storage.acquireBranchToPull(())
455 _, _, _, _, branch_type = pull_info458 _, _, _, _, branch_type = pull_info
456 self.assertEqual('IMPORTED', branch_type)459 self.assertEqual('IMPORTED', branch_type)
457460
@@ -459,7 +462,7 @@
459 branch = self.factory.makeProductBranch()462 branch = self.factory.makeProductBranch()
460 self.factory.enableDefaultStackingForProduct(branch.product)463 self.factory.enableDefaultStackingForProduct(branch.product)
461 branch.requestMirror()464 branch.requestMirror()
462 pull_info = self.storage.acquireBranchToPull()465 pull_info = self.storage.acquireBranchToPull(())
463 _, _, _, default_stacked_on_branch, _ = pull_info466 _, _, _, default_stacked_on_branch, _ = pull_info
464 self.assertEqual(467 self.assertEqual(
465 default_stacked_on_branch,468 default_stacked_on_branch,
@@ -475,11 +478,16 @@
475 mirrored_branch = self.factory.makeProductBranch(478 mirrored_branch = self.factory.makeProductBranch(
476 branch_type=BranchType.MIRRORED, product=product)479 branch_type=BranchType.MIRRORED, product=product)
477 mirrored_branch.requestMirror()480 mirrored_branch.requestMirror()
478 pull_info = self.storage.acquireBranchToPull()481 pull_info = self.storage.acquireBranchToPull(())
479 _, _, _, default_stacked_on_branch, _ = pull_info482 _, _, _, default_stacked_on_branch, _ = pull_info
480 self.assertEqual(483 self.assertEqual(
481 '', default_stacked_on_branch)484 '', default_stacked_on_branch)
482485
486 def test_unknown_branch_type_name_raises(self):
487 self.assertRaises(
488 UnknownBranchTypeError, self.storage.acquireBranchToPull,
489 ('NO_SUCH_TYPE',))
490
483491
484class BranchFileSystemTest(TestCaseWithFactory):492class BranchFileSystemTest(TestCaseWithFactory):
485 """Tests for the implementation of `IBranchFileSystem`."""493 """Tests for the implementation of `IBranchFileSystem`."""
486494
=== modified file 'lib/lp/codehosting/inmemory.py'
--- lib/lp/codehosting/inmemory.py 2010-02-24 01:57:35 +0000
+++ lib/lp/codehosting/inmemory.py 2010-02-24 19:04:21 +0000
@@ -18,6 +18,7 @@
18from zope.interface import implementer18from zope.interface import implementer
1919
20from canonical.database.constants import UTC_NOW20from canonical.database.constants import UTC_NOW
21from lp.code.errors import UnknownBranchTypeError
21from lp.code.model.branchnamespace import BranchNamespaceSet22from lp.code.model.branchnamespace import BranchNamespaceSet
22from lp.code.model.branchtarget import (23from lp.code.model.branchtarget import (
23 PackageBranchTarget, ProductBranchTarget)24 PackageBranchTarget, ProductBranchTarget)
@@ -442,11 +443,20 @@
442 self._branch_set = branch_set443 self._branch_set = branch_set
443 self._script_activity_set = script_activity_set444 self._script_activity_set = script_activity_set
444445
445 def acquireBranchToPull(self):446 def acquireBranchToPull(self, branch_type_names):
447 if not branch_type_names:
448 branch_type_names = 'HOSTED', 'MIRRORED', 'IMPORTED'
449 branch_types = []
450 for branch_type_name in branch_type_names:
451 try:
452 branch_types.append(BranchType.items[branch_type_name])
453 except KeyError:
454 raise UnknownBranchTypeError(
455 'Unknown branch type: %r' % (branch_type_name,))
446 branches = sorted(456 branches = sorted(
447 [branch for branch in self._branch_set457 [branch for branch in self._branch_set
448 if branch.next_mirror_time is not None458 if branch.next_mirror_time is not None
449 and branch.branch_type != BranchType.REMOTE],459 and branch.branch_type in branch_types],
450 key=operator.attrgetter('next_mirror_time'))460 key=operator.attrgetter('next_mirror_time'))
451 if branches:461 if branches:
452 branch = branches[-1]462 branch = branches[-1]
453463
=== modified file 'lib/lp/codehosting/puller/scheduler.py'
--- lib/lp/codehosting/puller/scheduler.py 2009-12-22 00:26:49 +0000
+++ lib/lp/codehosting/puller/scheduler.py 2010-02-24 19:04:21 +0000
@@ -417,9 +417,10 @@
417 branches.417 branches.
418 """418 """
419419
420 def __init__(self, branch_puller_endpoint, logger):420 def __init__(self, branch_puller_endpoint, logger, branch_type_names):
421 self.branch_puller_endpoint = branch_puller_endpoint421 self.branch_puller_endpoint = branch_puller_endpoint
422 self.logger = logger422 self.logger = logger
423 self.branch_type_names = branch_type_names
423 self.actualLock = None424 self.actualLock = None
424 self.name = 'branch-puller'425 self.name = 'branch-puller'
425 self.lockfilename = '/var/lock/launchpad-%s.lock' % self.name426 self.lockfilename = '/var/lock/launchpad-%s.lock' % self.name
@@ -455,7 +456,7 @@
455456
456 def _poll(self):457 def _poll(self):
457 deferred = self.branch_puller_endpoint.callRemote(458 deferred = self.branch_puller_endpoint.callRemote(
458 'acquireBranchToPull')459 'acquireBranchToPull', self.branch_type_names)
459 deferred.addCallback(self._turnJobTupleIntoTask)460 deferred.addCallback(self._turnJobTupleIntoTask)
460 return deferred461 return deferred
461462
462463
=== modified file 'lib/lp/codehosting/puller/tests/test_acceptance.py'
--- lib/lp/codehosting/puller/tests/test_acceptance.py 2010-01-20 20:56:29 +0000
+++ lib/lp/codehosting/puller/tests/test_acceptance.py 2010-02-24 19:04:21 +0000
@@ -122,7 +122,7 @@
122 output, error = process.communicate()122 output, error = process.communicate()
123 return process.returncode, output, error123 return process.returncode, output, error
124124
125 def runPuller(self):125 def runPuller(self, *args):
126 """Run the puller script for the given branch type.126 """Run the puller script for the given branch type.
127127
128 :param branch_type: One of 'upload', 'mirror' or 'import'128 :param branch_type: One of 'upload', 'mirror' or 'import'
@@ -132,7 +132,7 @@
132 stdout and stderr respectively.132 stdout and stderr respectively.
133 """133 """
134 command = [134 command = [
135 '%s/bin/py' % config.root, self._puller_script, '-q']135 '%s/bin/py' % config.root, self._puller_script, '-q'] + list(args)
136 retcode, output, error = self.runSubprocess(command)136 retcode, output, error = self.runSubprocess(command)
137 return command, retcode, output, error137 return command, retcode, output, error
138138
@@ -430,6 +430,23 @@
430 command, retcode, output, error = self.runPuller()430 command, retcode, output, error = self.runPuller()
431 self.assertRanSuccessfully(command, retcode, output, error)431 self.assertRanSuccessfully(command, retcode, output, error)
432432
433 def test_type_filtering(self):
434 # When run with --branch-type arguments, the puller only mirrors those
435 # branches of the specified types.
436 hosted_branch = self.factory.makeAnyBranch(
437 branch_type=BranchType.HOSTED)
438 mirrored_branch = self.factory.makeAnyBranch(
439 branch_type=BranchType.MIRRORED)
440 mirrored_branch.requestMirror()
441 transaction.commit()
442 self.pushBranch(hosted_branch)
443 command, retcode, output, error = self.runPuller(
444 '--branch-type', 'HOSTED')
445 self.assertRanSuccessfully(command, retcode, output, error)
446 self.assertMirrored(hosted_branch)
447 self.assertIsNot(
448 None, mirrored_branch.next_mirror_time)
449
433 def test_records_script_activity(self):450 def test_records_script_activity(self):
434 # A record gets created in the ScriptActivity table.451 # A record gets created in the ScriptActivity table.
435 script_activity_set = getUtility(IScriptActivitySet)452 script_activity_set = getUtility(IScriptActivitySet)
436453
=== modified file 'lib/lp/codehosting/puller/tests/test_scheduler.py'
--- lib/lp/codehosting/puller/tests/test_scheduler.py 2010-01-08 03:07:25 +0000
+++ lib/lp/codehosting/puller/tests/test_scheduler.py 2010-02-24 19:04:21 +0000
@@ -8,7 +8,6 @@
8from datetime import datetime8from datetime import datetime
9import logging9import logging
10import os10import os
11import sys
12import textwrap11import textwrap
13import unittest12import unittest
1413
@@ -42,8 +41,7 @@
4241
43class FakePullerEndpointProxy:42class FakePullerEndpointProxy:
4443
45 def __init__(self, branch_queues=None):44 def __init__(self):
46 self.branch_queues = branch_queues
47 self.calls = []45 self.calls = []
4846
49 def callRemote(self, method_name, *args):47 def callRemote(self, method_name, *args):
@@ -58,8 +56,8 @@
58 def _default(self, *args):56 def _default(self, *args):
59 return defer.succeed(None)57 return defer.succeed(None)
6058
61 def _remote_getBranchPullQueue(self, branch_type):59 def _remote_acquireBranchToPull(self, *args):
62 return defer.succeed(self.branch_queues[branch_type])60 return defer.succeed(0)
6361
64 def _remote_setStackedOn(self, branch_id, stacked_on_location):62 def _remote_setStackedOn(self, branch_id, stacked_on_location):
65 if stacked_on_location == 'raise-branch-not-found':63 if stacked_on_location == 'raise-branch-not-found':
@@ -70,7 +68,7 @@
70 return defer.succeed(None)68 return defer.succeed(None)
7169
7270
73class TestJobScheduler(unittest.TestCase):71class TestJobScheduler(TrialTestCase):
7472
75 def setUp(self):73 def setUp(self):
76 self.masterlock = 'master.lock'74 self.masterlock = 'master.lock'
@@ -80,8 +78,9 @@
80 if os.path.exists(self.masterlock):78 if os.path.exists(self.masterlock):
81 os.unlink(self.masterlock)79 os.unlink(self.masterlock)
8280
83 def makeJobScheduler(self):81 def makeJobScheduler(self, branch_type_names=()):
84 return scheduler.JobScheduler(None, logging.getLogger())82 return scheduler.JobScheduler(
83 FakePullerEndpointProxy(), logging.getLogger(), branch_type_names)
8584
86 def testManagerCreatesLocks(self):85 def testManagerCreatesLocks(self):
87 manager = self.makeJobScheduler()86 manager = self.makeJobScheduler()
@@ -100,6 +99,13 @@
100 self.failUnless(os.path.exists(self.masterlock))99 self.failUnless(os.path.exists(self.masterlock))
101 manager.unlock()100 manager.unlock()
102101
102 def test_run_calls_acquireBranchToPull(self):
103 manager = self.makeJobScheduler(('HOSTED',))
104 manager.run()
105 self.assertEqual(
106 [('acquireBranchToPull', ('HOSTED',))],
107 manager.branch_puller_endpoint.calls)
108
103109
104class TestPullerWireProtocol(TrialTestCase):110class TestPullerWireProtocol(TrialTestCase):
105 """Tests for the `PullerWireProtocol`.111 """Tests for the `PullerWireProtocol`.
@@ -516,7 +522,6 @@
516 layer = TwistedLayer522 layer = TwistedLayer
517523
518 def setUp(self):524 def setUp(self):
519 from twisted.internet import reactor
520 self.factory = ObjectFactory()525 self.factory = ObjectFactory()
521 self.available_oops_prefixes = set(['foo'])526 self.available_oops_prefixes = set(['foo'])
522 self.eventHandler = self.makePullerMaster(527 self.eventHandler = self.makePullerMaster(
@@ -526,7 +531,6 @@
526 self.commands_spawned = []531 self.commands_spawned = []
527532
528 def tearDown(self):533 def tearDown(self):
529 from twisted.internet import reactor
530 reactor.spawnProcess = self._realSpawnProcess534 reactor.spawnProcess = self._realSpawnProcess
531535
532 def makePullerMaster(self, branch_type_name, default_stacked_on_url=None,536 def makePullerMaster(self, branch_type_name, default_stacked_on_url=None,
533537
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2010-02-23 20:02:07 +0000
+++ lib/lp/testing/factory.py 2010-02-24 19:04:21 +0000
@@ -93,7 +93,7 @@
93 BranchType, CodeImportMachineState, CodeImportReviewStatus,93 BranchType, CodeImportMachineState, CodeImportReviewStatus,
94 CodeImportResultStatus, CodeReviewNotificationLevel,94 CodeImportResultStatus, CodeReviewNotificationLevel,
95 RevisionControlSystems)95 RevisionControlSystems)
96from lp.code.interfaces.branch import UnknownBranchTypeError96from lp.code.errors import UnknownBranchTypeError
97from lp.code.interfaces.branchmergequeue import IBranchMergeQueueSet97from lp.code.interfaces.branchmergequeue import IBranchMergeQueueSet
98from lp.code.interfaces.branchnamespace import get_branch_namespace98from lp.code.interfaces.branchnamespace import get_branch_namespace
99from lp.code.interfaces.codeimport import ICodeImportSet99from lp.code.interfaces.codeimport import ICodeImportSet