def log_message(self, message): """ Log message string to logfile. @param message: message string to log @type message: string """ with LogFile(level=SystemSettings()['system']['log_level'], filename=etpConst['entropylogfile'], header="[spm]") as log: log.write(message)
def logger(self): """ Return the Entropy Client Logger instance. """ with self._real_logger_lock: if self._real_logger is None: real_logger = LogFile( level=self._settings['system']['log_level'], filename=etpConst['entropylogfile'], header="[client]") const_debug_write(__name__, "Logger loaded") self._real_logger = real_logger return self._real_logger
def logger(self): """ Return the Entropy Client Logger instance. """ if self._real_logger is None: # once != None, will be always != None with self._real_logger_lock: if self._real_logger is None: self._real_logger = LogFile( level = self._settings['system']['log_level'], filename = etpConst['entropylogfile'], header = "[client]") const_debug_write(__name__, "Logger loaded") return self._real_logger
class Client(Singleton, TextInterface, LoadersMixin, CacheMixin, CalculatorsMixin, RepositoryMixin, MiscMixin, MatchMixin, NoticeBoardMixin): def init_singleton(self, indexing = True, installed_repo = None, xcache = True, user_xcache = False, repo_validation = True, url_fetcher = None, multiple_url_fetcher = None, **kwargs): """ Entropy Client Singleton interface. Your hitchhikers' guide to the Galaxy. @keyword indexing: enable metadata indexing (default is True) @type indexing: bool @keyword installed_repo: open installed packages repository? (default is True). Accepted values: True = open, False = open but consider it not available, -1 = do not even try to open @type installed_repo: bool or int @keyword xcache: enable on-disk cache (default is True) @type xcache: bool @keyword user_xcache: enable on-disk cache even for users not in the entropy group (default is False). Dangerous, could lead to cache inconsistencies. @type user_xcache: bool @keyword repo_validation: validate all the available repositories and automatically exclude the faulty ones @type repo_validation: bool @keyword url_fetcher: override default entropy.fetchers.UrlFetcher class usage. Provide your own implementation of UrlFetcher using this argument. @type url_fetcher: class or None @keyword multiple_url_fetcher: override default entropy.fetchers.MultipleUrlFetcher class usage. Provide your own implementation of MultipleUrlFetcher using this argument. """ self.__post_acquire_hook_idx = None self.__instance_destroyed = False self._repo_error_messages_cache = set() self._repodb_cache = {} self._repodb_cache_mutex = threading.RLock() self._memory_db_instances = {} self._real_installed_repository = None self._real_installed_repository_lock = threading.RLock() self._treeupdates_repos = set() self._can_run_sys_set_hooks = False const_debug_write(__name__, "debug enabled") self.safe_mode = 0 self._indexing = indexing self._repo_validation = repo_validation self._real_cacher = None self._real_cacher_lock = threading.Lock() # setup package settings (masking and other stuff) self._real_settings = None self._real_settings_lock = threading.Lock() self._real_settings_client_plg = None self._real_settings_client_plg_lock = threading.Lock() self._real_logger = None self._real_logger_lock = threading.Lock() self._real_enabled_repos = None self._real_enabled_repos_lock = threading.RLock() # class init LoadersMixin.__init__(self) self._multiple_url_fetcher = multiple_url_fetcher self._url_fetcher = url_fetcher if url_fetcher is None: self._url_fetcher = UrlFetcher if multiple_url_fetcher is None: self._multiple_url_fetcher = MultipleUrlFetcher self._do_open_installed_repo = True self._installed_repo_enable = True if installed_repo in (True, None, 1): self._installed_repo_enable = True elif installed_repo in (False, 0): self._installed_repo_enable = False elif installed_repo == -1: self._installed_repo_enable = False self._do_open_installed_repo = False self.xcache = xcache shell_xcache = os.getenv("ETP_NOCACHE") if shell_xcache: self.xcache = False # now if we are on live, we should disable it # are we running on a livecd? (/proc/cmdline has "cdroot") if entropy.tools.islive(): self.xcache = False elif (not entropy.tools.is_user_in_entropy_group()) and not user_xcache: self.xcache = False # Add Entropy Resources Lock post-acquire hook that cleans # repository caches. hook_ref = EntropyResourcesLock.add_post_acquire_hook( self._resources_post_hook) self.__post_acquire_hook_idx = hook_ref # enable System Settings hooks self._can_run_sys_set_hooks = True const_debug_write(__name__, "singleton loaded") @property def _settings(self): """ Return a SystemSettings object instance. """ if self._real_settings is None: # once != None, will be always != None with self._real_settings_lock: if self._real_settings is None: self._real_settings = SystemSettings() const_debug_write(__name__, "SystemSettings loaded") # add our SystemSettings plugin # Make sure we connect Entropy Client plugin # AFTER client db init self._real_settings.add_plugin( self._settings_client_plugin) return self._real_settings @property def _settings_client_plugin(self): """ Return the SystemSettings Entropy Client plugin. """ if self._real_settings_client_plg is None: # once != None, will be always != None with self._real_settings_client_plg_lock: if self._real_settings_client_plg is None: plugin = ClientSystemSettingsPlugin(self) self._real_settings_client_plg = plugin return self._real_settings_client_plg @property def _cacher(self): """ Return an EntropyCacher object instance. """ if self._real_cacher is None: # once != None, will be always != None with self._real_cacher_lock: if self._real_cacher is None: self._real_cacher = EntropyCacher() const_debug_write(__name__, "EntropyCacher loaded") # needs to be started here otherwise repository # cache will be always dropped if self.xcache: self._real_cacher.start() else: # disable STASHING_CACHE or we leak EntropyCacher.STASHING_CACHE = False return self._real_cacher @property def logger(self): """ Return the Entropy Client Logger instance. """ if self._real_logger is None: # once != None, will be always != None with self._real_logger_lock: if self._real_logger is None: self._real_logger = LogFile( level = self._settings['system']['log_level'], filename = etpConst['entropylogfile'], header = "[client]") const_debug_write(__name__, "Logger loaded") return self._real_logger @property def _enabled_repos(self): if self._real_enabled_repos is None: with self._real_enabled_repos_lock: if self._real_enabled_repos is None: self._real_enabled_repos = [] if self._repo_validation: self._validate_repositories( enabled_repos = self._real_enabled_repos) else: self._real_enabled_repos.extend( self._settings['repositories']['order']) return self._real_enabled_repos def _resources_post_hook(self): """ Hook running after Entropy Resources Lock acquisition. This method takes care of the repository memory caches, by invalidating it. """ with self._real_installed_repository_lock: if self._real_installed_repository is not None: self._real_installed_repository.clearCache() with self._repodb_cache_mutex: for repo in self._repodb_cache.values(): repo.clearCache() def destroy(self, _from_shutdown = False): """ Destroy this Singleton instance, closing repositories, removing SystemSettings plugins added during instance initialization. This method should be always called when instance is not used anymore. """ self.__instance_destroyed = True if self.__post_acquire_hook_idx is not None: EntropyResourcesLock.remove_post_acquire_hook( self.__post_acquire_hook_idx) self.__post_acquire_hook_idx = None if hasattr(self, '_installed_repository'): inst_repo = self.installed_repository() if inst_repo is not None: inst_repo.close(_token = InstalledPackagesRepository.NAME) if hasattr(self, '_real_logger_lock'): with self._real_logger_lock: if self._real_logger is not None: self._real_logger.close() if not _from_shutdown: if hasattr(self, '_real_settings') and \ hasattr(self._real_settings, 'remove_plugin'): # shutdown() will terminate the whole process # so there is no need to remove plugins from # SystemSettings, it wouldn't make any diff. if self._real_settings is not None: try: self._real_settings.remove_plugin( ClientSystemSettingsPlugin.ID) except KeyError: pass self.close_repositories(mask_clear = False) def shutdown(self): """ This method should be called when the whole process is going to be killed. It calls destroy() and stops any running thread """ self._cacher.sync() # enforce, destroy() may kill the current content self.destroy(_from_shutdown = True) self._cacher.stop() entropy.tools.kill_threads() def repository_packages_spm_sync(self, repository_identifier, repo_db, force = False): """ Service method used to sync package names with Source Package Manager via metadata stored in Repository dbs collected at server-time. Source Package Manager can change package names, categories or slot and Entropy repositories must be kept in sync. In other words, it checks for /usr/portage/profiles/updates changes, of course indirectly, since there is no way entropy.client can directly depend on Portage. @param repository_identifier: repository identifier which repo_db parameter is bound @type repository_identifier: string @param repo_db: repository database instance @type repo_db: entropy.db.EntropyRepository @return: bool stating if changes have been made @rtype: bool """ inst_repo = self.installed_repository() if not inst_repo: # nothing to do if client db is not availabe return False self._treeupdates_repos.add(repository_identifier) do_rescan = False shell_rescan = os.getenv("ETP_TREEUPDATES_RESCAN") if shell_rescan: do_rescan = True # check database digest stored_digest = repo_db.retrieveRepositoryUpdatesDigest( repository_identifier) if stored_digest == -1: do_rescan = True # check stored value in client database client_digest = "0" if not do_rescan: client_digest = \ inst_repo.retrieveRepositoryUpdatesDigest( repository_identifier) if do_rescan or (str(stored_digest) != str(client_digest)) or force: # reset database tables inst_repo.clearTreeupdatesEntries( repository_identifier) # load updates update_actions = repo_db.retrieveTreeUpdatesActions( repository_identifier) # now filter the required actions update_actions = inst_repo.filterTreeUpdatesActions( update_actions) if update_actions: mytxt = "%s: %s." % ( bold(_("ATTENTION")), red(_("forcing packages metadata update")), ) self.output( mytxt, importance = 1, level = "info", header = darkred(" * ") ) mytxt = "%s %s." % ( red(_("Updating system database using repository")), blue(repository_identifier), ) self.output( mytxt, importance = 1, level = "info", header = darkred(" * ") ) # run stuff inst_repo.runTreeUpdatesActions( update_actions) # store new digest into database inst_repo.setRepositoryUpdatesDigest( repository_identifier, stored_digest) # store new actions inst_repo.addRepositoryUpdatesActions( InstalledPackagesRepository.NAME, update_actions, self._settings['repositories']['branch']) inst_repo.commit() # clear client cache inst_repo.clearCache() return True def is_destroyed(self): return self.__instance_destroyed
def init_singleton(self, indexing = True, installed_repo = None, xcache = True, user_xcache = False, repo_validation = True, url_fetcher = None, multiple_url_fetcher = None, **kwargs): """ Entropy Client Singleton interface. Your hitchhikers' guide to the Galaxy. @keyword indexing: enable metadata indexing (default is True) @type indexing: bool @keyword installed_repo: open installed packages repository? (default is True). Accepted values: True = open, False = open but consider it not available, -1 = do not even try to open @type installed_repo: bool or int @keyword xcache: enable on-disk cache (default is True) @type xcache: bool @keyword user_xcache: enable on-disk cache even for users not in the entropy group (default is False). Dangerous, could lead to cache inconsistencies. @type user_xcache: bool @keyword repo_validation: validate all the available repositories and automatically exclude the faulty ones @type repo_validation: bool @keyword url_fetcher: override default entropy.fetchers.UrlFetcher class usage. Provide your own implementation of UrlFetcher using this argument. @type url_fetcher: class or None @keyword multiple_url_fetcher: override default entropy.fetchers.MultipleUrlFetcher class usage. Provide your own implementation of MultipleUrlFetcher using this argument. """ self.__instance_destroyed = False self._repo_error_messages_cache = set() self._repodb_cache = {} self._repodb_cache_mutex = threading.RLock() self._memory_db_instances = {} self._installed_repository = None self._treeupdates_repos = set() self._can_run_sys_set_hooks = False const_debug_write(__name__, "debug enabled") self.sys_settings_client_plugin_id = \ etpConst['system_settings_plugins_ids']['client_plugin'] self._enabled_repos = [] self.safe_mode = 0 self._indexing = indexing self._repo_validation = repo_validation # setup package settings (masking and other stuff) self._settings = SystemSettings() const_debug_write(__name__, "SystemSettings loaded") # class init LoadersMixin.__init__(self) self.logger = LogFile( level = self._settings['system']['log_level'], filename = etpConst['entropylogfile'], header = "[client]") self._multiple_url_fetcher = multiple_url_fetcher self._url_fetcher = url_fetcher if url_fetcher is None: self._url_fetcher = UrlFetcher if multiple_url_fetcher is None: self._multiple_url_fetcher = MultipleUrlFetcher self._cacher = EntropyCacher() # backward compatibility, will be removed after 2011 if "noclientdb" in kwargs: noclientdb = kwargs.get("noclientdb") self._do_open_installed_repo = True self._installed_repo_enable = True if noclientdb in (True, 1): self._installed_repo_enable = False elif noclientdb in (False, 0): self._installed_repo_enable = True elif noclientdb == 2: self._installed_repo_enable = False self._do_open_installed_repo = False else: self._do_open_installed_repo = True self._installed_repo_enable = True if installed_repo in (True, None, 1): self._installed_repo_enable = True elif installed_repo in (False, 0): self._installed_repo_enable = False elif installed_repo == -1: self._installed_repo_enable = False self._do_open_installed_repo = False self.xcache = xcache shell_xcache = os.getenv("ETP_NOCACHE") if shell_xcache: self.xcache = False do_validate_repo_cache = False # now if we are on live, we should disable it # are we running on a livecd? (/proc/cmdline has "cdroot") if entropy.tools.islive(): self.xcache = False elif (not entropy.tools.is_user_in_entropy_group()) and not user_xcache: self.xcache = False elif not user_xcache: do_validate_repo_cache = True if not self.xcache and (entropy.tools.is_user_in_entropy_group()): self.clear_cache() if self._do_open_installed_repo: self._open_installed_repository() # create our SystemSettings plugin self.sys_settings_client_plugin = ClientSystemSettingsPlugin( self.sys_settings_client_plugin_id, self) # needs to be started here otherwise repository cache will be # always dropped if self.xcache: self._cacher.start() else: # disable STASHING_CACHE or we leak EntropyCacher.STASHING_CACHE = False if do_validate_repo_cache: self._validate_repositories_cache() if self._repo_validation: self._validate_repositories() else: self._enabled_repos.extend(self._settings['repositories']['order']) # add our SystemSettings plugin # Make sure we connect Entropy Client plugin AFTER client db init self._settings.add_plugin(self.sys_settings_client_plugin) # enable System Settings hooks self._can_run_sys_set_hooks = True const_debug_write(__name__, "singleton loaded")