Skip to content

Commit

Permalink
Inhibit upgrade if multiple kernel-devel pkgs are installed
Browse files Browse the repository at this point in the history
When multiple kernel-devel packages are present, leapp can't process
the transaction in some cases, so we inhibit the upgrade and present
the user with hints on removing the surplus devel kernels.
  • Loading branch information
drehak authored and pirat89 committed Mar 17, 2020
1 parent 30958f3 commit 2ce678f
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from leapp.actors import Actor
from leapp.models import InstalledRedHatSignedRPM
from leapp.tags import IPUWorkflowTag, ChecksPhaseTag
from leapp.reporting import Report
from leapp.libraries.actor import library


class CheckInstalledDevelKernels(Actor):
"""
Inhibit IPU (in-place upgrade) when multiple devel kernels are installed.
Because of an issue in DNF, the transaction can't be validated if there's
more than one package named kernel-devel. Therefore, in this case, we
inhibit the upgrade with a clearer remediation.
"""

name = 'check_installed_devel_kernels'
consumes = (InstalledRedHatSignedRPM,)
produces = (Report,)
tags = (IPUWorkflowTag, ChecksPhaseTag)

def process(self):
library.process()
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from leapp import reporting
from leapp.libraries.stdlib import api
from leapp.models import InstalledRedHatSignedRPM


def get_kernel_rpm_release(rpm):
"""
Get the release of a kernel RPM as an integer.
:param rpm: An instance of an RPM derived model.
"""
return int(rpm.release.split('.')[0])


def get_kernel_devel_rpms():
"""
Get all installed kernel-devel packages ordered by release number (ascending).
"""
rpms = next(api.consume(InstalledRedHatSignedRPM), InstalledRedHatSignedRPM())
return sorted([pkg for pkg in rpms.items if pkg.name == 'kernel-devel'], key=get_kernel_rpm_release)


def process():
pkgs = get_kernel_devel_rpms()
if len(pkgs) > 1:
title = 'Multiple devel kernels installed'
summary = ('DNF cannot produce a valid upgrade transaction when'
' multiple kernel-devel packages are installed.')
hint = ('Remove all but one kernel-devel packages before running Leapp again.')
commands = ([['yum', '-y', 'remove', '{n}-{v}.{r}'.format(
n=pkg.name, v=pkg.version, r=pkg.release)] for pkg in pkgs[:-1]])
reporting.create_report([
reporting.Title(title),
reporting.Summary(summary),
reporting.Severity(reporting.Severity.HIGH),
reporting.Tags([reporting.Tags.KERNEL]),
reporting.Flags([reporting.Flags.INHIBITOR]),
reporting.Remediation(hint=hint, commands=commands),
reporting.RelatedResource('package', 'kernel')
])
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pytest

from leapp.models import InstalledRedHatSignedRPM, RPM, Report
from leapp.snactor.fixture import current_actor_context


RH_PACKAGER = 'Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>'

ballast1 = [
RPM(name='b1', version='1', release='1', epoch='1', packager=RH_PACKAGER, arch='noarch', pgpsig='s'),
RPM(name='kernel', version='1', release='1', epoch='1', packager=RH_PACKAGER, arch='noarch', pgpsig='s'),
RPM(name='b2', version='1', release='1', epoch='1', packager=RH_PACKAGER, arch='noarch', pgpsig='s')
]
ballast2 = [
RPM(name='b3', version='1', release='1', epoch='1', packager=RH_PACKAGER, arch='noarch', pgpsig='s'),
RPM(name='kernel', version='1', release='1', epoch='1', packager=RH_PACKAGER, arch='noarch', pgpsig='s'),
RPM(name='b4', version='1', release='1', epoch='1', packager=RH_PACKAGER, arch='noarch', pgpsig='s')
]
devel_kernels = [
RPM(name='kernel-devel', version='3.10.0', release='957.27.4.el7',
epoch='1', packager=RH_PACKAGER, arch='noarch', pgpsig='s'),
RPM(name='kernel-devel', version='3.10.0', release='957.35.1.el7',
epoch='1', packager=RH_PACKAGER, arch='noarch', pgpsig='s'),
RPM(name='kernel-devel', version='3.10.0', release='957.43.1.el7',
epoch='1', packager=RH_PACKAGER, arch='noarch', pgpsig='s')
]


@pytest.mark.parametrize('n', [0, 1, 2, 3])
def test_process_devel_kernels(current_actor_context, n):
current_actor_context.feed(InstalledRedHatSignedRPM(items=ballast1+devel_kernels[:n]+ballast2))
current_actor_context.run()
if n < 2:
assert not current_actor_context.consume(Report)
else:
assert current_actor_context.consume(Report)

0 comments on commit 2ce678f

Please sign in to comment.