Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion providers/base/units/info/jobs.pxu
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,6 @@ estimated_duration: 0.005
_purpose: Checks the value of the CONFIG_INTEL_IOMMU_DEFAULT_ON flag in the kernel configuration
_summary: Check if the kernel is compiled with IOMMU support


plugin: shell
category_id: com.canonical.plainbox::info
id: info/systemd-analyze
Expand Down
64 changes: 64 additions & 0 deletions providers/resource/bin/kernel_package_resource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env python3
# Copyright 2025 Canonical Ltd.
# All rights reserved.
#
# Authors:
# Fernando Bravo <fernando.bravo.hernandez@canonical.com>
#
# Checkbox is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3,
# as published by the Free Software Foundation.
#
# Checkbox is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.


from checkbox_support.snap_utils.system import on_ubuntucore, get_kernel_snap
from checkbox_support.helpers.release_info import get_release_info
import subprocess
import os


def get_kernel_package_info():

# If we are on Ubuntu Core, just call the get_kernel_snap function
if on_ubuntucore():
return get_kernel_snap(), "snap"

# If we are not on Ubuntu Core, we need to check the kernel package
# installed on the system.

# Get the kernel version
kernel_version = os.uname().release
linux_modules_info = subprocess.check_output(
["apt-cache", "show", "linux-modules-{}".format(kernel_version)],
universal_newlines=True,
stderr=subprocess.DEVNULL,
)
for line in linux_modules_info.splitlines():
if line.startswith("Source:"):
kernel_package = line.split(":")[1].strip()
return kernel_package, "deb"


def main():
release = get_release_info().get("release")
if not release:
raise SystemExit("Unable to get release information.")

kernel_package, kernel_type = get_kernel_package_info()
if not kernel_package:
raise SystemExit("No kernel package found.")

print("name: {}".format(kernel_package))
print("type: {}".format(kernel_type))
print("release: {}".format(release))


if __name__ == "__main__":
main()
9 changes: 9 additions & 0 deletions providers/resource/jobs/resource.pxu
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ command:
_description: Generates a list of packages
_summary: Collect information about installed software packages

id: kernel_package
plugin: resource
category_id: information_gathering
command: kernel_package_resource.py
_description:
Gets kernel package from the source of the linux-modules package or from
snapd if we are on Ubuntu Core.
_summary: Collect information about the kernel package

id: executable
estimated_duration: 0.78
plugin: resource
Expand Down
89 changes: 89 additions & 0 deletions providers/resource/tests/test_kernel_package_resource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/usr/bin/env python3
# Copyright 2025 Canonical Ltd.
# All rights reserved.
#
# Authors:
# Fernando Bravo <fernando.bravo.hernandez@canonical.com>
#
# Checkbox is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3,
# as published by the Free Software Foundation.
#
# Checkbox is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.

import unittest
from unittest.mock import Mock, call, patch

from kernel_package_resource import get_kernel_package_info, main


class TestKernelPackageResource(unittest.TestCase):

@patch("kernel_package_resource.on_ubuntucore")
@patch("kernel_package_resource.get_kernel_snap")
def test_get_kernel_package_info_core(
self, mock_get_kernel_snap, mock_on_ubuntucore
):
"Test the function to get the kernel package info on Ubuntu Core"
mock_get_kernel_snap.return_value = "pc-kernel"
mock_on_ubuntucore.return_value = True
result = get_kernel_package_info()
self.assertEqual(result, ("pc-kernel", "snap"))

@patch("kernel_package_resource.subprocess.check_output")
@patch("kernel_package_resource.os.uname")
def test_get_kernel_package_info_non_core(
self, mock_uname, mock_check_output
):
"Test the function to get the kernel package info on classic"
apt_result = (
"Package: linux-modules-6.8.0-57-generic\n"
"Architecture: amd64\n"
"Version: 6.8.0-57.59\n"
"Priority: optional\n"
"Section: kernel\n"
"Source: linux\n"
"Origin: Ubuntu\n"
)
mock_uname.return_value.release = "6.8.0-57-generic"
mock_check_output.return_value = apt_result
result = get_kernel_package_info()
self.assertEqual(result, ("linux", "deb"))

@patch("kernel_package_resource.get_release_info")
@patch("kernel_package_resource.get_kernel_package_info")
def test_main(self, mock_get_kernel_package_info, mock_get_release_info):
"Test the main function"
mock_get_release_info.return_value = {"release": "22.04"}
mock_get_kernel_package_info.return_value = ("linux", "deb")
with patch("builtins.print") as mock_print:
main()

mock_print.assert_has_calls(
[call("name: linux"), call("type: deb"), call("release: 22.04")]
)

@patch("kernel_package_resource.get_release_info")
def test_main_no_release(self, mock_get_release_info):
"Test the main function with no release"
mock_get_release_info.return_value = {}
with self.assertRaises(SystemExit) as cm:
main()
self.assertEqual(
str(cm.exception), "Unable to get release information."
)

@patch("kernel_package_resource.get_release_info", Mock())
@patch("kernel_package_resource.get_kernel_package_info")
def test_main_no_kernel_package(self, mock_get_kernel_package_info):
"Test the main function with no kernel package"
mock_get_kernel_package_info.return_value = (None, None)
with self.assertRaises(SystemExit) as cm:
main()
self.assertEqual(str(cm.exception), "No kernel package found.")
Loading