Skip to content

Commit

Permalink
Handle no installed dkms modules (BugFix) (#1426)
Browse files Browse the repository at this point in the history
* Handle no installed dkms modules

* more testing
  • Loading branch information
jocave authored Aug 21, 2024
1 parent 8a0bb41 commit 77b84c8
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 34 deletions.
13 changes: 12 additions & 1 deletion providers/sru/bin/dkms_build_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ def parse_dkms_status(dkms_status: str, ubuntu_release: str) -> List[Dict]:
else:
kernel_ver = details.split(", ")[2]
kernel_info.append({"version": kernel_ver, "status": status})
print(
"Found module {}, status {} for kernel version {}".format(
details, status, kernel_ver
)
)

sorted_kernel_info = sorted(
kernel_info, key=lambda x: parse_version(x["version"])
Expand Down Expand Up @@ -177,14 +182,20 @@ def main():
# Parse and sort the DKMS status and sort the kernel versions
sorted_kernel_info = parse_dkms_status(dkms_status, ubuntu_release)

# if there are no built or installed dkms modules there is nothing
# to check
if not sorted_kernel_info:
print("No installed dkms modules found, nothing to check")
return 0

# kernel_ver_max should be the same as kernel_ver_current
kernel_ver_current = run_command(["uname", "-r"])
if check_kernel_version(
kernel_ver_current, sorted_kernel_info, dkms_status
):
return 1

# Count the occurernces of the latest and the oldest kernel version and
# Count the occurrences of the latest and the oldest kernel version and
# compare the number of DKMS modules for min and max kernel versions
check_dkms_module_count(sorted_kernel_info, dkms_status)

Expand Down
175 changes: 142 additions & 33 deletions providers/sru/tests/test_dkms_build_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class TestDKMSValidation(unittest.TestCase):
"fwts/24.01.00, 6.5.0-15-generic, x86_64: installed"
)

dkms_status_empty = ""

dkms_status_added_only = "fwts-efi-runtime-dkms/24.07.00: added"

# Example output of `dkms status` on machine
# in which efi_test driver is used rather than
# fwts dkms driver
Expand All @@ -47,11 +51,25 @@ class TestDKMSValidation(unittest.TestCase):
"(WARNING! Diff between built and installed module!)"
)

dkms_status_oem_focal = (
"fwts-efi-runtime-dkms, 24.07.00, 5.14.0-1042-oem, x86_64: installed\n"
"fwts-efi-runtime-dkms, 24.07.00, 5.15.0-117-generic, x86_64: installed"
)

dkms_status_stock_noble = (
"fwts-efi-runtime-dkms/24.07.00: added\n"
"nvidia/550.107.02, 6.8.0-44-generic, x86_64: installed"
)

sorted_kernel_info = [
{"version": "6.5.0-15-generic", "status": "installed"},
{"version": "6.5.0-17-generic", "status": "installed"},
]

sorted_kernel_info_empty = []

sorted_kernel_info_added_only = []

sorted_kernel_info_efi_test_driver = [
{"version": "6.1.0-1028-oem", "status": "installed"},
{"version": "6.1.0-1032-oem", "status": "installed"},
Expand All @@ -66,6 +84,10 @@ class TestDKMSValidation(unittest.TestCase):
{"version": "6.8.0-40-generic", "status": "installed"},
]

sorted_kernel_info_with_warning = [
{"version": "6.0.0-1011-oem", "status": "installed"}
]

@patch("dkms_build_validation.subprocess.check_output")
def test_run_command(self, mock_check_output):
mock_check_output.return_value = "output"
Expand Down Expand Up @@ -98,6 +120,20 @@ def test_parse_dkms_status(self):
]
self.assertEqual(kernel_info, expected_kernel_info)

def test_parse_dkms_status_empty(self):
ubuntu_release = "20.04"
kernel_info = parse_dkms_status(self.dkms_status_empty, ubuntu_release)
expected_kernel_info = []
self.assertEqual(kernel_info, expected_kernel_info)

def test_parse_dkms_status_added_only(self):
ubuntu_release = "22.04"
kernel_info = parse_dkms_status(
self.dkms_status_added_only, ubuntu_release
)
expected_kernel_info = []
self.assertEqual(kernel_info, expected_kernel_info)

def test_parse_dkms_status_efi_test(self):
ubuntu_release = "22.04"
kernel_info = parse_dkms_status(
Expand Down Expand Up @@ -181,6 +217,7 @@ def test_check_kernel_version(self):
1,
)

def test_check_kernel_version_efi_test_driver(self):
self.assertEqual(
check_kernel_version(
"6.1.0-1028-oem",
Expand Down Expand Up @@ -208,6 +245,16 @@ def test_check_kernel_version(self):
0,
)

def test_check_kernel_version_with_warning(self):
self.assertEqual(
check_kernel_version(
"6.0.0-1011-oem",
self.sorted_kernel_info_with_warning,
self.dkms_status_with_warning,
),
0,
)

def test_check_dkms_module_count(self):
# Test with the same number of modules
self.assertEqual(
Expand Down Expand Up @@ -268,46 +315,108 @@ def test_has_dkms_build_errors(self):
self.assertEqual(has_dkms_build_errors(kernel_ver_current), True)

@patch("dkms_build_validation.run_command")
@patch("dkms_build_validation.parse_dkms_status")
@patch("dkms_build_validation.check_kernel_version")
@patch("dkms_build_validation.check_dkms_module_count")
@patch("dkms_build_validation.has_dkms_build_errors")
def test_main(
self, mock_err, mock_count, mock_ver, mock_parse, mock_run_command
):
mock_run_command.return_value = "output"
mock_parse.return_value = []
mock_ver.return_value = 0
mock_count.return_value = 0
def test_main(self, mock_err, mock_run_command):
# 0: lsb_release -r
# 1: dkms status
# 2: uname -r
mock_run_command.side_effect = [
"Release: 22.04",
self.dkms_status,
"6.5.0-17-generic",
]
mock_err.return_value = 0
result = main()
self.assertEqual(mock_err.call_count, 1)
self.assertEqual(result, 0)

@patch("dkms_build_validation.run_command")
@patch("dkms_build_validation.has_dkms_build_errors")
def test_main_empty(self, mock_err, mock_run_command):
mock_run_command.side_effect = [
"Release: 22.04",
"",
"6.8.0-40-generic",
]
mock_err.return_value = 0
result = main()
self.assertEqual(mock_err.call_count, 0)
self.assertEqual(result, 0)

@patch("dkms_build_validation.run_command")
@patch("dkms_build_validation.has_dkms_build_errors")
def test_main_added_only(self, mock_err, mock_run_command):
mock_run_command.side_effect = [
"Release: 22.04",
self.dkms_status_added_only,
"6.8.0-40-generic",
]
mock_err.return_value = 0
result = main()
self.assertEqual(mock_err.call_count, 0)
self.assertEqual(result, 0)

@patch("dkms_build_validation.run_command")
@patch("dkms_build_validation.has_dkms_build_errors")
def test_main_efi_test_driver(self, mock_err, mock_run_command):
mock_run_command.side_effect = [
"Release: 22.04",
self.dkms_status_efi_test_driver,
"6.8.0-40-generic",
]
mock_err.return_value = 0
self.assertEqual(main(), 0)
result = main()
self.assertEqual(mock_err.call_count, 1)
self.assertEqual(result, 0)

@patch("dkms_build_validation.run_command")
@patch("dkms_build_validation.parse_dkms_status")
@patch("dkms_build_validation.check_kernel_version")
@patch("dkms_build_validation.check_dkms_module_count")
@patch("dkms_build_validation.has_dkms_build_errors")
def test_main_different_kernel_version(
self, mock_err, mock_count, mock_ver, mock_parse, mock_run_command
):
mock_run_command.return_value = "output"
mock_parse.return_value = []
mock_ver.return_value = 1
mock_count.return_value = 0
def test_main_with_warning(self, mock_err, mock_run_command):
mock_run_command.side_effect = [
"Release: 22.04",
self.dkms_status_with_warning,
"6.0.0-1011-oem",
]
mock_err.return_value = 0
self.assertEqual(main(), 1)
result = main()
self.assertEqual(mock_err.call_count, 1)
self.assertEqual(result, 0)

@patch("dkms_build_validation.run_command")
@patch("dkms_build_validation.parse_dkms_status")
@patch("dkms_build_validation.check_kernel_version")
@patch("dkms_build_validation.check_dkms_module_count")
@patch("dkms_build_validation.has_dkms_build_errors")
def test_main_with_dkms_build_errors(
self, mock_err, mock_count, mock_ver, mock_parse, mock_run_command
):
mock_run_command.return_value = "output"
mock_parse.return_value = []
mock_ver.return_value = 0
mock_count.return_value = 0
def test_main_with_dkms_build_errors(self, mock_err, mock_run_command):
mock_run_command.side_effect = [
"Release: 22.04",
self.dkms_status,
"6.5.0-17-generic",
]
mock_err.return_value = 1
self.assertEqual(main(), 1)
result = main()
self.assertEqual(mock_err.call_count, 1)
self.assertEqual(result, 1)

@patch("dkms_build_validation.run_command")
@patch("dkms_build_validation.has_dkms_build_errors")
def test_main_oem_focal(self, mock_err, mock_run_command):
mock_run_command.side_effect = [
"Release: 20.04",
self.dkms_status_oem_focal,
"5.15.0-117-generic",
]
mock_err.return_value = 0
result = main()
self.assertEqual(mock_err.call_count, 1)
self.assertEqual(result, 0)

@patch("dkms_build_validation.run_command")
@patch("dkms_build_validation.has_dkms_build_errors")
def test_main_stock_noble(self, mock_err, mock_run_command):
mock_run_command.side_effect = [
"No LSB modules are available.\nRelease: 24.04",
self.dkms_status_stock_noble,
"6.8.0-44-generic",
]
mock_err.return_value = 0
result = main()
self.assertEqual(mock_err.call_count, 1)
self.assertEqual(result, 0)

0 comments on commit 77b84c8

Please sign in to comment.