From 8148bc9c8c113c41fcb18b397669b1f13447c653 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 6 Sep 2012 02:27:04 +0900 Subject: more generic error handler in EipConductorAppMixin documentation of the Exception Hierarchy and attributes. also a bit of general cleanup around error handling in conductor. Hopefully to be polished an abstracted to leap.base with time. not all errors are converted (and the old with_errors/ignoring errors) are still there, but we should be using this style of handlers from now on. wrapping up with this pseudo-feature for now. as we work on individual features we can mimick the exceptions that are working. --- src/leap/baseapp/eip.py | 150 +++++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 73 deletions(-) (limited to 'src/leap/baseapp/eip.py') diff --git a/src/leap/baseapp/eip.py b/src/leap/baseapp/eip.py index dd88b7f5..afdb7adc 100644 --- a/src/leap/baseapp/eip.py +++ b/src/leap/baseapp/eip.py @@ -11,8 +11,7 @@ from leap.eip.eipconnection import EIPConnection logger = logging.getLogger(name=__name__) -class EIPConductorApp(object): - # XXX EIPConductorMixin ? +class EIPConductorAppMixin(object): """ initializes an instance of EIPConnection, gathers errors, and passes status-change signals @@ -52,86 +51,90 @@ class EIPConductorApp(object): lambda: self.start_or_stopVPN()) def error_check(self): + """ + consumes the conductor error queue. + pops errors, and acts accordingly (launching user dialogs). + """ logger.debug('error check') ##################################### # XXX refactor in progress (by #504) + errq = self.conductor.error_queue while errq.qsize() != 0: logger.debug('%s errors left in conductor queue', errq.qsize()) error = errq.get() + + # redundant log, debugging the loop. logger.error('%s: %s', error.__class__.__name__, error.message) if issubclass(error.__class__, eip_exceptions.EIPClientError): - if error.critical: - logger.critical(error.message) - logger.error('quitting') - - # XXX - # check headless = False before - # launching dialog. - # (for Qt tests) - - dialog = ErrorDialog() - if getattr(error, 'usermessage', None): - message = error.usermessage - else: - message = error.message - dialog.criticalMessage(message, 'error') - else: - logger.exception(error.message) + self.handle_eip_error(error) + else: + # This is not quite working. FIXME import traceback traceback.print_exc() raise error - if self.conductor.missing_definition is True: - dialog = ErrorDialog() - dialog.criticalMessage( - 'The default ' - 'definition.json file cannot be found', - 'error') + if error.failfirst is True: + break - if self.conductor.missing_provider is True: - dialog = ErrorDialog() - dialog.criticalMessage( - 'Missing provider. Add a remote_ip entry ' - 'under section [provider] in eip.cfg', - 'error') + ############################################# + # old errors to check + # write test for them and them remove + # their corpses from here. - if self.conductor.missing_vpn_keyfile is True: - dialog = ErrorDialog() - dialog.criticalMessage( - 'Could not find the vpn keys file', - 'error') + #if self.conductor.missing_vpn_keyfile is True: + #dialog = ErrorDialog() + #dialog.criticalMessage( + #'Could not find the vpn keys file', + #'error') - # ... btw, review pending. - # os.kill of subprocess fails if we have - # some of this errors. + #if self.conductor.bad_keyfile_perms is True: + #dialog = ErrorDialog() + #dialog.criticalMessage( + #'The vpn keys file has bad permissions', + #'error') - # deprecated. - # get something alike. - #if self.conductor.bad_provider is True: + # deprecated. configchecker takes care of that. + #if self.conductor.missing_definition is True: #dialog = ErrorDialog() #dialog.criticalMessage( - #'Bad provider entry. Check that remote_ip entry ' - #'has an IP under section [provider] in eip.cfg', + #'The default ' + #'definition.json file cannot be found', #'error') - if self.conductor.bad_keyfile_perms is True: - dialog = ErrorDialog() - dialog.criticalMessage( - 'The vpn keys file has bad permissions', - 'error') + def handle_eip_error(self, error): + """ + check severity and launches + dialogs informing user about the errors. + in the future we plan to derive errors to + our log viewer. + """ - if self.conductor.missing_pkexec is True: + if getattr(error, 'usermessage', None): + message = error.usermessage + else: + message = error.message + + # XXX + # check headless = False before + # launching dialog. + # (so Qt tests can assert stuff) + + if error.critical: + logger.critical(error.message) + #critical error (non recoverable), + #we give user some info and quit. + #(critical error dialog will exit app) + ErrorDialog(errtype="critical", + msg=message, + label="critical error") + + else: dialog = ErrorDialog() - dialog.warningMessage( - 'We could not find pkexec in your ' - 'system.
Do you want to try ' - 'setuid workaround? ' - '(DOES NOTHING YET)', - 'error') + dialog.warningMessage(message, 'error') @QtCore.pyqtSlot() def statusUpdate(self): @@ -188,29 +191,30 @@ class EIPConductorApp(object): """ stub for running child process with vpn """ + if self.conductor.has_errors(): + logger.debug('not starting vpn; conductor has errors') + if self.eip_service_started is False: try: self.conductor.connect() - # XXX move this to error queue - except eip_exceptions.EIPNoCommandError: - dialog = ErrorDialog() - dialog.warningMessage( - 'No suitable openvpn command found. ' - '
(Might be a permissions problem)', - 'error') - if self.debugmode: - self.startStopButton.setText('&Disconnect') - self.eip_service_started = True - # XXX what is optimum polling interval? - # too little is overkill, too much - # will miss transition states.. + except eip_exceptions.EIPNoCommandError as exc: + self.handle_eip_error(exc) + + except Exception as err: + # raise generic exception (Bad Thing Happened?) + logger.exception(err) + else: + # no errors, so go on. + if self.debugmode: + self.startStopButton.setText('&Disconnect') + self.eip_service_started = True - # XXX decouple! (timer is init by icons class). - # should bring it here? - # to its own class? + # XXX decouple! (timer is init by icons class). + # we could bring Timer Init to this Mixin + # or to its own Mixin. + self.timer.start(constants.TIMER_MILLISECONDS) - self.timer.start(constants.TIMER_MILLISECONDS) return if self.eip_service_started is True: -- cgit v1.2.3