Merge lp:~free.ekanayaka/landscape-client/config-failure into lp:~landscape/landscape-client/trunk

Proposed by Free Ekanayaka
Status: Merged
Merged at revision: 246
Proposed branch: lp:~free.ekanayaka/landscape-client/config-failure
Merge into: lp:~landscape/landscape-client/trunk
Diff against target: 307 lines (+31/-104)
6 files modified
landscape/broker/client.py (+3/-1)
landscape/broker/server.py (+0/-15)
landscape/broker/tests/test_client.py (+2/-1)
landscape/broker/tests/test_server.py (+0/-55)
landscape/configuration.py (+8/-9)
landscape/tests/test_configuration.py (+18/-23)
To merge this branch: bzr merge lp:~free.ekanayaka/landscape-client/config-failure
Reviewer Review Type Date Requested Status
Muharem Hrnjadovic (community) Approve
Sidnei da Silva (community) Approve
Kevin McDermott Pending
Review via email: mp+24889@code.launchpad.net

Description of the change

A slightly tricky change, apparently it's not possible to call sys.exit inside a running callback, so I simply changed it to run after reactor.run() returns.

To post a comment you must log in.
Revision history for this message
Sidnei da Silva (sidnei) wrote :

[1] I'm a little bit worried about a scoping problem with 'exit_with_error' being assigned a value *after* the 'got_error' function is defined. It might be just because scoping is trickier in Javascript. I would just move the assignment before the function or pass the variable as an argument to the function instead.

[2] The setup() function has a similar code path. I suspect it can stay as it is because it's not used as a callback? Just for clarification.

Other than that, looks good. +1.

review: Approve
Revision history for this message
Sidnei da Silva (sidnei) wrote :

Oh, some small cleanups too:

=== pep8 ===

landscape/tests/test_configuration.py:1493:1: E302 expected 2 blank lines, found 3
landscape/tests/test_configuration.py:1529:9: E301 expected 1 blank line, found 2
landscape/tests/test_configuration.py:1579:9: E301 expected 1 blank line, found 2
landscape/configuration.py:496:5: E301 expected 1 blank line, found 2

=== pyflakes ===

landscape/tests/test_configuration.py:6: 'reactor' imported but unused

Revision history for this message
Free Ekanayaka (free.ekanayaka) wrote :

Thanks for the careful review, Sidnei.

I fixed all the lints but two, as they are due to comments preceding function definitions.

[1]

Good point, I moved exit_with_error at the beginning of the main function.

[2]

Right, that's not an issue because we're not running that code inside a callback.

243. By Free Ekanayaka

Fix Sidnei's review comment [1] and lints

Revision history for this message
Muharem Hrnjadovic (al-maisan) wrote :

Looks good, +1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'landscape/broker/client.py'
2--- landscape/broker/client.py 2010-04-23 11:37:25 +0000
3+++ landscape/broker/client.py 2010-05-10 15:05:39 +0000
4@@ -178,4 +178,6 @@
5
6 def exit(self):
7 """Stop the reactor and exit the process."""
8- self.reactor.stop()
9+ # Stop with a short delay to give a chance to reply to the
10+ # caller over AMP.
11+ self.reactor.call_later(0.1, self.reactor.stop)
12
13=== modified file 'landscape/broker/server.py'
14--- landscape/broker/server.py 2010-04-22 15:44:38 +0000
15+++ landscape/broker/server.py 2010-05-10 15:05:39 +0000
16@@ -52,9 +52,6 @@
17
18 reactor.call_on("message", self.broadcast_message)
19 reactor.call_on("impending-exchange", self.impending_exchange)
20- reactor.call_on("exchange-failed", self.exchange_failed)
21- reactor.call_on("registration-done", self.registration_done)
22- reactor.call_on("registration-failed", self.registration_failed)
23 reactor.call_on("message-type-acceptance-changed",
24 self.message_type_acceptance_changed)
25 reactor.call_on("server-uuid-changed", self.server_uuid_changed)
26@@ -201,18 +198,6 @@
27 def impending_exchange(self):
28 """Broadcast an C{impending-exchange} event to the clients."""
29
30- @event
31- def exchange_failed(self):
32- """Broadcast a C{exchange-failed} event to the clients."""
33-
34- @event
35- def registration_done(self):
36- """Broadcast a C{registration-done} event to the clients."""
37-
38- @event
39- def registration_failed(self):
40- """Broadcast a C{registration-failed} event to the clients."""
41-
42 def listen_events(self, event_types):
43 """
44 Return a C{Deferred} that fires when the first event occurs among the
45
46=== modified file 'landscape/broker/tests/test_client.py'
47--- landscape/broker/tests/test_client.py 2010-03-19 09:34:15 +0000
48+++ landscape/broker/tests/test_client.py 2010-05-10 15:05:39 +0000
49@@ -283,7 +283,8 @@
50 """
51 The L{BrokerClient.exit} method causes the reactor to be stopped.
52 """
53- self.client.reactor = self.mocker.mock()
54+ self.client.reactor.stop = self.mocker.mock()
55 self.client.reactor.stop()
56 self.mocker.replay()
57 self.client.exit()
58+ self.client.reactor.advance(0.1)
59
60=== modified file 'landscape/broker/tests/test_server.py'
61--- landscape/broker/tests/test_server.py 2010-04-22 15:44:38 +0000
62+++ landscape/broker/tests/test_server.py 2010-05-10 15:05:39 +0000
63@@ -316,39 +316,6 @@
64 self.client.add(plugin)
65 return self.assertSuccess(self.broker.impending_exchange(), [[None]])
66
67- def test_exchange_failed(self):
68- """
69- The L{BrokerServer.exchange_failed} method broadcasts an
70- C{exchange-failed} event to all connected clients.
71- """
72- callback = self.mocker.mock()
73- callback()
74- self.mocker.replay()
75- self.client_reactor.call_on("exchange-failed", callback)
76- return self.assertSuccess(self.broker.exchange_failed(), [[None]])
77-
78- def test_registration_done(self):
79- """
80- The L{BrokerServer.registration_done} method broadcasts a
81- C{registration-done} event to all connected clients.
82- """
83- callback = self.mocker.mock()
84- callback()
85- self.mocker.replay()
86- self.client_reactor.call_on("registration-done", callback)
87- return self.assertSuccess(self.broker.registration_done(), [[None]])
88-
89- def test_registration_failed(self):
90- """
91- The L{BrokerServer.registration_failed} method broadcasts a
92- C{registration-failed} event to all connected clients.
93- """
94- callback = self.mocker.mock()
95- callback()
96- self.mocker.replay()
97- self.client_reactor.call_on("registration-failed", callback)
98- return self.assertSuccess(self.broker.registration_failed(), [[None]])
99-
100 def test_broker_started(self):
101 """
102 The L{BrokerServer.broker_started} method broadcasts a
103@@ -470,28 +437,6 @@
104 self.mocker.replay()
105 self.reactor.fire("impending-exchange")
106
107- def test_exchange_failed(self):
108- """
109- When an C{exchange-failed} event is fired by the reactor, the
110- broker broadcasts it to its clients.
111- """
112- self.client.fire_event = self.mocker.mock()
113- self.client.fire_event("exchange-failed")
114- self.mocker.result(succeed(None))
115- self.mocker.replay()
116- self.reactor.fire("exchange-failed")
117-
118- def test_registration_done(self):
119- """
120- When a C{registration-done} event is fired by the reactor, the
121- broker broadcasts it to its clients.
122- """
123- self.client.fire_event = self.mocker.mock()
124- self.client.fire_event("registration-done")
125- self.mocker.result(succeed(None))
126- self.mocker.replay()
127- self.reactor.fire("registration-done")
128-
129 def test_message_type_acceptance_changed(self):
130 """
131 When a C{message-type-acceptance-changed} event is fired by the
132
133=== modified file 'landscape/configuration.py'
134--- landscape/configuration.py 2010-04-22 16:02:14 +0000
135+++ landscape/configuration.py 2010-05-10 15:05:39 +0000
136@@ -489,16 +489,14 @@
137 will happen.
138 """
139 reactor = TwistedReactor()
140+ exit_with_error = []
141
142 # XXX: many of these reactor.stop() calls should also specify a non-0 exit
143 # code, unless ok-no-register is passed.
144
145 def stop():
146 connector.disconnect()
147- # For some obscure reason our TwistedReactor.stop method calls
148- # reactor.crash() instead of reactor.stop(), which doesn't work
149- # here. Maybe TwistedReactor.stop should simply use reactor.stop().
150- reactor.call_later(0, reactor._reactor.stop)
151+ reactor.stop()
152
153 def failure():
154 print_text("Invalid account name or "
155@@ -545,7 +543,6 @@
156 remote.register().addErrback(handle_registration_errors)]
157 # We consume errors here to ignore errors after the first one.
158 # catch_all will be called for the very first deferred that fails.
159-
160 results = gather_results(deferreds, consume_errors=True)
161 return results.addErrback(catch_all)
162
163@@ -554,10 +551,9 @@
164 "client.", error=True)
165 print_text("This machine will be registered with the provided "
166 "details when the client runs.", error=True)
167- exit_code = 2
168- if config.ok_no_register:
169- exit_code = 0
170- sys.exit(exit_code)
171+ if not config.ok_no_register:
172+ exit_with_error.append(2)
173+ stop()
174
175 connector = RemoteBrokerConnector(reactor, config)
176 result = connector.connect(max_retries=0, quiet=True)
177@@ -566,6 +562,9 @@
178
179 reactor.run()
180
181+ if exit_with_error:
182+ sys.exit(exit_with_error[0])
183+
184 return result
185
186
187
188=== modified file 'landscape/tests/test_configuration.py'
189--- landscape/tests/test_configuration.py 2010-04-28 19:27:18 +0000
190+++ landscape/tests/test_configuration.py 2010-05-10 15:05:39 +0000
191@@ -3,7 +3,6 @@
192 from ConfigParser import ConfigParser
193
194 from twisted.internet.defer import succeed, fail
195-from twisted.internet import reactor
196
197 from landscape.reactor import TwistedReactor
198 from landscape.lib.fetch import HTTPCodeError, PyCurlError
199@@ -1492,12 +1491,6 @@
200
201 class RegisterFunctionTest(LandscapeTest):
202
203- # Due to the way these tests run, the run() method on the reactor is called
204- # *before* any of the remote methods (reload, register) are called, because
205- # these tests "hold" the reactor until after the tests runs, then the
206- # reactor is given back control of the process, *then* all the remote calls
207- # in the dbus queue are fired.
208-
209 helpers = [BrokerServiceHelper]
210
211 def test_register_success(self):
212@@ -1534,7 +1527,7 @@
213 # The deferred callback finally prints out this message.
214 print_text_mock("System successfully registered.")
215
216- reactor_mock.call_later(0, reactor.stop)
217+ reactor_mock.stop()
218
219 # Nothing else is printed!
220 print_text_mock(ANY)
221@@ -1585,7 +1578,7 @@
222 print_text_mock("Invalid account name or registration password.",
223 error=True)
224
225- reactor_mock.call_later(0, reactor.stop)
226+ reactor_mock.stop()
227
228 # Nothing else is printed!
229 print_text_mock(ANY)
230@@ -1636,7 +1629,7 @@
231 error=True)
232
233
234- reactor_mock.call_later(0, reactor.stop)
235+ reactor_mock.stop()
236
237 # Nothing else is printed!
238 print_text_mock(ANY)
239@@ -1700,8 +1693,15 @@
240 # This will make the RemoteBrokerConnector.connect call fail
241 print_text_mock = self.mocker.replace(print_text)
242 time_mock = self.mocker.replace("time")
243+ sys_mock = self.mocker.replace("sys")
244 reactor_mock = self.mocker.patch(TwistedReactor)
245
246+ connector_factory = self.mocker.replace(
247+ "landscape.broker.amp.RemoteBrokerConnector", passthrough=False)
248+ connector = connector_factory(ANY, ANY)
249+ connector.connect(max_retries=0, quiet=True)
250+ self.mocker.result(fail(ZeroDivisionError))
251+
252 print_text_mock(ARGS)
253 time_mock.sleep(ANY)
254 reactor_mock.run()
255@@ -1713,15 +1713,14 @@
256 print_text_mock(CONTAINS("This machine will be registered"),
257 error=True)
258
259+ sys_mock.exit(2)
260+ connector.disconnect()
261+ reactor_mock.stop()
262+
263 self.mocker.replay()
264
265- def assert_exit_code(system_exit):
266- self.assertEquals(system_exit.code, 2)
267-
268 config = get_config(self, ["-a", "accountname", "--silent"])
269- result = register(config)
270- self.assertFailure(result, SystemExit)
271- return result.addCallback(assert_exit_code)
272+ return register(config)
273
274 def test_register_bus_connection_failure_ok_no_register(self):
275 """
276@@ -1735,6 +1734,7 @@
277 print_text_mock(ARGS)
278 time_mock.sleep(ANY)
279 reactor_mock.run()
280+ reactor_mock.stop()
281
282 print_text_mock(
283 CONTAINS("There was an error communicating with the "
284@@ -1745,14 +1745,9 @@
285
286 self.mocker.replay()
287
288- def assert_exit_code(system_exit):
289- self.assertEquals(system_exit.code, 0)
290-
291 config = get_config(self, ["-a", "accountname", "--silent",
292 "--ok-no-register"])
293- result = register(config)
294- self.assertFailure(result, SystemExit)
295- return result.addCallback(assert_exit_code)
296+ return self.assertSuccess(register(config))
297
298
299 class RegisterFunctionNoServiceTest(LandscapeTest):
300@@ -1801,7 +1796,7 @@
301
302 # WHOAH DUDE. This waits for callLater(0, reactor.stop).
303 connector.disconnect()
304- reactor_mock.call_later(0, reactor.stop)
305+ reactor_mock.stop()
306
307 self.mocker.replay()
308

Subscribers

People subscribed via source and target branches

to all changes: