Uploaded image for project: 'RHEL Conversions'
  1. RHEL Conversions
  2. RHELC-1117

convert2rhel fails with a backtrace in _bad_kernel_package_signature() constantly

XMLWordPrintable

    • False
    • False
    • Hide

      None

      Show
      None
    • 3
    • 2023-R4
    • Testable

      Description of problem:

      A customer hits constantly a failure when trying to convert his CentOS7 system:
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
      Traceback: Traceback (most recent call
      last):
      File "/usr/lib/python2.7/site-packages/convert2rhel/actions/_init_.py", line 393, in run
      action.run()
      File
      "/usr/lib/python2.7/site-packages/convert2rhel/actions/system_checks/rhel_compatible_kernel.py", line 49, in run
      _bad_kernel_package_signature(system_info.booted_kernel),
      File "/usr/lib/python2.7/site-
      packages/convert2rhel/actions/system_checks/rhel_compatible_kernel.py", line 119, in _bad_kernel_package_signature
      kernel_pkg_obj = get_installed_pkg_objects(name, version, release, arch)[0]
      IndexError: list index out of range
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

      The reason for the failure is no kernel matching name/version/release/arch was found.
      To check the installed kernel (which is used to populate name/version/release/arch), the following command is executed:
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
      103 kernel_pkg, return_code = run_subprocess(
      104 ["rpm", "qf", "-qf", "%

      {VERSION}&%{RELEASE}&%{ARCH}&%{NAME}", vmlinuz_path], print_output=False
      105 )
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

      Then output split:
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
      116 version, release, arch, name = tuple(kernel_pkg.split("&"))
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

      Finally "kernel_pkg_obj" extracted:
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
      119 kernel_pkg_obj = get_installed_pkg_objects(name, version, release, arch)[0]
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

      If, on line 104, the rpm command returns something on stderr, then the "version" will be corrupted, causing the issue.
      For some reason, this always happens on the customer system, as shown below through adding some instrumentation on line 119 below:
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
      119 logger.warning("name='%s', version='%s', release='%s', arch='%s'" % (name, version, release, arch))
      120 kernel_pkg_obj = get_installed_pkg_objects(name, version, release, arch)[0]
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

      Resulting output ("version" field corrupted by stderr):
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
      WARNING - name='kernel', version='BDB2053 Freeing read locks for locker 0x3f9: 129310/139621967034176
      BDB2053 Freeing read locks for locker 0x3fb: 129310/139621967034176
      3.10.0', release='1160.95.1.el7', arch='x86_64'
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

      Version-Release number of selected component (if applicable):

      convert2rhel-1.3.2-1.el7.noarch

      How reproducible:

      Always on customer system, didn't manage to force getting a warning for now

      Additional info:

      A quick and dirty solution is to discard stderr when executing "rpm -qf" command on line 104, which requires wrapping in a shell, as shown below:
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
      104 ["sh", "-c", "rpm -qf --qf \"%%{VERSION}

      &%%

      {RELEASE}

      &%%

      {ARCH}

      &%%

      {NAME}

      \" %s 2>/dev/null" % vmlinuz_path], print_output=False
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

      Ideally, utils.run_subprocess() should be reimplemented to not merge stdout and stderr and make the merge be optional.
      Currently it is implementing automatic merging:
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
      345 def run_subprocess(cmd, print_cmd=True, print_output=True):
      :
      362 process = subprocess.Popen(
      363 cmd,
      364 stdout=subprocess.PIPE,
      365 stderr=subprocess.STDOUT,
      366 bufsize=1,
      367 )
      -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

      It's very possible many other calls to utils.run_process() may fail similarly.
      Probably a robust implementation would be to add some more function parameters:

      • "expect_stderr" parameter which will make run_subprocess() DIE if some stderr is found when "expect_stderr=False"
      • "discard_stderr" parameter which will redirect stderr to /dev/null when "discard_stderr=True"

              rolivier@redhat.com Rodolfo Olivieri
              rhn-support-rmetrich Renaud Métrich
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: