← Back to team overview

curtin-dev team mailing list archive

[Merge] ~dbungert/curtin:no-grep-status into curtin:master

 

Dan Bungert has proposed merging ~dbungert/curtin:no-grep-status into curtin:master.

Commit message:
do not squash

switch to dpkg-query for finding the linux-image packages

Requested reviews:
  curtin developers (curtin-dev)

For more details, see:
https://code.launchpad.net/~dbungert/curtin/+git/curtin/+merge/467075
-- 
Your team curtin developers is requested to review the proposed merge of ~dbungert/curtin:no-grep-status into curtin:master.
diff --git a/curtin/distro.py b/curtin/distro.py
index 404590b..4f9fe26 100644
--- a/curtin/distro.py
+++ b/curtin/distro.py
@@ -478,21 +478,25 @@ def install_packages(pkglist, osfamily=None, opts=None, target=None, env=None,
                        assume_downloaded=assume_downloaded)
 
 
-def grep_status_list_kernels(target=None):
+def dpkg_query_list_kernels(target=None):
     target = target_path(target)
     cmd = [
-        "grep-status",
-        "--whole-pkg",
-        "-FProvides",
-        "linux-image",
-        "--and",
-        "-FStatus",
-        "installed",
-        "--show-field=Package",
-        "--no-field-names",
+        "dpkg-query",
+        "--show",
+        "--showformat=${Package}/${db:Status-Abbrev}/${Provides}\n",
     ]
-    out, _ = subp(cmd, capture=True, target=target, rcs=(0, 1))
-    return out.splitlines()
+
+    out, _ = subp(cmd, capture=True, target=target)
+    results = []
+    for line in out.splitlines():
+        package, status, provides = line.strip().split("/")
+        # status abbreviation is 3 columns, 3rd is error state
+        if status != "ii ":
+            continue
+        provide_packages = provides.split(", ")
+        if "linux-image" in provide_packages:
+            results.append(package)
+    return results
 
 
 def list_kernels(osfamily=None, target=None):
@@ -500,7 +504,7 @@ def list_kernels(osfamily=None, target=None):
         osfamily = get_osfamily(target=target)
 
     distro_cfg = {
-        DISTROS.debian: grep_status_list_kernels
+        DISTROS.debian: dpkg_query_list_kernels
     }
 
     list_kernels_cmd = distro_cfg.get(osfamily)
@@ -520,6 +524,7 @@ def ensure_one_kernel(osfamily=None, target=None):
     before = set(list_kernels(osfamily=osfamily, target=target))
     yield
 
+    LOG.debug('ensure_one_kernel: kernels before install %s', before)
     if not bool(before):
         LOG.debug('No kernels to remove - no kernels preinstalled')
         return
@@ -532,6 +537,7 @@ def ensure_one_kernel(osfamily=None, target=None):
     # being preinstalled, but will fail to remove in the case of 2 kernels
     # preinstalled but only one of them is intended.
     after = set(list_kernels(osfamily=osfamily, target=target))
+    LOG.debug('ensure_one_kernel: kernels after install %s', after)
     if not bool(after - before):
         LOG.debug(
             'No kernels to remove - kernel to install was already installed'
diff --git a/tests/unittests/test_curthooks.py b/tests/unittests/test_curthooks.py
index 6819f7a..1543122 100644
--- a/tests/unittests/test_curthooks.py
+++ b/tests/unittests/test_curthooks.py
@@ -60,9 +60,7 @@ class TestCurthooksInstallKernel(CiTestCase):
         self.add_patch('curtin.distro.has_pkg_available', 'mock_haspkg')
         self.add_patch('curtin.distro.install_packages', 'mock_instpkg')
         self.add_patch('curtin.distro.purge_packages', 'mock_purgepkg')
-        self.add_patch(
-            'curtin.distro.grep_status_list_kernels', 'mock_list_kernels',
-        )
+        self.add_patch('curtin.distro.list_kernels', 'mock_list_kernels')
         self.add_patch(
             'curtin.distro.os_release', return_value={"ID": "ubuntu"}
         )
diff --git a/tests/unittests/test_distro.py b/tests/unittests/test_distro.py
index a28a741..41c3b15 100644
--- a/tests/unittests/test_distro.py
+++ b/tests/unittests/test_distro.py
@@ -745,4 +745,56 @@ class TestGetArchitecture(CiTestCase):
                          self.m_rpm_get_arch.call_args_list)
         self.assertEqual(0, self.m_dpkg_get_arch.call_count)
 
+
+class TestListKernels(CiTestCase):
+    def setUp(self):
+        self.add_patch('curtin.distro.subp', 'm_subp')
+
+    def test_dpkg_query_list_kernels_installed(self):
+        data = """\
+linux-image-6.8.0-26-generic/rc /a, linux-image, b
+linux-image-6.8.0-27-generic/ii /a, linux-image, b
+linux-image-6.8.0-28-generic/ii /a, linux-image, b
+"""
+        self.m_subp.return_value = (data, None)
+        actual = distro.dpkg_query_list_kernels()
+        expected = [
+            "linux-image-6.8.0-27-generic",
+            "linux-image-6.8.0-28-generic",
+        ]
+
+        self.assertEqual(expected, actual)
+
+    def test_dpkg_query_list_kernels_no_provide(self):
+        data = """\
+linux-image-6.8.0-28-generic/ii /
+"""
+        self.m_subp.return_value = (data, None)
+        actual = distro.dpkg_query_list_kernels()
+        self.assertEqual([], actual)
+
+    def test_dpkg_query_list_kernels_not_installed(self):
+        data = """\
+linux-image-6.8.0-22-generic/rc /a, linux-image, b
+"""
+        self.m_subp.return_value = (data, None)
+        actual = distro.dpkg_query_list_kernels()
+        self.assertEqual([], actual)
+
+    def test_dpkg_query_list_kernels_provide_no_commas(self):
+        data = """\
+linux-image-6.8.0-28-generic/ii /linux-image
+"""
+        self.m_subp.return_value = (data, None)
+        actual = distro.dpkg_query_list_kernels()
+        self.assertEqual(["linux-image-6.8.0-28-generic"], actual)
+
+    def test_dpkg_query_list_kernels_provides_last(self):
+        data = """\
+linux-image-6.8.0-28-generic/ii /a, linux-image
+"""
+        self.m_subp.return_value = (data, None)
+        actual = distro.dpkg_query_list_kernels()
+        self.assertEqual(["linux-image-6.8.0-28-generic"], actual)
+
 # vi: ts=4 expandtab syntax=python
diff --git a/tools/vmtest-system-setup b/tools/vmtest-system-setup
index 482e431..2f82464 100755
--- a/tools/vmtest-system-setup
+++ b/tools/vmtest-system-setup
@@ -15,7 +15,6 @@ DEPS=(
   build-essential
   cloud-image-utils
   cryptsetup
-  dctrl-tools
   git
   make
   net-tools

Follow ups