Split test_s390x_secure_ipl() into two subtests. Each tests with a
different boot device: virtio-blk-ccw or virtio-blk-pci. Use class-level
variables and a temporary shared workdir such that the time-consuming
setup is not run multiple times.

Signed-off-by: Joshua Daley <[email protected]>
---
 tests/functional/s390x/test_secure_ipl.py | 131 ++++++++++++++--------
 1 file changed, 87 insertions(+), 44 deletions(-)

diff --git a/tests/functional/s390x/test_secure_ipl.py 
b/tests/functional/s390x/test_secure_ipl.py
index 5af36b91d8..cc9bff5737 100755
--- a/tests/functional/s390x/test_secure_ipl.py
+++ b/tests/functional/s390x/test_secure_ipl.py
@@ -8,6 +8,9 @@
 secure-boot enabled, and verifying cryptographic validation results.
 """
 
+import os
+import shutil
+import tempfile
 from subprocess import check_call, DEVNULL
 
 from qemu_test import QemuSystemTest, Asset, get_qemu_img
@@ -22,12 +25,24 @@ class S390xSecureIpl(QemuSystemTest):
          'Fedora-Server-KVM-40-1.14.s390x.qcow2'),
         '091c232a7301be14e19c76ce9a0c1cbd2be2c4157884a731e1fc4f89e7455a5f')
 
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.root_password = None
-        self.qcow2_path = None
-        self.cert_path = None
-        self.prompt = None
+    _shared_workdir = None
+    _root_password = None
+    _qcow2_path = None
+    _cert_path = None
+    _prompt = None
+    _setup_done = None
+
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass()
+        cls._shared_workdir = tempfile.mkdtemp(prefix='qemu_sipl_')
+
+    @classmethod
+    def tearDownClass(cls):
+        if cls._shared_workdir is not None:
+            shutil.rmtree(cls._shared_workdir, ignore_errors=True)
+            cls._shared_workdir = None
+        super().tearDownClass()
 
     def _require_host_secure_ipl_support(self, vm):
         """
@@ -62,7 +77,7 @@ def _sign_binaries(self, vm):
         exec_command_and_wait_for_pattern(self,
                                 'sudo dnf install kernel-devel-$(uname -r) -y',
                                 'Complete!', vm=vm)
-        wait_for_console_pattern(self, self.prompt, vm=vm)
+        wait_for_console_pattern(self, S390xSecureIpl._prompt, vm=vm)
         exec_command_and_wait_for_pattern(self,
                                     'ls /usr/src/kernels/$(uname -r)/scripts/',
                                     'sign-file', vm=vm)
@@ -71,11 +86,11 @@ def _sign_binaries(self, vm):
         exec_command(self, '/usr/src/kernels/$(uname -r)/scripts/sign-file '
                     'sha256 mykey.pem mycert.pem /lib/s390-tools/stage3.bin',
                     vm=vm)
-        wait_for_console_pattern(self, self.prompt, vm=vm)
+        wait_for_console_pattern(self, S390xSecureIpl._prompt, vm=vm)
         exec_command(self, '/usr/src/kernels/$(uname -r)/scripts/sign-file '
                     'sha256 mykey.pem mycert.pem /boot/vmlinuz-$(uname -r)',
                     vm=vm)
-        wait_for_console_pattern(self, self.prompt, vm=vm)
+        wait_for_console_pattern(self, S390xSecureIpl._prompt, vm=vm)
 
     def _run_zipl_secure(self, vm):
         """Run zipl to prepare for secure boot"""
@@ -91,10 +106,11 @@ def _extract_certificate(self, vm):
         cert = "\n".join(out.decode("utf-8").splitlines()[1:])
         self.log.info("%s", cert)
 
-        self.cert_path = self.scratch_file("mycert.pem")
+        cert_path = os.path.join(S390xSecureIpl._shared_workdir, "mycert.pem")
 
-        with open(self.cert_path, 'w', encoding="utf-8") as file_object:
+        with open(cert_path, 'w', encoding="utf-8") as file_object:
             file_object.write(cert)
+        S390xSecureIpl._cert_path = cert_path
 
     def setup_s390x_secure_ipl(self):
         """
@@ -109,39 +125,42 @@ def setup_s390x_secure_ipl(self):
         temp_vm.set_machine('s390-ccw-virtio')
 
         asset_path = self.ASSET_F40_QCOW2.fetch()
-        self.qcow2_path = self.scratch_file('f40.qcow2')
+        qcow2_path = os.path.join(S390xSecureIpl._shared_workdir, 'f40.qcow2')
         qemu_img = get_qemu_img(self)
         check_call([qemu_img, 'create', '-f', 'qcow2', '-b', asset_path,
-                    '-F', 'qcow2', self.qcow2_path], stdout=DEVNULL, 
stderr=DEVNULL)
+                    '-F', 'qcow2', qcow2_path], stdout=DEVNULL, stderr=DEVNULL)
+        S390xSecureIpl._qcow2_path = qcow2_path
 
         temp_vm.set_console()
         temp_vm.add_args('-nographic',
                          '-accel', 'kvm',
                          '-m', '1024',
                          '-drive',
-                         
f'id=drive0,if=none,format=qcow2,file={self.qcow2_path}',
+                         f'id=drive0,if=none,format=qcow2,file={qcow2_path}',
                          '-device', 'virtio-blk-ccw,drive=drive0,bootindex=1')
         temp_vm.launch()
 
         self._require_host_secure_ipl_support(temp_vm)
 
         # Initial root account setup (Fedora first boot screen)
-        self.root_password = 'fedora40password'
+        S390xSecureIpl._root_password = 'fedora40password'
         wait_for_console_pattern(self, 'Please make a selection from the 
above',
                                  vm=temp_vm)
         exec_command_and_wait_for_pattern(self, '4', 'Password:', vm=temp_vm)
-        exec_command_and_wait_for_pattern(self, self.root_password,
+        exec_command_and_wait_for_pattern(self, S390xSecureIpl._root_password,
                                           'Password (confirm):', vm=temp_vm)
-        exec_command_and_wait_for_pattern(self, self.root_password,
+        exec_command_and_wait_for_pattern(self, S390xSecureIpl._root_password,
                                     'Please make a selection from the above',
                                     vm=temp_vm)
 
         # Login as root
-        self.prompt = '[root@localhost ~]#'
-        exec_command_and_wait_for_pattern(self, 'c', 'localhost login:', 
vm=temp_vm)
-        exec_command_and_wait_for_pattern(self, 'root', 'Password:', 
vm=temp_vm)
-        exec_command_and_wait_for_pattern(self, self.root_password, 
self.prompt,
+        S390xSecureIpl._prompt = '[root@localhost ~]#'
+        exec_command_and_wait_for_pattern(self, 'c', 'localhost login:',
                                           vm=temp_vm)
+        exec_command_and_wait_for_pattern(self, 'root', 'Password:',
+                                          vm=temp_vm)
+        exec_command_and_wait_for_pattern(self, S390xSecureIpl._root_password,
+                                          S390xSecureIpl._prompt, vm=temp_vm)
 
         self._create_certificate(temp_vm)
         self._sign_binaries(temp_vm)
@@ -150,41 +169,65 @@ def setup_s390x_secure_ipl(self):
 
         # Shutdown temp vm
         temp_vm.shutdown()
+        S390xSecureIpl._setup_done = True
 
-    @skipBigDataTest()
-    def test_s390x_secure_ipl(self):
+    def verify_s390x_secure_ipl(self, boot_dev_bus: str):
         """
         Verify secure boot validation during s390x guest boot.
 
         Expects two "Verified component" messages and confirms
         /sys/firmware/ipl/secure reports secure boot is active.
         """
-        self.require_accelerator('kvm')
-        self.setup_s390x_secure_ipl()
-
-        self.set_machine('s390-ccw-virtio')
-
-        self.vm.set_console()
-        self.vm.add_args('-nographic',
-                         '-machine', 's390-ccw-virtio,secure-boot=on,'
-                         f'boot-certs.0.path={self.cert_path}',
-                         '-accel', 'kvm',
-                         '-m', '1024',
-                         '-drive',
-                         
f'id=drive1,if=none,format=qcow2,file={self.qcow2_path}',
-                         '-device', 'virtio-blk-ccw,drive=drive1,bootindex=1')
-        self.vm.launch()
+        if boot_dev_bus not in ['ccw', 'pci']:
+            raise ValueError(
+                f"boot_dev_bus must be 'ccw' or 'pci', got {boot_dev_bus}")
+
+        vm = self.get_vm(name=f'sipl_test_vblk_{boot_dev_bus}')
+        vm.set_machine('s390-ccw-virtio')
+
+        vm.set_console()
+        vm.add_args('-nographic',
+                    '-machine', 's390-ccw-virtio,secure-boot=on,'
+                    f'boot-certs.0.path={S390xSecureIpl._cert_path}',
+                    '-accel', 'kvm',
+                    '-m', '1024',
+                    '-drive',
+                    f'id=drive1,if=none,format=qcow2,'
+                    f'file={S390xSecureIpl._qcow2_path}',
+                    '-device',
+                    f'virtio-blk-{boot_dev_bus},drive=drive1,bootindex=1')
+        vm.launch()
 
         # Expect two verified components
         verified_output = "Verified component"
-        wait_for_console_pattern(self, verified_output)
-        wait_for_console_pattern(self, verified_output)
+        wait_for_console_pattern(self, verified_output, vm=vm)
+        wait_for_console_pattern(self, verified_output, vm=vm)
 
         # Login and verify the vm is booted using secure boot
-        wait_for_console_pattern(self, 'localhost login:')
-        exec_command_and_wait_for_pattern(self, 'root', 'Password:')
-        exec_command_and_wait_for_pattern(self, self.root_password, 
self.prompt)
-        exec_command_and_wait_for_pattern(self, 'cat 
/sys/firmware/ipl/secure', '1')
+        wait_for_console_pattern(self, 'localhost login:', vm=vm)
+        exec_command_and_wait_for_pattern(self, 'root', 'Password:', vm=vm)
+        exec_command_and_wait_for_pattern(
+            self, S390xSecureIpl._root_password, S390xSecureIpl._prompt, vm=vm)
+        exec_command_and_wait_for_pattern(
+            self, 'cat /sys/firmware/ipl/secure', '1', vm=vm)
+
+        vm.shutdown()
+
+    @skipBigDataTest()
+    def test_s390x_secure_ipl_ccw(self):
+        """Test secure IPL with a virtio-blk-ccw boot device."""
+        self.require_accelerator('kvm')
+        if not S390xSecureIpl._setup_done:
+            self.setup_s390x_secure_ipl()
+        self.verify_s390x_secure_ipl('ccw')
+
+    @skipBigDataTest()
+    def test_s390x_secure_ipl_pci(self):
+        """Test secure IPL with a virtio-blk-pci boot device."""
+        self.require_accelerator('kvm')
+        if not S390xSecureIpl._setup_done:
+            self.setup_s390x_secure_ipl()
+        self.verify_s390x_secure_ipl('pci')
 
 if __name__ == '__main__':
     QemuSystemTest.main()
-- 
2.34.1


Reply via email to