Exemple #1
0
def pcmp(lhs, rhs):
    """
    Compare packages by these NVRAEs.

    :param lhs, rhs: dict(name, version, release, epoch, arch)

    :note: It does not utilize rpm.versionCompare even if yum is not available.

    >>> lhs = dict(name="gpg-pubkey", version="00a4d52b", release="4cb9dd70",
    ...           arch="noarch", epoch=0,
    ... )
    >>> rhs = dict(name="gpg-pubkey", version="069c8460", release="4d5067bf",
    ...           arch="noarch", epoch=0,
    ... )
    >>> pcmp(lhs, lhs) == 0
    True
    >>> pcmp(lhs, rhs) < 0
    True

    >>> p3 = dict(name="kernel", version="2.6.38.8", release="32",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> p4 = dict(name="kernel", version="2.6.38.8", release="35",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> pcmp(p3, p4) < 0
    True

    >>> p5 = dict(name="rsync", version="2.6.8", release="3.1",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> p6 = dict(name="rsync", version="3.0.6", release="4.el5",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> pcmp(p3, p4) < 0
    True
    """
    p2evr = operator.itemgetter("epoch", "version", "release")

    assert lhs["name"] == rhs["name"], "Trying to compare different packages!"
    return yum.compareEVR(p2evr(lhs), p2evr(rhs))
Exemple #2
0
def pcmp(p1, p2):
    """Compare packages by NVRAEs.

    :param p1, p2: dict(name, version, release, epoch, arch)

    TODO: Make it fallback to rpm.versionCompare if yum is not available?

    >>> p1 = dict(name="gpg-pubkey", version="00a4d52b", release="4cb9dd70",
    ...           arch="noarch", epoch=0,
    ... )
    >>> p2 = dict(name="gpg-pubkey", version="069c8460", release="4d5067bf",
    ...           arch="noarch", epoch=0,
    ... )
    >>> pcmp(p1, p1) == 0
    True
    >>> pcmp(p1, p2) < 0
    True

    >>> p3 = dict(name="kernel", version="2.6.38.8", release="32",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> p4 = dict(name="kernel", version="2.6.38.8", release="35",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> pcmp(p3, p4) < 0
    True

    >>> p5 = dict(name="rsync", version="2.6.8", release="3.1",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> p6 = dict(name="rsync", version="3.0.6", release="4.el5",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> pcmp(p3, p4) < 0
    True
    """
    p2evr = itemgetter("epoch", "version", "release")

    assert p1["name"] == p2["name"], "Trying to compare different packages!"
    return yum.compareEVR(p2evr(p1), p2evr(p2))
def pcmp(p1, p2):
    """Compare packages by these versions, releases and epoch numbers.

    :param p1, p2: (normalized) NVRE

    TODO: Fallback to rpm.versionCompare if yum is not available?

    # special cases:
    >>> p1 = dict(name="gpg-pubkey", version="00a4d52b", release="4cb9dd70",
    ...           epoch=0,
    ... )
    >>> p2 = dict(name="gpg-pubkey", version="069c8460", release="4d5067bf",
    ...           epoch=0,
    ... )
    >>> pcmp(p1, p1) == 0
    True
    >>> pcmp(p1, p2) < 0
    True

    >>> # compare by releases
    >>> p3 = dict(name="kernel", version="2.6.38.8", release="32", epoch=0)
    >>> p4 = dict(name="kernel", version="2.6.38.8", release="35", epoch=0)
    >>> pcmp(p3, p4) < 0
    True

    >>> # compare by versions and releases
    >>> p5 = dict(name="rsync", version="2.6.8", release="3.1", epoch=0)
    >>> p6 = dict(name="rsync", version="3.0.6", release="4.el5", epoch=0)
    >>> pcmp(p3, p4) < 0
    True

    >>> # compare by epoch numbers
    >>> p7 = dict(name="rsync", version="2.6.8", release="3.1", epoch=2)
    >>> p8 = dict(name="rsync", version="3.0.6", release="4.el5", epoch=0)
    >>> pcmp(p7, p8) > 0
    True
    """
    p2evr = lambda p: (p["epoch"], p["version"], p["release"])
    assert p1["name"] == p2["name"], "Trying to compare different packages!"
    return yum.compareEVR(p2evr(p1), p2evr(p2))
Exemple #4
0
def pcmp(p1, p2):
    """Compare packages by NVRAEs.

    :param p1, p2: dict(name, version, release, epoch, arch)

    TODO: Make it fallback to rpm.versionCompare if yum is not available?

    >>> p1 = dict(name="gpg-pubkey", version="00a4d52b", release="4cb9dd70",
    ...           arch="noarch", epoch=0,
    ... )
    >>> p2 = dict(name="gpg-pubkey", version="069c8460", release="4d5067bf",
    ...           arch="noarch", epoch=0,
    ... )
    >>> pcmp(p1, p1) == 0
    True
    >>> pcmp(p1, p2) < 0
    True

    >>> p3 = dict(name="kernel", version="2.6.38.8", release="32",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> p4 = dict(name="kernel", version="2.6.38.8", release="35",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> pcmp(p3, p4) < 0
    True

    >>> p5 = dict(name="rsync", version="2.6.8", release="3.1",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> p6 = dict(name="rsync", version="3.0.6", release="4.el5",
    ...           arch="x86_64", epoch=0,
    ... )
    >>> pcmp(p3, p4) < 0
    True
    """
    p2evr = itemgetter("epoch", "version", "release")

    assert p1["name"] == p2["name"], "Trying to compare different packages!"
    return yum.compareEVR(p2evr(p1), p2evr(p2))
def rpmcmp(p1, p2):
    p2evr = lambda p: (p["epoch"], p["version"], p["release"])
    return yum.compareEVR(p2evr(p1), p2evr(p2))
Exemple #6
0
                         yum.misc.prco_tuple_to_string(provides)))
                else:
                    current_evr = (current_pkg.epoch,
                                   current_pkg.version,
                                   current_pkg.release)
                    self.logger.info("  %s: Wrong version installed.  "
                                     "Want %s, but have %s" %
                                     (entry.get("name"),
                                      nevra2string(nevra),
                                      nevra2string(current_pkg)))
                wanted_evr = (nevra.get('epoch', 'any'),
                              nevra.get('version', 'any'),
                              nevra.get('release', 'any'))
                entry.set('current_version', "%s:%s-%s" % current_evr)
                entry.set('version', "%s:%s-%s" % wanted_evr)
                if yum.compareEVR(current_evr, wanted_evr) == 1:
                    entry.set("package_fail_action", "downgrade")
                else:
                    entry.set("package_fail_action", "update")

                qtext_versions.append("U(%s)" % str(all_pkg_objs[0]))
                continue

            if Bcfg2.Options.setup.quick:
                # Passed -q on the command line
                continue
            if not (pkg_verify and
                    inst.get('pkg_verify', 'true').lower() == 'true'):
                continue

            # XXX: We ignore GPG sig checking the package as it
Exemple #7
0
    def VerifyPackage(self, entry, modlist):
        """ Verify Package status for entry.
        Performs the following:
        * Checks for the presence of required Package Instances.
        * Compares the evra 'version' info against self.installed{}.
        * RPM level package verify (rpm --verify).
        * Checks for the presence of unrequired package instances.

        Produces the following dict and list for Yum.Install() to use:
        * For installs/upgrades/fixes of required instances::
            instance_status = { <Instance Element Object>:
                                       { 'installed': True|False,
                                         'version_fail': True|False,
                                         'verify_fail': True|False,
                                         'pkg': <Package Element Object>,
                                         'modlist': [ <filename>, ... ],
                                         'verify' : [ <rpm --verify results> ]
                                       }, ......
                                  }

        * For deletions of unrequired instances::
            extra_instances = [ <Package Element Object>, ..... ]

        Constructs the text prompts for interactive mode. """
        if entry.get('version', False) == 'auto':
            self._fixAutoVersion(entry)

        if entry.get('group'):
            self.logger.debug("Verifying packages for group %s" %
                              entry.get('group'))
        else:
            self.logger.debug("Verifying package instances for %s" %
                              entry.get('name'))

        self.verify_cache = dict()  # Used for checking multilib packages
        self.modlists[entry] = modlist
        instances = self._buildInstances(entry)
        pkg_cache = []
        package_fail = False
        qtext_versions = []
        virt_pkg = False
        pkg_checks = (Bcfg2.Options.setup.yum_pkg_checks and
                      entry.get('pkg_checks', 'true').lower() == 'true')
        pkg_verify = (Bcfg2.Options.setup.yum_pkg_verify and
                      entry.get('pkg_verify', 'true').lower() == 'true')
        yum_group = False

        if entry.get('name') == 'gpg-pubkey':
            all_pkg_objs = self._getGPGKeysAsPackages()
            pkg_verify = False  # No files here to verify
        elif entry.get('group'):
            entry.set('name', 'group:%s' % entry.get('group'))
            yum_group = True
            all_pkg_objs = []
            instances = []
            if self.yumbase.comps.has_group(entry.get('group')):
                group = self.yumbase.comps.return_group(entry.get('group'))
                group_packages = [p
                                  for p, d in group.mandatory_packages.items()
                                  if d]
                group_type = entry.get('choose', 'default')
                if group_type in ['default', 'optional', 'all']:
                    group_packages += [
                        p for p, d in group.default_packages.items()
                        if d]
                if group_type in ['optional', 'all']:
                    group_packages += [
                        p for p, d in group.optional_packages.items()
                        if d]
                if len(group_packages) == 0:
                    self.logger.error("No packages found for group %s" %
                                      entry.get("group"))
                for pkg in group_packages:
                    # create package instances for each package in yum group
                    instance = Bcfg2.Client.XML.SubElement(entry, 'Package')
                    instance.attrib['name'] = pkg
                    instance.attrib['type'] = 'yum'
                    try:
                        newest = \
                            self.yumbase.pkgSack.returnNewestByName(pkg)[0]
                        instance.attrib['version'] = newest['version']
                        instance.attrib['epoch'] = newest['epoch']
                        instance.attrib['release'] = newest['release']
                    except:  # pylint: disable=W0702
                        self.logger.info("Error finding newest package "
                                         "for %s" %
                                         pkg)
                        instance.attrib['version'] = 'any'
                    instances.append(instance)
            else:
                self.logger.error("Group not found: %s" % entry.get("group"))
        else:
            all_pkg_objs = \
                self.yumbase.rpmdb.searchNevra(name=entry.get('name'))
        if len(all_pkg_objs) == 0 and yum_group is not True:
            # Some sort of virtual capability?  Try to resolve it
            all_pkg_objs = self.yumbase.rpmdb.searchProvides(entry.get('name'))
            if len(all_pkg_objs) > 0:
                virt_pkg = True
                self.logger.info("%s appears to be provided by:" %
                                 entry.get('name'))
                for pkg in all_pkg_objs:
                    self.logger.info("  %s" % pkg)

        for inst in instances:
            if yum_group:
                # the entry is not the name of the package
                nevra = build_yname(inst.get('name'), inst)
                all_pkg_objs = \
                    self.yumbase.rpmdb.searchNevra(name=inst.get('name'))
            else:
                nevra = build_yname(entry.get('name'), inst)
            if nevra in pkg_cache:
                continue  # Ignore duplicate instances
            else:
                pkg_cache.append(nevra)

            self.logger.debug("Verifying: %s" % nevra2string(nevra))

            # Set some defaults here
            stat = self.instance_status.setdefault(inst, {})
            stat['installed'] = True
            stat['version_fail'] = False
            stat['verify'] = {}
            stat['verify_fail'] = False
            if yum_group:
                stat['pkg'] = inst
            else:
                stat['pkg'] = entry
            stat['modlist'] = modlist
            if inst.get('verify_flags'):
                # this splits on either space or comma
                verify_flags = \
                    inst.get('verify_flags').lower().replace(' ',
                                                             ',').split(',')
            else:
                verify_flags = Bcfg2.Options.setup.yum_verify_flags

            if 'arch' in nevra:
                # If arch is specified use it to select the package
                pkg_objs = [p for p in all_pkg_objs if p.arch == nevra['arch']]
            else:
                pkg_objs = all_pkg_objs
            if len(pkg_objs) == 0:
                # Package (name, arch) not installed
                entry.set('current_exists', 'false')
                self.logger.debug("  %s is not installed" %
                                  nevra2string(nevra))
                stat['installed'] = False
                package_fail = True
                qtext_versions.append("I(%s)" % nevra)
                continue

            if not pkg_checks:
                continue

            # Check EVR
            if virt_pkg:
                # we need to make sure that the version of the symbol
                # provided matches the one required in the
                # configuration
                vlist = []
                for attr in ["epoch", "version", "release"]:
                    vlist.append(nevra.get(attr))
                if tuple(vlist) == (None, None, None):
                    # we just require the package name, no particular
                    # version, so just make a copy of all_pkg_objs since every
                    # package that provides this symbol satisfies the
                    # requirement
                    pkg_objs = [po for po in all_pkg_objs]
                else:
                    pkg_objs = [po for po in all_pkg_objs
                                if po.checkPrco('provides',
                                                (nevra["name"], 'EQ',
                                                 tuple(vlist)))]
            elif entry.get('name') == 'gpg-pubkey':
                if 'version' not in nevra:
                    self.logger.warning("Skipping verify: gpg-pubkey without "
                                        "an RPM version")
                    continue
                if 'release' not in nevra:
                    self.logger.warning("Skipping verify: gpg-pubkey without "
                                        "an RPM release")
                    continue
                pkg_objs = [p for p in all_pkg_objs
                            if (p.version == nevra['version']
                                and p.release == nevra['release'])]
            else:
                pkg_objs = self.yumbase.rpmdb.searchNevra(**short_yname(nevra))
            if len(pkg_objs) == 0:
                package_fail = True
                stat['version_fail'] = True
                # Just chose the first pkg for the error message
                current_pkg = all_pkg_objs[0]
                if virt_pkg:
                    provides = \
                        [p for p in current_pkg.provides
                         if p[0] == entry.get("name")][0]
                    current_evr = provides[2]
                    self.logger.info(
                        "  %s: Wrong version installed.  "
                        "Want %s, but %s provides %s" %
                        (entry.get("name"),
                         nevra2string(nevra),
                         nevra2string(current_pkg),
                         yum.misc.prco_tuple_to_string(provides)))
                else:
                    current_evr = (current_pkg.epoch,
                                   current_pkg.version,
                                   current_pkg.release)
                    self.logger.info("  %s: Wrong version installed.  "
                                     "Want %s, but have %s" %
                                     (entry.get("name"),
                                      nevra2string(nevra),
                                      nevra2string(current_pkg)))
                wanted_evr = (nevra.get('epoch', 'any'),
                              nevra.get('version', 'any'),
                              nevra.get('release', 'any'))
                entry.set('current_version', "%s:%s-%s" % current_evr)
                entry.set('version', "%s:%s-%s" % wanted_evr)
                if yum.compareEVR(current_evr, wanted_evr) == 1:
                    entry.set("package_fail_action", "downgrade")
                else:
                    entry.set("package_fail_action", "update")

                qtext_versions.append("U(%s)" % str(all_pkg_objs[0]))
                continue

            if Bcfg2.Options.setup.quick:
                # Passed -q on the command line
                continue
            if not (pkg_verify and
                    inst.get('pkg_verify', 'true').lower() == 'true'):
                continue

            # XXX: We ignore GPG sig checking the package as it
            # has nothing to do with the individual file hash/size/etc.
            # GPG checking the package only eaxmines some header/rpmdb
            # wacky-ness, and will not properly detect a compromised rpmdb.
            # Yum's verify routine does not support it for that reaosn.

            if len(pkg_objs) > 1:
                self.logger.debug("  Verify Instance found many packages:")
                for pkg in pkg_objs:
                    self.logger.debug("    %s" % str(pkg))

            try:
                vrfy_result = self._verifyHelper(pkg_objs[0])
            except:  # pylint: disable=W0702
                err = sys.exc_info()[1]
                # Unknown Yum exception
                self.logger.warning("  Verify Exception: %s" % err)
                package_fail = True
                continue

            # Now take out the Yum specific objects / modlists / unproblems
            ignores = [ig.get('name') for ig in entry.findall('Ignore')] + \
                [ig.get('name') for ig in inst.findall('Ignore')] + \
                self.ignores
            for fname, probs in list(vrfy_result.items()):
                if fname in modlist:
                    self.logger.debug("  %s in modlist, skipping" % fname)
                    continue
                if fname in ignores:
                    self.logger.debug("  %s in ignore list, skipping" % fname)
                    continue
                tmp = []
                for prob in probs:
                    if prob.type == 'missing' and os.path.islink(fname):
                        continue
                    elif 'no' + prob.type in verify_flags:
                        continue
                    if prob.type not in ['missingok', 'ghost']:
                        tmp.append((prob.type, prob.message))
                if tmp != []:
                    stat['verify'][fname] = tmp

            if stat['verify'] != {}:
                stat['verify_fail'] = True
                package_fail = True
                self.logger.info("It is suggested that you either manage "
                                 "these files, revert the changes, or ignore "
                                 "false failures:")
                self.logger.info("  Verify Problems: %s" %
                                 stat['pkg'].get('name'))
                for fname, probs in list(stat['verify'].items()):
                    if len(probs) > 1:
                        self.logger.info("    %s" % fname)
                        for prob in probs:
                            self.logger.info("      %s" % prob[1])
                    else:
                        self.logger.info("    %s: %s" % (fname, probs[0]))

        if len(all_pkg_objs) > 0:
            # Is this an install only package?  We just look at the first one
            provides = set([p[0] for p in all_pkg_objs[0].provides] +
                           [all_pkg_objs[0].name])
            install_only = len(set(self.installonlypkgs) & provides) > 0
        else:
            install_only = False

        if virt_pkg or \
           (install_only and not Bcfg2.Options.setup.kevlar) or \
           yum_group:
            # virtual capability supplied, we are probably dealing
            # with multiple packages of different names.  This check
            # doesn't make a lot of since in this case.
            # install_only: Yum may clean some of these up itself.
            # Otherwise having multiple instances of install only packages
            # is considered correct
            self.extra_instances = None
        else:
            self.extra_instances = self.FindExtraInstances(entry, all_pkg_objs)
        if self.extra_instances is not None:
            package_fail = True

        return not package_fail