From 94d339ca4db68c0788f8ae768d69b16c1e80d676 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Wed, 28 Jun 2017 02:34:09 +0200 Subject: [feat] restart openvpn automatically Right now we are trying to restart openvpn every 2 seconds, for ever (or until the user turns down the VPN). Maybe we can be more smart making the retries longer with time. - Resolves: #8049 --- docs/changelog.rst | 1 + src/leap/bitmask/vpn/_control.py | 20 ++++++++++++-------- src/leap/bitmask/vpn/process.py | 4 ++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 455be5da..64a47e89 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -13,6 +13,7 @@ Features - `#8765 `_: Require a global authentication token for the api - `#8819 `_: Send key to provider if a new priv key is putted in the keyring - `#8821 `_: Add a 'fetch' flag to key export +- `#8049 `_: Restart the VPN automatically - Initial cli port of the legacy vpn code - Add VPN API to bitmask.js - Add vpn get_cert command diff --git a/src/leap/bitmask/vpn/_control.py b/src/leap/bitmask/vpn/_control.py index 98e94bba..1c352bed 100644 --- a/src/leap/bitmask/vpn/_control.py +++ b/src/leap/bitmask/vpn/_control.py @@ -1,7 +1,7 @@ import os from twisted.internet.task import LoopingCall -from twisted.internet import reactor +from twisted.internet import reactor, defer from twisted.logger import Logger from .process import VPNProcess @@ -91,8 +91,9 @@ class VPNControl(object): self._start_pollers() return True + @defer.inlineCallbacks def restart(self): - self.stop(shutdown=False, restart=True) + yield self.stop(shutdown=False, restart=True) reactor.callLater( self.RESTART_WAIT, self.start) @@ -115,6 +116,7 @@ class VPNControl(object): self.log.error('Error on vpn pre-down {0!r}'.format(e)) raise + d = defer.succeed(True) if IS_LINUX: # TODO factor this out to a linux-only launcher mechanism. # First we try to be polite and send a SIGTERM... @@ -122,17 +124,17 @@ class VPNControl(object): # We assume that the only valid stops are initiated # by an user action, not hard restarts self._user_stopped = not restart - self._vpnproc.restarting = restart self._sentterm = True self._vpnproc.terminate(shutdown=shutdown) # ...but we also trigger a countdown to be unpolite # if strictly needed. + d = defer.Deferred() reactor.callLater( - self.TERMINATE_WAIT, self._kill_if_left_alive) + self.TERMINATE_WAIT, self._kill_if_left_alive, d) self._vpnproc.traffic_status = (0, 0) - return True + return d @property def status(self): @@ -155,7 +157,7 @@ class VPNControl(object): self._vpnproc.aborted = True self._vpnproc.killProcess() - def _kill_if_left_alive(self, tries=0): + def _kill_if_left_alive(self, deferred, tries=0): """ Check if the process is still alive, and send a SIGKILL after a timeout period. @@ -163,15 +165,16 @@ class VPNControl(object): :param tries: counter of tries, used in recursion :type tries: int """ - while tries < self.TERMINATE_MAXTRIES: + if tries < self.TERMINATE_MAXTRIES: if self._vpnproc.transport.pid is None: + deferred.callback(True) return else: self.log.debug('Process did not die, waiting...') tries += 1 reactor.callLater(self.TERMINATE_WAIT, - self._kill_if_left_alive, tries) + self._kill_if_left_alive, deferred, tries) return # after running out of patience, we try a killProcess @@ -180,6 +183,7 @@ class VPNControl(object): self._killit() except OSError: self.log.error('Could not kill process!') + deferred.callback(True) def _start_pollers(self): """ diff --git a/src/leap/bitmask/vpn/process.py b/src/leap/bitmask/vpn/process.py index 170df446..5b8bc1b7 100644 --- a/src/leap/bitmask/vpn/process.py +++ b/src/leap/bitmask/vpn/process.py @@ -96,7 +96,7 @@ class _VPNProcess(protocol.ProcessProtocol, _management.VPNManagement): self._status = _status.VPNStatus() self.set_watcher(self._status) - self.restarting = False + self.restarting = True self._remotes = remotes @property @@ -171,7 +171,7 @@ class _VPNProcess(protocol.ProcessProtocol, _management.VPNManagement): self.log.debug('processEnded, status %d' % (exit_code,)) if self.restarting: self.log.debug('Restarting VPN process') - reactor.callLater(2, self._restartfun) + self._restartfun() # polling -- cgit v1.2.3