summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKali Kaneko <kali@leap.se>2017-08-23 00:34:22 -0400
committerKali Kaneko <kali@leap.se>2017-08-30 16:18:01 -0400
commitb314c73432da0797fc00e7a6d270b783929d4c08 (patch)
tree431c515b1c577593952848cd589369a930323e9b
parent2d7543e8c3828a8a0ab7b77b1c3a492c7ff28ed7 (diff)
[refactor] re-add retries for connecting to management
-rw-r--r--src/leap/bitmask/vpn/process.py29
-rw-r--r--src/leap/bitmask/vpn/tunnel.py25
-rw-r--r--tests/e2e/TODO4
3 files changed, 41 insertions, 17 deletions
diff --git a/src/leap/bitmask/vpn/process.py b/src/leap/bitmask/vpn/process.py
index 48d3f1ad..4ef9fd98 100644
--- a/src/leap/bitmask/vpn/process.py
+++ b/src/leap/bitmask/vpn/process.py
@@ -89,6 +89,7 @@ class _VPNProcess(protocol.ProcessProtocol):
self._restartfun = restartfun
self.restarting = True
+ self.failed = False
self.proto = None
self._remotes = remotes
@@ -106,18 +107,28 @@ class _VPNProcess(protocol.ProcessProtocol):
except Exception as exc:
print('[!] Error: %s' % exc)
- def _connect_to_management(self):
- # TODO -- add retries, twisted style, to this.
- # this sometimes raises 'file not found' error
+ def _connect_to_management(self, retries=30):
+ if retries == 0:
+ self.log.error('Timeout whilte connecting to management')
+ self.failed = True
+ return
+
+ def retry(retries):
+ ctr = retries - 1
+ self.log.warn(
+ 'Error connecting to management, retrying. Retries left: %s' % ctr)
+ reactor.callLater(
+ 0.1, self._connect_to_management, ctr)
+
self._d = connectProtocol(
self._management_endpoint,
ManagementProtocol(verbose=True))
- self._d.addCallback(self._got_management_protocol)
- self._d.addErrback(self.log.error)
+ self._d.addCallbacks(
+ self._got_management_protocol,
+ lambda f: retry(retries))
def connectionMade(self):
- # TODO cut this wait time when retries are done
- reactor.callLater(0.5, self._connect_to_management)
+ reactor.callLater(0.1, self._connect_to_management)
def processExited(self, failure):
err = failure.trap(
@@ -143,7 +154,9 @@ class _VPNProcess(protocol.ProcessProtocol):
Called when the child process exits and all file descriptors associated
with it have been closed.
"""
+ self.proto = None
exit_code = reason.value.exitCode
+
if isinstance(exit_code, int):
self.log.debug('processEnded, status %d' % (exit_code,))
if self.restarting:
@@ -174,6 +187,7 @@ class _VPNProcess(protocol.ProcessProtocol):
if not self.proto:
status = {'status': 'off', 'error': None}
return status
+
status = {'status': self.proto.state.simple.lower(),
'error': None}
if self.proto.traffic:
@@ -230,7 +244,6 @@ class _VPNProcess(protocol.ProcessProtocol):
self.log.debug('Process Exited Already')
def terminate_or_kill(self):
- # XXX this returns a deferred
return self._launcher.terminate_or_kill(
self.terminate, self.kill, self)
diff --git a/src/leap/bitmask/vpn/tunnel.py b/src/leap/bitmask/vpn/tunnel.py
index d05a50e2..d9a8be3d 100644
--- a/src/leap/bitmask/vpn/tunnel.py
+++ b/src/leap/bitmask/vpn/tunnel.py
@@ -76,11 +76,15 @@ class ConfiguredTunnel(object):
self._port = port
self._vpnproc = None
+ @defer.inlineCallbacks
def start(self):
- return self._start_vpn()
+ started = yield self._start_vpn()
+ defer.returnValue(started)
+ @defer.inlineCallbacks
def stop(self):
- return self._stop_vpn(restart=False)
+ stopped = yield self._stop_vpn(restart=False)
+ defer.returnValue(stopped)
# status
@@ -96,6 +100,7 @@ class ConfiguredTunnel(object):
# VPN Control
+ @defer.inlineCallbacks
def _start_vpn(self):
self.log.debug('VPN: start')
args = [self._vpnconfig, self._providerconfig, self._host,
@@ -105,15 +110,15 @@ class ConfiguredTunnel(object):
vpnproc = VPNProcess(*args, **kwargs)
self._vpnproc = vpnproc
- self._start_pre_up(vpnproc)
+ self.__start_pre_up(vpnproc)
cmd = self.__start_get_cmd(vpnproc)
- # XXX this should be a deferred
- running = self.__start_spawn_proc(vpnproc, cmd)
+
+ running = yield self.__start_spawn_proc(vpnproc, cmd)
if running:
vpnproc.pid = running.pid
- return True
+ defer.returnValue(True)
else:
- return False
+ defer.returnValue(False)
def __start_pre_up(self, proc):
try:
@@ -147,6 +152,7 @@ class ConfiguredTunnel(object):
reactor.callLater(
self.RESTART_WAIT, self.start)
+ @defer.inlineCallbacks
def _stop_vpn(self, restart=False):
"""
Stops the openvpn subprocess.
@@ -162,11 +168,12 @@ class ConfiguredTunnel(object):
if self._vpnproc is None:
self.log.debug('Tried to stop VPN but no process found')
- return
+ defer.returnValue(False)
self._vpnproc.restarting = restart
self.__stop_pre_down(self._vpnproc)
- self._vpnproc.terminate_or_kill()
+ stopped = yield self._vpnproc.terminate_or_kill()
+ defer.returnValue(stopped)
def __stop_pre_down(self, proc):
try:
diff --git a/tests/e2e/TODO b/tests/e2e/TODO
new file mode 100644
index 00000000..5cec6267
--- /dev/null
+++ b/tests/e2e/TODO
@@ -0,0 +1,4 @@
+VPN
+---------
+[ ] status when killed (fail-close)
+[ ] kill previously running vpn when launching one