Merge lp:~nataliabidart/ubuntuone-client/is-running-needs-yield into lp:ubuntuone-client

Proposed by Natalia Bidart
Status: Merged
Approved by: Natalia Bidart
Approved revision: 1157
Merged at revision: 1157
Proposed branch: lp:~nataliabidart/ubuntuone-client/is-running-needs-yield
Merge into: lp:ubuntuone-client
Diff against target: 419 lines (+104/-111)
6 files modified
bin/u1sdtool (+31/-32)
bin/ubuntuone-launch (+22/-49)
tests/platform/test_tools.py (+30/-6)
ubuntuone/platform/tools/__init__.py (+15/-13)
ubuntuone/platform/tools/linux.py (+5/-10)
ubuntuone/platform/tools/windows.py (+1/-1)
To merge this branch: bzr merge lp:~nataliabidart/ubuntuone-client/is-running-needs-yield
Reviewer Review Type Date Requested Status
John Lenton (community) Approve
Roman Yepishev (community) fieldtest Approve
Review via email: mp+81463@code.launchpad.net

Commit message

- Make callers of is_already_running to handle the returned deferred
  (LP: #885885).

Description of the change

To test, please stoip your syncdaemon and confirm that both ubuntuone-launch and u1sdtool -s start syncdaemon properly. That would be:

PYTHONPATH=. bin/u1sdtool -s
PYTHONPATH=. bin/u1sdtool -q
PYTHONPATH=. bin/ubuntuone-launch

To post a comment you must log in.
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Running the tests in windows will show this failing test:

twisted.trial.unittest.FailTest: not equal:
a = ''
b = 'x\x9cKT\xc8\xc9/Q\xc8OSHI,IT(\xc9WH\xce\xcf-(J-.\x06\x00o\xb2\t\x0f'

tests.syncdaemon.test_action_queue.TestZipQueue.test_compress_gets_compressed_data

This is reported in bug #887150 and will be addressed in another branch.

Revision history for this message
Roman Yepishev (rye) wrote :

Worked for me.

review: Approve (fieldtest)
Revision history for this message
John Lenton (chipaca) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/u1sdtool'
2--- bin/u1sdtool 2011-10-21 21:01:56 +0000
3+++ bin/u1sdtool 2011-11-07 15:48:24 +0000
4@@ -42,7 +42,7 @@
5
6 from ubuntuone.platform.tools import (
7 SyncDaemonTool,
8- is_running,
9+ is_already_running,
10 show_dirty_nodes,
11 show_downloads,
12 show_error,
13@@ -61,8 +61,9 @@
14 from ubuntuone.clientdefs import VERSION
15
16
17+@defer.inlineCallbacks
18 def main(options, args, stdout):
19- """entry point"""
20+ """Entry point."""
21 sync_daemon_tool = SyncDaemonTool(bus)
22
23 # get the encoding of the output stream, defaults to UTF-8
24@@ -71,24 +72,18 @@
25 out_encoding = 'utf-8'
26 out = codecs.getwriter(out_encoding)(stdout, errors='replace')
27 # start syncdaemon if it's required
28- if not is_running() and not options.quit and not options.start:
29- d = sync_daemon_tool.start()
30- d.addBoth(lambda _: run(options, sync_daemon_tool, out))
31- else:
32- d = run(options, sync_daemon_tool, out)
33-
34- def default_errback(error):
35- """ default error handler. """
36- out.write("\nOops, an error ocurred:\n")
37- error.printTraceback()
38-
39- def stop_reactor(result):
40- """ stop the reactor. """
41+ running = yield is_already_running()
42+ should_start = not running and not options.quit and not options.start
43+
44+ try:
45+ if should_start:
46+ yield sync_daemon_tool.start()
47+ yield run(options, sync_daemon_tool, out)
48+ except Exception, e:
49+ out.write("\nOops, an error ocurred:\n%s\n" % e)
50+ finally:
51 if reactor.running:
52 reactor.stop()
53- d.addErrback(default_errback)
54- d.addCallback(stop_reactor)
55- return d
56
57
58 def run(options, sync_daemon_tool, out):
59@@ -171,11 +166,16 @@
60 d.addCallback(lambda r: show_downloads(r, out))
61 elif options.quit:
62 d = sync_daemon_tool.quit()
63+
64+ @defer.inlineCallbacks
65 def shutdown_check(result):
66- if result is None and not is_running():
67+ """Shutdown and check if really stopped."""
68+ running = yield is_already_running()
69+ if result is None and not running:
70 out.write("ubuntuone-syncdaemon stopped.\n")
71 else:
72 out.write("ubuntuone-syncdaemon still running.\n")
73+
74 d.addBoth(shutdown_check)
75 elif options.connect:
76 d = sync_daemon_tool.connect()
77@@ -233,7 +233,7 @@
78 action="store_true",
79 help="Request a refresh of the list of shares to"
80 " the server")
81- parser.add_option("", "--offer-share", dest="offer_share", type="string",
82+ parser.add_option("", "--offer-share", dest="offer_share", type="string",
83 nargs=4, metavar="PATH USER SHARE_NAME ACCESS_LEVEL",
84 help="Share PATH to USER. ")
85 parser.add_option("", "--list-shared", dest="list_shared",
86@@ -268,8 +268,8 @@
87 parser.add_option("", "--info", dest="path_info",
88 metavar="PATH", help="Request the metadata of PATH")
89
90- parser.add_option("", "--list-dirty-nodes", dest="dirty_nodes",
91- action="store_true",
92+ parser.add_option("", "--list-dirty-nodes", dest="dirty_nodes",
93+ action="store_true",
94 help="Show the list of nodes marked as 'dirty'")
95 parser.add_option("", "--current-transfers", dest="current_transfers",
96 action="store_true",
97@@ -278,25 +278,25 @@
98 help="Shutdown the syncdaemon")
99 parser.add_option("-c", "--connect", dest="connect", action='store_true',
100 help="Connect the syncdaemon")
101- parser.add_option("-d", "--disconnect", dest="disconnect",
102+ parser.add_option("-d", "--disconnect", dest="disconnect",
103 action='store_true', help="Disconnect the syncdaemon")
104- parser.add_option("-s", "--status", dest="status", action='store_true',
105+ parser.add_option("-s", "--status", dest="status", action='store_true',
106 help="Get the current status of syncdaemon")
107- parser.add_option("", "--waiting", dest="waiting",
108- action='store_true',
109+ parser.add_option("", "--waiting", dest="waiting",
110+ action='store_true',
111 help="Get the list of operations being executed")
112- parser.add_option("", "--waiting-content", dest="waiting_content",
113- action='store_true',
114+ parser.add_option("", "--waiting-content", dest="waiting_content",
115+ action='store_true',
116 help="Get the waiting content list - Warning: this "
117 "option is deprecated, use '--waiting' instead")
118- parser.add_option("", "--waiting-metadata", dest="waiting_metadata",
119+ parser.add_option("", "--waiting-metadata", dest="waiting_metadata",
120 action='store_true',
121 help="Get the waiting metadata list - Warning: this "
122 "option is deprecated, use '--waiting' instead")
123- parser.add_option("", "--free-space", dest="free_space",
124+ parser.add_option("", "--free-space", dest="free_space",
125 metavar="VOLUME_ID",
126 help="Get the free space for the volume")
127- parser.add_option("", "--start", dest="start", action='store_true',
128+ parser.add_option("", "--start", dest="start", action='store_true',
129 help="Start syncdaemon if it's not running")
130 parser.add_option("", "--version", dest="version", action='store_true',
131 help="Print the version number and exit")
132@@ -304,4 +304,3 @@
133 (options, args) = parser.parse_args(sys.argv)
134 reactor.callWhenRunning(main, options, args, sys.stdout)
135 reactor.run()
136-
137
138=== modified file 'bin/ubuntuone-launch'
139--- bin/ubuntuone-launch 2011-03-22 15:18:50 +0000
140+++ bin/ubuntuone-launch 2011-11-07 15:48:24 +0000
141@@ -52,66 +52,39 @@
142 import dbus
143 import glib
144 import gobject
145+
146 from dbus.mainloop.glib import DBusGMainLoop
147-from ubuntuone.platform.credentials import CredentialsManagementTool
148-from ubuntuone.platform.tools import SyncDaemonTool, is_running
149 from twisted.internet import defer
150
151-
152-def stage_two(node, sync_daemon_tool):
153- """Do the last few checks and ask for a connect if all is ok."""
154- # if the node_id of the root node is None, the user has never
155- # connected. Do not connect in that case.
156- if node.get('node_id', '') is None:
157- d = defer.fail(RuntimeError("never connected?"))
158- else:
159- # one last check: avoid having sso pop up asking for creds if
160- # the user deleted them
161- creds_tools = CredentialsManagementTool()
162- d = creds_tools.find_credentials()
163-
164- return d
165-
166-
167-def wait_for_ready(_, sync_daemon_tool):
168- """Wait for syncdaemon to be READY."""
169- d = sync_daemon_tool.wait_for_signal(
170- 'StatusChanged',
171- lambda a: a.get('name', '') == 'READY')
172- return d
173-
174-
175+from ubuntuone.syncdaemon.config import get_user_config
176+from ubuntuone.platform.tools import SyncDaemonTool, is_already_running
177+
178+
179+@defer.inlineCallbacks
180 def main():
181 """Start syncdaemon and ask it to connect, if possible."""
182 gobject.set_application_name("ubuntuone-launch")
183+
184+ files_sync_enabled = get_user_config().get_files_sync_enabled()
185+ if not files_sync_enabled:
186+ # SD will not start (has been disabled by user)
187+ raise RuntimeError("File sync is disabled")
188+
189 loop = DBusGMainLoop(set_as_default=True)
190 bus = dbus.SessionBus(mainloop=loop)
191 sync_daemon_tool = SyncDaemonTool(bus)
192-
193- if sync_daemon_tool.is_files_sync_enabled():
194- if not is_running():
195- try:
196- # have SD start
197- d = sync_daemon_tool.start()
198- d.addBoth(wait_for_ready, sync_daemon_tool)
199- except dbus.exception.DBusException, e:
200- # some dbus error, shouldn't happen, bail out
201- d = defer.fail(e)
202- else:
203- # SD is already running
204- d = defer.succeed(True)
205- else:
206- # SD will not start (has been disabled by user)
207- d = defer.fail(RuntimeError("File sync is disabled"))
208-
209- d.addCallback(lambda _: sync_daemon_tool.get_metadata(U1ROOT))
210- d.addCallback(stage_two, sync_daemon_tool)
211+ running = yield is_already_running(bus=bus)
212+ if not running:
213+ # have SD start
214+ yield sync_daemon_tool.start()
215+ yield sync_daemon_tool.wait_for_signal('StatusChanged',
216+ lambda a: a.get('name', '') == 'READY')
217+
218+
219+if __name__ == '__main__':
220+ d = main()
221 # os._exit feels like it's cheating, but it's simple and fast
222 d.addCallbacks(lambda _: os._exit(0), lambda _: os._exit(1))
223
224 mainloop = glib.MainLoop()
225 mainloop.run()
226-
227-
228-if __name__ == '__main__':
229- main()
230
231=== modified file 'tests/platform/test_tools.py'
232--- tests/platform/test_tools.py 2011-10-28 15:30:54 +0000
233+++ tests/platform/test_tools.py 2011-11-07 15:48:24 +0000
234@@ -60,7 +60,8 @@
235 self.patch(self.main, 'quit',
236 lambda: self.called.append('quit') or defer.succeed(None))
237
238- self.patch(tools, 'is_already_running', lambda bus: True)
239+ self.patch(tools, 'is_already_running',
240+ lambda bus: defer.succeed(True))
241 yield self.main.wait_for_nirvana()
242
243 def _create_share(self, accepted=True, subscribed=True):
244@@ -189,14 +190,16 @@
245 @defer.inlineCallbacks
246 def test_quit_when_running(self):
247 """Test the quit method when the daemon is running."""
248- self.patch(tools, 'is_already_running', lambda bus: True)
249+ self.patch(tools, 'is_already_running',
250+ lambda bus: defer.succeed(True))
251 yield self.tool.quit()
252 self.assertEqual(self.called, ['quit'])
253
254 @defer.inlineCallbacks
255 def test_quit_not_running(self):
256 """Test the quit method when the daemon is not running."""
257- self.patch(tools, 'is_already_running', lambda bus: False)
258+ self.patch(tools, 'is_already_running',
259+ lambda bus: defer.succeed(False))
260 yield self.tool.quit()
261 self.assertEqual(self.called, [])
262
263@@ -497,15 +500,33 @@
264 @defer.inlineCallbacks
265 def test_start_when_running(self):
266 """Test the start method when the daemon is running."""
267- self.patch(tools, 'is_already_running', lambda bus: True)
268+ self.patch(tools, 'is_already_running',
269+ lambda bus: defer.succeed(True))
270+ self.patch(self.tool, 'wait_for_signals',
271+ lambda *a: defer.fail(AssertionError(a)))
272 yield self.tool.start()
273 self.assertEqual(self.called, [])
274
275 @defer.inlineCallbacks
276 def test_start_not_running(self):
277 """Test the start method when the daemon is not running."""
278- self.patch(tools, 'is_already_running', lambda bus: False)
279+ d = defer.Deferred()
280+
281+ def succed_status_changed(signal_name, *a):
282+ """Returned a fired deferred if signal_name is StatusChanged."""
283+ if signal_name == 'StatusChanged':
284+ return d.callback(True)
285+ else:
286+ return d.errback(AssertionError(signal_name))
287+
288+ self.patch(tools, 'is_already_running',
289+ lambda bus: defer.succeed(False))
290+ self.patch(self.tool, 'wait_for_signals', succed_status_changed)
291+ assert not d.called
292+
293 yield self.tool.start()
294+ yield d # d is fired when wait_for_signals on StatusChanged was called
295+
296 self.assertEqual(self.called, ['start'])
297
298 @defer.inlineCallbacks
299@@ -710,7 +731,10 @@
300 @defer.inlineCallbacks
301 def test_enable_files_sync_when_disabled(self):
302 """Test for enable_files_sync."""
303- self.patch(tools, 'is_already_running', lambda bus: False)
304+ self.patch(self.tool, 'start',
305+ lambda: self.called.append('start') or defer.succeed(None))
306+ self.patch(tools, 'is_already_running',
307+ lambda bus: defer.succeed(False))
308 # be sure file sync is disabled and clear called
309 yield self.tool.enable_files_sync(False)
310 self.called = []
311
312=== modified file 'ubuntuone/platform/tools/__init__.py'
313--- ubuntuone/platform/tools/__init__.py 2011-11-02 18:14:42 +0000
314+++ ubuntuone/platform/tools/__init__.py 2011-11-07 15:48:24 +0000
315@@ -474,14 +474,15 @@
316 (file_info,) = yield d
317 defer.returnValue(file_info)
318
319+ @defer.inlineCallbacks
320 @log_call(logger.debug)
321 def quit(self):
322 """Quit the syncdaemon."""
323- if is_already_running(bus=self.bus):
324- result = self.proxy.call_method('sync_daemon', 'quit')
325- else:
326- result = defer.succeed(None)
327- return result
328+ result = None
329+ running = yield is_already_running(bus=self.bus)
330+ if running:
331+ result = yield self.proxy.call_method('sync_daemon', 'quit')
332+ defer.returnValue(result)
333
334 @log_call(logger.debug)
335 def connect(self):
336@@ -524,14 +525,15 @@
337 """Return the waiting content queue elements."""
338 return self.proxy.call_method('status', 'waiting_content')
339
340+ @defer.inlineCallbacks
341 @log_call(logger.debug)
342 def start(self):
343 """Start syncdaemon if it's not running."""
344- if is_already_running(bus=self.bus):
345- result = defer.succeed(None)
346- else:
347- result = self.proxy.start()
348- return result
349+ running = yield is_already_running(bus=self.bus)
350+ if not running:
351+ wait_d = self.wait_for_signals('StatusChanged')
352+ yield self.proxy.start()
353+ yield wait_d
354
355 @log_call(logger.debug)
356 def get_throttling_limits(self):
357@@ -664,7 +666,7 @@
358 # callbacks used by u1sdtool script
359
360 def show_shared(shares, out):
361- """Callback that prints the list of shared shares."""
362+ """Print the list of shared shares."""
363 if len(shares) == 0:
364 out.write("No shared\n")
365 else:
366@@ -680,7 +682,7 @@
367
368
369 def show_folders(folders, out):
370- """Callback that prints the list of user defined folders."""
371+ """Print the list of user defined folders."""
372 if len(folders) == 0:
373 out.write("No folders\n")
374 else:
375@@ -704,7 +706,7 @@
376
377
378 def show_shares(shares, out):
379- """Callback that prints the list of shares."""
380+ """Print the list of shares."""
381 if len(shares) == 0:
382 out.write("No shares\n")
383 else:
384
385=== modified file 'ubuntuone/platform/tools/linux.py'
386--- ubuntuone/platform/tools/linux.py 2011-10-21 17:06:24 +0000
387+++ ubuntuone/platform/tools/linux.py 2011-11-07 15:48:24 +0000
388@@ -155,13 +155,8 @@
389 follow_name_owner_changes=True)
390
391 def start(self):
392- """Start syncdaemon if it's not running."""
393- wait_d = self.wait_for_signal('StatusChanged', lambda x: x)
394- bus_client = DBusClient(self.bus, dbus.bus.BUS_DAEMON_PATH,
395- dbus.bus.BUS_DAEMON_IFACE,
396- dbus.bus.BUS_DAEMON_NAME)
397- d = bus_client.call_method('StartServiceByName',
398- DBUS_IFACE_NAME, 0,
399- signature='su')
400- d.addCallback(lambda _: wait_d)
401- return d
402+ """Start syncdaemon, should *not* be running."""
403+ if DBUS_IFACE_NAME in self.bus.list_names():
404+ self.bus.release_name(DBUS_IFACE_NAME)
405+ _, result = self.bus.start_service_by_name(DBUS_IFACE_NAME, 0)
406+ return defer.succeed(result == dbus.bus.DBUS_START_REPLY_SUCCESS)
407
408=== modified file 'ubuntuone/platform/tools/windows.py'
409--- ubuntuone/platform/tools/windows.py 2011-11-02 19:28:33 +0000
410+++ ubuntuone/platform/tools/windows.py 2011-11-07 15:48:24 +0000
411@@ -149,7 +149,7 @@
412 return self.connected
413
414 def start(self):
415- """Start syncdaemon if it's not running."""
416+ """Start syncdaemon, should *not* be running."""
417 # look in the reg to find the path of the .exe to be executed
418 # to launch the sd on windows
419 key = OpenKey(HKEY_LOCAL_MACHINE, U1_REG_PATH)

Subscribers

People subscribed via source and target branches