Exemple #1
0
    def __init__(self, metadata, sources, basepath, debug=False):
        Collection.__init__(self, metadata, sources, basepath, debug=debug)
        self.keypath = os.path.join(self.basepath, "keys")

        if len(sources):
            config = sources[0].config
            self.use_yum = has_yum and config.getboolean(
                "yum", "use_yum_libraries", default=False)
        else:
            self.use_yum = False

        if self.use_yum:
            self.cachefile = os.path.join(self.cachepath,
                                          "cache-%s" % self.cachekey)
            if not os.path.exists(self.cachefile):
                os.mkdir(self.cachefile)

            self.configdir = os.path.join(self.basepath, "yum")
            if not os.path.exists(self.configdir):
                os.mkdir(self.configdir)
            self.cfgfile = os.path.join(self.configdir,
                                        "%s-yum.conf" % self.cachekey)
            self.write_config()

            self.helper = self.config.get("yum",
                                          "helper",
                                          default="/usr/sbin/bcfg2-yum-helper")
        if has_pulp:
            _setup_pulp(self.config)
Exemple #2
0
    def __init__(self, metadata, sources, basepath):
        Collection.__init__(self, metadata, sources, basepath)
        self.keypath = os.path.join(self.basepath, "keys")

        if len(sources):
            config = sources[0].config
            self.use_yum = has_yum
            try:
                self.use_yum &= config.getboolean("yum", "use_yum_libraries")
            except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
                self.use_yum = False
        else:
            self.use_yum = False

        if self.use_yum:
            self.cachefile = os.path.join(self.cachepath,
                                         "cache-%s" % self.cachekey)
            if not os.path.exists(self.cachefile):
                os.mkdir(self.cachefile)
                
            self.configdir = os.path.join(self.basepath, "yum")
            if not os.path.exists(self.configdir):
                os.mkdir(self.configdir)
            self.cfgfile = os.path.join(self.configdir,
                                        "%s-yum.conf" % self.cachekey)
            self.write_config()

            try:
                self.helper = self.config.get("yum", "helper")
            except ConfigParser.NoOptionError:
                self.helper = "/usr/sbin/bcfg2-yum-helper"
            
        if has_pulp:
            _setup_pulp(self.config)
Exemple #3
0
    def __init__(self, metadata, sources, cachepath, basepath, debug=False):
        Collection.__init__(self, metadata, sources, cachepath, basepath, debug=debug)
        self.keypath = os.path.join(self.cachepath, "keys")

        self._helper = None
        if self.use_yum:
            #: Define a unique cache file for this collection to use
            #: for cached yum metadata
            self.cachefile = os.path.join(self.cachepath, "cache-%s" % self.cachekey)
            if not os.path.exists(self.cachefile):
                os.mkdir(self.cachefile)

            #: The path to the server-side config file used when
            #: resolving packages with the Python yum libraries
            self.cfgfile = os.path.join(self.cachefile, "yum.conf")
            self.write_config()
            self.cmd = Executor()
        else:
            self.cachefile = None
            self.cmd = None

        if HAS_PULP and self.has_pulp_sources:
            _setup_pulp()
            if self.pulp_cert_set is None:
                certdir = os.path.join(self.basepath, "pulp", os.path.basename(PulpCertificateSet.certpath))
                try:
                    os.makedirs(certdir)
                except OSError:
                    err = sys.exc_info()[1]
                    if err.errno == errno.EEXIST:
                        pass
                    else:
                        self.logger.error("Could not create Pulp consumer " "cert directory at %s: %s" % (certdir, err))
                self.pulp_cert_set = PulpCertificateSet(certdir)
Exemple #4
0
    def __init__(self, metadata, sources, basepath, debug=False):
        Collection.__init__(self, metadata, sources, basepath, debug=debug)
        self.keypath = os.path.join(self.basepath, "keys")

        if len(sources):
            config = sources[0].config
            self.use_yum = has_yum and config.getboolean("yum",
                                                         "use_yum_libraries",
                                                         default=False)
        else:
            self.use_yum = False

        if self.use_yum:
            self.cachefile = os.path.join(self.cachepath,
                                         "cache-%s" % self.cachekey)
            if not os.path.exists(self.cachefile):
                os.mkdir(self.cachefile)

            self.configdir = os.path.join(self.basepath, "yum")
            if not os.path.exists(self.configdir):
                os.mkdir(self.configdir)
            self.cfgfile = os.path.join(self.configdir,
                                        "%s-yum.conf" % self.cachekey)
            self.write_config()

            self.helper = self.config.get("yum", "helper",
                                          default="/usr/sbin/bcfg2-yum-helper")
        if has_pulp:
            _setup_pulp(self.config)
Exemple #5
0
 def __init__(self, metadata, sources, cachepath, basepath, debug=False):
     # we define an __init__ that just calls the parent __init__,
     # so that we can set the docstring on __init__ to something
     # different from the parent __init__ -- namely, the parent
     # __init__ docstring, minus everything after ``.. -----``,
     # which we use to delineate the actual docs from the
     # .. autoattribute hacks we have to do to get private
     # attributes included in sphinx 1.0 """
     Collection.__init__(self, metadata, sources, cachepath, basepath, debug=debug)
Exemple #6
0
 def __init__(self, metadata, sources, cachepath, basepath, debug=False):
     # we define an __init__ that just calls the parent __init__,
     # so that we can set the docstring on __init__ to something
     # different from the parent __init__ -- namely, the parent
     # __init__ docstring, minus everything after ``.. -----``,
     # which we use to delineate the actual docs from the
     # .. autoattribute hacks we have to do to get private
     # attributes included in sphinx 1.0 """
     Collection.__init__(self, metadata, sources, cachepath, basepath,
                         debug=debug)
Exemple #7
0
    def __init__(self,
                 metadata,
                 sources,
                 cachepath,
                 basepath,
                 fam,
                 debug=False):
        Collection.__init__(self,
                            metadata,
                            sources,
                            cachepath,
                            basepath,
                            fam,
                            debug=debug)
        self.keypath = os.path.join(self.cachepath, "keys")

        if self.use_yum:
            #: Define a unique cache file for this collection to use
            #: for cached yum metadata
            self.cachefile = os.path.join(self.cachepath,
                                          "cache-%s" % self.cachekey)
            if not os.path.exists(self.cachefile):
                os.mkdir(self.cachefile)

            #: The path to the server-side config file used when
            #: resolving packages with the Python yum libraries
            self.cfgfile = os.path.join(self.cachefile, "yum.conf")
            self.write_config()
        else:
            self.cachefile = None

        if HAS_PULP and self.has_pulp_sources:
            _setup_pulp(self.setup)
            if self.pulp_cert_set is None:
                certdir = os.path.join(
                    self.basepath, "pulp",
                    os.path.basename(PulpCertificateSet.certpath))
                try:
                    os.makedirs(certdir)
                except OSError:
                    err = sys.exc_info()[1]
                    if err.errno == errno.EEXIST:
                        pass
                    else:
                        self.logger.error("Could not create Pulp consumer "
                                          "cert directory at %s: %s" %
                                          (certdir, err))
                self.pulp_cert_set = PulpCertificateSet(certdir, self.fam)

        self._helper = None
Exemple #8
0
    def __init__(self, metadata, sources, basepath, debug=False):
        Collection.__init__(self, metadata, sources, basepath, debug=debug)
        self.keypath = os.path.join(self.basepath, "keys")

        if self.use_yum:
            self.cachefile = os.path.join(self.cachepath, "cache-%s" % self.cachekey)
            if not os.path.exists(self.cachefile):
                os.mkdir(self.cachefile)

            self.cfgfile = os.path.join(self.cachefile, "yum.conf")
            self.write_config()
        if has_pulp and self.has_pulp_sources:
            _setup_pulp(self.setup)

        self._helper = None
Exemple #9
0
Fichier : Yum.py Projet : ab/bcfg2
 def get_deps(self, package):
     if not self.use_yum:
         return Collection.get_deps(self, package)
     else:
         # this should really never get called; it's just provided
         # for API completeness
         return self.call_helper("get_deps", package)
Exemple #10
0
Fichier : Yum.py Projet : ab/bcfg2
 def get_provides(self, required, all=False, silent=False):
     if not self.use_yum:
         return Collection.get_provides(self, package)
     else:
         # this should really never get called; it's just provided
         # for API completeness
         return self.call_helper("get_provides", package)
Exemple #11
0
    def setup_data(self, force_update=False):
        """ Do any collection-level data setup tasks. This is called
        when sources are loaded or reloaded by
        :class:`Bcfg2.Server.Plugins.Packages.Packages`.

        If the builtin yum parsers are in use, this defers to
        :func:`Bcfg2.Server.Plugins.Packages.Collection.Collection.setup_data`.
        If using the yum Python libraries, this cleans up cached yum
        metadata, regenerates the server-side yum config (in order to
        catch any new sources that have been added to this server),
        and then cleans up cached yum metadata again, in case the new
        config has any preexisting cache.

        :param force_update: Ignore all local cache and setup data
                             from its original upstream sources (i.e.,
                             the package repositories)
        :type force_update: bool
        """
        if not self.use_yum:
            return Collection.setup_data(self, force_update)

        if force_update:
            # we call this twice: one to clean up data from the old
            # config, and once to clean up data from the new config
            self.call_helper("clean")

        os.unlink(self.cfgfile)
        self.write_config()

        if force_update:
            self.call_helper("clean")
Exemple #12
0
    def setup_data(self, force_update=False):
        """ Do any collection-level data setup tasks. This is called
        when sources are loaded or reloaded by
        :class:`Bcfg2.Server.Plugins.Packages.Packages`.

        If the builtin yum parsers are in use, this defers to
        :func:`Bcfg2.Server.Plugins.Packages.Collection.Collection.setup_data`.
        If using the yum Python libraries, this cleans up cached yum
        metadata, regenerates the server-side yum config (in order to
        catch any new sources that have been added to this server),
        and then cleans up cached yum metadata again, in case the new
        config has any preexisting cache.

        :param force_update: Ignore all local cache and setup data
                             from its original upstream sources (i.e.,
                             the package repositories)
        :type force_update: bool
        """
        if not self.use_yum:
            return Collection.setup_data(self, force_update)

        if force_update:
            # we call this twice: one to clean up data from the old
            # config, and once to clean up data from the new config
            self.call_helper("clean")

        os.unlink(self.cfgfile)
        self.write_config()

        if force_update:
            self.call_helper("clean")
Exemple #13
0
 def is_virtual_package(self, package):
     if not self.use_yum:
         return Collection.is_virtual_package(self, package)
     else:
         # this should really never get called; it's just provided
         # for API completeness
         return self.call_helper("is_virtual_package", package)
Exemple #14
0
    def setup_data(self, force_update=False):
        if not self.use_yum:
            return Collection.setup_data(self, force_update)

        for cfile in glob.glob(os.path.join(self.configdir, "*-yum.conf")):
            os.unlink(cfile)
            self._yb = None
        
        self.pkgs_cache.clear()
        self.deps_cache.clear()
        self.vpkgs_cache.clear()
        self.group_cache.clear()
        self.pkgset_cache.clear()
        
        if force_update:
            for mdtype in ["Headers", "Packages", "Sqlite", "Metadata",
                           "ExpireCache"]:
                # for reasons that are entirely obvious, all of the
                # yum API clean* methods return a tuple of 0 (zero,
                # always zero) and a list containing a single message
                # about how many files were deleted.  so useful.
                # thanks, yum.
                self.logger.info("Packages: %s" %
                                 getattr(self.yumbase,
                                         "clean%s" % mdtype)()[1][0])
Exemple #15
0
 def get_deps(self, package):
     if not self.use_yum:
         return Collection.get_deps(self, package)
     else:
         # this should really never get called; it's just provided
         # for API completeness
         return self.call_helper("get_deps", package)
Exemple #16
0
    def get_provides(self, required, all=False, silent=False):
        if not self.use_yum:
            return Collection.get_provides(self, package)

        if not isinstance(required, tuple):
            required = (required, None, (None, None, None))

        try:
            return self.vpkgs_cache[required]
        except KeyError:
            pass
        
        try:
            prov = \
                self.yumbase.whatProvides(*required).returnNewestByNameArch()
        except yum.Errors.NoMoreMirrorsRepoError:
            err = sys.exc_info()[1]
            self.logger.error("Packages: Temporary failure loading metadata "
                              "for '%s': %s" %
                              (self.get_package_name(required),
                               err))
            self.vpkgs_cache[required] = None
            return []

        if prov and not all:
            prov = self._filter_provides(required, prov)
        elif not prov and not silent:
            self.logger.error("Packages: No package provides %s" %
                              self.get_package_name(required))
        self.vpkgs_cache[required] = prov
        return self.vpkgs_cache[required]
Exemple #17
0
 def get_provides(self, required, all=False, silent=False):
     if not self.use_yum:
         return Collection.get_provides(self, package)
     else:
         # this should really never get called; it's just provided
         # for API completeness
         return self.call_helper("get_provides", package)
Exemple #18
0
Fichier : Yum.py Projet : ab/bcfg2
 def is_virtual_package(self, package):
     if not self.use_yum:
         return Collection.is_virtual_package(self, package)
     else:
         # this should really never get called; it's just provided
         # for API completeness
         return self.call_helper("is_virtual_package", package)
Exemple #19
0
 def cachefiles(self):
     """ A list of the full path to all cachefiles used by this
     collection."""
     cachefiles = set(Collection.cachefiles(self))
     if self.cachefile:
         cachefiles.add(self.cachefile)
     return list(cachefiles)
Exemple #20
0
 def is_virtual_package(self, package):
     if self.use_yum:
         try:
             return bool(self.vpkgs_cache[package])
         except KeyError:
             return bool(self.get_provides(package, silent=True))
     else:
         return Collection.is_virtual_package(self, package)
Exemple #21
0
    def get_collection(self, metadata):
        """ Get a
        :class:`Bcfg2.Server.Plugins.Packages.Collection.Collection`
        object for this client.

        :param metadata: The client metadata to get a Collection for
        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata
        :returns: An instance of the appropriate subclass of
                  :class:`Bcfg2.Server.Plugins.Packages.Collection.Collection`
                  that contains all relevant sources that apply to the
                  given client
        """

        if not self.sources.loaded:
            # if sources.xml has not received a FAM event yet, defer;
            # instantiate a dummy Collection object
            return Collection(metadata, [], self.cachepath, self.data,
                              self.core.fam)

        if metadata.hostname in self.clients:
            return self.collections[self.clients[metadata.hostname]]

        sclasses = set()
        relevant = list()

        for source in self.sources.entries:
            if source.applies(metadata):
                relevant.append(source)
                sclasses.update([source.__class__])

        if len(sclasses) > 1:
            self.logger.warning("Packages: Multiple source types found for "
                                "%s: %s" %
                                ",".join([s.__name__ for s in sclasses]))
            cclass = Collection
        elif len(sclasses) == 0:
            self.logger.error("Packages: No sources found for %s" %
                              metadata.hostname)
            cclass = Collection
        else:
            cclass = get_collection_class(sclasses.pop().__name__.replace(
                "Source", ""))

        if self.debug_flag:
            self.logger.error("Packages: Using %s for Collection of sources "
                              "for %s" % (cclass.__name__, metadata.hostname))

        collection = cclass(metadata,
                            relevant,
                            self.cachepath,
                            self.data,
                            self.core.fam,
                            debug=self.debug_flag)
        ckey = collection.cachekey
        self.clients[metadata.hostname] = ckey
        self.collections[ckey] = collection
        return collection
Exemple #22
0
    def __init__(self, metadata, sources, basepath, debug=False):
        Collection.__init__(self, metadata, sources, basepath, debug=debug)
        self.keypath = os.path.join(self.basepath, "keys")

        if self.use_yum:
            self.cachefile = os.path.join(self.cachepath,
                                         "cache-%s" % self.cachekey)
            if not os.path.exists(self.cachefile):
                os.mkdir(self.cachefile)

            self.configdir = os.path.join(self.basepath, "yum")
            if not os.path.exists(self.configdir):
                os.mkdir(self.configdir)
            self.cfgfile = os.path.join(self.configdir,
                                        "%s-yum.conf" % self.cachekey)
            self.write_config()
        if has_pulp and self.has_pulp_sources:
            _setup_pulp(self.setup)

        self._helper = None
Exemple #23
0
 def is_package(self, package):
     if not self.use_yum:
         return Collection.is_package(self, package)
     elif isinstance(package, tuple):
         if package[1] is None and package[2] == (None, None, None):
             package = package[0]
         else:
             return None
     else:
         # this should really never get called; it's just provided
         # for API completeness
         return self.call_helper("is_package", package)
Exemple #24
0
Fichier : Yum.py Projet : ab/bcfg2
 def is_package(self, package):
     if not self.use_yum:
         return Collection.is_package(self, package)
     elif isinstance(package, tuple):
         if package[1] is None and package[2] == (None, None, None):
             package = package[0]
         else:
             return None
     else:
         # this should really never get called; it's just provided
         # for API completeness
         return self.call_helper("is_package", package)
Exemple #25
0
    def __init__(self, metadata, sources, basepath):
        Collection.__init__(self, metadata, sources, basepath)
        self.keypath = os.path.join(self.basepath, "keys")

        if len(sources):
            config = sources[0].config
            self.use_yum = has_yum
            try:
                self.use_yum &= config.getboolean("yum", "use_yum_libraries")
            except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
                self.use_yum = False
        else:
            self.use_yum = False

        if self.use_yum:
            self._yb = None
            self.cachefile = os.path.join(self.cachepath,
                                         "cache-%s" % self.cachekey)
            if not os.path.exists(self.cachefile):
                os.mkdir(self.cachefile)
                
            self.configdir = os.path.join(self.basepath, "yum")
            if not os.path.exists(self.configdir):
                os.mkdir(self.configdir)
            self.cfgfile = os.path.join(self.configdir,
                                        "%s-yum.conf" % self.cachekey)
            if self.config.has_option("yum", "metadata_expire"):
                cache_expire = self.config.getint("yum", "metadata_expire")
            else:
                cache_expire = 21600
            
            self.pkgs_cache = Cache(expiration=cache_expire)
            self.deps_cache = Cache(expiration=cache_expire)
            self.vpkgs_cache = Cache(expiration=cache_expire)
            self.group_cache = Cache(expiration=cache_expire)
            self.pkgset_cache = Cache(expiration=cache_expire)

        if has_pulp:
            _setup_pulp(self.config)
Exemple #26
0
    def __init__(self, metadata, sources, basepath, debug=False):
        Collection.__init__(self, metadata, sources, basepath, debug=debug)
        self.keypath = os.path.join(self.basepath, "keys")

        if len(sources):
            self.config = sources[0].config
        else:
            self.config = PackageConfig('Packages')

        if self.use_yum:
            self.cachefile = os.path.join(self.cachepath,
                                         "cache-%s" % self.cachekey)
            if not os.path.exists(self.cachefile):
                os.mkdir(self.cachefile)

            self.configdir = os.path.join(self.basepath, "yum")
            if not os.path.exists(self.configdir):
                os.mkdir(self.configdir)
            self.cfgfile = os.path.join(self.configdir,
                                        "%s-yum.conf" % self.cachekey)
            self.write_config()
        if has_pulp and self.has_pulp_sources:
            _setup_pulp(self.config)
Exemple #27
0
    def setup_data(self, force_update=False):
        if not self.use_yum:
            return Collection.setup_data(self, force_update)

        if force_update:
            # we call this twice: one to clean up data from the old
            # config, and once to clean up data from the new config
            self.call_helper("clean")

        os.unlink(self.cfgfile)
        self.write_config()

        if force_update:
            self.call_helper("clean")
Exemple #28
0
Fichier : Yum.py Projet : ab/bcfg2
    def setup_data(self, force_update=False):
        if not self.use_yum:
            return Collection.setup_data(self, force_update)

        if force_update:
            # we call this twice: one to clean up data from the old
            # config, and once to clean up data from the new config
            self.call_helper("clean")

        os.unlink(self.cfgfile)
        self.write_config()

        if force_update:
            self.call_helper("clean")
Exemple #29
0
    def is_package(self, package):
        if not self.use_yum:
            return Collection.is_package(self, package)

        if isinstance(package, tuple):
            if package[1] is None and package[2] == (None, None, None):
                package = package[0]
            else:
                return None

        try:
            return self.pkgs_cache[package]
        except KeyError:
            pass

        self.pkgs_cache[package] = bool(self.get_package_object(package,
                                                                silent=True))
        return self.pkgs_cache[package]
Exemple #30
0
    def complete(self, packagelist):
        if not self.use_yum:
            return Collection.complete(self, packagelist)

        packages = set()
        unknown = set(packagelist)

        if unknown:
            result = self.call_helper("complete", dict(packages=list(unknown), groups=list(self.get_relevant_groups())))
            if result and "packages" in result and "unknown" in result:
                # we stringify every package because it gets returned
                # in unicode; set.update() doesn't work if some
                # elements are unicode and other are strings.  (I.e.,
                # u'foo' and 'foo' get treated as unique elements.)
                packages.update([str(p) for p in result["packages"]])
                unknown = set([str(p) for p in result["unknown"]])

            self.filter_unknown(unknown)

        return packages, unknown
Exemple #31
0
    def get_deps(self, package):
        if not self.use_yum:
            return Collection.get_deps(self, package)

        try:
            return self.deps_cache[package]
        except KeyError:
            pass

        pkg = self.get_package_object(package)
        deps = []
        if pkg:
            deps = set(pkg.requires)
            # filter out things the package itself provides
            deps.difference_update([dep for dep in deps
                                        if pkg.checkPrco('provides', dep)])
        else:
            self.logger.error("Packages: No package available: %s" %
                              self.get_package_name(package))
        self.deps_cache[package] = deps
        return self.deps_cache[package]
Exemple #32
0
    def complete(self, packagelist):
        if not self.use_yum:
            return Collection.complete(self, packagelist)

        if packagelist:
            result = self.call_helper(
                "complete", dict(packages=list(packagelist), groups=list(self.get_relevant_groups()))
            )
            if not result:
                # some sort of error, reported by call_helper()
                return set(), packagelist
            # json doesn't understand sets or tuples, so we get back a
            # lists of lists (packages) and a list of unicode strings
            # (unknown).  turn those into a set of tuples and a set of
            # strings, respectively.
            unknown = set([str(u) for u in result["unknown"]])
            packages = set([tuple(p) for p in result["packages"]])
            self.filter_unknown(unknown)
            return packages, unknown
        else:
            return set(), set()
Exemple #33
0
    def packages_from_entry(self, entry):
        """ When using the Python yum libraries, convert a Package
        entry to a list of package tuples.  See :ref:`yum-pkg-objects`
        and :ref:`pkg-objects` for more information on this process.

        :param entry: The Package entry to convert
        :type entry: lxml.etree._Element
        :returns: list of tuples
        """
        if not self.use_yum:
            return Collection.packages_from_entry(self, entry)

        rv = set()
        name = entry.get("name")

        for inst in entry.getchildren():
            if inst.tag != "Instance":
                continue
            rv.add(self._element_to_pkg(inst, name))
        if not rv:
            rv.add(self._element_to_pkg(entry, name))
        return list(rv)
Exemple #34
0
    def complete(self, packagelist):
        """ Build a complete list of all packages and their dependencies.

        When using the Python yum libraries, this defers to the
        :ref:`bcfg2-yum-helper`; when using the builtin yum parser,
        this defers to
        :func:`Bcfg2.Server.Plugins.Packages.Collection.Collection.complete`.

        :param packagelist: Set of initial packages computed from the
                            specification.
        :type packagelist: set of strings, but see :ref:`pkg-objects`
        :returns: tuple of sets - The first element contains a set of
                  strings (but see :ref:`pkg-objects`) describing the
                  complete package list, and the second element is a
                  set of symbols whose dependencies could not be
                  resolved.
        """
        if not self.use_yum:
            return Collection.complete(self, packagelist)

        if packagelist:
            result = \
                self.call_helper("complete",
                                 dict(packages=list(packagelist),
                                      groups=list(self.get_relevant_groups())))
            if not result:
                # some sort of error, reported by call_helper()
                return set(), packagelist
            # json doesn't understand sets or tuples, so we get back a
            # lists of lists (packages) and a list of unicode strings
            # (unknown).  turn those into a set of tuples and a set of
            # strings, respectively.
            unknown = set([str(u) for u in result['unknown']])
            packages = set([tuple(p) for p in result['packages']])
            self.filter_unknown(unknown)
            return packages, unknown
        else:
            return set(), set()
Exemple #35
0
    def get_groups(self, grouplist):
        """ If using the yum libraries, given a list of package group
        names, return a dict of ``<group name>: <list of packages>``.
        This is much faster than implementing
        :func:`Bcfg2.Server.Plugins.Packages.Collection.Collection.get_group`,
        since we have to make a call to the bcfg2 Yum helper, and each
        time we do that we make another call to yum, which means we
        set up yum metadata from the cache (hopefully) each time.  So
        resolving ten groups once is much faster than resolving one
        group ten times.

        If you are using the builtin yum parser, this raises a warning
        and returns an empty dict.

        :param grouplist: The list of groups to query
        :type grouplist: list of strings - group names
        :returns: dict of ``<group name>: <list of packages>``

        In this implementation the packages may be strings or tuples.
        See :ref:`yum-pkg-objects` for more information. """
        if not grouplist:
            return dict()

        gdicts = []
        for group, ptype in grouplist:
            if group.startswith("@"):
                group = group[1:]
            if not ptype:
                ptype = "default"
            gdicts.append(dict(group=group, type=ptype))

        if self.use_yum:
            return self.call_helper("get_groups", inputdata=gdicts)
        else:
            pkgs = dict()
            for gdict in gdicts:
                pkgs[gdict["group"]] = Collection.get_group(self, gdict["group"], gdict["type"])
            return pkgs
Exemple #36
0
    def packages_to_entry(self, pkglist, entry):
        """ When using the Python yum libraries, convert a list of
        package tuples to a Package entry.  See :ref:`yum-pkg-objects`
        and :ref:`pkg-objects` for more information on this process.

        If pkglist contains only one package, then its data is
        converted to a single ``BoundPackage`` entry that is added as
        a subelement of ``entry``.  If pkglist contains more than one
        package, then a parent ``BoundPackage`` entry is created and
        child ``Instance`` entries are added to it.

        :param pkglist: A list of package tuples to convert to an XML
                         Package entry
        :type pkglist: list of tuples
        :param entry: The base XML entry to add Package entries to.
                      This is modified in place.
        :type entry: lxml.etree._Element
        :returns: None
        """
        if not self.use_yum:
            return Collection.packages_to_entry(self, pkglist, entry)

        packages = dict()
        for pkg in pkglist:
            try:
                packages[pkg[0]].append(pkg)
            except KeyError:
                packages[pkg[0]] = [pkg]
        for name, instances in packages.items():
            pkgattrs = dict(type=self.ptype, origin="Packages", name=name)
            if len(instances) > 1:
                pkg_el = lxml.etree.SubElement(entry, "BoundPackage", **pkgattrs)
                for inst in instances:
                    lxml.etree.SubElement(pkg_el, "Instance", self._get_entry_attrs(inst))
            else:
                attrs = self._get_entry_attrs(instances[0])
                attrs.update(pkgattrs)
                lxml.etree.SubElement(entry, "BoundPackage", **attrs)
Exemple #37
0
    def complete(self, packagelist):
        """ Build a complete list of all packages and their dependencies.

        When using the Python yum libraries, this defers to the
        :ref:`bcfg2-yum-helper`; when using the builtin yum parser,
        this defers to
        :func:`Bcfg2.Server.Plugins.Packages.Collection.Collection.complete`.

        :param packagelist: Set of initial packages computed from the
                            specification.
        :type packagelist: set of strings, but see :ref:`pkg-objects`
        :returns: tuple of sets - The first element contains a set of
                  strings (but see :ref:`pkg-objects`) describing the
                  complete package list, and the second element is a
                  set of symbols whose dependencies could not be
                  resolved.
        """
        if not self.use_yum:
            return Collection.complete(self, packagelist)

        if packagelist:
            result = \
                self.call_helper("complete",
                                 dict(packages=list(packagelist),
                                      groups=list(self.get_relevant_groups())))
            if not result:
                # some sort of error, reported by call_helper()
                return set(), packagelist
            # json doesn't understand sets or tuples, so we get back a
            # lists of lists (packages) and a list of unicode strings
            # (unknown).  turn those into a set of tuples and a set of
            # strings, respectively.
            unknown = set([str(u) for u in result['unknown']])
            packages = set([tuple(p) for p in result['packages']])
            self.filter_unknown(unknown)
            return packages, unknown
        else:
            return set(), set()
Exemple #38
0
    def complete(self, packagelist):
        if not self.use_yum:
            return Collection.complete(self, packagelist)

        packages = set()
        unknown = set(packagelist)

        if unknown:
            result = \
                self.call_helper("complete",
                                 dict(packages=list(unknown),
                                      groups=list(self.get_relevant_groups())))
            if result and "packages" in result and "unknown" in result:
                # we stringify every package because it gets returned
                # in unicode; set.update() doesn't work if some
                # elements are unicode and other are strings.  (I.e.,
                # u'foo' and 'foo' get treated as unique elements.)
                packages.update([str(p) for p in result['packages']])
                unknown = set([str(p) for p in result['unknown']])

            self.filter_unknown(unknown)

        return packages, unknown
Exemple #39
0
    def complete(self, packagelist):
        if not self.use_yum:
            return Collection.complete(self, packagelist)

        cachekey = cPickle.dumps(sorted(packagelist))
        try:
            packages = self.pkgset_cache[cachekey]
        except KeyError:
            packages = set()

        pkgs = set(packagelist).difference(packages)    
        requires = set()
        satisfied = set()
        unknown = set()
        final_pass = False

        while requires or pkgs:
            # infinite loop protection
            start_reqs = len(requires)
            
            while pkgs:
                package = pkgs.pop()
                if package in packages:
                    continue
                
                if not self.is_package(package):
                    # try this package out as a requirement
                    requires.add((package, None, (None, None, None)))
                    continue

                packages.add(package)
                reqs = set(self.get_deps(package)).difference(satisfied)
                if reqs:
                    requires.update(reqs)

            reqs_satisfied = set()
            for req in requires:
                if req in satisfied:
                    reqs_satisfied.add(req)
                    continue

                if req[1] is None and self.is_package(req[0]):
                    if req[0] not in packages:
                        pkgs.add(req[0])
                    reqs_satisfied.add(req)
                    continue
                    
                self.logger.debug("Packages: Handling requirement '%s'" %
                                  self.get_package_name(req))
                providers = list(set(self.get_provides(req)))
                if len(providers) > 1:
                    # hopefully one of the providing packages is already
                    # included
                    best = [p for p in providers if p in packages]
                    if best:
                        providers = best
                    else:
                        # pick a provider whose name matches the requirement
                        best = [p for p in providers if p == req[0]]
                        if len(best) == 1:
                            providers = best
                        elif not final_pass:
                            # found no "best" package, so defer
                            providers = None
                        # else: found no "best" package, but it's the
                        # final pass, so include them all
                
                if providers:
                    self.logger.debug("Packages: Requirement '%s' satisfied "
                                      "by %s" %
                                     (self.get_package_name(req),
                                      ",".join([self.get_package_name(p)
                                                for p in providers])))
                    newpkgs = set(providers).difference(packages)
                    if newpkgs:
                        for package in newpkgs:
                            if self.is_package(package):
                                pkgs.add(package)
                            else:
                                unknown.add(package)
                    reqs_satisfied.add(req)
                elif providers is not None:
                    # nothing provided this requirement at all
                    unknown.add(req)
                    reqs_satisfied.add(req)
                # else, defer
            requires.difference_update(reqs_satisfied)

            # infinite loop protection
            if len(requires) == start_reqs and len(pkgs) == 0:
                final_pass = True

            if final_pass and requires:
                unknown.update(requires)
                requires = set()

        self.filter_unknown(unknown)
        unknown = [self.get_package_name(p) for p in unknown]

        # we do not cache unknown packages, since those are likely to
        # be fixed
        self.pkgset_cache[cachekey] = packages

        return packages, unknown