← Back to team overview

curtin-dev team mailing list archive

[Merge] ~dbungert/curtin:fix-removal-set into curtin:master

 

Dan Bungert has proposed merging ~dbungert/curtin:fix-removal-set into curtin:master.

Commit message:
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.

Requested reviews:
  curtin developers (curtin-dev)

For more details, see:
https://code.launchpad.net/~dbungert/curtin/+git/curtin/+merge/491324
-- 
Your team curtin developers is requested to review the proposed merge of ~dbungert/curtin:fix-removal-set into curtin:master.
diff --git a/curtin/distro.py b/curtin/distro.py
index c91cbfc..af50481 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 41c3b15..f38b3a7 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

Follow ups