Пример #1
0
    def _settings(self):
        """
        Return a SystemSettings object instance.
        """
        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
Пример #2
0
    def __init__(self, repository_id):
        """
        object constructor, repository_id must be a valid repository
        identifier.

        @param repository_id: valid repository identifier
        @type repository_id: string
        """
        super(UGCErrorReport, self).__init__("#fake#")

        self.__system_settings = SystemSettings()
        self._entropy = Client()
        if repository_id not in self.__system_settings['repositories']['order']:
            raise AttributeError('invalid repository_id provided')
        self.__repository_id = repository_id

        self._factory = self._entropy.WebServices()
        try:
            self._webserv = self._factory.new(self.__repository_id)
        except WebService.UnsupportedService:
            raise AttributeError('Web Services not supported by %s' % (
                self.__repository_id,))

        try:
            available = self._webserv.service_available()
        except WebService.WebServiceException:
            available = False

        if not available:
            raise AttributeError('Web Services not supported by %s (2)' % (
                self.__repository_id,))
Пример #3
0
 def _settings(self):
     """
     Get SystemSettings instance
     """
     if self.__settings is None:
         self.__settings = SystemSettings()
     return self.__settings
Пример #4
0
 def _ensure_package_sets_dir():
     sets_dir = SystemSettings.packages_sets_directory()
     if not os.path.isdir(sets_dir):
         if os.path.lexists(sets_dir):
             os.remove(sets_dir)
         os.makedirs(sets_dir, 0o775)
         const_setup_perms(sets_dir, etpConst['entropygid'],
             recursion = False)
Пример #5
0
 def _ensure_package_sets_dir():
     sets_dir = SystemSettings.packages_sets_directory()
     if not os.path.isdir(sets_dir):
         if os.path.lexists(sets_dir):
             os.remove(sets_dir)
         os.makedirs(sets_dir, 0o775)
         const_setup_perms(sets_dir, etpConst['entropygid'],
             recursion = False)
Пример #6
0
    def __init__(self, repository_id):
        """
        Object constructor.

        @param repository_id: the repository identifier
        @type repository_id: string
        """
        self._repository_id = repository_id
        self._settings = SystemSettings()
Пример #7
0
    def update_entropy_repositories(self):

        progressQ.send_message(_("Downloading software repositories..."))

        settings = SystemSettings()
        chroot = ROOT_PATH
        root = etpSys['rootdir']
        if chroot != root:
            self._change_entropy_chroot(chroot)

        repos = list(settings['repositories']['available'].keys())

        try:
            # fetch_security = False => avoid spamming stdout
            try:
                repo_intf = self._backend.entropy.Repositories(
                    repos, fetch_security=False)
            except AttributeError as err:
                log.error("No repositories in repositories.conf")
                return False
            except Exception as err:
                log.error("Unhandled exception: %s" % (err, ))
                return False

            try:
                update_rc = repo_intf.sync()
            except Exception as err:
                log.error("Sync error: %s" % (err, ))
                return False

            if repo_intf.sync_errors or (update_rc != 0):
                log.error("Cannot download repositories atm")
                return False

            return update_rc == 0

        finally:

            self._backend.entropy.close_repositories()
            settings.clear()
            if chroot != root:
                self._change_entropy_chroot(root)
Пример #8
0
    def update_entropy_repositories(self):

        progressQ.send_message(_("Downloading software repositories..."))

        settings = SystemSettings()
        chroot = ROOT_PATH
        root = etpSys['rootdir']
        if chroot != root:
            self._change_entropy_chroot(chroot)

        repos = list(settings['repositories']['available'].keys())

        try:
            # fetch_security = False => avoid spamming stdout
            try:
                repo_intf = self._backend.entropy.Repositories(
                    repos, fetch_security=False)
            except AttributeError as err:
                log.error("No repositories in repositories.conf")
                return False
            except Exception as err:
                log.error("Unhandled exception: %s" % (err,))
                return False

            try:
                update_rc = repo_intf.sync()
            except Exception as err:
                log.error("Sync error: %s" % (err,))
                return False

            if repo_intf.sync_errors or (update_rc != 0):
                log.error("Cannot download repositories atm")
                return False

            return update_rc == 0

        finally:

            self._backend.entropy.close_repositories()
            settings.clear()
            if chroot != root:
                self._change_entropy_chroot(root)
Пример #9
0
    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)
Пример #10
0
    def _settings(self):
        """
        Return a SystemSettings object instance.
        """
        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
Пример #11
0
    def add(self, set_name, set_atoms):
        """
        Add a user-defined package set to Entropy Client (changes are permanent)

        @param set_name: package set name
        @type set_name: string
        @param set_atoms: list of package names in given set
        @type set_atoms: list (set)
        @raise entropy.exceptions.InvalidPackageSet: if package set data
            passed is invalid (non ASCII chars, invalid set_name).
            The encapsulated error string will contain a mnemonic reason.
        """
        def _ensure_package_sets_dir():
            sets_dir = SystemSettings.packages_sets_directory()
            if not os.path.isdir(sets_dir):
                if os.path.lexists(sets_dir):
                    os.remove(sets_dir)
                os.makedirs(sets_dir, 0o775)
                const_setup_perms(sets_dir, etpConst['entropygid'],
                    recursion = False)

        if not const_isunicode(set_name):
            raise InvalidPackageSet("%s %s" % (
                set_name, "must be unicode",))

        if set_name.startswith(etpConst['packagesetprefix']):
            raise InvalidPackageSet("%s %s '%s'" % (
                set_name, "cannot start with", etpConst['packagesetprefix'],))
        set_match = self.match(set_name)
        if set_match:
            raise InvalidPackageSet(_("Name already taken"))

        _ensure_package_sets_dir()
        set_file = os.path.join(SystemSettings.packages_sets_directory(),
                                set_name)

        set_file_tmp = set_file + ".sets_add_tmp"
        enc = etpConst['conf_encoding']
        try:
            with codecs.open(set_file_tmp, "w", encoding=enc) as f:
                for x in set_atoms:
                    f.write(x)
                    f.write("\n")
            os.rename(set_file_tmp, set_file)
        except (OSError, IOError) as err:
            raise InvalidPackageSet(_("Cannot create the element"))
        self._settings['system_package_sets'][set_name] = set(set_atoms)
Пример #12
0
    def add(self, set_name, set_atoms):
        """
        Add a user-defined package set to Entropy Client (changes are permanent)

        @param set_name: package set name
        @type set_name: string
        @param set_atoms: list of package names in given set
        @type set_atoms: list (set)
        @raise entropy.exceptions.InvalidPackageSet: if package set data
            passed is invalid (non ASCII chars, invalid set_name).
            The encapsulated error string will contain a mnemonic reason.
        """
        def _ensure_package_sets_dir():
            sets_dir = SystemSettings.packages_sets_directory()
            if not os.path.isdir(sets_dir):
                if os.path.lexists(sets_dir):
                    os.remove(sets_dir)
                os.makedirs(sets_dir, 0o775)
                const_setup_perms(sets_dir, etpConst['entropygid'],
                    recursion = False)

        if not const_isunicode(set_name):
            raise InvalidPackageSet("%s %s" % (
                set_name, "must be unicode",))

        if set_name.startswith(etpConst['packagesetprefix']):
            raise InvalidPackageSet("%s %s '%s'" % (
                set_name, "cannot start with", etpConst['packagesetprefix'],))
        set_match = self.match(set_name)
        if set_match:
            raise InvalidPackageSet(_("Name already taken"))

        _ensure_package_sets_dir()
        set_file = os.path.join(SystemSettings.packages_sets_directory(),
                                set_name)

        set_file_tmp = set_file + ".sets_add_tmp"
        enc = etpConst['conf_encoding']
        try:
            with codecs.open(set_file_tmp, "w", encoding=enc) as f:
                for x in set_atoms:
                    f.write(x)
                    f.write("\n")
            os.rename(set_file_tmp, set_file)
        except (OSError, IOError) as err:
            raise InvalidPackageSet(_("Cannot create the element"))
        self._settings['system_package_sets'][set_name] = set(set_atoms)
Пример #13
0
def build_application_store_url(app, sub_page):
    """
    take rigo.models.application.Application object
    and build up HTTP Entropy Application Store URL
    pointing to exact Application page.
    sub_page is used to load a specific part of the page,
    for example "ugc" can be passed to load URL/ugc page.
    """
    settings = SystemSettings()
    details = app.get_details()
    pkg_id, pkg_repo = details.pkg
    branch = settings['repositories']['branch']
    product = settings['repositories']['product']
    url = "%s/show/%s,%s,%s,%s,%s,%s/%s" % (
        etpConst['packages_website_url'], details.pkgname, pkg_id, pkg_repo,
        etpConst['currentarch'], branch, product, sub_page)
    return url
Пример #14
0
    def _clear_resources_after_lock(self):
        """
        Clear resources that could have become stale after
        the Entropy Lock acquisition.
        """
        cacher = EntropyCacher()
        with cacher:

            SystemSettings().clear()
            cacher.discard()

            with EntropyResourcesLock._POST_ACQUIRE_HOOK_LOCK:
                callables = list(
                    EntropyResourcesLock._POST_ACQUIRE_HOOKS.values())

            for callab in callables:
                callab()

        cacher.sync()
Пример #15
0
    def __init__(self, entropy_client, repo_identifiers = None,
        force = False, fetch_security = True, gpg = True):
        """
        Entropy Client Repositories management interface constructor.

        @param entropy_client: a valid entropy.client.interfaces.client.Client
            instance
        @type entropy_client: entropy.client.interfaces.client.Client
        @keyword repo_identifiers: list of repository identifiers you want to
            take into consideration
        @type repo_identifiers: list
        @
        """

        if repo_identifiers is None:
            repo_identifiers = []
        self._entropy = entropy_client
        self._settings = SystemSettings()
        self._pkg_size_warning_th = 512*1024000 # 500mb
        repo_ids = repo_identifiers
        self.force = force
        self.sync_errors = False
        self.updated = False
        self.new_entropy = False
        self.need_packages_cleanup = False
        self.updated_repos = set()
        self.fetch_security = fetch_security
        self.already_updated = 0
        self.not_available = 0
        self._gpg_feature = gpg
        env_gpg = os.getenv('ETP_DISBLE_GPG')
        if env_gpg is not None:
            self._gpg_feature = False

        if not repo_ids:
            avail_repos = self._settings['repositories']['available'].keys()
            repo_ids.extend(list(avail_repos))
        # filter out package repositories
        self.repo_ids = self._entropy.filter_repositories(repo_ids)
Пример #16
0
    def remove(self, set_name):
        """
        Remove a user-defined package set from Entropy Client
        (changes are permanent)

        @param set_name: package set name
        @type set_name: string
        @raise entropy.exceptions.InvalidPackageSet: if package set data
            passed is invalid (non ASCII chars, invalid set_name).
            The encapsulated error string will contain a mnemonic reason.
        """
        if not const_isunicode(set_name):
            raise InvalidPackageSet("%s %s" % (
                set_name, "must be unicode",))

        if set_name.startswith(etpConst['packagesetprefix']):
            raise InvalidPackageSet("InvalidPackageSet: %s %s '%s'" % (
                set_name, _("cannot start with"),
                    etpConst['packagesetprefix'],))

        set_match = self.match(set_name)
        if not set_match:
            raise InvalidPackageSet(_("Already removed"))
        set_id, set_x, set_y = set_match

        if set_id != etpConst['userpackagesetsid']:
            raise InvalidPackageSet(_("Not defined by user"))
        set_file = os.path.join(SystemSettings.packages_sets_directory(),
                                set_name)

        try:
            os.remove(set_file)
        except OSError as err:
            if err.errno != errno.ENOENT:
                raise InvalidPackageSet(_("Set not found or unable to remove"))

        self._settings['system_package_sets'].pop(set_name, None)
Пример #17
0
    def remove(self, set_name):
        """
        Remove a user-defined package set from Entropy Client
        (changes are permanent)

        @param set_name: package set name
        @type set_name: string
        @raise entropy.exceptions.InvalidPackageSet: if package set data
            passed is invalid (non ASCII chars, invalid set_name).
            The encapsulated error string will contain a mnemonic reason.
        """
        if not const_isunicode(set_name):
            raise InvalidPackageSet("%s %s" % (
                set_name, "must be unicode",))

        if set_name.startswith(etpConst['packagesetprefix']):
            raise InvalidPackageSet("InvalidPackageSet: %s %s '%s'" % (
                set_name, _("cannot start with"),
                    etpConst['packagesetprefix'],))

        set_match = self.match(set_name)
        if not set_match:
            raise InvalidPackageSet(_("Already removed"))
        set_id, set_x, set_y = set_match

        if set_id != etpConst['userpackagesetsid']:
            raise InvalidPackageSet(_("Not defined by user"))
        set_file = os.path.join(SystemSettings.packages_sets_directory(),
                                set_name)

        try:
            os.remove(set_file)
        except OSError as err:
            if err.errno != errno.ENOENT:
                raise InvalidPackageSet(_("Set not found or unable to remove"))

        self._settings['system_package_sets'].pop(set_name, None)
Пример #18
0
 def __init__(self, entropy_client, quiet=False):
     self._quiet = quiet
     self._entropy = entropy_client
     self._settings = SystemSettings()
     dict.__init__(self)
     self._load()
Пример #19
0
class Client(Singleton, TextInterface, CalculatorsMixin, RepositoryMixin,
             MiscMixin, MatchMixin):
    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.RLock()

        # setup package settings (masking and other stuff)
        self._real_settings = None
        self._real_settings_lock = threading.RLock()

        self._real_settings_client_plg = None
        self._real_settings_client_plg_lock = threading.RLock()

        self._real_logger = None
        self._real_logger_lock = threading.RLock()

        self._real_enabled_repos = None
        self._real_enabled_repos_lock = threading.RLock()

        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.
        """
        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.
        """
        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.
        """
        with self._real_cacher_lock:

            if self._real_cacher is None:
                real_cacher = EntropyCacher()
                const_debug_write(__name__, "EntropyCacher loaded")

                # needs to be started here otherwise repository
                # cache will be always dropped
                if self.xcache:
                    real_cacher.start()
                else:
                    # disable STASHING_CACHE or we leak
                    EntropyCacher.STASHING_CACHE = False

                self._real_cacher = real_cacher

        return self._real_cacher

    @property
    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

    @property
    def _enabled_repos(self):
        with self._real_enabled_repos_lock:

            if self._real_enabled_repos is None:
                real_enabled_repos = []

                if self._repo_validation:
                    self._validate_repositories(
                        enabled_repos=real_enabled_repos)
                else:
                    real_enabled_repos.extend(
                        self._settings['repositories']['order'])

                self._real_enabled_repos = real_enabled_repos

        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()

    @sharedinstlock
    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 clear_cache(self):
        """
        Clear all the Entropy default cache directory. This function is
        fault tolerant and will never return any exception.
        """
        with self._cacher:
            # no data is written while holding self._cacher by the balls
            # drop all the buffers then remove on-disk data
            self._cacher.discard()
            # clear repositories live cache
            inst_repo = self.installed_repository()
            if inst_repo is not None:
                inst_repo.clearCache()
            with self._repodb_cache_mutex:
                for repo in self._repodb_cache.values():
                    repo.clearCache()

            cache_dir = self._cacher.current_directory()
            try:
                shutil.rmtree(cache_dir, True)
            except (shutil.Error, IOError, OSError):
                return
            try:
                os.makedirs(cache_dir, 0o775)
            except (IOError, OSError):
                return
            try:
                const_setup_perms(cache_dir, etpConst['entropygid'])
            except (IOError, OSError):
                return

    def QA(self):
        """
        Load Entropy QA interface object

        @rtype: entropy.qa.QAInterface
        """
        qa_intf = QAInterface()
        qa_intf.output = self.output
        qa_intf.ask_question = self.ask_question
        qa_intf.input_box = self.input_box
        qa_intf.set_title = self.set_title
        return qa_intf

    def Settings(self):
        """
        Return SystemSettings instance object
        """
        return self._settings

    def ClientSettings(self):
        """
        Return SystemSettings Entropy Client plugin metadata dictionary
        """
        p_id = ClientSystemSettingsPlugin.ID
        return self._settings[p_id]

    def Cacher(self):
        """
        Return EntropyCacher instance object

        @return: EntropyCacher instance object
        @rtype: entropy.cache.EntropyCacher
        """
        return self._cacher

    def PackageActionFactory(self):
        """
        Load Entropy PackageActionFactory instance object
        """
        return PackageActionFactory(self)

    def ConfigurationUpdates(self):
        """
        Return Entropy Configuration File Updates management object.
        """
        return ConfigurationUpdates(self)

    def Spm(self):
        """
        Load Source Package Manager instance object
        """
        return get_spm(self)

    def Spm_class(self):
        """
        Load Source Package Manager default plugin class
        """
        return get_spm_default_class()

    def Repositories(self, *args, **kwargs):
        """
        Load Entropy Repositories manager instance object

        @return: Repository instance object
        @rtype: entropy.client.interfaces.repository.Repository
        """
        client_data = self.ClientSettings()['misc']
        kwargs['gpg'] = client_data['gpg']
        return Repository(self, *args, **kwargs)

    def Security(self, *args, **kwargs):
        """
        Load Entropy Security Advisories interface object

        @return: Repository Security instance object
        @rtype: entropy.security.System
        """
        return System(self, *args, **kwargs)

    def RepositorySecurity(self, keystore_dir=None):
        """
        Load Entropy Repository Security interface object

        @return: Repository Repository Security instance object
        @rtype: entropy.security.Repository
        @raise RepositorySecurity.GPGError: GPGError based instances in case
            of problems.
        """
        if keystore_dir is None:
            keystore_dir = etpConst['etpclientgpgdir']
        return RepositorySecurity(keystore_dir=keystore_dir)

    def Sets(self):
        """
        Load Package Sets interface object

        @return: Sets instance object
        @rtype: entropy.client.interfaces.sets.Sets
        """
        return Sets(self)

    def WebServices(self):
        """
        Load the Entropy Web Services Factory interface, that can be used
        to obtain a WebService object that is able to communicate with
        repository remote services, if available.

        @return: WebServicesFactory instance object
        @rtype: entropy.client.services.interfaces.WebServicesFactory
        """
        return ClientWebServiceFactory(self)

    def RepositoryWebServices(self):
        """
        Load the Repository Entropy Web Services Factory interface, that can
        be used to obtain a RepositoryWebService object that is able to
        communicate with repository remote services, querying for package
        metadata and general repository status.

        @return: RepositoryWebServiceFactory instance object
        @rtype: entropy.client.services.interfaces.RepositoryWebServiceFactory
        """
        return RepositoryWebServiceFactory(self)
Пример #20
0
def handle_exception(exc_class, exc_instance, exc_tb):

    # restore original exception handler, to avoid loops
    uninstall_exception_handler()

    _text = TextInterface()

    if exc_class is SystemDatabaseError:
        _text.output(darkred(
            _("Installed packages repository corrupted. "
              "Please re-generate it")),
                     importance=1,
                     level="error")
        os._exit(101)

    generic_exc_classes = (OnlineMirrorError, RepositoryError,
                           PermissionDenied, FileNotFound, SPMError,
                           SystemError)
    if exc_class in generic_exc_classes:
        _text.output("%s: %s" % (
            exc_instance,
            darkred(_("Cannot continue")),
        ),
                     importance=1,
                     level="error")
        os._exit(1)

    if exc_class is SystemExit:
        return

    if issubclass(exc_class, IOError):  # in Python 3.3+ it's BrokenPipeError
        if exc_instance.errno == errno.EPIPE:
            return

    if exc_class is KeyboardInterrupt:
        os._exit(1)

    t_back = entropy.tools.get_traceback(tb_obj=exc_tb)
    if const_debug_enabled():
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__
        sys.stdin = sys.__stdin__
        entropy.tools.print_exception(tb_data=exc_tb)
        pdb.set_trace()

    if exc_class in (IOError, OSError):
        if exc_instance.errno == errno.ENOSPC:
            print_generic(t_back)
            _text.output("%s: %s" % (
                exc_instance,
                darkred(_("Your hard drive is full! Your fault!")),
            ),
                         importance=1,
                         level="error")
            os._exit(5)
        elif exc_instance.errno == errno.ENOMEM:
            print_generic(t_back)
            _text.output("%s: %s" % (
                exc_instance,
                darkred(_("No more memory dude! Your fault!")),
            ),
                         importance=1,
                         level="error")
            os._exit(5)

    _text.output(darkred(
        _("Hi. My name is Bug Reporter. "
          "I am sorry to inform you that the program crashed. "
          "Well, you know, shit happens.")),
                 importance=1,
                 level="error")
    _text.output(darkred(
        _("But there's something you could "
          "do to help me to be a better application.")),
                 importance=1,
                 level="error")
    _text.output(darkred(
        _("-- BUT, DO NOT SUBMIT THE SAME REPORT MORE THAN ONCE --")),
                 importance=1,
                 level="error")
    _text.output(darkred(
        _("Now I am showing you what happened. "
          "Don't panic, I'm here to help you.")),
                 importance=1,
                 level="error")

    entropy.tools.print_exception(tb_data=exc_tb)

    exception_data = entropy.tools.print_exception(silent=True,
                                                   tb_data=exc_tb,
                                                   all_frame_data=True)
    exception_tback_raw = const_convert_to_rawstring(t_back)

    error_fd, error_file = None, None
    try:
        error_fd, error_file = const_mkstemp(prefix="entropy.error.report.",
                                             suffix=".txt")

        with os.fdopen(error_fd, "wb") as ferror:
            ferror.write(
                const_convert_to_rawstring("\nRevision: %s\n\n" %
                                           (etpConst['entropyversion'], )))
            ferror.write(exception_tback_raw)
            ferror.write(const_convert_to_rawstring("\n\n"))
            ferror.write(const_convert_to_rawstring(''.join(exception_data)))
            ferror.write(const_convert_to_rawstring("\n"))

    except (OSError, IOError) as err:
        _text.output("%s: %s" %
                     (err,
                      darkred(
                          _("Oh well, I cannot even write to TMPDIR. "
                            "So, please copy the error and "
                            "mail [email protected]."))),
                     importance=1,
                     level="error")
        os._exit(1)
    finally:
        if error_fd is not None:
            try:
                os.close(error_fd)
            except OSError:
                pass

    _text.output("", level="error")

    ask_msg = _("Erm... Can I send the error, "
                "along with some other information\nabout your "
                "hardware to my creators so they can fix me? "
                "(Your IP will be logged)")
    rc = _text.ask_question(ask_msg)
    if rc == _("No"):
        _text.output(darkgreen(_("Ok, ok ok ok... Sorry!")), level="error")
        os._exit(2)

    _text.output(darkgreen(
        _("If you want to be contacted back "
          "(and actively supported), also answer "
          "the questions below:")),
                 level="error")

    try:
        name = readtext(_("Your Full name:"))
        email = readtext(_("Your E-Mail address:"))
        description = readtext(_("What you were doing:"))
    except EOFError:
        os._exit(2)

    try:
        from entropy.client.interfaces.qa import UGCErrorReport
        from entropy.core.settings.base import SystemSettings
        _settings = SystemSettings()
        repository_id = _settings['repositories']['default_repository']
        error = UGCErrorReport(repository_id)
    except (
            OnlineMirrorError,
            AttributeError,
            ImportError,
    ):
        error = None

    result = None
    if error is not None:
        error.prepare(exception_tback_raw, name, email,
                      '\n'.join([x for x in exception_data]), description)
        result = error.submit()

    if result:
        _text.output(darkgreen(
            _("Thank you very much. The error has been "
              "reported and hopefully, the problem will "
              "be solved as soon as possible.")),
                     level="error")
    else:
        _text.output(darkred(
            _("Ugh. Cannot send the report. "
              "Please mail the file below "
              "to [email protected].")),
                     level="error")
        _text.output("", level="error")
        _text.output("==> %s" % (error_file, ), level="error")
        _text.output("", level="error")
Пример #21
0
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
Пример #22
0
    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")
Пример #23
0
    def config(cls, repository_id):
        """
        Return the WebService configuration for the given repository.
        The object returned is a dictionary containing the following
        items:
          - url: the Entropy WebService base URL (or None, if not supported)
          - update_eapi: the maximum supported EAPI for repository updates.
          - repo_eapi: the maximum supported EAPI for User Generate Content.

        @param repository_id: repository identifier
        @type repository_id: string
        """
        settings = SystemSettings()
        _repository_data = settings['repositories']['available'].get(
            repository_id)
        if _repository_data is None:
            const_debug_write(__name__, "WebService.config error: no repo")
            return None

        web_services_conf = _repository_data.get('webservices_config')
        if web_services_conf is None:
            const_debug_write(__name__, "WebService.config error: no metadata")
            return None

        data = {
            'url': None,
            '_url_obj': None,
            'update_eapi': None,
            'repo_eapi': None,
        }

        content = []
        try:
            content += entropy.tools.generic_file_content_parser(
                web_services_conf, encoding=etpConst['conf_encoding'])
        except (OSError, IOError) as err:
            const_debug_write(__name__,
                              "WebService.config error: %s" % (err, ))
            return None

        if not content:
            const_debug_write(__name__,
                              "WebService.config error: empty config")
            return None

        remote_url = content.pop(0)
        if remote_url == "-":  # as per specs
            remote_url = None
        elif not remote_url:
            remote_url = None
        data['url'] = remote_url

        if data['url']:
            url_obj = entropy.tools.spliturl(data['url'])
            if url_obj.scheme in WebService.SUPPORTED_URL_SCHEMAS:
                data['_url_obj'] = url_obj
            else:
                data['url'] = None

        for line in content:
            for k in ("UPDATE_EAPI", "REPO_EAPI"):
                if line.startswith(k + "="):
                    try:
                        data[k.lower()] = int(line.split("=", 1)[-1])
                    except (IndexError, ValueError):
                        pass

        return data
Пример #24
0
 def __init__(self, entropy_client):
     self._entropy = entropy_client
     self._settings = SystemSettings()
Пример #25
0
"""

    @author: Fabio Erculiani <*****@*****.**>
    @contact: [email protected]
    @copyright: Fabio Erculiani
    @license: GPL-2

    B{Entropy Source Package Manager Plugins factory module}.

"""
from entropy.core import EntropyPluginFactory
from entropy.core.settings.base import SystemSettings
from entropy.spm.plugins.skel import SpmPlugin
import entropy.spm.plugins.interfaces as plugs

_settings = SystemSettings()
_USER_PLUG = _settings['system'].get('spm_backend')

FACTORY = EntropyPluginFactory(SpmPlugin, plugs,
    default_plugin_name = _USER_PLUG)

get_available_plugins = FACTORY.get_available_plugins

def get_default_class():
    """
    Return default Source Package Manager plugin class.

    @return: default Source Package Manager plugin class
    @raise SystemError: if no default plugin class has been specified.
        This usually means a programming error.
    """
Пример #26
0
    def __init__(self, url_path_list, checksum = True,
                 show_speed = True, resume = True,
                 abort_check_func = None, disallow_redirect = False,
                 url_fetcher_class = None, timeout = None,
                 download_context_func = None,
                 pre_download_hook = None, post_download_hook = None):
        """
        @param url_path_list: list of tuples composed by url and
            path to save, for eg. [(url,path_to_save,),...]
        @type url_path_list: list
        @keyword checksum: return md5 hash instead of status code
        @type checksum: bool
        @keyword show_speed: show download speed
        @type show_speed: bool
        @keyword resume: enable resume support
        @type resume: bool
        @keyword abort_check_func: callback used to stop download, it has to
            raise an exception that has to be caught by provider application.
            This exception will be considered an "abort" request.
        @type abort_check_func: callable
        @keyword disallow_redirect: disallow automatic HTTP redirects
        @type disallow_redirect: bool
        @keyword thread_stop_func: callback used to stop download, it has to
            raise an exception that has to be caught by provider application.
            This exception will be considered a "stop" request.
        @type thread_stop_func: callable
        @param url_fetcher_class: UrlFetcher based class to use
        @type url_fetcher_class: subclass of UrlFetcher
        @keyword timeout: custom request timeout value (in seconds), if None
            the value is read from Entropy configuration files.
        @type timeout: int
        @keyword download_context_func: if not None, it must be a function
            exposing a context manager and taking a path (the download path)
            as argument. This can be used to implement locking on files to be
            downloaded.
        @type download_context_func: callable
        @keyword pre_download_hook: hook called before starting the download
            process, inside the download_context_func context. This can be
            used to verify if the download is actually needed or just return.
            If the returned value is not None, the download method will return
            that value. The function takes a path (the download path) and the
            download id as arguments.
        @type pre_download_hook: callable
        @keyword post_download_hook: hook called after the download is complete,
            inside the download_context_func context. This can be used to verify
            the integrity of the downloaded data.
            The function takes a path (the download path) and the download
            status and the download id as arguments.
        @type post_download_hook: callable
        """
        self._progress_data = {}
        self._url_path_list = url_path_list

        self.__system_settings = SystemSettings()
        self.__resume = resume
        self.__checksum = checksum
        self.__show_speed = show_speed
        self.__abort_check_func = abort_check_func
        self.__disallow_redirect = disallow_redirect
        self.__timeout = timeout
        self.__download_context_func = download_context_func
        self.__pre_download_hook = pre_download_hook
        self.__post_download_hook = post_download_hook

        # important to have a declaration here
        self.__data_transfer = 0
        self.__average = 0
        self.__old_average = 0
        self.__time_remaining_secs = 0

        self.__url_fetcher = url_fetcher_class
        if self.__url_fetcher == None:
            self.__url_fetcher = UrlFetcher
Пример #27
0
    def __init__(self, url, path_to_save, checksum = True,
                 show_speed = True, resume = True,
                 abort_check_func = None, disallow_redirect = False,
                 thread_stop_func = None, speed_limit = None,
                 timeout = None, download_context_func = None,
                 pre_download_hook = None, post_download_hook = None):
        """
        Entropy URL downloader constructor.

        @param url: download URL (do not URL-encode it!)
        @type url: string
        @param path_to_save: file path where to save downloaded data
        @type path_to_save: string
        @keyword checksum: return md5 hash instead of status code
        @type checksum: bool
        @keyword show_speed: show download speed
        @type show_speed: bool
        @keyword resume: enable resume support
        @type resume: bool
        @keyword abort_check_func: callback used to stop download, it has to
            raise an exception that has to be caught by provider application.
            This exception will be considered an "abort" request.
        @type abort_check_func: callable
        @keyword disallow_redirect: disallow automatic HTTP redirects
        @type disallow_redirect: bool
        @keyword thread_stop_func: callback used to stop download, it has to
            raise an exception that has to be caught by provider application.
            This exception will be considered a "stop" request.
        @type thread_stop_func: callable
        @keyword speed_limit: speed limit in kb/sec
        @type speed_limit: int
        @keyword timeout: custom request timeout value (in seconds), if None
            the value is read from Entropy configuration files.
        @type timeout: int
        @keyword download_context_func: if not None, it must be a function
            exposing a context manager and taking a path (the download path)
            as argument. This can be used to implement locking on files to be
            downloaded.
        @type download_context_func: callable
        @keyword pre_download_hook: hook called before starting the download
            process, inside the download_context_func context. This can be
            used to verify if the download is actually needed or just return.
            If the returned value is not None, the download method will return
            that value. The function takes a path (the download path) and the
            download id as arguments.
        @type pre_download_hook: callable
        @keyword post_download_hook: hook called after the download is complete,
            inside the download_context_func context. This can be used to verify
            the integrity of the downloaded data.
            The function takes a path (the download path) and the download
            status and the download id as arguments.
        @type post_download_hook: callable
        """
        self.__supported_uris = {
            'file': self._urllib_download,
            'http': self._urllib_download,
            'https': self._urllib_download,
            'ftp': self._urllib_download,
            'ftps': self._urllib_download,
            'rsync': self._rsync_download,
            'ssh': self._rsync_download,
        }

        self.__system_settings = SystemSettings()
        if speed_limit == None:
            speed_limit = \
                self.__system_settings['repositories']['transfer_limit']

        if timeout is None:
            self.__timeout = \
                self.__system_settings['repositories']['timeout']
        else:
            self.__timeout = timeout
        self.__th_id = 0

        if download_context_func is None:
            @contextlib.contextmanager
            def download_context_func(path):
                yield

        self.__download_context_func = download_context_func
        self.__pre_download_hook = pre_download_hook
        self.__post_download_hook = post_download_hook

        self.__resume = resume
        self.__url = url
        self.__path_to_save = path_to_save
        self.__checksum = checksum
        self.__show_speed = show_speed
        self.__abort_check_func = abort_check_func
        self.__thread_stop_func = thread_stop_func
        self.__disallow_redirect = disallow_redirect
        self.__speedlimit = speed_limit # kbytes/sec

        self._init_vars()
        self.__init_urllib()
Пример #28
0
 def _settings(self):
     """
     Return a SystemSettings instance.
     """
     return SystemSettings()
Пример #29
0
    def __init__(self,
                 entropy_interface,
                 uris,
                 files_to_upload,
                 download=False,
                 remove=False,
                 txc_basedir=None,
                 local_basedir=None,
                 critical_files=None,
                 handlers_data=None,
                 repo=None,
                 copy_herustic_support=False):

        if critical_files is None:
            critical_files = []
        if handlers_data is None:
            handlers_data = {}

        self._entropy = entropy_interface
        if not isinstance(uris, list):
            raise AttributeError("uris must be a list instance")
        if not isinstance(files_to_upload, (list, dict)):
            raise AttributeError(
                "files_to_upload must be a list or dict instance")
        self.uris = uris
        if isinstance(files_to_upload, list):
            self.myfiles = files_to_upload[:]
        else:
            self.myfiles = sorted([x for x in files_to_upload])

        self._settings = SystemSettings()
        self.sys_settings_plugin_id = \
            etpConst['system_settings_plugins_ids']['server_plugin']
        srv_set = self._settings[self.sys_settings_plugin_id]['server']

        # server-side speed limit
        self.speed_limit = srv_set['sync_speed_limit']
        self.download = download
        self.remove = remove
        self.repo = repo
        if self.repo == None:
            self.repo = self._entropy.repository()
        if self.remove:
            self.download = False
        self._copy_herustic = copy_herustic_support
        if self._copy_herustic and (self.download or self.remove):
            raise AttributeError(
                "copy_herustic_support can be enabled only for uploads")

        if not txc_basedir:
            raise AttributeError("invalid txc_basedir passed")
        self.txc_basedir = txc_basedir

        if not local_basedir:
            # default to database directory
            self.local_basedir = os.path.dirname(
                self._entropy._get_local_repository_file(self.repo))
        else:
            self.local_basedir = local_basedir

        self.critical_files = critical_files
        self.handlers_data = handlers_data.copy()