diff options
author | Dan Bungert <[email protected]> | 2025-08-25 17:02:02 +0000 |
---|---|---|
committer | Server Team CI Bot <[email protected]> | 2025-08-25 17:02:02 +0000 |
commit | 74cccc4e3b41d35e8b9e11c6d80021ce2384284d (patch) | |
tree | d249014b413f61b94f61d9d5a84d318a6065554f | |
parent | 941edfe7bc336dc14aaa7990ed03d221b9c41bca (diff) |
distro: ensure_one_kernel - fix metapackage + no kernel install
In the case where we list metapackages in the before list for
ensure_one_kernel(), and we haven't actually installed a kernel during
the yield, there is nothing to remove. Strict set equality check
doesn't handle that correctly.
-rw-r--r-- | curtin/distro.py | 6 | ||||
-rw-r--r-- | tests/unittests/test_distro.py | 57 |
2 files changed, 62 insertions, 1 deletions
diff --git a/curtin/distro.py b/curtin/distro.py index c91cbfcc..af504811 100644 --- a/curtin/distro.py +++ b/curtin/distro.py @@ -542,7 +542,11 @@ def ensure_one_kernel(osfamily=None, target=None, before=None): # is too late to accurately capture the initial state. after = set(list_kernels(osfamily=osfamily, target=target)) LOG.debug('ensure_one_kernel: kernels after install %s', after) - if before == after: + if not bool(after - before): + # this `after - before` construction is similar to checking that they + # are equal, but also handles the case that we haven't installed + # anything during the yield AND the before list includes extra info + # like a kernel metapackage name. LOG.debug( 'No kernels to remove - kernel to install was already installed' ) diff --git a/tests/unittests/test_distro.py b/tests/unittests/test_distro.py index 41c3b154..f38b3a7b 100644 --- a/tests/unittests/test_distro.py +++ b/tests/unittests/test_distro.py @@ -797,4 +797,61 @@ linux-image-6.8.0-28-generic/ii /a, linux-image actual = distro.dpkg_query_list_kernels() self.assertEqual(["linux-image-6.8.0-28-generic"], actual) + +class TestEnsureOneKernel(CiTestCase): + def setUp(self): + self.add_patch('curtin.distro.list_kernels', 'm_list') + self.add_patch('curtin.distro.purge_packages', 'm_purge') + self.generic_a = "linux-image-6.8.0-11-generic" + self.generic_b = "linux-image-6.8.0-28-generic" + self.hwe = "linux-image-generic-hwe-24.04" + + def test_no_preinstall(self): + # nothing preinstalled, we install a kernel, nothing to purge + self.m_list.side_effect = [[], [self.generic_a]] + with distro.ensure_one_kernel(): + pass + self.m_purge.assert_not_called() + + def test_correct_preinstall(self): + # correct kernel preinstalled, nothing to purge + self.m_list.side_effect = [[self.generic_a], [self.generic_a]] + with distro.ensure_one_kernel(): + pass + self.m_purge.assert_not_called() + + def test_change_preinstall(self): + # change from kernel a to b + self.m_list.side_effect = [ + [self.generic_a], + [self.generic_a, self.generic_b] + ] + with distro.ensure_one_kernel(): + pass + self.m_purge.assert_called_with([self.generic_a], target=None) + + def test_change_preinstall_with_metapkg(self): + # change from kernel a to b + self.m_list.side_effect = [ + [self.generic_a, self.hwe], + [self.generic_a, self.generic_b] + ] + with distro.ensure_one_kernel(): + pass + # assert_called_with would be flaky due to unpredictable order of items + # from the set + purged = set(self.m_purge.mock_calls[0].args[0]) + self.assertEqual(set([self.generic_a, self.hwe]), purged) + + def test_fewer(self): + # the initial list may include a kernel metapackage, which won't be + # listed later + self.m_list.side_effect = [ + [self.generic_a, self.hwe], + [self.generic_a] + ] + with distro.ensure_one_kernel(): + pass + self.m_purge.assert_not_called() + # vi: ts=4 expandtab syntax=python |