diff --git a/.gitignore b/.gitignore index ab64faa..6881f65 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.pyc .cache/ .idea/ +.venv/ diff --git a/check_kernel b/check_kernel index 5d6201a..73a69a0 100755 --- a/check_kernel +++ b/check_kernel @@ -73,7 +73,7 @@ def running_kernel_version(): proc_version_ = re.sub('\(gcc.*?\)', '', proc_version_) # Then look for the Debian kernel version - m = re.search('(?<=Debian )(\S+)', proc_version_) + m = re.search('((?<=Debian )(\S+)|(?<=PVE )(\S+))', proc_version_) if m: version_str = m.group(1).strip('()') version = clean_kernel_version(version_str) @@ -99,8 +99,17 @@ def is_redhat(): def installed_kernel_versions(): + """ + Debian-based kernels come in different flavors. + + On some of them, like Proxmox' PVE kernels, special care has to be taken + when selecting the right packages to run `dpkg-query` on. + """ if is_debian(): - return installed_kernel_versions_debian() + return \ + installed_kernel_versions_debian(pkgname='linux-image') \ + or installed_kernel_versions_debian(pkgname='pve-kernel', + pkgquery='pve-kernel*-pve') if is_fedora() or is_redhat(): return installed_kernel_versions_fedora() return [None] @@ -108,18 +117,22 @@ def installed_kernel_versions(): def check_output(cmd): """Emulate subprocess.check_output for ancient Python versions""" - return subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] + return subprocess.Popen( + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ).communicate()[0] -def installed_kernel_versions_debian(): +def installed_kernel_versions_debian(pkgname='linux-image', pkgquery=None): + if not pkgquery: + pkgquery = '%s*' % pkgname dpkg_out = check_output( ['dpkg-query', '--show', '--showformat', '${Package} ${Version}\n', - 'linux-image*']) + pkgquery]) dpkg_out = dpkg_out.decode('ascii', 'ignore').strip() versions = dpkg_out.split('\n') - versions = [v for v in versions if re.search('^linux-image-\d.* \S+$', v)] + versions = [v for v in versions if re.search('^%s-\d.* \S+$' % pkgname, v)] versions = [clean_kernel_version(v.split(' ')[1]) for v in versions] return versions @@ -137,7 +150,11 @@ def installed_kernel_versions_fedora(): def installed_kernel_version(): - return sorted(installed_kernel_versions())[-1] + installed = sorted(installed_kernel_versions()) + if not installed: + print('KERNEL UNKNOWN - unable to determine running kernel version') + sys.exit(3) + return installed[-1] def clean_kernel_version(version): diff --git a/check_kernel_test.py b/check_kernel_test.py index bcaf344..7263f13 100644 --- a/check_kernel_test.py +++ b/check_kernel_test.py @@ -26,11 +26,16 @@ if not hasattr(unittest.TestCase, 'assertLess'): class CleanKernelVersionTestCase(unittest.TestCase): - def testDebian(self): + def testDebianVanilla(self): versions = [('3.16.7-ckt9-3~deb8u2', '3.16.7-ckt9-3~deb8u2')] for dirty, clean in versions: self.assertEqual(clean_kernel_version(dirty), Version(clean)) + def testDebianProxmox(self): + versions = [('5.13.19-14', '5.13.19-14')] + for dirty, clean in versions: + self.assertEqual(clean_kernel_version(dirty), Version(clean)) + def testFedora(self): versions = [ ('4.0.4-301.fc22.x86_64', '4.0.4-301'), @@ -54,7 +59,7 @@ class RunningKernelVersionTestCase(unittest.TestCase): self.assertEqual(check_kernel.running_kernel_version(), Version('4.0.3-301')) - def testDebian(self): + def testDebianVanilla(self): patch_object(check_kernel, 'proc_version', return_value='Linux version 4.19.0-5-amd64 (debian-kernel@lists.debian.org) (gcc version 8.3.0 (Debian 8.3.0-7)) #1 SMP Debian 4.19.37-5 (2019-06-19)') self.assertEqual(check_kernel.running_kernel_version(), Version('4.19.37-5')) @@ -71,6 +76,15 @@ class RunningKernelVersionTestCase(unittest.TestCase): self.assertEqual(check_kernel.running_kernel_version(), Version('5.10.46-4')) + def testDebianProxmox(self): + patch_object(check_kernel, 'proc_version', return_value='Linux version 5.4.162-1-pve (build@proxmox) (gcc version 8.3.0 (Debian 8.3.0-6)) #1 SMP PVE 5.4.162-2 (Thu, 20 Jan 2022 16:38:53 +0100)') + self.assertEqual(check_kernel.running_kernel_version(), + Version('5.4.162-2')) + + patch_object(check_kernel, 'proc_version', return_value='Linux version 5.13.19-6-pve (build@proxmox) (gcc (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2) #1 SMP PVE 5.13.19-14 (Thu, 10 Mar 2022 16:24:52 +0100)') + self.assertEqual(check_kernel.running_kernel_version(), + Version('5.13.19-14')) + class VersionTestCase(unittest.TestCase): def testStr(self):