def _check_for_updates(self): """Check if an update for FileRock is available. If a new a client version is found, user is prompted to download and install the upgrade. """ # Never check for updates when running from source if RUNNING_FROM_SOURCE: self.logger.debug( u"Skipping update procedures (client is running from sources)") return # Get updater class for current platform (win32/darwin/linux2) try: updater = PlatformUpdater( self.cfg.get('Application Paths', 'temp_dir'), self.cfg.get('Application Paths', 'webserver_ca_chain')) # Note: this should never happen except UpdateRequestedFromTrunkClient as e: self.logger.debug( u"Skipping update procedures (running from trunk)") return except UnsupportedPlatformException as e: self.logger.warning(u"%s" % e) return # Updater failed to fetch latest version info (just log a warning) except ClientUpdateInfoRetrievingException as e: self.logger.warning(u"Error reading client update info: %s" % e) return # If client version is obsolete, prompt user to install updates if updater.is_client_version_obsolete(): last_version = updater.get_latest_version_available() self.logger.info( u"Current client version (%s) is obsolete, latest is %s" % (CURRENT_CLIENT_VERSION, last_version)) if self.cfg.get(u"User Defined Options", "auto_update") == u'True': user_choice = True else: # If cfg param 'auto_update' is off, prompt user to perform update user_choice = updater.prompt_user_for_update( self._ui_controller) if user_choice: raise UpdateRequestedException() elif updater.is_update_mandatory(): raise MandatoryUpdateDeniedException() else: # Remove update data updater.flush_update_file()
def _check_for_updates(self): """Check if an update for FileRock is available. If a new a client version is found, user is prompted to download and install the upgrade. """ # Never check for updates when running from source if RUNNING_FROM_SOURCE: self.logger.debug(u"Skipping update procedures (client is running from sources)") return # Get updater class for current platform (win32/darwin/linux2) try: updater = PlatformUpdater( self.cfg.get('Application Paths', 'temp_dir'), self.cfg.get('Application Paths', 'webserver_ca_chain')) # Note: this should never happen except UpdateRequestedFromTrunkClient as e: self.logger.debug(u"Skipping update procedures (running from trunk)") return except UnsupportedPlatformException as e: self.logger.warning(u"%s" % e) return # Updater failed to fetch latest version info (just log a warning) except ClientUpdateInfoRetrievingException as e: self.logger.warning(u"Error reading client update info: %s" % e) return # If client version is obsolete, prompt user to install updates if updater.is_client_version_obsolete(): last_version = updater.get_latest_version_available() self.logger.info( u"Current client version (%s) is obsolete, latest is %s" % (CURRENT_CLIENT_VERSION, last_version)) if self.cfg.get(u"User Defined Options", "auto_update") == u'True': user_choice = True else: # If cfg param 'auto_update' is off, prompt user to perform update user_choice = updater.prompt_user_for_update(self._ui_controller) if user_choice: raise UpdateRequestedException() elif updater.is_update_mandatory(): raise MandatoryUpdateDeniedException() else: # Remove update data updater.flush_update_file()
def main_loop(self): """ The never-ending loop where the main thread runs, listening for termination events. Calling this method means actually starting FileRock. Each iteration of the loop implies a re-initialization of some part of the application: just the core, the UI as well, the whole OS process, etc. Most of the time the thread sleeps, waiting for a command in the input queue, in a blocking fashion. """ logging_helper = LoggerManager() logger = self._get_logger(logging_helper) self.logger = logger cfg = ConfigManager(self.configdir) cfg.load() self._lockfile = self._check_unique_instance_running(cfg, logger) if not self._lockfile: self._open_warebox_folder(cfg) return self._save_process_pid() running = True skip_ui_creation = False command_queue = Queue.Queue() file_handler = None oldhook = None last_reset_time = datetime.datetime.now() - datetime.timedelta(days=1) if self.restartcount > 0: self.startupslides = False self.showpanel = False if self.restartcount >= MAX_NUMBER_OF_RESTART: self.restartcount = 0 self._pause_client(True) def sigterm_handler(sig, sframe): command_queue.put('TERMINATE') def sigabrt_handler(sig, sframe): command_queue.put('HARD_RESET') signal.signal(signal.SIGTERM, sigterm_handler) signal.signal(signal.SIGABRT, sigabrt_handler) while running: cfg.load() self._reload_connection_proxy_settings(cfg, logger) file_handler = self._configure_file_logging(logger, logging_helper, file_handler, cfg.get_config_dir()) logger.debug("Current configuration:\n%s" % cfg) core = Core(cfg, self.startupslides, self.showpanel, command_queue, self.cmdline_args, self._lockfile.fileno(), self.auto_start, self.restart_after_minute) # In case of SOFT_RESET startupslides and panel # should not be shown self.startupslides = False self.showpanel = False logger.debug("Command line arguments: %r" % self.cmdline_args) bug_reporter, oldhook = self._setup_bug_reporting( core, cfg, logging_helper, command_queue) try: self._setup_user_interfaces(core, logger, logging_helper, cfg, skip_ui_creation) skip_ui_creation = False self.auto_start = True # Let the magic begin core.start_service() # Listen for termination commands from other threads while True: try: # Note: the actual blocking get cannot be interrupted # by signals, e.g. by pressing Ctrl-C, so we use the # timeout version with a very large timeout value. command = command_queue.get(True, 999999) except Queue.Empty: continue if command == 'TERMINATE': logger.debug('Executing command TERMINATE...') self._terminate(core, logger) running = False logger.debug('Command TERMINATE executed.') break elif command == 'START': logger.debug('Executing command START...') self.restart_after_minute = -1 core.connect() logger.debug('Command START executed.') elif command == 'PAUSE': logger.debug('Executing command PAUSE...') self._terminate(core, logger, terminate_ui=False) core.unschedule_start() skip_ui_creation = True self._pause_client() logger.debug('Command PAUSE executed.') break elif command == 'PAUSE_AND_RESTART': logger.debug('Executing command PAUSE AND RESTART...') self._terminate(core, logger, terminate_ui=False) skip_ui_creation = True self._pause_client(schedule_a_start=True) logger.debug('Command PAUSE AND RESTART executed.') break elif command == 'RESET_PAUSE_TIMER': logger.debug('Resetting waiting after reset') self.restart_after_minute = -1 elif command == 'SOFT_RESET': logger.debug('Executing command SOFT_RESET...') self._terminate(core, logger, terminate_ui=False) skip_ui_creation = True logger.debug('Command SOFT_RESET executed.') break elif command == 'FULL_RESET': running = self._full_reset( core, logger, last_reset_time) last_reset_time = datetime.datetime.now() break elif command == 'HARD_RESET': logger.debug('Executing command HARD_RESET...') self._terminate(core, logger) exc = None try: # Note: this call doesn't return self._hard_reset(logger) except Exception as e: exc = e logger.critical('Error while hard resetting: %r' % exc) os._exit(1) else: logger.error( 'Application is unable to handle ' 'command %s. Forcing termination...' % command) raise UnknownCommandError(command) except KeyboardInterrupt: # Ctrl-C is equivalent to the TERMINATE command self._terminate(core, logger) running = False except LogOutRequiredException: logger.info(u"Logout is required to continue, shutting down..") self._terminate(core, logger) running = False except MandatoryUpdateDeniedException: logger.info(u"User denied a mandatory update, shutting down...") self._terminate(core, logger) running = False except UpdateRequestedException: # TODO: this will be replaced by an UPDATE command logger.info(u"Client is going to be updated, shutting down") self._terminate(core, logger) self._close_lockfile() logger.info(u"Starting update procedure...") try: updater = PlatformUpdater( cfg.get_config_dir(), cfg.get('Application Paths', 'webserver_ca_chain')) updater.execute_update() except UpdateProcedureException as e: logger.error(u"Update procedure error: %s" % e) except Exception: # The main thread shouldn't rely on automatic bug reporting, # she must handle her own exceptions or nobody will be there to # terminate the application at the end! bug_reporter.on_exception(*sys.exc_info()) running = self._full_reset(core, logger, last_reset_time) last_reset_time = datetime.datetime.now() if oldhook: sys.excepthook = oldhook logger.info(u"Shut down. Goodbye.")
def main_loop(self): """ The never-ending loop where the main thread runs, listening for termination events. Calling this method means actually starting FileRock. Each iteration of the loop implies a re-initialization of some part of the application: just the core, the UI as well, the whole OS process, etc. Most of the time the thread sleeps, waiting for a command in the input queue, in a blocking fashion. """ logging_helper = LoggerManager() logger = self._get_logger(logging_helper) self.logger = logger cfg = ConfigManager(self.configdir) cfg.load() self._lockfile = self._check_unique_instance_running(cfg, logger) if not self._lockfile: self._open_warebox_folder(cfg) return self._save_process_pid() running = True skip_ui_creation = False command_queue = Queue.Queue() file_handler = None oldhook = None last_reset_time = datetime.datetime.now() - datetime.timedelta(days=1) if self.restartcount > 0: self.startupslides = False self.showpanel = False if self.restartcount >= MAX_NUMBER_OF_RESTART: self.restartcount = 0 self._pause_client(True) def sigterm_handler(sig, sframe): command_queue.put('TERMINATE') def sigabrt_handler(sig, sframe): command_queue.put('HARD_RESET') signal.signal(signal.SIGTERM, sigterm_handler) signal.signal(signal.SIGABRT, sigabrt_handler) while running: cfg.load() self._reload_connection_proxy_settings(cfg, logger) file_handler = self._configure_file_logging( logger, logging_helper, file_handler, cfg.get_config_dir()) logger.debug("Current configuration:\n%s" % cfg) core = Core(cfg, self.startupslides, self.showpanel, command_queue, self.cmdline_args, self._lockfile.fileno(), self.auto_start, self.restart_after_minute) # In case of SOFT_RESET startupslides and panel # should not be shown self.startupslides = False self.showpanel = False logger.debug("Command line arguments: %r" % self.cmdline_args) bug_reporter, oldhook = self._setup_bug_reporting( core, cfg, logging_helper, command_queue) try: self._setup_user_interfaces(core, logger, logging_helper, cfg, skip_ui_creation) skip_ui_creation = False self.auto_start = True # Let the magic begin core.start_service() # Listen for termination commands from other threads while True: try: # Note: the actual blocking get cannot be interrupted # by signals, e.g. by pressing Ctrl-C, so we use the # timeout version with a very large timeout value. command = command_queue.get(True, 999999) except Queue.Empty: continue if command == 'TERMINATE': logger.debug('Executing command TERMINATE...') self._terminate(core, logger) running = False logger.debug('Command TERMINATE executed.') break elif command == 'START': logger.debug('Executing command START...') self.restart_after_minute = -1 core.connect() logger.debug('Command START executed.') elif command == 'PAUSE': logger.debug('Executing command PAUSE...') self._terminate(core, logger, terminate_ui=False) core.unschedule_start() skip_ui_creation = True self._pause_client() logger.debug('Command PAUSE executed.') break elif command == 'PAUSE_AND_RESTART': logger.debug('Executing command PAUSE AND RESTART...') self._terminate(core, logger, terminate_ui=False) skip_ui_creation = True self._pause_client(schedule_a_start=True) logger.debug('Command PAUSE AND RESTART executed.') break elif command == 'RESET_PAUSE_TIMER': logger.debug('Resetting waiting after reset') self.restart_after_minute = -1 elif command == 'SOFT_RESET': logger.debug('Executing command SOFT_RESET...') self._terminate(core, logger, terminate_ui=False) skip_ui_creation = True logger.debug('Command SOFT_RESET executed.') break elif command == 'FULL_RESET': running = self._full_reset(core, logger, last_reset_time) last_reset_time = datetime.datetime.now() break elif command == 'HARD_RESET': logger.debug('Executing command HARD_RESET...') self._terminate(core, logger) exc = None try: # Note: this call doesn't return self._hard_reset(logger) except Exception as e: exc = e logger.critical('Error while hard resetting: %r' % exc) os._exit(1) else: logger.error('Application is unable to handle ' 'command %s. Forcing termination...' % command) raise UnknownCommandError(command) except KeyboardInterrupt: # Ctrl-C is equivalent to the TERMINATE command self._terminate(core, logger) running = False except LogOutRequiredException: logger.info(u"Logout is required to continue, shutting down..") self._terminate(core, logger) running = False except MandatoryUpdateDeniedException: logger.info( u"User denied a mandatory update, shutting down...") self._terminate(core, logger) running = False except UpdateRequestedException: # TODO: this will be replaced by an UPDATE command logger.info(u"Client is going to be updated, shutting down") self._terminate(core, logger) self._close_lockfile() logger.info(u"Starting update procedure...") try: updater = PlatformUpdater( cfg.get_config_dir(), cfg.get('Application Paths', 'webserver_ca_chain')) updater.execute_update() except UpdateProcedureException as e: logger.error(u"Update procedure error: %s" % e) except Exception: # The main thread shouldn't rely on automatic bug reporting, # she must handle her own exceptions or nobody will be there to # terminate the application at the end! bug_reporter.on_exception(*sys.exc_info()) running = self._full_reset(core, logger, last_reset_time) last_reset_time = datetime.datetime.now() if oldhook: sys.excepthook = oldhook logger.info(u"Shut down. Goodbye.")