diff options
Diffstat (limited to 'src/leap/base')
| -rw-r--r-- | src/leap/base/checks.py | 23 | ||||
| -rw-r--r-- | src/leap/base/network.py | 17 | ||||
| -rw-r--r-- | src/leap/base/tests/test_checks.py | 38 | 
3 files changed, 76 insertions, 2 deletions
diff --git a/src/leap/base/checks.py b/src/leap/base/checks.py index 4d4a5d8b..e5767018 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,21 @@ 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: +            # 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: +                        if callable(cb): +                            cb() 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,)) 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()  | 
