urpm-package-cleanup: fix removal of the old kernels

It has been broken for a long time, may be longer than ROSA has been
using nrj kernels. The tool relied on the version and release numbers of
the kernel packages to find the proper ones - but these numbers have
been (1, 1) for at least several years now.

The relevant parts of urpm-package-cleanup have been rewritten.

There are a few more notable differences compared to the old
implementation:

1. The number of kernels to keep is now read from
/etc/urpmi/kernels.cfg.
2. --count option is no longer supported.
3. If remove_old_kernels is set to no in /etc/urpmi/kernels.cfg,
urpm-package-cleanup --oldkernels will have no effect. This may be
convenient when running urpm-package-cleanup from scripts, etc.
4. The packages required by any kernel*-latest package will not be
removed, so urpm-package-cleanup may keep more kernels than requested.
This commit is contained in:
Evgenii Shatokhin 2017-08-28 19:07:26 +03:00
parent b9911a0845
commit e502756547
3 changed files with 181 additions and 114 deletions

View file

@ -38,10 +38,8 @@ When listing leaf nodes do not list development packages.
When listing leaf nodes do not list packages with files in bin directories. When listing leaf nodes do not list packages with files in bin directories.
.PP .PP
.SH "OLDKERNELS OPTIONS" .SH "OLDKERNELS OPTIONS"
.IP "\fB\-\-count <COUNT>\fP"
Number of kernel packages to keep on the system (default 2)
.IP "\fB\-\-keepdevel\fP" .IP "\fB\-\-keepdevel\fP"
Do not remove kernel-devel packages when removing kernels Do not remove kernel-devel packages when removing kernels.
.PP .PP
.SH "DUPLICATE PACKAGE OPTIONS" .SH "DUPLICATE PACKAGE OPTIONS"
.IP "\fB\-\-cleandupes\fP" .IP "\fB\-\-cleandupes\fP"
@ -60,8 +58,8 @@ List missing suggestions of installed packages
\fBurpm-package-cleanup --problems\fP \fBurpm-package-cleanup --problems\fP
.IP "List all packages that are not in any configured repository:" .IP "List all packages that are not in any configured repository:"
\fBurpm-package-cleanup --orphans\fP \fBurpm-package-cleanup --orphans\fP
.IP "Remove old kernels keeping 3 and leaving old kernel-devel packages installed:" .IP "Remove old kernels while leaving old kernel-devel packages installed:"
\fBurpm-package-cleanup --oldkernels --count=3 --keepdevel\fP \fBurpm-package-cleanup --oldkernels --keepdevel\fP
.PP .PP
.IP "List all leaf packages with no files in a bin directory whose name begins with either 'perl' or 'python':" .IP "List all leaf packages with no files in a bin directory whose name begins with either 'perl' or 'python':"
\fBurpm-package-cleanup --leaves --exclude-bin --leaf-regex="^(perl)|(python)"\fP \fBurpm-package-cleanup --leaves --exclude-bin --leaf-regex="^(perl)|(python)"\fP
@ -73,6 +71,12 @@ configuration file:
.nf .nf
/etc/urpmi/urpmi.cfg /etc/urpmi/urpmi.cfg
.fi .fi
.PP
urpm-package-cleanup --oldkernels also reads the options from /etc/urpmi/kernels.cfg:
.IP \fBremove_old_kernels (yes|no)\fP
If remove_old_kernels is set to "no", urpm-package-cleanup --oldkernels has no effect.
.IP \fBkernels_to_keep\fP
How many kernels to keep.
.PP .PP
.SH "EXIT CODES" .SH "EXIT CODES"

View file

@ -704,137 +704,150 @@ msgstr " Всего пакетов с пониженной версией: "
msgid "Creating HTML file." msgid "Creating HTML file."
msgstr "Создание HTML файла." msgstr "Создание HTML файла."
#: urpm-package-cleanup.py:58 urpm-tools/urpm-package-cleanup.py:58 #: urpm-package-cleanup.py:62 urpm-tools/urpm-package-cleanup.py:62
msgid "Find problems in the rpmdb of system and correct them" msgid "Find problems in the rpmdb of system and correct them"
msgstr "Найти проблемы в локальной базе RPM и исправить их" msgstr "Найти проблемы в локальной базе RPM и исправить их"
#: urpm-package-cleanup.py:62 urpm-tools/urpm-package-cleanup.py:62 #: urpm-package-cleanup.py:66 urpm-tools/urpm-package-cleanup.py:66
msgid "Query format to use for output." msgid "Query format to use for output."
msgstr "Формат вывода." msgstr "Формат вывода."
#: urpm-package-cleanup.py:65 urpm-tools/urpm-package-cleanup.py:65 #: urpm-package-cleanup.py:69 urpm-tools/urpm-package-cleanup.py:69
msgid "Use non-interactive mode" msgid "Use non-interactive mode"
msgstr "Работать в неинтерактивном режиме" msgstr "Работать в неинтерактивном режиме"
#: urpm-package-cleanup.py:68 urpm-tools/urpm-package-cleanup.py:68 #: urpm-package-cleanup.py:72 urpm-tools/urpm-package-cleanup.py:72
msgid "Orphans Options" msgid "Orphans Options"
msgstr "Осиротевшие пакеты" msgstr "Осиротевшие пакеты"
#: urpm-package-cleanup.py:71 urpm-tools/urpm-package-cleanup.py:71 #: urpm-package-cleanup.py:75 urpm-tools/urpm-package-cleanup.py:75
msgid "List installed packages which are not available from currently configured repositories" msgid "List installed packages which are not available from currently configured repositories"
msgstr "Перечислить пакеты, недоступные в настроенных на текущий момент репозиториях" msgstr "Перечислить пакеты, недоступные в настроенных на текущий момент репозиториях"
#: urpm-package-cleanup.py:75 urpm-tools/urpm-package-cleanup.py:75 #: urpm-package-cleanup.py:79 urpm-tools/urpm-package-cleanup.py:79
msgid "Use only update media. This means that urpmq will search and resolve dependencies only in media marked as containing updates (e.g. which have been created with \"urpmi.addmedia --update\")." msgid "Use only update media. This means that urpmq will search and resolve dependencies only in media marked as containing updates (e.g. which have been created with \"urpmi.addmedia --update\")."
msgstr "Ипользовать только источники обновлений. Это означает, что urpmq будет искать и разрешать зависимости только используя источники, помеченные как источники обновлений (например, которые были добавлены при помощи \"urpmi.addmedia --update\")" msgstr "Ипользовать только источники обновлений. Это означает, что urpmq будет искать и разрешать зависимости только используя источники, помеченные как источники обновлений (например, которые были добавлены при помощи \"urpmi.addmedia --update\")"
#: urpm-package-cleanup.py:80 urpm-tools/urpm-package-cleanup.py:80 #: urpm-package-cleanup.py:84 urpm-tools/urpm-package-cleanup.py:84
msgid "Select specific media to be used, instead of defaulting to all available media (or all update media if --update is used). No rpm will be found in other media." msgid "Select specific media to be used, instead of defaulting to all available media (or all update media if --update is used). No rpm will be found in other media."
msgstr "Выбрать особые источники вместо того чтобы использовать все доступные по умолчанию источники (или все источники обновлений, если указан флаг --update). В других источниках пакеты искаться не будут." msgstr "Выбрать особые источники вместо того чтобы использовать все доступные по умолчанию источники (или все источники обновлений, если указан флаг --update). В других источниках пакеты искаться не будут."
#: urpm-package-cleanup.py:85 urpm-tools/urpm-package-cleanup.py:85 #: urpm-package-cleanup.py:89 urpm-tools/urpm-package-cleanup.py:89
msgid "Do not use the specified media." msgid "Do not use the specified media."
msgstr "Не использовать указанные источники." msgstr "Не использовать указанные источники."
#: urpm-package-cleanup.py:87 urpm-tools/urpm-package-cleanup.py:87 #: urpm-package-cleanup.py:91 urpm-tools/urpm-package-cleanup.py:91
msgid "Dependency Problems Options" msgid "Dependency Problems Options"
msgstr "Проблемы с зависимостями" msgstr "Проблемы с зависимостями"
#: urpm-package-cleanup.py:90 urpm-tools/urpm-package-cleanup.py:90 #: urpm-package-cleanup.py:94 urpm-tools/urpm-package-cleanup.py:94
msgid "List dependency problems in the local RPM database" msgid "List dependency problems in the local RPM database"
msgstr "Перечислить проблемы с зависимостями в локальной базе RPM" msgstr "Перечислить проблемы с зависимостями в локальной базе RPM"
#: urpm-package-cleanup.py:93 urpm-tools/urpm-package-cleanup.py:93 #: urpm-package-cleanup.py:97 urpm-tools/urpm-package-cleanup.py:97
msgid "List missing suggestions of installed packages" msgid "List missing suggestions of installed packages"
msgstr "Перечислить список мягких зависимостей установленных пакетов" msgstr "Перечислить список мягких зависимостей установленных пакетов"
#: urpm-package-cleanup.py:96 urpm-tools/urpm-package-cleanup.py:96 #: urpm-package-cleanup.py:100 urpm-tools/urpm-package-cleanup.py:100
msgid "Duplicate Package Options" msgid "Duplicate Package Options"
msgstr "Дублирующиеся пакеты" msgstr "Дублирующиеся пакеты"
#: urpm-package-cleanup.py:99 urpm-tools/urpm-package-cleanup.py:99 #: urpm-package-cleanup.py:103 urpm-tools/urpm-package-cleanup.py:103
msgid "Scan for duplicates in your rpmdb" msgid "Scan for duplicates in your rpmdb"
msgstr "Найти дубликаты в локальной базе RPM" msgstr "Найти дубликаты в локальной базе RPM"
#: urpm-package-cleanup.py:102 urpm-tools/urpm-package-cleanup.py:102 #: urpm-package-cleanup.py:106 urpm-tools/urpm-package-cleanup.py:106
msgid "Scan for duplicates in your rpmdb and remove older " msgid "Scan for duplicates in your rpmdb and remove older "
msgstr "Найти дубликаты в локальной базе RPM и удалить более старые" msgstr "Найти дубликаты в локальной базе RPM и удалить более старые"
#: urpm-package-cleanup.py:105 urpm-tools/urpm-package-cleanup.py:105 #: urpm-package-cleanup.py:109 urpm-tools/urpm-package-cleanup.py:109
msgid "disable rpm scriptlets from running when cleaning duplicates" msgid "disable rpm scriptlets from running when cleaning duplicates"
msgstr "отключить скриптлеты rpm при очистке дубликатов" msgstr "отключить скриптлеты rpm при очистке дубликатов"
#: urpm-package-cleanup.py:107 urpm-tools/urpm-package-cleanup.py:107 #: urpm-package-cleanup.py:111 urpm-tools/urpm-package-cleanup.py:111
msgid "Leaf Node Options" msgid "Leaf Node Options"
msgstr "Листовые узлы" msgstr "Листовые узлы"
#: urpm-package-cleanup.py:110 urpm-tools/urpm-package-cleanup.py:110 #: urpm-package-cleanup.py:114 urpm-tools/urpm-package-cleanup.py:114
msgid "List leaf nodes in the local RPM database" msgid "List leaf nodes in the local RPM database"
msgstr "Перечислить листовые узлы в локальной базе RPM" msgstr "Перечислить листовые узлы в локальной базе RPM"
#: urpm-package-cleanup.py:113 urpm-tools/urpm-package-cleanup.py:113 #: urpm-package-cleanup.py:117 urpm-tools/urpm-package-cleanup.py:117
msgid "list all packages leaf nodes that do not match leaf-regex" msgid "list all packages leaf nodes that do not match leaf-regex"
msgstr "перечислить все пакеты-листовые узлы, имя которых не подходить под регулярное выражение" msgstr "перечислить все пакеты-листовые узлы, имя которых не подходить под регулярное выражение"
#: urpm-package-cleanup.py:117 urpm-tools/urpm-package-cleanup.py:117 #: urpm-package-cleanup.py:121 urpm-tools/urpm-package-cleanup.py:121
msgid "A package name that matches this regular expression (case insensitively) is a leaf" msgid "A package name that matches this regular expression (case insensitively) is a leaf"
msgstr "Считать листовым узлом пакет, имя которого подходит по регулярному выражению (регистронезависимо)." msgstr "Считать листовым узлом пакет, имя которого подходит по регулярному выражению (регистронезависимо)."
#: urpm-package-cleanup.py:121 urpm-tools/urpm-package-cleanup.py:121 #: urpm-package-cleanup.py:125 urpm-tools/urpm-package-cleanup.py:125
msgid "do not list development packages as leaf nodes" msgid "do not list development packages as leaf nodes"
msgstr "не считать devel пакеты листовыми узлами" msgstr "не считать devel пакеты листовыми узлами"
#: urpm-package-cleanup.py:124 urpm-tools/urpm-package-cleanup.py:124 #: urpm-package-cleanup.py:128 urpm-tools/urpm-package-cleanup.py:128
msgid "do not list packages with files in a bin dirs as leaf nodes" msgid "do not list packages with files in a bin dirs as leaf nodes"
msgstr "не считать пакеты, имеющие файлы в bin директориях, листовыми узлами" msgstr "не считать пакеты, имеющие файлы в bin директориях, листовыми узлами"
#: urpm-package-cleanup.py:127 urpm-tools/urpm-package-cleanup.py:127 #: urpm-package-cleanup.py:131 urpm-tools/urpm-package-cleanup.py:131
msgid "Old Kernel Options" msgid "Old Kernel Options"
msgstr "Старые ядра" msgstr "Старые ядра"
#: urpm-package-cleanup.py:130 urpm-tools/urpm-package-cleanup.py:130 #: urpm-package-cleanup.py:134 urpm-tools/urpm-package-cleanup.py:134
msgid "Remove old kernel and kernel-devel packages" msgid "Remove old kernel and kernel-devel packages"
msgstr "Удалить старые ядра и их devel пакеты." msgstr "Удалить старые ядра и их devel пакеты."
#: urpm-package-cleanup.py:133 urpm-tools/urpm-package-cleanup.py:133
msgid "Number of kernel packages to keep on the system (default 2)"
msgstr "Количество пакетов с ядрами, которые надо сохранить в системе (по умолчанию 2)"
#: urpm-package-cleanup.py:137 urpm-tools/urpm-package-cleanup.py:137 #: urpm-package-cleanup.py:137 urpm-tools/urpm-package-cleanup.py:137
msgid "Do not remove kernel-devel packages when removing kernels" msgid "Do not remove kernel-devel packages when removing kernels"
msgstr "Не удалять kernel-devel пакеты при удалении ядер" msgstr "Не удалять kernel-devel пакеты при удалении ядер"
#: urpm-package-cleanup.py:306 urpm-tools/urpm-package-cleanup.py:306 #: urpm-package-cleanup.py:177 urpm-tools/urpm-package-cleanup.py:177
#, python-format
msgid "Warning: invalid value of kernels_to_keep (%(keep)d) in %(cfg)s."
msgstr "Предупреждение: недопустимое значение параметра kernels_to_keep (%(keep)d) в %(cfg)s."
#: urpm-package-cleanup.py:180 urpm-tools/urpm-package-cleanup.py:180
#, python-format
msgid "Warning: unable to read %(cfg)s: %(err)s."
msgstr "Предупреждение: не удалось прочитать %(cfg)s: %(err)s."
#: urpm-package-cleanup.py:182 urpm-tools/urpm-package-cleanup.py:182
#, python-format
msgid "Warning: %(cfg)s may contain incorrect data: %(err)s."
msgstr "Предупреждение: в %(cfg)s могут быть некорректные данные: %(err)s."
#: urpm-package-cleanup.py:339 urpm-tools/urpm-package-cleanup.py:339
#, python-format #, python-format
msgid "Warning: neither single nor multi lib arch: %s " msgid "Warning: neither single nor multi lib arch: %s "
msgstr "Некорректная архитектура: %s " msgstr "Некорректная архитектура: %s "
#: urpm-package-cleanup.py:417 urpm-tools/urpm-package-cleanup.py:417 #: urpm-package-cleanup.py:391 urpm-tools/urpm-package-cleanup.py:391
#, python-format #, python-format
msgid "Not removing kernel %(kver)s-%(krel)s because it is the running kernel" msgid "%(pkg)s will not be removed: it is required by %(req)s."
msgstr "Невозможно удалить пакет %(kver)s-%(krel)s, потому что это запущенное ядро" msgstr "Пакет %(pkg)s не будет удалён, т.к. от его зависит пакет %(req)s."
#: urpm-package-cleanup.py:447 urpm-tools/urpm-package-cleanup.py:447 #: urpm-package-cleanup.py:456 urpm-tools/urpm-package-cleanup.py:456
#, python-format
msgid "%s will not be removed: it might be a custom-built kernel."
msgstr "Пакет %s не будет удалён: возможно, это специальная сборка ядра."
#: urpm-package-cleanup.py:463 urpm-tools/urpm-package-cleanup.py:463
#, python-format
msgid "%s will not be removed: it contains the running kernel."
msgstr "Пакет %s не будет удалён, т.к. содержит работающее в данный момент ядро."
#: urpm-package-cleanup.py:493 urpm-tools/urpm-package-cleanup.py:493
#, python-format #, python-format
msgid "Package %(qf)s %(prob)s" msgid "Package %(qf)s %(prob)s"
msgstr "Пакет %(qf)s %(prob)s" msgstr "Пакет %(qf)s %(prob)s"
#: urpm-package-cleanup.py:450 urpm-tools/urpm-package-cleanup.py:450 #: urpm-package-cleanup.py:496 urpm-tools/urpm-package-cleanup.py:496
msgid "Missing suggests:" msgid "Missing suggests:"
msgstr "Недостающие мягкие зависимости:" msgstr "Недостающие мягкие зависимости:"
#: urpm-package-cleanup.py:458 urpm-tools/urpm-package-cleanup.py:458 #: urpm-package-cleanup.py:504 urpm-tools/urpm-package-cleanup.py:504
msgid "No Problems Found" msgid "No Problems Found"
msgstr "Проблем не найдено" msgstr "Проблем не найдено"
#: urpm-package-cleanup.py:473 urpm-tools/urpm-package-cleanup.py:473
msgid "Error: Cannot remove kernels as a user, must be root"
msgstr "Ошибка: Невозможно удалить ядро, нужны права root."
#: urpm-package-cleanup.py:476 urpm-tools/urpm-package-cleanup.py:476
msgid "Error: should keep at least 1 kernel!"
msgstr "Ошибка: нужно оставить хотя бы одно ядро!"
#: urpm-package-cleanup.py:529 urpm-tools/urpm-package-cleanup.py:529 #: urpm-package-cleanup.py:529 urpm-tools/urpm-package-cleanup.py:529
msgid "Error: Cannot remove packages as a user, must be root" msgid "Error: Cannot remove packages as a user, must be root"
msgstr "Ошибка: невозможно удалить пакет, нужны права root." msgstr "Ошибка: невозможно удалить пакет, нужны права root."

View file

@ -42,6 +42,10 @@ def exactlyOne(l):
return len(filter(None, l)) == 1 return len(filter(None, l)) == 1
KERNEL_CFG = '/etc/urpmi/kernels.cfg'
KERNELS_TO_KEEP_DEFAULT = 3
class PackageCleanup(): class PackageCleanup():
NAME = 'urpm-package-cleanup' NAME = 'urpm-package-cleanup'
VERSION = '0.1' VERSION = '0.1'
@ -128,10 +132,6 @@ class PackageCleanup():
kernelgrp.add_argument("--oldkernels", default=False, kernelgrp.add_argument("--oldkernels", default=False,
dest="kernels",action="store_true", dest="kernels",action="store_true",
help=_("Remove old kernel and kernel-devel packages")) help=_("Remove old kernel and kernel-devel packages"))
kernelgrp.add_argument("--count",default=2,dest="kernelcount",
action="store",
help=_('Number of kernel packages to keep on the '\
'system (default 2)'))
kernelgrp.add_argument("--keepdevel", default=False, dest="keepdevel", kernelgrp.add_argument("--keepdevel", default=False, dest="keepdevel",
action="store_true", action="store_true",
help=_('Do not remove kernel-devel packages when ' help=_('Do not remove kernel-devel packages when '
@ -149,6 +149,39 @@ class PackageCleanup():
else: else:
subprocess.call(['urpme', pkgName]) subprocess.call(['urpme', pkgName])
def get_kernel_options(self):
"""Returns a tuple (remove_old_kernels, kernels_to_keep)
remove_old_kernels (bool) - whether to remove the old kernels.
kernels_to_keep (int) - how many kernels to keep, ignored if
remove_old_kernels is False.
"""
remove_old_kernels = True
to_keep = KERNELS_TO_KEEP_DEFAULT
try:
with open(KERNEL_CFG, 'r') as cfg:
for line in cfg:
(name, tmp, value) = line.partition('=')
name = name.strip()
value = value.strip().lower()
if not name or not value:
continue
if name == 'remove_old_kernels':
if value in ['false', 'no', 'off', '0']:
remove_old_kernels = False
elif name == 'kernels_to_keep':
to_keep = int(value)
if to_keep < 1:
print _('Warning: invalid value of kernels_to_keep (%(keep)d) in %(cfg)s.') % {'keep': to_keep, 'cfg': KERNEL_CFG}
to_keep = KERNELS_TO_KEEP_DEFAULT
except IOError as e:
print _('Warning: unable to read %(cfg)s: %(err)s.') % {'cfg': KERNEL_CFG, 'err': str(e)}
except ValueError as e:
print _('Warning: %(cfg)s may contain incorrect data: %(err)s.') % {'cfg': KERNEL_CFG, 'err': str(e)}
return remove_old_kernels, to_keep
@staticmethod @staticmethod
def _genDeptup(name, flags, version): def _genDeptup(name, flags, version):
@ -351,82 +384,95 @@ class PackageCleanup():
return True return True
return False return False
def _get_kernels(self): def _required_by_latest(self, pkg, latest):
"""return a list of all installed kernels, sorted newest to oldest""" """Checks whether 'pkg' is required by some package from 'latest'."""
for lp in latest:
if pkg['name'] in lp['requires']:
print _('%(pkg)s will not be removed: it is required by %(req)s.') % {'pkg': pkg['name'], 'req': lp['name']}
return True
return False
def _devel_to_remove(self, to_remove, kernels, latest):
"""Returns the list of kernel development packages to remove.
The list includes the devel packages corresponding to the kernels
from 'to_remove' and the packages that have no matching kernel package
in 'kernels'.
The devel packages required by kernel*-latest ('latest' list) will
not be removed.
"""
# Get the list of devel packages for the kernels.
ts = rpm.TransactionSet() ts = rpm.TransactionSet()
mi = ts.dbMatch('provides','kernel') devel = [pkg for pkg in ts.dbMatch('provides','kernel-devel')]
kernlist = []
for h in mi: to_remove_names = [p['name'] for p in to_remove]
kernlist.append(h) kernel_names = [p['name'] for p in kernels]
kernlist.sort() devel_to_remove = []
kernlist.reverse() for pkg in devel:
return kernlist if self._required_by_latest(pkg, latest):
def _get_old_kernel_devel(self, kernels, removelist):
""" List all kernel devel packages that either belong to kernel versions that
are no longer installed or to kernel version that are in the removelist"""
devellist = []
ts = rpm.TransactionSet()
mi = ts.dbMatch('provides','kernel-devel')
for po in mi:
# For all kernel-devel packages see if there is a matching kernel
# in kernels but not in removelist
keep = False
for kernel in kernels:
if kernel in removelist:
continue continue
(kname,karch,kepoch,kver,krel) = (kernel['name'],kernel['arch'],kernel['epoch'],kernel['version'],kernel['release'])
(dname,darch,depoch,dver,drel) = (po['name'],po['arch'],po['epoch'],po['version'],po['release']) kname = pkg['name'].replace('-devel', '', 1)
if (karch,kepoch,kver,krel) == (darch,depoch,dver,drel): if kname not in kernel_names:
keep = True devel_to_remove.append(pkg)
if not keep: continue
devellist.append(po)
return devellist if kname in to_remove_names:
devel_to_remove.append(pkg)
continue
return devel_to_remove
def _remove_old_kernels(self, count, keepdevel): def _remove_old_kernels(self, count, keepdevel):
"""Remove old kernels, keep at most count kernels (and always keep the running """Remove old kernels, keep at most count kernels (and always keep the running
kernel""" kernel"""
count = int(count) ts = rpm.TransactionSet()
kernels = self._get_kernels()
runningkernel = os.uname()[2]
# Vanilla kernels dont have a release, only a version
if '-' in runningkernel:
splt = runningkernel.split('-')
if len(splt) == 2:
(kver,krel) = splt
else: # Handle cases where a custom build kernel has an extra '-' in the release
kver=splt[1]
krel="-".join(splt[1:])
if krel.split('.')[-1] == os.uname()[-1]:
krel = ".".join(krel.split('.')[:-1])
else:
kver = runningkernel
krel = ""
remove = kernels[count:]
toremove = [] # Get the list of installed kernel packages and sort it by
# Remove running kernel from remove list # installation timestamp, from the newest to the oldest.
for kernel in remove: kernels = [pkg for pkg in ts.dbMatch('provides','kernel')]
if kernel['version'] == kver and krel.startswith(kernel['release']): kernels.sort(key=lambda k: k[rpm.RPMTAG_INSTALLTIME], reverse=True)
print _("Not removing kernel %(kver)s-%(krel)s because it is the running kernel") % {'kver': kver, 'krel': krel}
else:
toremove.append(kernel)
# kernel*-latest packages may require some of the installed kernels
# and/or their devel packages. Such packages will not be removed.
mi = ts.dbMatch()
mi.pattern('name', rpm.RPMMIRE_GLOB, 'kernel*-latest*')
latest = [pkg for pkg in mi]
# Note that the version shown by uname -r has a different format
# compared to the name of the kernel package. Example:
# pkg: kernel-desktop-4.12.0-12.1rosa-x86_64
# uname: 4.12.0-desktop-12.1rosa-x86_64
running = os.uname()[2]
to_remove = []
for kpkg in kernels[count : ]:
# To ['kernel-nrj-desktop', '4.9.20', '1rosa', 'x86_64'] or so.
splt = kpkg['name'].rsplit('-', 3)
if len(splt) != 4:
print _('%s will not be removed: it might be a custom-built kernel.') % kpkg['name']
continue
# get the version as 'uname -r' would return
uname_ver = '-'.join([
splt[1], splt[0].replace('kernel-', '', 1), splt[2], splt[3]])
if uname_ver == running:
print _('%s will not be removed: it contains the running kernel.') % kpkg['name']
continue
if self._required_by_latest(kpkg, latest):
continue
to_remove.append(kpkg)
# Now extend the list with all kernel-devel pacakges that either
# have no matching kernel installed or belong to a kernel that is to
# be removed
if not keepdevel: if not keepdevel:
toremove.extend(self._get_old_kernel_devel(kernels, toremove)) to_remove.extend(self._devel_to_remove(to_remove, kernels, latest))
for po in toremove: for pkg in to_remove:
self._removePkg(po) self._removePkg(pkg)
def main(self): def main(self):
@ -469,16 +515,20 @@ class PackageCleanup():
sys.exit(0) sys.exit(0)
if opts.kernels: if opts.kernels:
remove_old_kernels, kernels_to_keep = self.get_kernel_options()
if not remove_old_kernels:
# Removal of the old kernels is disabled in the config file,
# nothing to do.
sys.exit(0)
if os.geteuid() != 0: if os.geteuid() != 0:
print _("Error: Cannot remove kernels as a user, must be root") print _("Error: Cannot remove kernels as a user, must be root")
sys.exit(1) sys.exit(1)
if int(opts.kernelcount) < 1:
print _("Error: should keep at least 1 kernel!")
sys.exit(100)
if opts.auto: if opts.auto:
self.tsflags.append('--auto') self.tsflags.append('--auto')
self._remove_old_kernels(opts.kernelcount, opts.keepdevel) self._remove_old_kernels(kernels_to_keep, opts.keepdevel)
sys.exit(0) sys.exit(0)
#~ self.run_with_package_names.add('yum-utils') #~ self.run_with_package_names.add('yum-utils')
#~ if hasattr(self, 'doUtilBuildTransaction'): #~ if hasattr(self, 'doUtilBuildTransaction'):