diff --git a/convert2rhel/pkghandler.py b/convert2rhel/pkghandler.py index 248495a553..4e64ff8fd3 100644 --- a/convert2rhel/pkghandler.py +++ b/convert2rhel/pkghandler.py @@ -36,6 +36,26 @@ _VERSIONLOCK_FILE_PATH = "/etc/yum/pluginconf.d/versionlock.list" # This file is used by the dnf plugin as well versionlock_file = utils.RestorableFile(_VERSIONLOCK_FILE_PATH) # pylint: disable=C0103 +# +# Regular expressions used to find package names in yum output +# + +# This regex finds package NEVRs + arch (name epoch version release and +# architechture) in a string. Note that the regex requires at least two dashes but the +# NEVR can contain more than that. For instance: gcc-c++-4.8.5-44.0.3.el7.x86_64 +PKG_NEVR = r"\b(?:([0-9]+):)?(\S+)-(\S+)-(\S+)\b" + +# It would be better to construct this dynamically but we don't have lru_cache +# in Python-2.6 and modifying a global after your program initializes isn't a +# good idea. +_KNOWN_PKG_MESSAGE_KEYS = ( + "%s", + "Error: Package: %s", + "multilib versions: %s", + "problem with installed package %s", +) +_PKG_REGEX_CACHE = dict((k, re.compile(k % PKG_NEVR, re.MULTILINE)) for k in _KNOWN_PKG_MESSAGE_KEYS) + class PkgWFingerprint(object): """Tuple-like storage for a package object and a fingerprint with which the package was signed.""" @@ -161,27 +181,29 @@ def get_problematic_pkgs(output, excluded_pkgs=frozenset()): loggerinst.info("Found protected packages: %s" % set(protected)) problematic_pkgs["protected"] = set(protected) - excluded_pkgs - package_nevr_re = r"[0-9]*:?([a-z][a-z0-9-_]*?)-[0-9]" - deps = re.findall("Error: Package: %s" % package_nevr_re, output, re.MULTILINE) + deps = find_pkg_names(output, "Error: Package: %s") if deps: - loggerinst.info("Found packages causing dependency errors: %s" % set(deps)) - problematic_pkgs["errors"] = set(deps) - excluded_pkgs + loggerinst.info("Found packages causing dependency errors: %s" % deps) + problematic_pkgs["errors"] = deps - excluded_pkgs - multilib = re.findall("multilib versions: %s" % package_nevr_re, output, re.MULTILINE) + multilib = find_pkg_names(output, "multilib versions: %s") if multilib: - loggerinst.info("Found multilib packages: %s" % set(multilib)) - problematic_pkgs["multilib"] = set(multilib) - excluded_pkgs + loggerinst.info("Found multilib packages: %s" % multilib) + problematic_pkgs["multilib"] = multilib - excluded_pkgs - mismatches = re.findall("problem with installed package %s" % package_nevr_re, output, re.MULTILINE) + mismatches = find_pkg_names(output, "problem with installed package %s") if mismatches: - loggerinst.info("Found mismatched packages: %s" % set(mismatches)) - problematic_pkgs["mismatches"] = set(mismatches) - excluded_pkgs + loggerinst.info("Found mismatched packages: %s" % mismatches) + problematic_pkgs["mismatches"] = mismatches - excluded_pkgs # What yum prints in the Requires is a capability, not a package name. And capability can be an arbitrary string, # e.g. perl(Carp) or redhat-lsb-core(x86-64). # Yet, passing a capability to yum distro-sync does not yield the expected result - the packages that provide the # capability are not getting downgraded. So here we're getting only the part of a capability that consists of # package name characters only. It will work in most cases but not in all (e.g. "perl(Carp)"). + # + # We can fix this with another yum or rpm call. This rpm command line will print the package name: + # rpm -q --whatprovides "CAPABILITY" package_name_re = r"([a-z][a-z0-9-]*)" req = re.findall("Requires: %s" % package_name_re, output, re.MULTILINE) if req: @@ -191,6 +213,32 @@ def get_problematic_pkgs(output, excluded_pkgs=frozenset()): return problematic_pkgs +def find_pkg_names(output, message_key="%s"): + """ + Find all the package names of a "type" from amongst a string of output from yum. + + :arg output: The yum output to parse for package names + :arg message_key: This function tries to retrieve "types" of packages from the yum output. + Packages that have multilib problems or dependency errors for instance. + The message_key is a format string which contains some of the yum + message which can be used as context for finding the type. ie: + "multilib versions: %s" would be enough to only select package names + that yum said were multilib problems. + :returns: A set of the package names found. + """ + try: + regular_expression = _PKG_REGEX_CACHE[message_key] + except KeyError: + regular_expression = re.compile(message_key % PKG_NEVR, re.MULTILINE) + + names = set() + nvrs = regular_expression.findall(output) + for _epoch, name, _version, _release in nvrs: + names.add(name) + + return names + + def get_pkgs_to_distro_sync(problematic_pkgs): """Consolidate all the different problematic packages to one list.""" return ( diff --git a/convert2rhel/unit_tests/data/pkghandler_yum_distro_sync_output_expect_deps_for_3_pkgs_found.txt b/convert2rhel/unit_tests/data/pkghandler_yum_distro_sync_output_expect_deps_for_3_pkgs_found.txt new file mode 100644 index 0000000000..e1a20ef30c --- /dev/null +++ b/convert2rhel/unit_tests/data/pkghandler_yum_distro_sync_output_expect_deps_for_3_pkgs_found.txt @@ -0,0 +1,294 @@ +Loaded plugins: product-id, search-disabled-repos, subscription-manager +Repository rhel-7-server-rpms is listed more than once in the configuration +Repository rhel-7-server-optional-rpms is listed more than once in the configuration +Repository rhel-7-server-extras-rpms is listed more than once in the configuration +Resolving Dependencies +--> Running transaction check +---> Package glibc.x86_64 0:2.17-325.el7_9 will be a downgrade +---> Package glibc.x86_64 0:2.17-325.0.1.el7_9 will be erased +---> Package glibc-common.x86_64 0:2.17-325.el7_9 will be a downgrade +---> Package glibc-common.x86_64 0:2.17-325.0.1.el7_9 will be erased +---> Package glibc-devel.x86_64 0:2.17-325.el7_9 will be a downgrade +---> Package glibc-devel.x86_64 0:2.17-325.0.1.el7_9 will be erased +---> Package glibc-headers.x86_64 0:2.17-325.el7_9 will be a downgrade +---> Package glibc-headers.x86_64 0:2.17-325.0.1.el7_9 will be erased +---> Package libgcc.x86_64 0:4.8.5-44.el7 will be a downgrade +---> Package libgcc.x86_64 0:4.8.5-44.0.3.el7 will be erased +---> Package libstdc++.x86_64 0:4.8.5-44.el7 will be a downgrade +---> Package libstdc++.x86_64 0:4.8.5-44.0.3.el7 will be erased +---> Package systemd.x86_64 0:219-78.el7_9.3 will be a downgrade +---> Package systemd.x86_64 0:219-78.0.5.el7_9.3 will be erased +---> Package systemd-libs.x86_64 0:219-78.el7_9.3 will be a downgrade +---> Package systemd-libs.x86_64 0:219-78.0.5.el7_9.3 will be erased +---> Package systemd-sysv.x86_64 0:219-78.el7_9.3 will be a downgrade +---> Package systemd-sysv.x86_64 0:219-78.0.5.el7_9.3 will be erased +--> Finished Dependency Resolution +Error: Package: gcc-c++-4.8.5-44.0.3.el7.x86_64 (@ol7_latest) + Requires: libstdc++ = 4.8.5-44.0.3.el7 + Removing: libstdc++-4.8.5-44.0.3.el7.x86_64 (installed) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-44.0.3.el7 + Downgraded By: libstdc++-4.8.5-44.el7.x86_64 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-44.el7 + Available: libstdc++-4.8.2-16.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + Available: libstdc++-4.8.2-16.2.el7_0.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.2.el7_0 + Available: libstdc++-4.8.3-9.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.3-9.el7 + Available: libstdc++-4.8.5-4.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-4.el7 + Available: libstdc++-4.8.5-11.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-11.el7 + Available: libstdc++-4.8.5-16.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-16.el7 + Available: libstdc++-4.8.5-16.el7_4.1.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7_4 + libstdc++ = 4.8.5-16.el7_4.1 + Available: libstdc++-4.8.5-16.el7_4.2.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7_4 + libstdc++ = 4.8.5-16.el7_4.2 + Available: libstdc++-4.8.5-28.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-28.el7 + Available: libstdc++-4.8.5-28.el7_5.1.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7_5 + libstdc++ = 4.8.5-28.el7_5.1 + Available: libstdc++-4.8.5-36.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-36.el7 + Available: libstdc++-4.8.5-36.el7_6.1.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7_6 + libstdc++ = 4.8.5-36.el7_6.1 + Available: libstdc++-4.8.5-36.el7_6.2.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7_6 + libstdc++ = 4.8.5-36.el7_6.2 + Available: libstdc++-4.8.5-39.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-39.el7 +Error: Package: libstdc++-devel-4.8.5-44.0.3.el7.x86_64 (@ol7_latest) + Requires: libstdc++(x86-64) = 4.8.5-44.0.3.el7 + Removing: libstdc++-4.8.5-44.0.3.el7.x86_64 (installed) + libstdc++(x86-64) = 4.8.5-44.0.3.el7 + Downgraded By: libstdc++-4.8.5-44.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-44.el7 + Available: libstdc++-4.8.2-16.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.2-16.el7 + Available: libstdc++-4.8.2-16.2.el7_0.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.2-16.2.el7_0 + Available: libstdc++-4.8.3-9.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.3-9.el7 + Available: libstdc++-4.8.5-4.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-4.el7 + Available: libstdc++-4.8.5-11.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-11.el7 + Available: libstdc++-4.8.5-16.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-16.el7 + Available: libstdc++-4.8.5-16.el7_4.1.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-16.el7_4.1 + Available: libstdc++-4.8.5-16.el7_4.2.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-16.el7_4.2 + Available: libstdc++-4.8.5-28.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-28.el7 + Available: libstdc++-4.8.5-28.el7_5.1.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-28.el7_5.1 + Available: libstdc++-4.8.5-36.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-36.el7 + Available: libstdc++-4.8.5-36.el7_6.1.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-36.el7_6.1 + Available: libstdc++-4.8.5-36.el7_6.2.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-36.el7_6.2 + Available: libstdc++-4.8.5-39.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-39.el7 +Error: Package: gcc-4.8.5-44.0.3.el7.x86_64 (@ol7_latest) + Requires: libgcc >= 4.8.5-44.0.3.el7 + Removing: libgcc-4.8.5-44.0.3.el7.x86_64 (installed) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-44.0.3.el7 + Downgraded By: libgcc-4.8.5-44.el7.x86_64 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-44.el7 + Available: libgcc-4.8.2-16.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + Available: libgcc-4.8.2-16.2.el7_0.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.2.el7_0 + Available: libgcc-4.8.3-9.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.3-9.el7 + Available: libgcc-4.8.5-4.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-4.el7 + Available: libgcc-4.8.5-11.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-11.el7 + Available: libgcc-4.8.5-16.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-16.el7 + Available: libgcc-4.8.5-16.el7_4.1.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7_4 + libgcc = 4.8.5-16.el7_4.1 + Available: libgcc-4.8.5-16.el7_4.2.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7_4 + libgcc = 4.8.5-16.el7_4.2 + Available: libgcc-4.8.5-28.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-28.el7 + Available: libgcc-4.8.5-28.el7_5.1.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7_5 + libgcc = 4.8.5-28.el7_5.1 + Available: libgcc-4.8.5-36.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-36.el7 + Available: libgcc-4.8.5-36.el7_6.1.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7_6 + libgcc = 4.8.5-36.el7_6.1 + Available: libgcc-4.8.5-36.el7_6.2.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7_6 + libgcc = 4.8.5-36.el7_6.2 + Available: libgcc-4.8.5-39.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-39.el7 +********************************************************************** +yum can be configured to try to resolve such errors by temporarily enabling +disabled repos and searching for missing dependencies. +To enable this functionality please set 'notify_only=0' in /etc/yum/pluginconf.d/search-disabled-repos.conf +********************************************************************** + +Error: Package: gcc-c++-4.8.5-44.0.3.el7.x86_64 (@ol7_latest) + Requires: libstdc++ = 4.8.5-44.0.3.el7 + Removing: libstdc++-4.8.5-44.0.3.el7.x86_64 (installed) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-44.0.3.el7 + Downgraded By: libstdc++-4.8.5-44.el7.x86_64 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-44.el7 + Available: libstdc++-4.8.2-16.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + Available: libstdc++-4.8.2-16.2.el7_0.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.2.el7_0 + Available: libstdc++-4.8.3-9.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.3-9.el7 + Available: libstdc++-4.8.5-4.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-4.el7 + Available: libstdc++-4.8.5-11.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-11.el7 + Available: libstdc++-4.8.5-16.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-16.el7 + Available: libstdc++-4.8.5-16.el7_4.1.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7_4 + libstdc++ = 4.8.5-16.el7_4.1 + Available: libstdc++-4.8.5-16.el7_4.2.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7_4 + libstdc++ = 4.8.5-16.el7_4.2 + Available: libstdc++-4.8.5-28.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-28.el7 + Available: libstdc++-4.8.5-28.el7_5.1.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7_5 + libstdc++ = 4.8.5-28.el7_5.1 + Available: libstdc++-4.8.5-36.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-36.el7 + Available: libstdc++-4.8.5-36.el7_6.1.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7_6 + libstdc++ = 4.8.5-36.el7_6.1 + Available: libstdc++-4.8.5-36.el7_6.2.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7_6 + libstdc++ = 4.8.5-36.el7_6.2 + Available: libstdc++-4.8.5-39.el7.i686 (rhel-7-server-rpms) + libstdc++ = 4.8.2-16.el7 + libstdc++ = 4.8.5-39.el7 +Error: Package: libstdc++-devel-4.8.5-44.0.3.el7.x86_64 (@ol7_latest) + Requires: libstdc++(x86-64) = 4.8.5-44.0.3.el7 + Removing: libstdc++-4.8.5-44.0.3.el7.x86_64 (installed) + libstdc++(x86-64) = 4.8.5-44.0.3.el7 + Downgraded By: libstdc++-4.8.5-44.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-44.el7 + Available: libstdc++-4.8.2-16.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.2-16.el7 + Available: libstdc++-4.8.2-16.2.el7_0.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.2-16.2.el7_0 + Available: libstdc++-4.8.3-9.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.3-9.el7 + Available: libstdc++-4.8.5-4.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-4.el7 + Available: libstdc++-4.8.5-11.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-11.el7 + Available: libstdc++-4.8.5-16.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-16.el7 + Available: libstdc++-4.8.5-16.el7_4.1.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-16.el7_4.1 + Available: libstdc++-4.8.5-16.el7_4.2.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-16.el7_4.2 + Available: libstdc++-4.8.5-28.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-28.el7 + Available: libstdc++-4.8.5-28.el7_5.1.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-28.el7_5.1 + Available: libstdc++-4.8.5-36.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-36.el7 + Available: libstdc++-4.8.5-36.el7_6.1.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-36.el7_6.1 + Available: libstdc++-4.8.5-36.el7_6.2.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-36.el7_6.2 + Available: libstdc++-4.8.5-39.el7.x86_64 (rhel-7-server-rpms) + libstdc++(x86-64) = 4.8.5-39.el7 +Error: Package: gcc-4.8.5-44.0.3.el7.x86_64 (@ol7_latest) + Requires: libgcc >= 4.8.5-44.0.3.el7 + Removing: libgcc-4.8.5-44.0.3.el7.x86_64 (installed) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-44.0.3.el7 + Downgraded By: libgcc-4.8.5-44.el7.x86_64 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-44.el7 + Available: libgcc-4.8.2-16.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + Available: libgcc-4.8.2-16.2.el7_0.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.2.el7_0 + Available: libgcc-4.8.3-9.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.3-9.el7 + Available: libgcc-4.8.5-4.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-4.el7 + Available: libgcc-4.8.5-11.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-11.el7 + Available: libgcc-4.8.5-16.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-16.el7 + Available: libgcc-4.8.5-16.el7_4.1.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7_4 + libgcc = 4.8.5-16.el7_4.1 + Available: libgcc-4.8.5-16.el7_4.2.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7_4 + libgcc = 4.8.5-16.el7_4.2 + Available: libgcc-4.8.5-28.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-28.el7 + Available: libgcc-4.8.5-28.el7_5.1.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7_5 + libgcc = 4.8.5-28.el7_5.1 + Available: libgcc-4.8.5-36.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-36.el7 + Available: libgcc-4.8.5-36.el7_6.1.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7_6 + libgcc = 4.8.5-36.el7_6.1 + Available: libgcc-4.8.5-36.el7_6.2.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7_6 + libgcc = 4.8.5-36.el7_6.2 + Available: libgcc-4.8.5-39.el7.i686 (rhel-7-server-rpms) + libgcc = 4.8.2-16.el7 + libgcc = 4.8.5-39.el7 + You could try using --skip-broken to work around the problem +** Found 1 pre-existing rpmdb problem(s), 'yum check' output follows: +initscripts-9.49.53-1.0.1.el7_9.1.x86_64 has missing requires of oraclelinux-release diff --git a/convert2rhel/unit_tests/pkghandler_test.py b/convert2rhel/unit_tests/pkghandler_test.py index 11e89c18cf..f678105624 100644 --- a/convert2rhel/unit_tests/pkghandler_test.py +++ b/convert2rhel/unit_tests/pkghandler_test.py @@ -284,39 +284,6 @@ def test_call_yum_cmd_w_downgrades_remove_problematic_pkgs(self): self.assertIn(pkghandler.call_yum_cmd.return_string, utils.remove_pkgs.pkgs) self.assertEqual(utils.remove_pkgs.critical, False) - def test_get_problematic_pkgs(self): - error_pkgs = pkghandler.get_problematic_pkgs("", set()) - self.assertEqual( - error_pkgs, - { - "protected": set(), - "errors": set(), - "multilib": set(), - "required": set(), - "mismatches": set(), - }, - ) - - error_pkgs = pkghandler.get_problematic_pkgs(YUM_PROTECTED_ERROR, set()) - self.assertIn("systemd", error_pkgs["protected"]) - self.assertIn("yum", error_pkgs["protected"]) - - error_pkgs = pkghandler.get_problematic_pkgs(YUM_REQUIRES_ERROR, set()) - self.assertIn("libreport-anaconda", error_pkgs["errors"]) - self.assertIn("abrt-cli", error_pkgs["errors"]) - self.assertIn("libreport-plugin-rhtsupport", error_pkgs["required"]) - self.assertIn("python2-hawkey", error_pkgs["required"]) - self.assertIn("mod_ldap", error_pkgs["errors"]) - self.assertIn("redhat-lsb-trialuse", error_pkgs["errors"]) - self.assertIn("redhat-lsb-core", error_pkgs["required"]) - - error_pkgs = pkghandler.get_problematic_pkgs(YUM_MULTILIB_ERROR, set()) - self.assertIn("openldap", error_pkgs["multilib"]) - self.assertIn("p11-kit", error_pkgs["multilib"]) - - error_pkgs = pkghandler.get_problematic_pkgs(YUM_MISMATCHED_PKGS_ERROR, set()) - self.assertIn("python39-psycopg2-debug", error_pkgs["mismatches"]) - def test_get_pkgs_to_distro_sync(self): problematic_pkgs = { "protected": set(["a"]), @@ -1415,9 +1382,39 @@ def test_fix_default_kernel_with_no_incorrect_kernel(self): Removing: python2_hawkey-0.22.5-2.el7_9.x86_64 (@extras/7) python2_hawkey = 0.22.5-2.el7_9 Downgraded By: python2_hawkey-0.6.3-4.el7.x86_64 (rhel-7-server-rpms) - python2_hawkey = 0.6.3-4.el7""" + python2_hawkey = 0.6.3-4.el7 +Error: Package: gcc-c++-4.8.5-44.0.3.el7.x86_64 (@ol7_latest) + Requires: gcc = 4.8.5-44.0.3.el7 + Removing: gcc-4.8.5-44.0.3.el7.x86_64 (@ol7_latest) + gcc = 4.8.2-16.el7 + gcc = 4.8.5-44.0.3.el7 + Downgraded By: gcc-4.8.5-44.el7.x86_64 (rhel-7-server-rpms) + gcc = 4.8.2-16.el7 + gcc = 4.8.5-44.el7 + Available: gcc-4.8.2-16.el7.x86_64 (rhel-7-server-rpms) + gcc = 4.8.2-16.el7""" + +# Test for bugs in parsing package names that have unusual features +# This is artificial test data; these packages don't normally dep on themselves +# but we want to test that both the code handling packages in error state and +# the code handling packages they require will catch these package names. +YUM_UNUSUAL_PKG_NAME_REQUIRES_ERROR = """ +Error: Package: gcc-c++-4.8.5-44.0.3.el7.x86_64 (rhel-7-server-rpms) + Requires: gcc-c++ = 4.8.5-44.0.3.el7 +Error: Package: NetworkManager-1.18.8-2.0.1.el7_9.x86_64 (rhel-7-server-rpms) + Requires: NetworkManager = 1.18.8-2.0.1.el7_9 +Error: Package: ImageMagick-c++-6.9.10.68-6.el7_9.x86_64 (rhel-7-server-rpms) + Requires: ImageMagick-c++ = 6.9.10.68-6.el7_9 +Error: Package: devtoolset-11-libstdc++-devel-11.2.1-1.2.el7.x86_64 (rhel-7-server-rpms) + Requires: devtoolset-11-libstdc++-devel = 11.2.1-1.2.el7 +Error: Package: java-1.8.0-openjdk-1.8.0.312.b07-2.fc33.x86_64 (rhel-7-server-rpms) + Requires: java-1.8.0-openjdk = 1.8.0.312.b07-2.fc33 +Error: Package: 389-ds-base-1.3.10.2-14.el7_9.x86_64 (rhel-7-server-rpms) + Requires: 389-ds-base = 1.3.10.2-14.el7_9 + """ YUM_MULTILIB_ERROR = """ + Protected multilib versions: libstdc++-4.8.5-44.el7.i686 != libstdc++-4.8.5-44.0.3.el7.x86_64 Error: Protected multilib versions: 2:p11-kit-0.18.7-1.fc19.i686 != p11-kit-0.18.3-1.fc19.x86_64 Error: Protected multilib versions: openldap-2.4.36-4.fc19.i686 != openldap-2.4.35-4.fc19.x86_64""" @@ -1453,3 +1450,176 @@ def test_fix_default_kernel_with_no_incorrect_kernel(self): kernel.x86_64 4.7.4-200.fc24 @updates Available Packages kernel.x86_64 4.7.4-200.fc24 @updates""" + +with open( + os.path.join(os.path.dirname(__file__), "data/pkghandler_yum_distro_sync_output_expect_deps_for_3_pkgs_found.txt") +) as f: + YUM_DISTRO_SYNC_OUTPUT = f.read() + + +@pytest.mark.parametrize( + "yum_output, expected", + ( + ( + "", + { + "protected": set(), + "errors": set(), + "multilib": set(), + "required": set(), + "mismatches": set(), + }, + ), + ( + YUM_PROTECTED_ERROR, + { + "protected": set(("systemd", "yum")), + "errors": set(), + "multilib": set(), + "required": set(), + "mismatches": set(), + }, + ), + ( + YUM_MULTILIB_ERROR, + { + "protected": set(), + "errors": set(), + "multilib": set(("libstdc++", "openldap", "p11-kit")), + "required": set(), + "mismatches": set(), + }, + ), + ( + YUM_MISMATCHED_PKGS_ERROR, + { + "protected": set(), + "errors": set(), + "multilib": set(), + "required": set(), + "mismatches": set(("python39-psycopg2-debug",)), + }, + ), + # These currently do not pass because the Requires handling + # misparses a Requires in the test data (It turns + # python2_hawkey into python2). Testing it in its own function + # for now. + # ( + # YUM_REQUIRES_ERROR, + # { + # "protected": set(), + # "errors": set(("gcc-c++", "libreport-anaconda", "abrt-cli", "mod_ldap", "redhat-lsb-trialuse")), + # "multilib": set(), + # "required": set(("gcc", "libreport-plugin-rhtsupport", "python2-hawkey", "redhat-lsb-core")), + # "mismatches": set(), + # }, + # ), + # ( + # YUM_UNUSUAL_PKG_NAME_REQUIRES_ERROR, + # { + # "protected": set(), + # "errors": set(("gcc-c++", "NetworkManager", "ImageMagick-c++", + # "devtoolset-11-libstdc++-devel", "java-1.8.0-openjdk", "389-ds-base")), + # "multilib": set(), + # "required": set(("gcc-c++", "NetworkManager", "ImageMagick-c++", + # "devtoolset-11-libstdc++-devel", "java-1.8.0-openjdk", "389-ds-base")), + # "mismatches": set(), + # }, + # ), + ), +) +def test_get_problematic_pkgs(yum_output, expected): + error_pkgs = pkghandler.get_problematic_pkgs(yum_output, set()) + + assert error_pkgs == expected + + +# FIXME: There is a bug in requires handling. We're detecting the python2 +# package is a problem because there's a Requires: python2_hawkey line. Until +# that's fixed, the following two test cases will test the things that work +# (Errors parsing). Once it is fixed, re-implement this test via parametrize +# on test_get_problematic_pkgs instead of a standalone test case. +# https://github.com/oamg/convert2rhel/issues/378 +def test_get_problematic_pkgs_requires(): + """Merge into test_get_problematic_pkgs once requires parsing bug is fixed.""" + error_pkgs = pkghandler.get_problematic_pkgs(YUM_REQUIRES_ERROR, set()) + assert "libreport-anaconda" in error_pkgs["errors"] + assert "abrt-cli" in error_pkgs["errors"] + assert "libreport-plugin-rhtsupport" in error_pkgs["required"] + assert "python2-hawkey" in error_pkgs["required"] + assert "mod_ldap" in error_pkgs["errors"] + assert "redhat-lsb-trialuse" in error_pkgs["errors"] + assert "redhat-lsb-core" in error_pkgs["required"] + assert "gcc-c++" in error_pkgs["errors"] + assert "gcc" in error_pkgs["required"] + + +def test_get_problematic_pkgs_requires_unusual_names(): + """Merge into test_get_problematic_pkgs once requires parsing bug is fixed.""" + error_pkgs = pkghandler.get_problematic_pkgs(YUM_UNUSUAL_PKG_NAME_REQUIRES_ERROR, set()) + assert "gcc-c++" in error_pkgs["errors"] + assert "NetworkManager" in error_pkgs["errors"] + assert "ImageMagick-c++" in error_pkgs["errors"] + assert "devtoolset-11-libstdc++-devel" in error_pkgs["errors"] + assert "java-1.8.0-openjdk" in error_pkgs["errors"] + assert "389-ds-base" in error_pkgs["errors"] + + +@pytest.mark.parametrize( + "output, message, expected_names", + ( + # Test just the regex itself + ("Test", "%s", set()), + ("Error: Package: not_a_package_name", "%s", set()), + ("gcc-10.3.1-1.el8.x86_64", "%s", set(["gcc"])), + ("gcc-c++-10.3.1-1.el8.x86_64", "%s", set(["gcc-c++"])), + ("ImageMagick-c++-6.9.10.68-6.el7_9.i686", "%s", set(["ImageMagick-c++"])), + ("389-ds-base-1.3.10.2-14.el7_9.x86_64", "%s", set(["389-ds-base"])), + ("devtoolset-11-libstdc++-devel-11.2.1-1.2.el7.x86_64", "%s", set(["devtoolset-11-libstdc++-devel"])), + ("devtoolset-1.1-libstdc++-devel-11.2.1-1.2.el7.x86_64", "%s", set(["devtoolset-1.1-libstdc++-devel"])), + ("java-1.8.0-openjdk-1.8.0.312.b07-2.fc33.x86_64", "%s", set(["java-1.8.0-openjdk"])), + # Test NEVR with an epoch + ("NetworkManager-1:1.18.8-2.0.1.el7_9.x86_64", "%s", set(["NetworkManager"])), + # Test with simple error messages that we've pre-compiled the regex for + ("Error: Package: gcc-10.3.1-1.el8.x86_64", "Error: Package: %s", set(["gcc"])), + ("multilib versions: gcc-10.3.1-1.el8.i686", "multilib versions: %s", set(["gcc"])), + ("problem with installed package: gcc-10.3.1-1.el8.x86_64", "problem with installed package: %s", set(["gcc"])), + # Test that a template that was not pre-compiled works + ( + """Some Test Junk + Test gcc-1-2.i686""", + "Test %s", + set(["gcc"]), + ), + # Test with multiple packages to be found + ( + """Junk + Test gcc-1-2.i686 + Test gcc-c++-1-2.i686 + More Junk + Test bash-3-4.x86_64""", + "Test %s", + set(["gcc", "gcc-c++", "bash"]), + ), + # Test with actual yum output + (YUM_DISTRO_SYNC_OUTPUT, "Error: Package: %s", set(["gcc", "gcc-c++", "libstdc++-devel"])), + ), +) +def test_find_pkg_names(output, message, expected_names): + """Test that find_pkg_names finds the expected packages.""" + assert pkghandler.find_pkg_names(output, message) == expected_names + + +@pytest.mark.parametrize( + "output, message", + ( + # Test just the regex itself + ("Test", "%s"), + ("Error: Package: not_a_package_name", "%s"), + # Test that the message key is having an influence + ("multilib versions: gcc-10.3.1-1.el8.i686", "Error: Package: %s"), + ), +) +def test_find_pkg_names_no_names(output, message): + """Test that find_pkg_names does not find any names in these outputs.""" + assert pkghandler.find_pkg_names(output, message) == set() diff --git a/tests/integration/tier1/resolve-dependency/install_dependency_packages.py b/tests/integration/tier1/resolve-dependency/install_dependency_packages.py index 326bf41ac4..e05a52018b 100644 --- a/tests/integration/tier1/resolve-dependency/install_dependency_packages.py +++ b/tests/integration/tier1/resolve-dependency/install_dependency_packages.py @@ -27,6 +27,10 @@ def get_system_version(system_release_content=None): def test_install_dependency_packages(shell): + """Having certain packages installed used to cause conversion failures - namely yum dependency resolution errors. + + This test verifies that having these packages pre-installed does not cause a failure anymore + """ with open("/etc/system-release", "r") as file: system_release = file.read() @@ -40,6 +44,7 @@ def test_install_dependency_packages(shell): "python2-dnf-plugins-core", # OAMG-4690 "redhat-lsb-trialuse", # OAMG-4942 "ldb-tools", # OAMG-4941 + "gcc-c++", # OAMG-6136 "python-requests", # OAMG-4936 ] elif system_version.major == 8: