From 348eb0852d6f1b8b2b72baba8a236bc30a6f2a4e Mon Sep 17 00:00:00 2001 From: antialias Date: Fri, 16 Nov 2012 17:38:46 -0800 Subject: reads and searches for strings from openvpn logs via the management interface. --- src/leap/base/network.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/leap/base') diff --git a/src/leap/base/network.py b/src/leap/base/network.py index 765d8ea0..bd8f15c7 100644 --- a/src/leap/base/network.py +++ b/src/leap/base/network.py @@ -14,6 +14,9 @@ from time import sleep logger = logging.getLogger(name=__name__) +#EVENTS OF NOTE +EVENT_CONNECT_REFUSED = "[ECONNREFUSED]: Connection refused (code=111)" + class NetworkCheckerThread(object): """ @@ -54,6 +57,12 @@ class NetworkCheckerThread(object): def run_checks(self): pass + def parse_log(self, log): + for line in log: + if EVENT_CONNECT_REFUSED in line: + #fire cb to stop openvpn server + pass + #private methods #here all the observers in fail_callbacks expect one positional argument, -- cgit v1.2.3 From 14f433c16de60753d122d5946df68e8e82285ca3 Mon Sep 17 00:00:00 2001 From: antialias Date: Mon, 19 Nov 2012 16:16:01 -0800 Subject: implemented abstracted layer with matching and passed callback. tests as well. --- src/leap/base/checks.py | 21 +++++++++++++++++++++ src/leap/base/network.py | 9 --------- src/leap/base/tests/test_checks.py | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 9 deletions(-) (limited to 'src/leap/base') diff --git a/src/leap/base/checks.py b/src/leap/base/checks.py index 4d4a5d8b..587012fb 100644 --- a/src/leap/base/checks.py +++ b/src/leap/base/checks.py @@ -12,6 +12,9 @@ from leap.base import exceptions logger = logging.getLogger(name=__name__) +#EVENTS OF NOTE +EVENT_CONNECT_REFUSED = "[ECONNREFUSED]: Connection refused (code=111)" + class LeapNetworkChecker(object): """ @@ -34,6 +37,8 @@ class LeapNetworkChecker(object): if self.provider_gateway: checker.ping_gateway(self.provider_gateway) + checker.parse_log_and_react([], ()) + def check_internet_connection(self): try: # XXX remove this hardcoded random ip @@ -136,3 +141,19 @@ class LeapNetworkChecker(object): return True except socket.gaierror: raise exceptions.CannotResolveDomainError + + def parse_log_and_react(self, log, error_matrix=None): + """ + compares the recent openvpn status log to + strings passed in and executes the callbacks passed in. + @param log: openvpn log + @type log: list of strings + @param error_matrix: tuples of strings and tuples of callbacks + @type error_matrix: tuples strings and call backs + """ + for line in log: + for each in error_matrix: + error, callbacks = each + if error in line: + for cb in callbacks: + cb() diff --git a/src/leap/base/network.py b/src/leap/base/network.py index bd8f15c7..765d8ea0 100644 --- a/src/leap/base/network.py +++ b/src/leap/base/network.py @@ -14,9 +14,6 @@ from time import sleep logger = logging.getLogger(name=__name__) -#EVENTS OF NOTE -EVENT_CONNECT_REFUSED = "[ECONNREFUSED]: Connection refused (code=111)" - class NetworkCheckerThread(object): """ @@ -57,12 +54,6 @@ class NetworkCheckerThread(object): def run_checks(self): pass - def parse_log(self, log): - for line in log: - if EVENT_CONNECT_REFUSED in line: - #fire cb to stop openvpn server - pass - #private methods #here all the observers in fail_callbacks expect one positional argument, diff --git a/src/leap/base/tests/test_checks.py b/src/leap/base/tests/test_checks.py index 7a694f89..645e615c 100644 --- a/src/leap/base/tests/test_checks.py +++ b/src/leap/base/tests/test_checks.py @@ -37,6 +37,8 @@ class LeapNetworkCheckTest(BaseLeapTest): "missing meth") self.assertTrue(hasattr(checker, "ping_gateway"), "missing meth") + self.assertTrue(hasattr(checker, "parse_log_and_react"), + "missing meth") def test_checker_should_actually_call_all_tests(self): checker = checks.LeapNetworkChecker() @@ -45,6 +47,7 @@ class LeapNetworkCheckTest(BaseLeapTest): self.assertTrue(mc.check_internet_connection.called, "not called") self.assertTrue(mc.check_tunnel_default_interface.called, "not called") self.assertTrue(mc.is_internet_up.called, "not called") + self.assertTrue(mc.parse_log_and_react.called, "not called") # ping gateway only called if we pass provider_gw checker = checks.LeapNetworkChecker(provider_gw="0.0.0.0") @@ -54,6 +57,7 @@ class LeapNetworkCheckTest(BaseLeapTest): self.assertTrue(mc.check_tunnel_default_interface.called, "not called") self.assertTrue(mc.ping_gateway.called, "not called") self.assertTrue(mc.is_internet_up.called, "not called") + self.assertTrue(mc.parse_log_and_react.called, "not called") def test_get_default_interface_no_interface(self): checker = checks.LeapNetworkChecker() @@ -134,6 +138,40 @@ class LeapNetworkCheckTest(BaseLeapTest): mock_ping.side_effect = exceptions.NoConnectionToGateway checker.check_internet_connection() + def test_parse_log_and_react(self): + checker = checks.LeapNetworkChecker() + to_call = Mock() + log = [("leap.openvpn - INFO - Mon Nov 19 13:36:24 2012 " + "read UDPv4 [ECONNREFUSED]: Connection refused (code=111)"] + err_matrix = [(checks.EVENT_CONNECT_REFUSED, (to_call, ))] + checker.parse_log_and_react(log, err_matrix) + self.assertTrue(to_call.called) + + log = [("2012-11-19 13:36:26,177 - leap.openvpn - INFO - " + "Mon Nov 19 13:36:24 2012 ERROR: Linux route delete command " + "failed: external program exited"), + ("2012-11-19 13:36:26,178 - leap.openvpn - INFO - " + "Mon Nov 19 13:36:24 2012 ERROR: Linux route delete command " + "failed: external program exited"), + ("2012-11-19 13:36:26,180 - leap.openvpn - INFO - " + "Mon Nov 19 13:36:24 2012 ERROR: Linux route delete command " + "failed: external program exited"), + ("2012-11-19 13:36:26,181 - leap.openvpn - INFO - " + "Mon Nov 19 13:36:24 2012 /sbin/ifconfig tun0 0.0.0.0"), + ("2012-11-19 13:36:26,182 - leap.openvpn - INFO - " + "Mon Nov 19 13:36:24 2012 Linux ip addr del failed: external " + "program exited with error stat"), + ("2012-11-19 13:36:26,183 - leap.openvpn - INFO - " + "Mon Nov 19 13:36:26 2012 SIGTERM[hard,] received, process" + "exiting"), ] + to_call.reset_mock() + checker.parse_log_and_react(log, err_matrix) + self.assertFalse(to_call.called) + + to_call.reset_mock() + checker.parse_log_and_react([], err_matrix) + self.assertFalse(to_call.called) + @unittest.skipUnless(_uid == 0, "root only") def test_ping_gateway(self): checker = checks.LeapNetworkChecker() -- cgit v1.2.3 From 8139b39dedc3dc99d310d082f6edb10d2303a1ce Mon Sep 17 00:00:00 2001 From: antialias Date: Wed, 21 Nov 2012 11:06:19 -0800 Subject: added if callable sanity check. --- src/leap/base/checks.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/leap/base') diff --git a/src/leap/base/checks.py b/src/leap/base/checks.py index 587012fb..e5767018 100644 --- a/src/leap/base/checks.py +++ b/src/leap/base/checks.py @@ -152,8 +152,10 @@ class LeapNetworkChecker(object): @type error_matrix: tuples strings and call backs """ for line in log: + # we could compile a regex here to save some cycles up -- kali for each in error_matrix: error, callbacks = each if error in line: for cb in callbacks: - cb() + if callable(cb): + cb() -- cgit v1.2.3 From bf39c45eddc62733fdb72b4f46cdb81ec649cb30 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 16 Jan 2013 00:58:22 +0900 Subject: handle loss of tun iface trigger only one dialog and disconnect. additional cleanup of log handling. --- src/leap/base/network.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/leap/base') diff --git a/src/leap/base/network.py b/src/leap/base/network.py index 765d8ea0..d841e692 100644 --- a/src/leap/base/network.py +++ b/src/leap/base/network.py @@ -21,8 +21,8 @@ class NetworkCheckerThread(object): connection. """ def __init__(self, *args, **kwargs): + self.status_signals = kwargs.pop('status_signals', None) - #self.watcher_cb = kwargs.pop('status_signals', None) self.error_cb = kwargs.pop( 'error_cb', lambda exc: logger.error("%s", exc.message)) @@ -48,6 +48,7 @@ class NetworkCheckerThread(object): (self.error_cb,)) def stop(self): + self.process_handle.join(timeout=0.1) self.shutdown.set() logger.debug("network checked stopped.") @@ -59,6 +60,7 @@ class NetworkCheckerThread(object): #here all the observers in fail_callbacks expect one positional argument, #which is exception so we can try by passing a lambda with logger to #check it works. + def _network_checks_thread(self, fail_callbacks): #TODO: replace this with waiting for a signal from openvpn while True: @@ -69,11 +71,15 @@ class NetworkCheckerThread(object): # XXX ??? why do we sleep here??? # aa: If the openvpn isn't up and running yet, # let's give it a moment to breath. + #logger.error('NOT DEFAULT ROUTE!----') + # Instead of this, we should flag when the + # iface IS SUPPOSED to be up imo. -- kali sleep(1) fail_observer_dict = dict((( observer, process_events(observer)) for observer in fail_callbacks)) + while not self.shutdown.is_set(): try: self.checker.check_tunnel_default_interface() @@ -83,11 +89,18 @@ class NetworkCheckerThread(object): for obs in fail_observer_dict: fail_observer_dict[obs].send(exc) sleep(ROUTE_CHECK_INTERVAL) + #reset event + # I see a problem with this. You cannot stop it, it + # resets itself forever. -- kali + + # XXX use QTimer for the recurrent triggers, + # and ditch the sleeps. + logger.debug('resetting event') self.shutdown.clear() def _launch_recurrent_network_checks(self, fail_callbacks): - #we need to wrap the fail callback in a tuple + # XXX reimplement using QTimer -- kali watcher = launch_thread( self._network_checks_thread, (fail_callbacks,)) -- cgit v1.2.3