Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2013-04-21 23:41:56 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2013-04-21 23:41:56 (GMT)
commit7b15c66e69bd86c30cee9bdbf7c65100904fba7e (patch)
tree65ed21ca5dbb7d85a4b0a19b8117545915d277f6
parentb0b869f102a29ba02ac32789f346b3e0d079b350 (diff)
Do not reset connection if route was not changed
-rwxr-xr-xsugar-network1
-rw-r--r--sugar_network/client/commands.py27
-rw-r--r--sugar_network/toolkit/coroutine.py8
-rw-r--r--sugar_network/toolkit/netlink.py32
-rwxr-xr-xtests/integration/master_personal.py4
-rwxr-xr-xtests/integration/node_client.py5
-rwxr-xr-xtests/integration/node_packages.py7
-rwxr-xr-xtests/units/client/commands.py11
-rwxr-xr-xtests/units/client/online_commands.py12
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([