diff --git a/test/check-machines-consoles b/test/check-machines-consoles index 0c6ded489..3cc8e2c46 100755 --- a/test/check-machines-consoles +++ b/test/check-machines-consoles @@ -19,14 +19,14 @@ import time -from machineslib import VirtualMachinesCase -from testlib import nondestructive, skipImage, test_main, wait +import machineslib +import testlib -@nondestructive -class TestMachinesConsoles(VirtualMachinesCase): +@testlib.nondestructive +class TestMachinesConsoles(machineslib.VirtualMachinesCase): - @skipImage('SPICE not supported on RHEL', "rhel-*", "centos-*") + @testlib.skipImage('SPICE not supported on RHEL', "rhel-*", "centos-*") def testExternalConsole(self): b = self.browser @@ -121,7 +121,7 @@ class TestMachinesConsoles(VirtualMachinesCase): break time.sleep(1) # Make sure the content of console is expected - wait(lambda: "cirros login" in b.text(f"#{name}-terminal .xterm-accessibility-tree")) + testlib.wait(lambda: "cirros login" in b.text(f"#{name}-terminal .xterm-accessibility-tree")) b.click(f"#{name}-serialconsole-disconnect") b.wait_text(f"#{name}-terminal", "Disconnected from serial console. Click the connect button.") @@ -219,4 +219,4 @@ class TestMachinesConsoles(VirtualMachinesCase): if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-create b/test/check-machines-create index 21ea93624..d4dee0242 100755 --- a/test/check-machines-create +++ b/test/check-machines-create @@ -24,17 +24,17 @@ import time import xml.etree.ElementTree as ET from datetime import datetime -from machineslib import VirtualMachinesCase +import machineslib +import testlib from machinesxmls import NETWORK_XML_PXE, PXE_SERVER_CFG -from testlib import Error, nondestructive, skipImage, test_main, wait NO_STORAGE = "No storage" NEW_VOLUME_QCOW2 = "Create new qcow2 volume" NEW_VOLUME_RAW = "Create new raw volume" -@nondestructive -class TestMachinesCreate(VirtualMachinesCase): +@testlib.nondestructive +class TestMachinesCreate(machineslib.VirtualMachinesCase): # This test contains basic button and form validation of the Create VM dialog # None of the sub-tests will actually call virt-install @@ -496,8 +496,8 @@ class TestMachinesCreate(VirtualMachinesCase): # virt-install will overwrite our changes. # Wait for virt-install to define the VM, stop it, and wait for virt-install to be done - wait(lambda: "pxe-guest" in self.machine.execute("virsh list --name --persistent"), delay=3) - wait(lambda: "pxe-guest" in self.machine.execute("virsh list --name"), delay=3) + testlib.wait(lambda: "pxe-guest" in self.machine.execute("virsh list --name --persistent"), delay=3) + testlib.wait(lambda: "pxe-guest" in self.machine.execute("virsh list --name"), delay=3) self.machine.execute("virsh destroy pxe-guest") runner._assertScriptFinished() self.assertEqual(self.machine.execute("virsh list --name").strip(), "") @@ -542,7 +542,7 @@ class TestMachinesCreate(VirtualMachinesCase): self.machine.execute("virsh start pxe-guest") # The file is full of ANSI control characters in between every letter, filter them out - wait(lambda: self.machine.execute(r"sed 's,\x1B\[[0-9;]*[a-zA-Z],,g' /tmp/serial.txt | grep 'Rebooting in 60'"), delay=3) + testlib.wait(lambda: self.machine.execute(r"sed 's,\x1B\[[0-9;]*[a-zA-Z],,g' /tmp/serial.txt | grep 'Rebooting in 60'"), delay=3) self.goToMainPage() self.machine.execute("virsh destroy pxe-guest") @@ -557,7 +557,7 @@ class TestMachinesCreate(VirtualMachinesCase): create_and_run=True, delete=False)) # Wait for virt-install to define the VM and then stop it - wait(lambda: "pxe-guest" in self.machine.execute("virsh list --persistent"), delay=3) + testlib.wait(lambda: "pxe-guest" in self.machine.execute("virsh list --persistent"), delay=3) b.wait_in_text("#vm-pxe-guest-system-state", "Running") self.machine.execute("virsh destroy pxe-guest") @@ -596,7 +596,7 @@ vnc_password= "{vnc_passwd}" location=config.NOVELL_MOCKUP_ISO_PATH), "127.0.0.1", "::1", None, None) - @skipImage("TODO: Arch Linux has no iscsi support", "arch") + @testlib.skipImage("TODO: Arch Linux has no iscsi support", "arch") def testCreateThenInstall(self): runner = TestMachinesCreate.CreateVmRunner(self) config = TestMachinesCreate.TestCreateConfig @@ -631,7 +631,7 @@ vnc_password= "{vnc_passwd}" "virsh pool-start iscsi-pool" ] print(self.machine.execute("; ".join(cmd).format(target_iqn))) - wait(lambda: "unit:0:0:0" in self.machine.execute("virsh pool-refresh iscsi-pool; virsh vol-list iscsi-pool"), delay=3) + testlib.wait(lambda: "unit:0:0:0" in self.machine.execute("virsh pool-refresh iscsi-pool; virsh vol-list iscsi-pool"), delay=3) self.addCleanup(self.machine.execute, "virsh pool-destroy iscsi-pool; virsh pool-undefine iscsi-pool") @@ -1190,7 +1190,7 @@ vnc_password= "{vnc_passwd}" # usual tricks: prevent grep from seeing itself in the output of ps virt_install_cmd = "ps aux | grep '[v]irt-install --connect'" - wait(lambda: self.machine.execute(virt_install_cmd), delay=3) + testlib.wait(lambda: self.machine.execute(virt_install_cmd), delay=3) virt_install_cmd_out = self.machine.execute(virt_install_cmd) if self.user_login or self.user_password: self.assertIn("--cloud-init user-data=", virt_install_cmd_out) @@ -1215,7 +1215,7 @@ vnc_password= "{vnc_passwd}" # Wait for it to become permanent before destruction. If # we destroy it while it is still transient, the domain # will come back as running. - wait(lambda: "yes" in self.machine.execute(f"virsh dominfo {self.name} | grep ^Persistent")) + testlib.wait(lambda: "yes" in self.machine.execute(f"virsh dominfo {self.name} | grep ^Persistent")) self.machine.execute(f"virsh destroy {self.name}") # wait for virt-install to finish @@ -1264,7 +1264,7 @@ vnc_password= "{vnc_passwd}" # usual tricks: prevent grep from seeing itself in the output of ps virt_install_cmd = "ps aux | grep '[v]irt-install --connect'" - wait(lambda: self.machine.execute(virt_install_cmd), delay=3) + testlib.wait(lambda: self.machine.execute(virt_install_cmd), delay=3) virt_install_cmd_out = self.machine.execute(virt_install_cmd) self.assertIn(f"--install os={self.os_short_id}", virt_install_cmd_out) if self.is_unattended: @@ -1440,7 +1440,7 @@ vnc_password= "{vnc_passwd}" break time.sleep(5) else: - raise Error("Retry limit exceeded: None of [%s] is part of the error message '%s'" % ( + raise testlib.Error("Retry limit exceeded: None of [%s] is part of the error message '%s'" % ( ', '.join(errors), b.text(error_location))) if self.create_and_run: @@ -1458,7 +1458,7 @@ vnc_password= "{vnc_passwd}" waitForError(errors, error_location) # dialog can complete if the error was not returned immediately - except Error: + except testlib.Error: if b.is_present("#create-vm-dialog"): raise else: @@ -1628,7 +1628,7 @@ vnc_password= "{vnc_passwd}" # because we might end up checking the text for the new state the momment it disappears # HACK: Ensure that the selector exists to avoid a quadratic timeout loop; see # https://github.com/cockpit-project/cockpit/pull/16200 - wait(lambda: b.is_present(selector) and b.text(selector) != before, tries=30, delay=3) + testlib.wait(lambda: b.is_present(selector) and b.text(selector) != before, tries=30, delay=3) b.wait_in_text(selector, after) def _create(self, dialog): @@ -1718,7 +1718,7 @@ vnc_password= "{vnc_passwd}" self._assertCorrectConfiguration(dialog) # Wait for virt-install to define the VM and then stop it - otherwise we get 'domain is ready being removed' error - wait(lambda: dialog.name in self.machine.execute("virsh list --persistent"), delay=3) + testlib.wait(lambda: dialog.name in self.machine.execute("virsh list --persistent"), delay=3) # unfinished install script runs indefinitely, so we need to force it off self.test_obj.performAction(name, "forceOff", checkExpectedState=False) @@ -1812,7 +1812,7 @@ vnc_password= "{vnc_passwd}" b.click(f"#vm-{name}-disks-adddisk-dialog-cancel") if dialog.sourceType == 'pxe' and "network" not in dialog.location: - wait(lambda: "mode='bridge'" in m.execute(f"virsh dumpxml {name}")) + testlib.wait(lambda: "mode='bridge'" in m.execute(f"virsh dumpxml {name}")) return self @@ -1843,7 +1843,7 @@ vnc_password= "{vnc_passwd}" b = self.browser # wait until virt-install process is finished - wait(lambda: "virt-install" not in self.machine.execute("ps aux | grep '[v]irt-install --connect' || true")) + testlib.wait(lambda: "virt-install" not in self.machine.execute("ps aux | grep '[v]irt-install --connect' || true")) b.wait_in_text("#virtual-machines-listing .pf-v5-c-empty-state", "No VM is running") # wait for the vm and disks to be deleted self.machine.execute("until test -z $(virsh list --all --name); do sleep 1; done") @@ -2040,7 +2040,7 @@ vnc_password= "{vnc_passwd}" b.click(".pf-v5-c-modal-box__footer button:contains(Create and edit)") b.wait_not_present("#create-vm-dialog") - wait(lambda: "fedora28" in m.execute("virsh dumpxml VmNotInstalled"), delay=3) + testlib.wait(lambda: "fedora28" in m.execute("virsh dumpxml VmNotInstalled"), delay=3) self.waitVmPage("VmNotInstalled") @@ -2115,12 +2115,12 @@ vnc_password= "{vnc_passwd}" b.click("#vm-VmNotInstalled-system-install") # Wait for virt-install to define the VM and then stop it - otherwise we get 'domain is ready being removed' error - wait(lambda: "VmNotInstalled" in m.execute("virsh list --persistent"), delay=3) + testlib.wait(lambda: "VmNotInstalled" in m.execute("virsh list --persistent"), delay=3) logfile = "/var/log/libvirt/qemu/VmNotInstalled.log" m.execute(f"> {logfile}") # clear logfile self.performAction("VmNotInstalled", "forceOff", checkExpectedState=False) b.wait_in_text("#vm-VmNotInstalled-system-state", "Shut off") - wait(lambda: "133120" in m.execute("virsh dominfo VmNotInstalled | grep 'Used memory'"), delay=1) # Wait until memory parameters get adjusted after shutting the VM + testlib.wait(lambda: "133120" in m.execute("virsh dominfo VmNotInstalled | grep 'Used memory'"), delay=1) # Wait until memory parameters get adjusted after shutting the VM # Check configuration changes survived installation # Check memory settings have persisted @@ -2278,4 +2278,4 @@ vnc_password= "{vnc_passwd}" if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-disks b/test/check-machines-disks index 4a2db5dde..39c67f745 100755 --- a/test/check-machines-disks +++ b/test/check-machines-disks @@ -21,8 +21,8 @@ import os import time import xml.etree.ElementTree as ET -from machineslib import VirtualMachinesCase -from testlib import BOTS_DIR, Error, nondestructive, skipImage, test_main, timeout, wait +import machineslib +import testlib SYSTEM_LOCAL_CONF = '''. -from machineslib import VirtualMachinesCase -from testlib import nondestructive, test_main +import machineslib +import testlib -@nondestructive -class TestMachinesFilesystems(VirtualMachinesCase): +@testlib.nondestructive +class TestMachinesFilesystems(machineslib.VirtualMachinesCase): def testBasicSystemConnection(self): self._testBasic() @@ -134,4 +134,4 @@ class TestMachinesFilesystems(VirtualMachinesCase): if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-hostdevs b/test/check-machines-hostdevs index 62e1565f7..b425a38fb 100755 --- a/test/check-machines-hostdevs +++ b/test/check-machines-hostdevs @@ -21,17 +21,17 @@ import re import subprocess import xml.etree.ElementTree as ET -from machineslib import VirtualMachinesCase +import machineslib +import testlib from machinesxmls import PCI_HOSTDEV, SCSI_HOST_HOSTDEV, USB_HOSTDEV, USB_HOSTDEV_NONEXISTENT -from testlib import nondestructive, test_main, wait virt_xml_mock = """#!/usr/bin/python raise Exception("Mock error message")""" -@nondestructive -class TestMachinesHostDevs(VirtualMachinesCase): +@testlib.nondestructive +class TestMachinesHostDevs(machineslib.VirtualMachinesCase): def testHostDevicesList(self): b = self.browser @@ -233,11 +233,11 @@ class TestMachinesHostDevs(VirtualMachinesCase): dialog = HostDevAddDialog(self, fail_message="No host device selected") dialog.open() dialog.add() - wait(lambda: "true" == m.execute(f"virsh -c qemu:///{connectionName} dumpxml subVmTest1 | grep -A 5 hostdev || echo true").strip()) + testlib.wait(lambda: "true" == m.execute(f"virsh -c qemu:///{connectionName} dumpxml subVmTest1 | grep -A 5 hostdev || echo true").strip()) # Check no host devices attached after shutting off the VM self.performAction("subVmTest1", "forceOff", connectionName=connectionName) b.wait_in_text(f"#vm-subVmTest1-{connectionName}-state", "Shut off") - wait(lambda: "true" == m.execute("virsh -c qemu:///{connectionName} dumpxml subVmTest1 | grep -A 5 hostdev || echo true").strip()) + testlib.wait(lambda: "true" == m.execute("virsh -c qemu:///{connectionName} dumpxml subVmTest1 | grep -A 5 hostdev || echo true").strip()) output = self.run_admin(f"virsh -c qemu:///{connectionName} nodedev-list --cap usb_device", connectionName) if output.strip() != "": @@ -346,4 +346,4 @@ class TestMachinesHostDevs(VirtualMachinesCase): if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-lifecycle b/test/check-machines-lifecycle index d4cbedbb0..3b98c2fb3 100755 --- a/test/check-machines-lifecycle +++ b/test/check-machines-lifecycle @@ -17,12 +17,12 @@ # You should have received a copy of the GNU Lesser General Public License # along with Cockpit; If not, see . -from machineslib import VirtualMachinesCase -from testlib import nondestructive, test_main, wait +import machineslib +import testlib -@nondestructive -class TestMachinesLifecycle(VirtualMachinesCase): +@testlib.nondestructive +class TestMachinesLifecycle(machineslib.VirtualMachinesCase): def testBasic(self): self._testBasic(run_pixel_tests=True) @@ -124,12 +124,12 @@ class TestMachinesLifecycle(VirtualMachinesCase): b.wait_in_text(".memory-usage-chart .pf-v5-c-progress__status > .pf-v5-c-progress__measure", "128 MiB") b.wait_not_in_text(".memory-usage-chart .pf-v5-c-progress__status > .pf-v5-c-progress__measure", "0 /") usage = b.text(".memory-usage-chart .pf-v5-c-progress__status > .pf-v5-c-progress__measure").split("/ 128 MiB")[0] - wait(lambda: float(usage) > 0.0, delay=3) + testlib.wait(lambda: float(usage) > 0.0, delay=3) b.wait_in_text(".vcpu-usage-chart .pf-v5-c-progress__status > .pf-v5-c-progress__measure", "1 vCPU") usage = b.text(".vcpu-usage-chart .pf-v5-c-progress__status > .pf-v5-c-progress__measure").split("% of 1 vCPU")[0] # CPU usage cannot be nonzero with blank image, so just ensure it's a percentage - wait(lambda: float(usage) <= 100.0, delay=3) + testlib.wait(lambda: float(usage) <= 100.0, delay=3) # suspend/resume m.execute("virsh suspend subVmTest1") @@ -490,14 +490,14 @@ class TestMachinesLifecycle(VirtualMachinesCase): name = "vm-keep-vol" args = self.createVm(name) self.waitVmRow(name) - wait(lambda: name in m.execute("virsh list --all --name")) + testlib.wait(lambda: name in m.execute("virsh list --all --name")) self.performAction(name, "delete") b.set_checked(f"#vm-{name}-delete-modal-dialog input[type=checkbox]", False) b.click(f"#vm-{name}-delete-modal-dialog button:contains(Delete)") self.waitVmRow(name, present=False) - wait(lambda: name not in m.execute("virsh list --all --name")) + testlib.wait(lambda: name not in m.execute("virsh list --all --name")) m.execute(f"test -f {args['image']}") # Try to delete a transient VM @@ -518,7 +518,7 @@ class TestMachinesLifecycle(VirtualMachinesCase): args = self.createVm(name) self.waitVmRow(name) self.goToVmPage(name) - wait(lambda: name in m.execute("virsh list --all --name")) + testlib.wait(lambda: name in m.execute("virsh list --all --name")) addDisk(secondDiskVolName, poolName, name) # Remove VM's disk from command line m.execute(f"rm {(secondDiskPoolPath + secondDiskVolName)}") @@ -533,7 +533,7 @@ class TestMachinesLifecycle(VirtualMachinesCase): # Check VM got deleted, but there is a warning about unsuccessful storage deletion self.waitVmRow(name, present=False) - wait(lambda: name not in m.execute("virsh list --all --name")) + testlib.wait(lambda: name not in m.execute("virsh list --all --name")) b.wait_visible(".pf-v5-c-alert-group li .pf-v5-c-alert") b.wait_in_text(".pf-v5-c-alert-group li .pf-v5-c-alert .pf-v5-c-alert__title", f"Could not delete all storage for {name}") b.click("button.alert-link.more-button") @@ -569,4 +569,4 @@ class TestMachinesLifecycle(VirtualMachinesCase): if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-manifest b/test/check-machines-manifest index 21edbaf08..bf09f7db0 100755 --- a/test/check-machines-manifest +++ b/test/check-machines-manifest @@ -19,11 +19,11 @@ import os -from testlib import MachineCase, nondestructive, test_main +import testlib -@nondestructive -class TestMachinesManifest(MachineCase): +@testlib.nondestructive +class TestMachinesManifest(testlib.MachineCase): def testBasic(self): b = self.browser @@ -42,4 +42,4 @@ class TestMachinesManifest(MachineCase): if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-migrate b/test/check-machines-migrate index f409746db..79b1a31b2 100755 --- a/test/check-machines-migrate +++ b/test/check-machines-migrate @@ -17,12 +17,12 @@ # You should have received a copy of the GNU Lesser General Public License # along with Cockpit; If not, see . -from machineslib import VirtualMachinesCase +import machineslib +import testlib from machinesxmls import POOL_XML -from testlib import skipImage, test_main, wait -class TestMachinesMigration(VirtualMachinesCase): +class TestMachinesMigration(machineslib.VirtualMachinesCase): provision = { # noqa: RUF012 "machine1": {"address": "10.111.113.1/20", "dns": "10.111.112.100"}, "machine2": {"address": "10.111.113.2/20", "dns": "10.111.112.100"}, @@ -87,46 +87,46 @@ class TestMachinesMigration(VirtualMachinesCase): def testSharedStorageMigration(self): self._testMigrationGeneric(False, False, None) - @skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") + @testlib.skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") def testCopyStorageMigration(self): self._testMigrationGeneric(True, False, None) def testMoveTemporarilyMigration(self): self._testMigrationGeneric(False, True, None) - @skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") + @testlib.skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") def testFailMigrationPoolNotFound(self): # Equivalent storage pool is not present on the destination self._testMigrationGeneric(True, False, "pool") # Only qemu 5.1.0 and above does checking for volumes compatibility during migration # See https://mail.gnu.org/archive/html/qemu-devel/2020-04/msg05559.html - @skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") + @testlib.skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") def testFailMigrationVolumesNotCompatible(self): # Different sized volume already exists on destination self._testMigrationGeneric(True, False, "volume") - @skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") + @testlib.skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") def testFailMigrationTCPPortClosed(self): # Ports for TCP transfer are closed self._testMigrationGeneric(True, False, "port_closed") - @skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") + @testlib.skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") def testFailMigrationAuthentication(self): # No key authentication is set up self._testMigrationGeneric(True, False, "authentication") - @skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") + @testlib.skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") def testFailMigrationUriIncorrect(self): # Incorrect uri inputted self._testMigrationGeneric(True, False, "uri") - @skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") + @testlib.skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") def testFailMigrationDomainUnknown(self): # Destination domain name is not defined in /etc/hosts and is not resolvable self._testMigrationGeneric(True, False, "domain") - @skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") + @testlib.skipImage('RHEL does not provide support for copy-storage migration', "rhel-8-*", "rhel-9-*", "centos-9-stream") def testFailMigrationStopLibvirtd(self): # Libvirtd.service is not working on the destination self._testMigrationGeneric(True, False, "libvirtd") @@ -188,7 +188,7 @@ class TestMachinesMigration(VirtualMachinesCase): machine2.execute(f"systemctl start {self.getLibvirtServiceName()}.service") machine2.execute(f"systemctl start {self.getLibvirtServiceName()}.socket") - wait(lambda: "subVmTest1" not in machine2.execute("virsh list --all"), delay=3) + testlib.wait(lambda: "subVmTest1" not in machine2.execute("virsh list --all"), delay=3) self.assertIn("subVmTest1", machine1.execute("virsh list --all")) else: with b.wait_timeout(120): @@ -196,8 +196,8 @@ class TestMachinesMigration(VirtualMachinesCase): # Verify the state of the migrated VM in the destination host # The migrated VM should always exist on destination - domstate depends on the options of the dialog set - wait(lambda: "subVmTest1" in machine2.execute("virsh list --all"), delay=3) - wait(lambda: "running" in machine2.execute("virsh domstate subVmTest1"), delay=3) + testlib.wait(lambda: "subVmTest1" in machine2.execute("virsh list --all"), delay=3) + testlib.wait(lambda: "running" in machine2.execute("virsh domstate subVmTest1"), delay=3) if temporary: # VM on the destination host should be transient self.assertIn("Persistent: no", machine2.execute("virsh dominfo subVmTest1")) @@ -225,4 +225,4 @@ class TestMachinesMigration(VirtualMachinesCase): if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-networks b/test/check-machines-networks index fb29668ca..c64a2fba6 100755 --- a/test/check-machines-networks +++ b/test/check-machines-networks @@ -19,9 +19,9 @@ import xml.etree.ElementTree as ET -from machineslib import VirtualMachinesCase +import machineslib +import testlib from machinesxmls import TEST_NETWORK2_XML, TEST_NETWORK3_XML, TEST_NETWORK4_XML, TEST_NETWORK_IPV6_XML, TEST_NETWORK_XML -from testlib import nondestructive, test_main, wait def getNetworkDevice(m): @@ -37,8 +37,8 @@ def getNetworkDevice(m): return device -@nondestructive -class TestMachinesNetworks(VirtualMachinesCase): +@testlib.nondestructive +class TestMachinesNetworks(machineslib.VirtualMachinesCase): def testNetworks(self): b = self.browser @@ -760,7 +760,7 @@ class TestMachinesNetworks(VirtualMachinesCase): b.click(f"#activate-network-test_network2-{connectionName}") b.wait_in_text(f"#network-test_network2-{connectionName}-state", "active") # check virsh state - wait(lambda: "yes" == m.execute("virsh net-info test_network2 | grep 'Active:' | awk '{print $2}'").strip(), tries=5) + testlib.wait(lambda: "yes" == m.execute("virsh net-info test_network2 | grep 'Active:' | awk '{print $2}'").strip(), tries=5) # deactivate network b.wait_visible(f"#deactivate-network-test_network2-{connectionName}") @@ -768,7 +768,7 @@ class TestMachinesNetworks(VirtualMachinesCase): b.wait_in_text(f"#network-test_network2-{connectionName}-state", "inactive") b.wait_visible(f"#activate-network-test_network2-{connectionName}") # check virsh state - wait(lambda: "no" == m.execute("virsh net-info test_network2 | grep 'Active:' | awk '{print $2}'").strip(), tries=5) + testlib.wait(lambda: "no" == m.execute("virsh net-info test_network2 | grep 'Active:' | awk '{print $2}'").strip(), tries=5) # check "X" button of the deletion dialog b.click(f"#network-test_network2-{connectionName}-action-kebab button") @@ -971,8 +971,8 @@ class TestMachinesNetworks(VirtualMachinesCase): # Check that the static IP is correctly assigned to the VM m.execute("virsh start subVmTest1") - wait(lambda: "1" in self.machine.execute("virsh domifaddr subVmTest1 | grep 192.168.122.222 | wc -l"), delay=3) + testlib.wait(lambda: "1" in self.machine.execute("virsh domifaddr subVmTest1 | grep 192.168.122.222 | wc -l"), delay=3) if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-nics b/test/check-machines-nics index c00e331ed..e3afa52f8 100755 --- a/test/check-machines-nics +++ b/test/check-machines-nics @@ -19,19 +19,19 @@ import json -from machineslib import VirtualMachinesCase +import machineslib +import testlib from machinesxmls import TEST_NETWORK4_XML, TEST_NETWORK_XML -from testlib import no_retry_when_changed, nondestructive, test_main, wait -@nondestructive -class TestMachinesNICs(VirtualMachinesCase): +@testlib.nondestructive +class TestMachinesNICs(machineslib.VirtualMachinesCase): def setUp(self): super().setUp() # querying object manager often runs into that on network changes; irrelevant self.allow_journal_messages("org.freedesktop.NetworkManager: couldn't get managed objects at /org/freedesktop: Timeout was reached") - @no_retry_when_changed + @testlib.no_retry_when_changed def testVmNICs(self): b = self.browser m = self.machine @@ -47,7 +47,7 @@ class TestMachinesNICs(VirtualMachinesCase): # Wait for the dynamic IP address to be assigned before logging in # If the IP will change or get assigned after fetching the domain data the user will not see any # changes until they refresh the page, since there is not any signal associated with this change - wait(lambda: "1" in self.machine.execute("virsh domifaddr subVmTest1 | grep 192.168.122. | wc -l"), delay=3) + testlib.wait(lambda: "1" in self.machine.execute("virsh domifaddr subVmTest1 | grep 192.168.122. | wc -l"), delay=3) self.goToVmPage("subVmTest1") b.wait_in_text("#vm-subVmTest1-network-1-type", "network") @@ -134,7 +134,7 @@ class TestMachinesNICs(VirtualMachinesCase): skip_layouts=["medium", "rtl"]) # Start vm and wait until kernel is booted - wait(lambda: "1" in self.machine.execute("virsh domifaddr subVmTest1 | grep 192.168.122. | wc -l"), delay=3) + testlib.wait(lambda: "1" in self.machine.execute("virsh domifaddr subVmTest1 | grep 192.168.122. | wc -l"), delay=3) b.reload() b.enter_page('/machines') self.waitPageInit() @@ -171,14 +171,14 @@ class TestMachinesNICs(VirtualMachinesCase): b.wait_in_text("#vm-subVmTest1-network-1-state", "down") b.wait_in_text("#vm-subVmTest1-iface-1-plug", "Plug") - wait(lambda: "down" in m.execute(f"virsh domif-getlink subVmTest1 {mac_address}")) + testlib.wait(lambda: "down" in m.execute(f"virsh domif-getlink subVmTest1 {mac_address}")) # Click "plug" b.click("#vm-subVmTest1-iface-1-plug") b.wait_in_text("#vm-subVmTest1-network-1-state", "up") b.wait_in_text("#vm-subVmTest1-iface-1-unplug", "Unplug") - wait(lambda: "up" in m.execute(f"virsh domif-getlink subVmTest1 {mac_address}")) + testlib.wait(lambda: "up" in m.execute(f"virsh domif-getlink subVmTest1 {mac_address}")) plugAndUnplugNICs() @@ -732,4 +732,4 @@ class TestMachinesNICs(VirtualMachinesCase): if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-settings b/test/check-machines-settings index b79ad104c..9c227a255 100755 --- a/test/check-machines-settings +++ b/test/check-machines-settings @@ -19,8 +19,8 @@ import subprocess -from machineslib import VirtualMachinesCase -from testlib import nondestructive, test_main, wait +import machineslib +import testlib # If this test fails to run, the host machine needs: # echo "options kvm-intel nested=1" > /etc/modprobe.d/kvm-intel.conf @@ -31,8 +31,8 @@ from testlib import nondestructive, test_main, wait distrosWithDefaultHostModel = ["centos-8-stream"] -@nondestructive -class TestMachinesSettings(VirtualMachinesCase): +@testlib.nondestructive +class TestMachinesSettings(machineslib.VirtualMachinesCase): def testVCPU(self): b = self.browser @@ -132,7 +132,7 @@ class TestMachinesSettings(VirtualMachinesCase): b.click("#machines-cpu-modal-dialog-apply") b.wait_not_present("#machines-cpu-modal-dialog") - wait(lambda: m.execute( + testlib.wait(lambda: m.execute( "virsh dumpxml subVmTest1 | tee /tmp/subVmTest1.xml | xmllint --xpath '/domain/cpu/topology[@sockets=\"2\"][@threads=\"1\"][@cores=\"2\"]' -")) # Run VM - this ensures that the internal state is updated before we move on. @@ -482,10 +482,10 @@ class TestMachinesSettings(VirtualMachinesCase): dom_xml = "virsh -c qemu:///system dumpxml subVmTest1" xmllint_elem = f"{dom_xml} | xmllint --xpath 'string(//domain/cpu/@mode)' - 2>&1 || true" - wait(lambda: cpu_model in m.execute(xmllint_elem).strip()) + testlib.wait(lambda: cpu_model in m.execute(xmllint_elem).strip()) xmllint_elem = f"{dom_xml} | xmllint --xpath 'string(//domain/vcpu)' - 2>&1 || true" - wait(lambda: "3" in m.execute(xmllint_elem).strip()) + testlib.wait(lambda: "3" in m.execute(xmllint_elem).strip()) virsh_output = m.execute("virsh dumpxml subVmTest1 | xmllint --xpath '/domain/devices/watchdog/@action' -").strip() self.assertEqual(virsh_output, 'action="reset"') @@ -685,7 +685,7 @@ class TestMachinesSettings(VirtualMachinesCase): self.waitPageInit() self.goToVmPage("subVmTest2") m.execute("virsh undefine subVmTest2") - wait(lambda: "no" in m.execute("virsh dominfo subVmTest2 | grep ^Persistent"), delay=3) + testlib.wait(lambda: "no" in m.execute("virsh dominfo subVmTest2 | grep ^Persistent"), delay=3) # UI was notified that VM is transient b.wait_visible("#vm-subVmTest2-memory-count button[aria-disabled=true]") @@ -865,7 +865,7 @@ class TestMachinesSettings(VirtualMachinesCase): setVsockLive(new_auto=False, new_address="4", previous_auto=True, previous_address=default_libvirt_vsock_address) m.execute("virsh undefine subVmTest1") - wait(lambda: "no" in m.execute("virsh dominfo subVmTest1 | grep ^Persistent"), delay=3) + testlib.wait(lambda: "no" in m.execute("virsh dominfo subVmTest1 | grep ^Persistent"), delay=3) # UI was notified that VM is transient b.wait_visible("#vm-subVmTest1-memory-count button[aria-disabled=true]") @@ -878,4 +878,4 @@ class TestMachinesSettings(VirtualMachinesCase): if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-snapshots b/test/check-machines-snapshots index 5d2ffcd8c..cd8297816 100755 --- a/test/check-machines-snapshots +++ b/test/check-machines-snapshots @@ -20,8 +20,8 @@ import time from datetime import datetime -from machineslib import VirtualMachinesCase -from testlib import nondestructive, test_main +import machineslib +import testlib # libvirt-dbus snapshot APIs are available since 1.4.0, see https://github.com/libvirt/libvirt-dbus/commit/642b1b71 @@ -29,8 +29,8 @@ def supportsSnapshot(image): return image != "centos-8-stream" and not image.startswith("rhel-8") -@nondestructive -class TestMachinesSnapshots(VirtualMachinesCase): +@testlib.nondestructive +class TestMachinesSnapshots(machineslib.VirtualMachinesCase): def testSnapshots(self): # Checks if difference of @time1 and @time2 is not greater than @difference (in seconds) @@ -320,4 +320,4 @@ class TestMachinesSnapshots(VirtualMachinesCase): if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-storage-pools b/test/check-machines-storage-pools index bdc612328..f146a4d88 100755 --- a/test/check-machines-storage-pools +++ b/test/check-machines-storage-pools @@ -19,12 +19,12 @@ import os -from machineslib import VirtualMachinesCase -from testlib import nondestructive, test_main, wait +import machineslib +import testlib -@nondestructive -class TestMachinesStoragePools(VirtualMachinesCase): +@testlib.nondestructive +class TestMachinesStoragePools(machineslib.VirtualMachinesCase): def gotoVolumesTab(self, poolName, connectionName="system"): selector = f"tr[data-row-id='pool-{poolName}-{connectionName}'] + tr li:contains('Storage volumes')" @@ -64,7 +64,7 @@ class TestMachinesStoragePools(VirtualMachinesCase): m.execute("virsh vol-create-as myPoolTwo VolumeTwo --capacity 1G --format qcow2") m.execute("virsh vol-create-as myPoolTwo VolumeThree --capacity 1G --format qcow2") m.execute("virsh vol-create-as myPoolTwo VolumeFour --capacity 1G --format qcow2") - wait(lambda: all(volume in m.execute("virsh vol-list myPoolTwo") for volume in ["VolumeOne", "VolumeTwo", "VolumeThree", "VolumeFour"])) + testlib.wait(lambda: all(volume in m.execute("virsh vol-list myPoolTwo") for volume in ["VolumeOne", "VolumeTwo", "VolumeThree", "VolumeFour"])) m.execute('virsh pool-refresh myPoolOne; virsh pool-refresh myPoolTwo') connectionName = m.execute("virsh uri | head -1 | cut -d/ -f4").strip() @@ -858,7 +858,7 @@ class TestMachinesStoragePools(VirtualMachinesCase): m.execute(create_cmd) # Check whether the pool creation is successful - wait(lambda: self.name in m.execute("virsh pool-list --all")) + testlib.wait(lambda: self.name in m.execute("virsh pool-list --all")) # Check the pool state b.wait_text(f"#pool-{self.name}-{self.connection}-state", "inactive") @@ -868,11 +868,11 @@ class TestMachinesStoragePools(VirtualMachinesCase): if self.pool_type == "iscsi": # these should get picked up through StoragePoolEvent CREATED - wait(lambda: "unit:0:0:0" in m.execute(f"virsh vol-list {self.name}")) + testlib.wait(lambda: "unit:0:0:0" in m.execute(f"virsh vol-list {self.name}")) elif self.vol_name: if self.vol_name not in m.execute(f"virsh vol-list {self.name}"): m.execute(f"virsh vol-create-as {self.name} {self.vol_name} 1M") - wait(lambda: self.vol_name in m.execute(f"virsh vol-list {self.name}")) + testlib.wait(lambda: self.vol_name in m.execute(f"virsh vol-list {self.name}")) # need refresh after volume creation b.reload() b.enter_page('/machines') @@ -925,24 +925,24 @@ class TestMachinesStoragePools(VirtualMachinesCase): if self.activate and self.vol_name: if self.remove_volume: if self.pool_type == "netfs": - wait(lambda: self.vol_name not in m.execute(f'ls -A {self.source_path}')) + testlib.wait(lambda: self.vol_name not in m.execute(f'ls -A {self.source_path}')) elif self.pool_type == "dir": - wait(lambda: self.vol_name not in m.execute(f'ls -A {self.target}')) + testlib.wait(lambda: self.vol_name not in m.execute(f'ls -A {self.target}')) elif self.pool_type == "disk": - wait(lambda: self.vol_name not in m.execute("lsblk")) + testlib.wait(lambda: self.vol_name not in m.execute("lsblk")) else: if self.pool_type == "netfs": vol_path = os.path.join(self.source_path, self.vol_name) - wait(lambda: m.execute(f'test -f {vol_path}')) + testlib.wait(lambda: m.execute(f'test -f {vol_path}')) elif self.pool_type == "dir": vol_path = os.path.join(self.target, self.vol_name) - wait(lambda: m.execute(f'test -f {vol_path}')) + testlib.wait(lambda: m.execute(f'test -f {vol_path}')) elif self.pool_type == "disk": - wait(lambda: self.vol_name in m.execute("lsblk")) + testlib.wait(lambda: self.vol_name in m.execute("lsblk")) # general check self.test_obj.waitPoolRow(self.name, self.connection, present=False) - wait(lambda: self.name not in m.execute("virsh pool-list --all")) + testlib.wait(lambda: self.name not in m.execute("virsh pool-list --all")) # dir pool deletion StoragePoolsCreationAndDeletion(self, @@ -1083,7 +1083,7 @@ class TestMachinesStoragePools(VirtualMachinesCase): # Delete the VM, or the deletion button will be disabled m.execute("virsh undefine subVmTest1") # Check both command and UI that the VM is not shown - wait(lambda: "subVmTest1" not in m.execute("virsh list --all")) + testlib.wait(lambda: "subVmTest1" not in m.execute("virsh list --all")) b.click(".machines-listing-breadcrumb li a:contains(Virtual machines)") b.wait_not_present("#vm-subVmTest1-system-name") # Go back to the storage pool list @@ -1098,8 +1098,8 @@ class TestMachinesStoragePools(VirtualMachinesCase): b.set_checked("#storage-pool-delete-volumes", True) b.click(".pf-v5-c-backdrop footer button[aria-disabled=false]:contains(Delete)") b.assert_pixels("#storage-pool-delete-modal", "storage-pool-delete-modal-error") - wait(lambda: "forDeletion" not in m.execute("ls /var/lib/libvirt/images/")) + testlib.wait(lambda: "forDeletion" not in m.execute("ls /var/lib/libvirt/images/")) if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/check-machines-virtualization b/test/check-machines-virtualization index c3b694b2d..f23a576b7 100755 --- a/test/check-machines-virtualization +++ b/test/check-machines-virtualization @@ -17,12 +17,12 @@ # You should have received a copy of the GNU Lesser General Public License # along with Cockpit; If not, see . -from machineslib import VirtualMachinesCase -from testlib import nondestructive, test_main +import machineslib +import testlib -@nondestructive -class TestMachinesVirtualization(VirtualMachinesCase): +@testlib.nondestructive +class TestMachinesVirtualization(machineslib.VirtualMachinesCase): def testVirtualizationDisabled(self): b = self.browser @@ -106,4 +106,4 @@ class TestMachinesVirtualization(VirtualMachinesCase): if __name__ == '__main__': - test_main() + testlib.test_main() diff --git a/test/machineslib.py b/test/machineslib.py index 0c1e03952..57ecc8e4f 100644 --- a/test/machineslib.py +++ b/test/machineslib.py @@ -19,9 +19,9 @@ import sys import traceback -from netlib import NetworkHelpers -from storagelib import StorageHelpers -from testlib import Error, MachineCase, attach, wait +import netlib +import storagelib +import testlib def hasMonolithicDaemon(image): @@ -315,8 +315,8 @@ def setup_mock_server(self, mock_server_filename, subj_names): def waitLogFile(self, logfile, expected_text): try: - wait(lambda: expected_text in self.machine.execute(f"cat {logfile}"), delay=3) - except Error: + testlib.wait(lambda: expected_text in self.machine.execute(f"cat {logfile}"), delay=3) + except testlib.Error: log = self.machine.execute(f"cat {logfile}") print(f"----- log of failed VM ------\n{log}\n---------") raise @@ -325,7 +325,7 @@ def waitCirrOSBooted(self, logfile): self.waitLogFile(logfile, "login as 'cirros' user.") -class VirtualMachinesCase(MachineCase, VirtualMachinesCaseHelpers, StorageHelpers, NetworkHelpers): +class VirtualMachinesCase(testlib.MachineCase, VirtualMachinesCaseHelpers, storagelib.StorageHelpers, netlib.NetworkHelpers): def setUp(self): super().setUp() @@ -450,7 +450,7 @@ def downloadVmXml(self, vm): dest_file = f"{self.label()}-{m.label}-{vm}.xml" dest = os.path.abspath(dest_file) m.download(vms_xml, dest) - attach(dest, move=False) + testlib.attach(dest, move=False) print(f"Wrote {vm} XML to {dest_file}") def downloadVmLog(self, vm): @@ -462,7 +462,7 @@ def downloadVmLog(self, vm): dest_file = f"{self.label()}-{m.label}-{vm}.log" dest = os.path.abspath(dest_file) m.download(vms_log, dest) - attach(dest, move=True) + testlib.attach(dest, move=True) print(f"Wrote {vm} log to {dest_file}") def downloadVmsArtifacts(self):