Merge lp:~stevenk/launchpad/db-add-parameters-to-idsjob into lp:launchpad/db-devel

Proposed by Steve Kowalik
Status: Merged
Approved by: Graham Binns
Approved revision: no longer in the source branch.
Merged at revision: 9892
Proposed branch: lp:~stevenk/launchpad/db-add-parameters-to-idsjob
Merge into: lp:launchpad/db-devel
Prerequisite: lp:~stevenk/launchpad/ids-limit-packagesets
Diff against target: 363 lines (+90/-79)
6 files modified
Makefile (+0/-1)
lib/canonical/launchpad/scripts/runlaunchpad.py (+45/-62)
lib/canonical/launchpad/scripts/tests/test_runlaunchpad.py (+5/-12)
lib/lp/soyuz/interfaces/distributionjob.py (+1/-1)
lib/lp/soyuz/model/initialisedistroseriesjob.py (+23/-3)
lib/lp/soyuz/tests/test_initialisedistroseriesjob.py (+16/-0)
To merge this branch: bzr merge lp:~stevenk/launchpad/db-add-parameters-to-idsjob
Reviewer Review Type Date Requested Status
Graham Binns (community) code Approve
Review via email: mp+38188@code.launchpad.net

Commit message

Allow parameters to be passed to InitialiseDistroSeriesJobs.

Description of the change

This branch allows creators of InitialiseDistroSeriesJob to specify (if needed) the architecutures and the packagesets to limit copying to, and if all source packages are to be rebuilt.

To post a comment you must log in.
Revision history for this message
Graham Binns (gmb) wrote :

Some minor nitpicks that need fixing before landing:

> 22 + def create(
> 23 + cls, distroseries, arches=(), packagesets=(), rebuild=False):

This should be wrapped thus:

    def create(cls, distroseries, arches=(), packagesets=(),
               rebuild=False):
     """See `IInitialiseDistroSeriesJob`."""

> 25 + metadata = {
> 26 + 'arches': arches, 'packagesets': packagesets,
> 27 + 'rebuild': rebuild}

And this should be wrapped one-item-per-line with the closing brace on
its own line:

        metadata = {
            'arches': arches,
            'packagesets': packagesets,
            'rebuild': rebuild,
            }

review: Approve (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-09-16 09:04:13 +0000
3+++ Makefile 2010-10-14 13:02:47 +0000
4@@ -255,7 +255,6 @@
5 $(RM) thread*.request
6 bin/run -r librarian,sftp,codebrowse -i $(LPCONFIG)
7
8-
9 start_librarian: compile
10 bin/start_librarian
11
12
13=== modified file 'lib/canonical/launchpad/scripts/runlaunchpad.py'
14--- lib/canonical/launchpad/scripts/runlaunchpad.py 2010-09-17 20:46:58 +0000
15+++ lib/canonical/launchpad/scripts/runlaunchpad.py 2010-10-14 13:02:47 +0000
16@@ -7,16 +7,18 @@
17 __all__ = ['start_launchpad']
18
19
20-import atexit
21+from contextlib import nested
22 import os
23 import signal
24 import subprocess
25 import sys
26
27+import fixtures
28 from zope.app.server.main import main
29
30 from canonical.config import config
31 from lp.services.mailman import runmailman
32+from canonical.launchpad.daemons import tachandler
33 from canonical.launchpad.testing import googletestservice
34 from canonical.lazr.pidfile import (
35 make_pidfile,
36@@ -28,20 +30,25 @@
37 return os.path.abspath(os.path.join(config.root, *path.split('/')))
38
39
40-TWISTD_SCRIPT = make_abspath('bin/twistd')
41-
42-
43-class Service(object):
44+class Service(fixtures.Fixture):
45
46 @property
47 def should_launch(self):
48- """Return true if this service should be launched."""
49+ """Return true if this service should be launched by default."""
50 return False
51
52 def launch(self):
53- """Launch the service, but do not block."""
54+ """Run the service in a thread or external process.
55+
56+ May block long enough to kick it off, but must return control to
57+ the caller without waiting for it to shutdown.
58+ """
59 raise NotImplementedError
60
61+ def setUp(self):
62+ super(Service, self).setUp()
63+ self.launch()
64+
65
66 class TacFile(Service):
67
68@@ -56,8 +63,7 @@
69 :param pre_launch: A callable that is called before the launch
70 process.
71 """
72- # No point calling super's __init__.
73- # pylint: disable-msg=W0231
74+ super(TacFile, self).__init__()
75 self.name = name
76 self.tac_filename = tac_filename
77 self.section_name = section_name
78@@ -80,10 +86,6 @@
79 return config[self.section_name].logfile
80
81 def launch(self):
82- # Don't run the server if it wasn't asked for.
83- if not self.should_launch:
84- return
85-
86 self.pre_launch()
87
88 pidfile = pidfile_path(self.name)
89@@ -91,7 +93,7 @@
90 tacfile = make_abspath(self.tac_filename)
91
92 args = [
93- TWISTD_SCRIPT,
94+ tachandler.twistd_script,
95 "--no_save",
96 "--nodaemon",
97 "--python", tacfile,
98@@ -109,15 +111,8 @@
99 # ability to cycle the log files by sending a signal to the twisted
100 # process.
101 process = subprocess.Popen(args, stdin=subprocess.PIPE)
102+ self.addCleanup(stop_process, process)
103 process.stdin.close()
104- # I've left this off - we still check at termination and we can
105- # avoid the startup delay. -- StuartBishop 20050525
106- #time.sleep(1)
107- #if process.poll() != None:
108- # raise RuntimeError(
109- # "%s did not start: %d"
110- # % (self.name, process.returncode))
111- stop_at_exit(process)
112
113
114 class MailmanService(Service):
115@@ -127,11 +122,8 @@
116 return config.mailman.launch
117
118 def launch(self):
119- # Don't run the server if it wasn't asked for. Also, don't attempt to
120- # shut it down at exit.
121- if self.should_launch:
122- runmailman.start_mailman()
123- atexit.register(runmailman.stop_mailman)
124+ runmailman.start_mailman()
125+ self.addCleanup(runmailman.stop_mailman)
126
127
128 class CodebrowseService(Service):
129@@ -144,8 +136,8 @@
130 process = subprocess.Popen(
131 ['make', 'run_codebrowse'],
132 stdin=subprocess.PIPE)
133+ self.addCleanup(stop_process, process)
134 process.stdin.close()
135- stop_at_exit(process)
136
137
138 class GoogleWebService(Service):
139@@ -155,9 +147,7 @@
140 return config.google_test_service.launch
141
142 def launch(self):
143- if self.should_launch:
144- process = googletestservice.start_as_process()
145- stop_at_exit(process)
146+ self.addCleanup(stop_process, googletestservice.start_as_process())
147
148
149 class MemcachedService(Service):
150@@ -180,23 +170,18 @@
151 else:
152 cmd.append('-v')
153 process = subprocess.Popen(cmd, stdin=subprocess.PIPE)
154+ self.addCleanup(stop_process, process)
155 process.stdin.close()
156- stop_at_exit(process)
157-
158-
159-def stop_at_exit(process):
160- """Create and register an atexit hook for killing a process.
161-
162- The hook will BLOCK until the process dies.
163+
164+
165+def stop_process(process):
166+ """kill process and BLOCK until process dies.
167
168 :param process: An instance of subprocess.Popen.
169 """
170-
171- def stop_process():
172- if process.poll() is None:
173- os.kill(process.pid, signal.SIGTERM)
174- process.wait()
175- atexit.register(stop_process)
176+ if process.poll() is None:
177+ os.kill(process.pid, signal.SIGTERM)
178+ process.wait()
179
180
181 def prepare_for_librarian():
182@@ -273,26 +258,24 @@
183 services, argv = split_out_runlaunchpad_arguments(argv[1:])
184 argv = process_config_arguments(argv)
185 services = get_services_to_run(services)
186- for service in services:
187- service.launch()
188-
189- # Store our process id somewhere
190- make_pidfile('launchpad')
191-
192 # Create the ZCML override file based on the instance.
193 config.generate_overrides()
194
195- if config.launchpad.launch:
196- main(argv)
197- else:
198- # We just need the foreground process to sit around forever waiting
199- # for the signal to shut everything down. Normally, Zope itself would
200- # be this master process, but we're not starting that up, so we need
201- # to do something else.
202- try:
203- signal.pause()
204- except KeyboardInterrupt:
205- pass
206+ with nested(*services):
207+ # Store our process id somewhere
208+ make_pidfile('launchpad')
209+
210+ if config.launchpad.launch:
211+ main(argv)
212+ else:
213+ # We just need the foreground process to sit around forever waiting
214+ # for the signal to shut everything down. Normally, Zope itself would
215+ # be this master process, but we're not starting that up, so we need
216+ # to do something else.
217+ try:
218+ signal.pause()
219+ except KeyboardInterrupt:
220+ pass
221
222
223 def start_librarian():
224@@ -303,7 +286,7 @@
225 prepare_for_librarian()
226 pidfile = pidfile_path('librarian')
227 cmd = [
228- TWISTD_SCRIPT,
229+ tachandler.twistd_script,
230 "--python", 'daemons/librarian.tac',
231 "--pidfile", pidfile,
232 "--prefix", 'Librarian',
233
234=== modified file 'lib/canonical/launchpad/scripts/tests/test_runlaunchpad.py'
235--- lib/canonical/launchpad/scripts/tests/test_runlaunchpad.py 2010-08-20 20:31:18 +0000
236+++ lib/canonical/launchpad/scripts/tests/test_runlaunchpad.py 2010-10-14 13:02:47 +0000
237@@ -13,7 +13,8 @@
238 import os
239 import shutil
240 import tempfile
241-import unittest
242+
243+import testtools
244
245 import canonical.config
246 from canonical.config import config
247@@ -119,12 +120,12 @@
248 self.assertEquals('test', config.instance_name)
249
250
251-class ServersToStart(unittest.TestCase):
252+class ServersToStart(testtools.TestCase):
253 """Test server startup control."""
254
255 def setUp(self):
256 """Make sure that only the Librarian is configured to launch."""
257- unittest.TestCase.setUp(self)
258+ testtools.TestCase.setUp(self)
259 launch_data = """
260 [librarian_server]
261 launch: True
262@@ -134,11 +135,7 @@
263 launch: False
264 """
265 config.push('launch_data', launch_data)
266-
267- def tearDown(self):
268- """Restore the default configuration."""
269- config.pop('launch_data')
270- unittest.TestCase.tearDown(self)
271+ self.addCleanup(config.pop, 'launch_data')
272
273 def test_nothing_explictly_requested(self):
274 """Implicitly start services based on the config.*.launch property.
275@@ -167,7 +164,3 @@
276
277 def test_launchpad_systems_red(self):
278 self.failIf(config.launchpad.launch)
279-
280-
281-def test_suite():
282- return unittest.TestLoader().loadTestsFromName(__name__)
283
284=== modified file 'lib/lp/soyuz/interfaces/distributionjob.py'
285--- lib/lp/soyuz/interfaces/distributionjob.py 2010-09-16 01:38:42 +0000
286+++ lib/lp/soyuz/interfaces/distributionjob.py 2010-10-14 13:02:47 +0000
287@@ -58,7 +58,7 @@
288 class IInitialiseDistroSeriesJobSource(IJobSource):
289 """An interface for acquiring IDistributionJobs."""
290
291- def create(distroseries):
292+ def create(distroseries, arches, packagesets, rebuild):
293 """Create a new initialisation job for a distroseries."""
294
295
296
297=== modified file 'lib/lp/soyuz/model/initialisedistroseriesjob.py'
298--- lib/lp/soyuz/model/initialisedistroseriesjob.py 2010-09-16 01:38:42 +0000
299+++ lib/lp/soyuz/model/initialisedistroseriesjob.py 2010-10-14 13:02:47 +0000
300@@ -33,16 +33,36 @@
301 classProvides(IInitialiseDistroSeriesJobSource)
302
303 @classmethod
304- def create(cls, distroseries):
305+ def create(cls, distroseries, arches=(), packagesets=(),
306+ rebuild=False):
307 """See `IInitialiseDistroSeriesJob`."""
308+ metadata = {
309+ 'arches': arches,
310+ 'packagesets': packagesets,
311+ 'rebuild': rebuild,
312+ }
313 job = DistributionJob(
314 distroseries.distribution, distroseries, cls.class_job_type,
315- ())
316+ metadata)
317 IMasterStore(DistributionJob).add(job)
318 return cls(job)
319
320+ @property
321+ def arches(self):
322+ return tuple(self.metadata['arches'])
323+
324+ @property
325+ def packagesets(self):
326+ return tuple(self.metadata['packagesets'])
327+
328+ @property
329+ def rebuild(self):
330+ return self.metadata['rebuild']
331+
332 def run(self):
333 """See `IRunnableJob`."""
334- ids = InitialiseDistroSeries(self.distroseries)
335+ ids = InitialiseDistroSeries(
336+ self.distroseries, self.arches, self.packagesets,
337+ self.rebuild)
338 ids.check()
339 ids.initialise()
340
341=== modified file 'lib/lp/soyuz/tests/test_initialisedistroseriesjob.py'
342--- lib/lp/soyuz/tests/test_initialisedistroseriesjob.py 2010-09-16 01:38:42 +0000
343+++ lib/lp/soyuz/tests/test_initialisedistroseriesjob.py 2010-10-14 13:02:47 +0000
344@@ -72,3 +72,19 @@
345 # returns an InitialisationError, then it's good.
346 self.assertRaisesWithContent(
347 InitialisationError, "Parent series required.", job.run)
348+
349+ def test_arguments(self):
350+ """Test that InitialiseDistroSeriesJob specified with arguments can
351+ be gotten out again."""
352+ distroseries = self.factory.makeDistroSeries()
353+ arches = (u'i386', u'amd64')
354+ packagesets = (u'foo', u'bar', u'baz')
355+
356+ job = getUtility(IInitialiseDistroSeriesJobSource).create(
357+ distroseries, arches, packagesets)
358+
359+ naked_job = removeSecurityProxy(job)
360+ self.assertEqual(naked_job.distroseries, distroseries)
361+ self.assertEqual(naked_job.arches, arches)
362+ self.assertEqual(naked_job.packagesets, packagesets)
363+ self.assertEqual(naked_job.rebuild, False)

Subscribers

People subscribed via source and target branches

to status/vote changes: