diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2013-04-21 23:41:56 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2013-04-21 23:41:56 (GMT) |
commit | 7b15c66e69bd86c30cee9bdbf7c65100904fba7e (patch) | |
tree | 65ed21ca5dbb7d85a4b0a19b8117545915d277f6 | |
parent | b0b869f102a29ba02ac32789f346b3e0d079b350 (diff) |
Do not reset connection if route was not changed
-rwxr-xr-x | sugar-network | 1 | ||||
-rw-r--r-- | sugar_network/client/commands.py | 27 | ||||
-rw-r--r-- | sugar_network/toolkit/coroutine.py | 8 | ||||
-rw-r--r-- | sugar_network/toolkit/netlink.py | 32 | ||||
-rwxr-xr-x | tests/integration/master_personal.py | 4 | ||||
-rwxr-xr-x | tests/integration/node_client.py | 5 | ||||
-rwxr-xr-x | tests/integration/node_packages.py | 7 | ||||
-rwxr-xr-x | tests/units/client/commands.py | 11 | ||||
-rwxr-xr-x | tests/units/client/online_commands.py | 12 |
9 files changed, 75 insertions, 32 deletions
diff --git a/sugar-network b/sugar-network index 5eb95a9..b423ca4 100755 --- a/sugar-network +++ b/sugar-network @@ -160,6 +160,7 @@ class Application(application.Application): if not offline.value: for __ in cp.subscribe(event='inline', state='online'): break + coroutine.dispatch() server = coroutine.WSGIServer( ('localhost', client.ipc_port.value), IPCRouter(cp)) coroutine.spawn(server.serve_forever) diff --git a/sugar_network/client/commands.py b/sugar_network/client/commands.py index 3f89481..8fe21d1 100644 --- a/sugar_network/client/commands.py +++ b/sugar_network/client/commands.py @@ -15,7 +15,6 @@ import os import time -import socket import logging from os.path import join @@ -107,6 +106,9 @@ class ClientCommands(db.CommandsProcessor, Commands, journal.Commands): @db.volume_command(method='GET', cmd='inline', mime_type='application/json') def inline(self): + if not self._offline and not self._server_mode and \ + not self._inline.is_set(): + self._remote_connect() return self._inline.is_set() @db.volume_command(method='GET', cmd='whoami', @@ -277,10 +279,6 @@ class ClientCommands(db.CommandsProcessor, Commands, journal.Commands): } def call(self, request, response=None): - if not self._offline and not self._server_mode and \ - not self._inline.is_set(): - self._remote_connect() - request.static_prefix = self._static_prefix request.accept_language = [toolkit.default_lang()] request.allow_redirects = True @@ -323,15 +321,10 @@ class ClientCommands(db.CommandsProcessor, Commands, journal.Commands): self._remote_connect() def _wait_for_connectivity(self): - with netlink.Netlink(socket.NETLINK_ROUTE, netlink.RTMGRP_IPV4_ROUTE | - netlink.RTMGRP_IPV6_ROUTE | netlink.RTMGRP_NOTIFY) as monitor: - while True: + for route in netlink.wait_for_route(): + self._node_job.kill() + if route: self._remote_connect() - coroutine.select([monitor.fileno()], [], []) - while coroutine.select([monitor.fileno()], [], [], 1)[0]: - monitor.read() - self._node_job.kill() - coroutine.reset_resolver() def _remote_connect(self): @@ -368,10 +361,12 @@ class ClientCommands(db.CommandsProcessor, Commands, journal.Commands): listen_for_events() except Exception: exception(_logger, 'Connection to %r failed', url) - self._node.close() - self._got_offline() + finally: + if not self._no_subscription: + self._node.close() + self._got_offline() - if not self._node_job and util.default_route_exists(): + if not self._node_job: self._node_job.spawn(connect) def _found_mount(self, root): diff --git a/sugar_network/toolkit/coroutine.py b/sugar_network/toolkit/coroutine.py index 64b7cf5..60d7772 100644 --- a/sugar_network/toolkit/coroutine.py +++ b/sugar_network/toolkit/coroutine.py @@ -113,13 +113,13 @@ def Queue(*args, **kwargs): def Lock(*args, **kwargs): - import gevent.coros - return gevent.coros.Semaphore(*args, **kwargs) + import gevent.lock + return gevent.lock.Semaphore(*args, **kwargs) def RLock(*args, **kwargs): - import gevent.coros - return gevent.coros.RLock(*args, **kwargs) + import gevent.lock + return gevent.lock.RLock(*args, **kwargs) class AsyncEvent(object): diff --git a/sugar_network/toolkit/netlink.py b/sugar_network/toolkit/netlink.py index 53b0f2c..0eb857a 100644 --- a/sugar_network/toolkit/netlink.py +++ b/sugar_network/toolkit/netlink.py @@ -20,6 +20,8 @@ import socket import struct import logging +from sugar_network.toolkit import coroutine + # RTnetlink multicast groups - backwards compatibility for userspace RTMGRP_LINK = 1 @@ -53,6 +55,36 @@ _MESSAGE_MAX_SIZE = 16384 _logger = logging.getLogger('netlink') +def wait_for_route(): + + def get_route(): + with file('/proc/self/net/route') as f: + # Skip header + f.readline() + while True: + line = f.readline() + if not line: + break + dst, gw = line.split('\t', 3)[1:3] + if int(dst, 16) == 0: + return gw + + old_route = get_route() + if old_route: + yield old_route + with Netlink(socket.NETLINK_ROUTE, + RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE) as monitor: + while True: + coroutine.select([monitor.fileno()], [], []) + while coroutine.select([monitor.fileno()], [], [], 1)[0]: + monitor.read() + new_route = get_route() + if new_route != old_route: + coroutine.reset_resolver() + yield new_route + old_route = new_route + + class Netlink(object): def __init__(self, proto, groups): diff --git a/tests/integration/master_personal.py b/tests/integration/master_personal.py index 9771565..5ebbe37 100755 --- a/tests/integration/master_personal.py +++ b/tests/integration/master_personal.py @@ -49,7 +49,9 @@ class MasterPersonalTest(tests.Test): os.makedirs('client/mnt/disk/sugar-network') coroutine.sleep(2) - self.wait_for_events(Client('http://localhost:8102'), event='inline', state='online').wait() + ipc = Client('http://localhost:8102') + if not ipc.get(cmd='inline'): + self.wait_for_events(ipc, event='inline', state='online').wait() Client('http://localhost:8100').get(cmd='whoami') Client('http://localhost:8101').get(cmd='whoami') diff --git a/tests/integration/node_client.py b/tests/integration/node_client.py index 130c62b..2ebbed0 100755 --- a/tests/integration/node_client.py +++ b/tests/integration/node_client.py @@ -10,7 +10,7 @@ from os.path import exists from __init__ import tests, src_root -from sugar_network.client import IPCClient +from sugar_network.client import IPCClient, Client from sugar_network.toolkit import coroutine, util @@ -113,6 +113,9 @@ class NodeClientTest(tests.Test): '--api-url=http://localhost:8100', ]) coroutine.sleep(2) + ipc = Client('http://localhost:5101') + if not ipc.get(cmd='inline'): + self.wait_for_events(ipc, event='inline', state='online').wait() result = util.assert_call(cmd, stdin=json.dumps(stdin)) if result and '--porcelain' not in cmd: diff --git a/tests/integration/node_packages.py b/tests/integration/node_packages.py index bf69a83..38bc035 100755 --- a/tests/integration/node_packages.py +++ b/tests/integration/node_packages.py @@ -108,6 +108,8 @@ class NodePackagesSlaveTest(tests.Test): client.ipc_port.value = 8200 ipc = IPCClient() coroutine.sleep(2) + if not ipc.get(cmd='inline'): + self.wait_for_events(ipc, event='inline', state='online').wait() self.assertEqual( [{'url': 'http://localhost:8100/packages/OLPC-11.3.1/i586/rpm', 'name': 'rpm'}], ipc.get(['presolve', 'OLPC-11.3.1', 'i586', 'package'])) @@ -144,6 +146,8 @@ class NodePackagesSlaveTest(tests.Test): client.ipc_port.value = 8200 ipc = IPCClient() coroutine.sleep(2) + if not ipc.get(cmd='inline'): + self.wait_for_events(ipc, event='inline', state='online').wait() self.assertEqual( [{'url': 'http://localhost:8101/packages/OLPC-11.3.1/i586/rpm', 'name': 'rpm'}], ipc.get(['presolve', 'OLPC-11.3.1', 'i586', 'package'])) @@ -163,7 +167,8 @@ class NodePackagesSlaveTest(tests.Test): conn = Client('http://localhost:8102') client.ipc_port.value = 8202 ipc = IPCClient() - self.wait_for_events(ipc, event='inline', state='online').wait() + if not ipc.get(cmd='inline'): + self.wait_for_events(ipc, event='inline', state='online').wait() pid = self.popen('V=1 sugar-network-sync sync/sugar-network-sync http://localhost:8100', shell=True) self.waitpid(pid, 0) diff --git a/tests/units/client/commands.py b/tests/units/client/commands.py index 98e8525..54ff7fe 100755 --- a/tests/units/client/commands.py +++ b/tests/units/client/commands.py @@ -50,10 +50,11 @@ class CommandsTest(tests.Test): self.assertRaises(RuntimeError, cp.launch, 'fake-document', 'app', []) + trigger = self.wait_for_events(cp, event='launch') cp.launch('context', 'app', []) self.assertEqual( {'event': 'launch', 'args': ['app', []], 'kwargs': {'color': None, 'activity_id': None, 'uri': None, 'object_id': None}}, - self.wait_for_events(cp, event='launch').wait()) + trigger.wait()) def test_launch_ResumeJobject(self): self.override(injector, 'launch', lambda *args, **kwargs: [{'args': args, 'kwargs': kwargs}]) @@ -61,10 +62,11 @@ class CommandsTest(tests.Test): volume = Volume('db') cp = ClientCommands(volume, offline=True) + trigger = self.wait_for_events(cp, event='launch') cp.launch('context', 'app', [], object_id='object_id') self.assertEqual( {'event': 'launch', 'args': ['app', []], 'kwargs': {'color': None, 'activity_id': None, 'uri': None, 'object_id': 'object_id'}}, - self.wait_for_events(cp, event='launch').wait()) + trigger.wait()) def test_InlineSwitchInFind(self): self.home_volume = self.start_online_client() @@ -202,7 +204,7 @@ class CommandsTest(tests.Test): trigger = self.wait_for_events(cp, event='push') self.start_master() - cp.call(db.Request(method='GET', cmd='whoami')) + cp.call(db.Request(method='GET', cmd='inline')) trigger.wait() self.assertEqual([[3, None]], json.load(file('client/push.sequence'))) @@ -214,13 +216,14 @@ class CommandsTest(tests.Test): trigger = self.wait_for_events(cp, event='inline', state='offline') self.node.stop() trigger.wait() + self.node_volume.close() volume['context'].update(guid1, {'title': 'title_'}) volume['context'].delete(guid2) trigger = self.wait_for_events(cp, event='push') self.start_master() - cp.call(db.Request(method='GET', cmd='whoami')) + cp.call(db.Request(method='GET', cmd='inline')) trigger.wait() self.assertEqual([[4, None]], json.load(file('client/push.sequence'))) diff --git a/tests/units/client/online_commands.py b/tests/units/client/online_commands.py index aaf2a5d..e3bc8ee 100755 --- a/tests/units/client/online_commands.py +++ b/tests/units/client/online_commands.py @@ -431,7 +431,7 @@ class OnlineCommandsTest(tests.Test): event.pop('props') events.append(event) job = coroutine.spawn(read_events) - coroutine.dispatch() + coroutine.dispatch(.1) guid = ipc.post(['context'], { 'type': 'activity', @@ -439,11 +439,11 @@ class OnlineCommandsTest(tests.Test): 'summary': 'summary', 'description': 'description', }) - coroutine.dispatch() + coroutine.dispatch(.1) ipc.put(['context', guid], { 'title': 'title_2', }) - coroutine.dispatch() + coroutine.dispatch(.1) ipc.delete(['context', guid]) coroutine.sleep(.5) job.kill() @@ -458,18 +458,20 @@ class OnlineCommandsTest(tests.Test): del events[:] job = coroutine.spawn(read_events) - coroutine.dispatch() + coroutine.dispatch(.1) guid = self.node_volume['context'].create({ 'type': 'activity', 'title': 'title', 'summary': 'summary', 'description': 'description', }) + coroutine.dispatch(.1) self.node_volume['context'].update(guid, { 'title': 'title_2', }) + coroutine.dispatch(.1) self.node_volume['context'].delete(guid) - coroutine.sleep(.5) + coroutine.dispatch(.1) job.kill() self.assertEqual([ |