diff --git a/tests/data/testdriver/testdriver.xml b/tests/data/testdriver/testdriver.xml
index 43a7b9222..d77b650b4 100644
--- a/tests/data/testdriver/testdriver.xml
+++ b/tests/data/testdriver/testdriver.xml
@@ -753,6 +753,16 @@ test-many-devices, like an alternate RNG, EOL OS ID, title field
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/uitests/data/keyfile/allstats.ini b/tests/uitests/data/keyfile/allstats.ini
index d85dbe827..e971374e6 100644
--- a/tests/uitests/data/keyfile/allstats.ini
+++ b/tests/uitests/data/keyfile/allstats.ini
@@ -6,7 +6,7 @@ host-cpu-usage=true
memory-usage=true
[org/virt-manager/virt-manager/connections]
-uris=['test:///default', 'foo:///']
+uris=['test:///default']
autoconnect=['test:///default']
[org/virt-manager/virt-manager]
diff --git a/tests/uitests/test_cli.py b/tests/uitests/test_cli.py
index 44c98699c..f036ed697 100644
--- a/tests/uitests/test_cli.py
+++ b/tests/uitests/test_cli.py
@@ -107,5 +107,18 @@ class VMMCLI(uiutils.UITestCase):
uiutils.check(lambda: not self.app.is_running())
def testCLITraceLibvirt(self):
- self.app.open(extra_opts=["--trace-libvirt=mainloop"])
- self.sleep(5)
+ # Just test this for code coverage
+ self.app.open(keyfile="allstats.ini",
+ extra_opts=["--trace-libvirt=mainloop"])
+ # Give it a little time to work
+ self.sleep(2)
+ uiutils.check(lambda: self.app.topwin.active)
+
+ def testCLILeakDebug(self):
+ # Just test this for code coverage
+ self.app.open(keyfile="allstats.ini",
+ extra_opts=["--test-options=leak-debug"])
+ self.sleep(2)
+ # Give it a little time to work
+ uiutils.check(lambda: self.app.topwin.active)
+ self.app.topwin.keyCombo("F4")
diff --git a/tests/uitests/test_createconn.py b/tests/uitests/test_createconn.py
index 65ef19c0e..6a27cf2fb 100644
--- a/tests/uitests/test_createconn.py
+++ b/tests/uitests/test_createconn.py
@@ -17,8 +17,7 @@ class VMMConnect(uiutils.UITestCase):
# Start with connection delete
c = self.app.root.find("test testdriver.xml", "table cell")
c.click(button=3)
- self.app.root.find("conn-disconnect",
- "menu item").click()
+ self.app.root.find("conn-disconnect", "menu item").click()
uiutils.check(lambda: "Not Connected" in c.text)
c.click(button=3)
self.app.root.find("conn-delete", "menu item").click()
@@ -138,3 +137,8 @@ class VMMConnect(uiutils.UITestCase):
c.doubleClick()
c = self.app.root.find("test default", "table cell")
c.click()
+ # Delete it
+ c.click(button=3)
+ self.app.root.find("conn-delete", "menu item").click()
+ self._click_alert_button("will remove the connection", "Yes")
+ uiutils.check(lambda: c.dead)
diff --git a/tests/uitests/test_createvm.py b/tests/uitests/test_createvm.py
index df9e88ea5..12babd893 100644
--- a/tests/uitests/test_createvm.py
+++ b/tests/uitests/test_createvm.py
@@ -234,7 +234,6 @@ class NewVM(uiutils.UITestCase):
# Change NIC mac
vmwindow.find_fuzzy("NIC", "table cell").click()
tab = vmwindow.find("network-tab")
- tab.print_nodes()
tab.find("mac-entry", "text").set_text("00:11:00:11:00:11")
appl.click()
uiutils.check(lambda: not appl.sensitive)
@@ -307,9 +306,73 @@ class NewVM(uiutils.UITestCase):
self.app.root.find_fuzzy("fedora10 on", "frame")
uiutils.check(lambda: not newvm.showing)
- def testNewKVMQ35(self):
+ def testNewKVMQ35Tweaks(self):
"""
- New VM that should default to Q35
+ New VM that should default to Q35, but tweak things a bunch
+ """
+ self.app.uri = tests.utils.URIs.kvm
+ newvm = self._open_create_wizard()
+
+ newvm.find_fuzzy("Import", "radio").click()
+ self.forward(newvm)
+ newvm.find("import-entry").set_text("/dev/default-pool/testvol1.img")
+ newvm.find("oslist-entry").set_text("fedora30")
+ popover = newvm.find("oslist-popover")
+ popover.find("include-eol").click()
+ popover.find_fuzzy("Fedora 30").click()
+ self.forward(newvm)
+ self.forward(newvm)
+
+ # Select customize wizard, we will use this VM to
+ # hit some code paths elsewhere
+ newvm.find_fuzzy("Customize", "check").click()
+ newvm.find_fuzzy("Finish", "button").click()
+ vmname = "fedora30"
+ details = self.app.root.find_fuzzy("%s on" % vmname, "frame")
+ appl = details.find("config-apply")
+
+ # Tweak some Overview settings
+ details.combo_check_default("Chipset:", "Q35")
+ details.combo_check_default("Firmware:", "BIOS")
+
+ # Switch i440FX and back
+ details.combo_select("Chipset:", "i440FX")
+ appl.click()
+ uiutils.check(lambda: not appl.sensitive)
+ details.combo_select("Chipset:", "Q35")
+ appl.click()
+ uiutils.check(lambda: not appl.sensitive)
+ # Switch to UEFI, back to BIOS, back to UEFI
+ details.combo_select("Firmware:", ".*x86_64.*")
+ appl.click()
+ uiutils.check(lambda: not appl.sensitive)
+ # Switch back to BIOS
+ details.combo_select("Firmware:", "BIOS")
+ appl.click()
+ uiutils.check(lambda: not appl.sensitive)
+ # Switch back to UEFI
+ details.combo_select("Firmware:", ".*x86_64.*")
+ appl.click()
+ uiutils.check(lambda: not appl.sensitive)
+
+ # Add another network device
+ details.find("add-hardware", "push button").click()
+ addhw = self.app.root.find("Add New Virtual Hardware", "frame")
+ addhw.find("Network", "table cell").click()
+ tab = addhw.find("network-tab", None)
+ uiutils.check(lambda: tab.showing)
+ addhw.find("Finish", "push button").click()
+ uiutils.check(lambda: not addhw.active)
+ uiutils.check(lambda: details.active)
+
+ # Finish
+ details.find_fuzzy("Begin Installation", "button").click()
+ uiutils.check(lambda: details.dead)
+ self.app.root.find_fuzzy("%s on" % vmname, "frame")
+
+ def testNewKVMQ35UEFI(self):
+ """
+ New VM that should default to Q35, and set UEFI
"""
self.app.uri = tests.utils.URIs.kvm
newvm = self._open_create_wizard()
@@ -331,28 +394,17 @@ class NewVM(uiutils.UITestCase):
vmname = "fedora30"
details = self.app.root.find_fuzzy("%s on" % vmname, "frame")
- # Tweak some Overview settings
+ # Change to UEFI
details.combo_check_default("Chipset:", "Q35")
details.combo_check_default("Firmware:", "BIOS")
details.combo_select("Firmware:", ".*x86_64.*")
details.find("config-apply").click()
- # Add another network device
- details.find("add-hardware", "push button").click()
- addhw = self.app.root.find("Add New Virtual Hardware", "frame")
- addhw.find("Network", "table cell").click()
- tab = addhw.find("network-tab", None)
- uiutils.check(lambda: tab.showing)
- addhw.find("Finish", "push button").click()
- uiutils.check(lambda: not addhw.active)
- uiutils.check(lambda: details.active)
-
# Finish
details.find_fuzzy("Begin Installation", "button").click()
uiutils.check(lambda: details.dead)
self.app.root.find_fuzzy("%s on" % vmname, "frame")
-
def testNewPPC64(self):
"""
New PPC64 VM to test architecture selection
@@ -380,6 +432,13 @@ class NewVM(uiutils.UITestCase):
newvm.find_fuzzy("Finish", "button").click()
details = self.app.root.find_fuzzy("vm-ppc64 on", "frame")
+ tab = details.find("overview-tab")
+ tab.combo_check_default("machine-combo", "pseries")
+ tab.combo_select("machine-combo", "pseries-2.1")
+ appl = details.find("config-apply")
+ appl.click()
+ uiutils.check(lambda: not appl.sensitive)
+
# Add a TPM SPAPR device
details.find("add-hardware", "push button").click()
addhw = self.app.root.find("Add New Virtual Hardware", "frame")
@@ -513,7 +572,6 @@ class NewVM(uiutils.UITestCase):
# Tweak init values
details.find("Boot Options", "table cell").click()
tab = details.find("boot-tab")
- tab.print_nodes()
tab.find("Init path:", "text").set_text("")
tab.find("Init args:", "text").set_text("some args")
appl = details.find("config-apply")
@@ -772,11 +830,28 @@ class NewVM(uiutils.UITestCase):
newvm.find_fuzzy("Customize", "check").click()
newvm.find_fuzzy("Name", "text").set_text(vmname)
newvm.find_fuzzy("Finish", "button").click()
-
- # Change a VM setting and verify it
win = self.app.root.find_fuzzy("%s on" % vmname, "frame")
xmleditor = win.find("XML editor")
finish = win.find("config-apply")
+
+ # Change a device setting with the XML editor
+ win.find_fuzzy("IDE Disk 1", "table cell").click()
+ tab = win.find("disk-tab")
+ win.find("XML", "page tab").click()
+ # Change the disk path via the XML editor
+ fname = vmname + ".qcow2"
+ uiutils.check(lambda: fname in xmleditor.text)
+ newx = xmleditor.text.replace(fname, "default-vol")
+ xmleditor.set_text(newx)
+ appl = win.find("config-apply")
+ # This is kindof a bug, changing path in XML editor in Customize
+ # doesn't take effect for storage with creation parameters, but
+ # it's a pain to fix.
+ appl.click()
+ uiutils.check(lambda: not appl.sensitive)
+ uiutils.check(lambda: vmname in xmleditor.text)
+
+ # Change a VM setting and verify it
win.find_fuzzy("Boot", "table cell").click()
tab = win.find("boot-tab")
bootmenu = tab.find("Enable boot menu", "check box")
@@ -833,7 +908,6 @@ class NewVM(uiutils.UITestCase):
browser = self.app.root.find("vmm-storage-browser")
browser.find("%s.qcow2" % vmname, "table cell")
-
def testNewVMRemote(self):
"""
Hit some is_remote code paths
diff --git a/tests/uitests/test_details.py b/tests/uitests/test_details.py
index a2729f786..b73c063a5 100644
--- a/tests/uitests/test_details.py
+++ b/tests/uitests/test_details.py
@@ -49,13 +49,18 @@ class Details(uiutils.UITestCase):
# Select XML editor, and reverse walk the list
win.find("XML", "page tab").click()
self._walkUIList(win, lst, lambda: False, reverse=True)
+ return win
def testDetailsHardwareSmokeTest(self):
self._testSmokeTest(None)
def testDetailsHardwareSmokeTestAlternate(self):
self.app.open(keyfile="allstats.ini")
- self._testSmokeTest("test alternate devs title")
+ win = self._testSmokeTest("test alternate devs title")
+ win.find("Details", "page tab").click()
+ self._select_hw(win, "Performance", "performance-tab")
+ # Wait for perf signals to trigger, to cover more code
+ self.sleep(2)
def _testRename(self, origname, newname):
# Enable all stats prefs to hit some extra code
@@ -66,8 +71,16 @@ class Details(uiutils.UITestCase):
win.find("Overview", "table cell").click()
oldcell = self.app.root.find_fuzzy(origname, "table cell")
+ badname = "foo/bar"
+ win.find("Name:", "text").set_text(badname)
+ appl = win.find("config-apply")
+ appl.click()
+ self._click_alert_button(badname, "Close")
+
+ # Actual name change
win.find("Name:", "text").set_text(newname)
- win.find("config-apply", "push button").click()
+ appl.click()
+ uiutils.check(lambda: not appl.sensitive)
# Confirm lists were updated
self.app.root.find("%s on" % newname, "frame")
@@ -91,7 +104,6 @@ class Details(uiutils.UITestCase):
self.app.root.find_fuzzy(origname, "table cell").click()
b = self.app.root.find("Shut Down", "push button")
b.click()
- # This insures the VM finished shutting down
uiutils.check(lambda: b.sensitive is False)
self._testRename(origname, "test-new-name")
@@ -102,7 +114,9 @@ class Details(uiutils.UITestCase):
"""
self.app.uri = tests.utils.URIs.kvm
win = self._open_details_window(vmname="test", shutdown=True)
- self.app.topwin.click_title()
+ fmenu = win.find("File", "menu")
+ fmenu.click()
+ fmenu.find("View Manager").click()
# Double run to hit a show() codepath
win = self._open_details_window(vmname="test")
uiutils.check(lambda: win.active)
@@ -308,6 +322,30 @@ class Details(uiutils.UITestCase):
tab = self._select_hw(win, "Boot Options", "boot-tab")
uiutils.check(lambda: "backing" in initrd.text)
+ def testDetailsAlternateEdits(self):
+ """
+ Some specific handling via test-alternate-devs
+ """
+ win = self._open_details_window(vmname="test alternate devs title")
+
+ # tests the console dup removal
+ self._select_hw(win, "Serial 1", "char-tab")
+ win.find("config-remove").click()
+ self._click_alert_button("Are you sure", "Yes")
+ self._click_alert_button("take effect after", "OK")
+ self._stop_vm(win)
+
+ def testDetailsEmptyBoot(self):
+ """
+ Check boot handling when VM has no devices
+ """
+ win = self._open_details_window(vmname="test-state-crashed")
+ self._select_hw(win, "Boot Options", "boot-tab")
+ win.find("No bootable devices")
+
+ # Add in switching back to the console view to hit a vmwindow path
+ win.find("Console", "radio button").click()
+
def testDetailsEditDiskNet(self):
"""
Test disk and network devices
@@ -398,8 +436,7 @@ class Details(uiutils.UITestCase):
"""
Test all other devices
"""
- win = self._open_details_window(vmname="test-many-devices",
- shutdown=True)
+ win = self._open_details_window(vmname="test-many-devices")
appl = win.find("config-apply", "push button")
# Fail to hotremove
@@ -506,6 +543,10 @@ class Details(uiutils.UITestCase):
tab.combo_select("controller-model", "USB 3")
appl.click()
uiutils.check(lambda: not appl.sensitive)
+ tab = self._select_hw(win, "Controller USB 0", "controller-tab")
+ tab.find("controller-model").find(None, "text").text = "piix3-uhci"
+ appl.click()
+ uiutils.check(lambda: not appl.sensitive)
# Filesystem tweaks
diff --git a/tests/uitests/test_host.py b/tests/uitests/test_host.py
index a4757658f..6235a3017 100644
--- a/tests/uitests/test_host.py
+++ b/tests/uitests/test_host.py
@@ -160,7 +160,8 @@ class Host(uiutils.UITestCase):
win.find_fuzzy("Network", "tab").click()
win.find_fuzzy("Overview", "tab").click()
- # Unset autoconnect
+ # Toggle autoconnect
+ win.find("Autoconnect:", "check box").click()
win.find("Autoconnect:", "check box").click()
# Change the name, verify that title bar changed
diff --git a/tests/uitests/test_inspection.py b/tests/uitests/test_inspection.py
index b46941bee..8cf3d5879 100644
--- a/tests/uitests/test_inspection.py
+++ b/tests/uitests/test_inspection.py
@@ -42,3 +42,14 @@ class VMMInspection(uiutils.UITestCase):
assert "test_app1_summary" in nodestr1
tab.find("Refresh", "push button").click()
uiutils.check(lambda: apps.fmt_nodes() != nodestr1)
+
+ details.keyCombo("F4")
+ uiutils.check(lambda: not details.showing)
+
+ # Open a VM with no disks which will report an inspection error
+ self.app.root.find_fuzzy("test\n", "table cell").doubleClick()
+ details = self.app.root.find("test on", "frame")
+ details.find("Details", "radio button").click()
+ details.find("OS information", "table cell").click()
+ tab = details.find("os-tab")
+ tab.find_fuzzy("Fake test error no disks")
diff --git a/tests/uitests/test_manager.py b/tests/uitests/test_manager.py
index 0d83db97e..2dda674a9 100644
--- a/tests/uitests/test_manager.py
+++ b/tests/uitests/test_manager.py
@@ -1,6 +1,7 @@
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
+from tests import utils
from tests.uitests import utils as uiutils
@@ -47,6 +48,8 @@ class Manager(uiutils.UITestCase):
uiutils.check(lambda: shutdown.sensitive, timeout=5)
def testVMLifecycle(self):
+ # qemu hits some different domain code paths for setTime
+ self.app.uri = utils.URIs.kvm
self._testVMLifecycle()
def testVMNoEventsLifecycle(self):
@@ -130,7 +133,7 @@ class Manager(uiutils.UITestCase):
test_action("Restore", shutdown=False, confirm=False)
confirm_is_running()
- def testManagedManagedSaveCornerCases(self):
+ def testManagerSaveCancelError(self):
"""
Test managed save special behavior
"""
@@ -162,6 +165,32 @@ class Manager(uiutils.UITestCase):
self._click_alert_button("remove the saved state", "Yes")
uiutils.check(lambda: not run.sensitive)
+ def testManagerQEMUSetTime(self):
+ """
+ Fake qemu setTime behavior for code coverage
+ """
+ self.app.uri = utils.URIs.kvm
+ manager = self.app.topwin
+ run = manager.find("Run", "push button")
+ smenu = manager.find("Menu", "toggle button")
+ save = manager.find("Save", "menu item")
+
+ c = manager.find("test alternate devs title", "table cell")
+ c.click()
+
+ # Save -> resume -> save
+ smenu.click()
+ save.click()
+ uiutils.check(lambda: run.sensitive)
+ self.sleep(1)
+ run.click()
+ uiutils.check(lambda: not run.sensitive)
+ self.sleep(1)
+ smenu.click()
+ save.click()
+ uiutils.check(lambda: run.sensitive)
+ self.sleep(1)
+
def testManagerVMRunFail(self):
# Force VM startup to fail so we can test the error path
self.app.open(extra_opts=["--test-options=test-vm-run-fail"])
@@ -220,6 +249,10 @@ class Manager(uiutils.UITestCase):
"""
manager = self.app.topwin
host = self._open_host_window("Storage")
+ fmenu = host.find("File", "menu")
+ fmenu.click()
+ fmenu.find("View Manager", "menu item").click()
+ uiutils.check(lambda: manager.active)
# Double click title to maximize
manager.click_title()
diff --git a/tests/uitests/test_snapshot.py b/tests/uitests/test_snapshot.py
index a6cd55224..a04d52e9d 100644
--- a/tests/uitests/test_snapshot.py
+++ b/tests/uitests/test_snapshot.py
@@ -44,6 +44,13 @@ class Snapshots(uiutils.UITestCase):
vmpause = win.find("Pause", "toggle button")
snaprun = win.find("snapshot-start", "push button")
+ # Start already running snapshot
+ snapname = "internal-root"
+ win.find(snapname, "table cell").click()
+ snaprun.click()
+ self._click_alert_button("run the snapshot '%s'" % snapname, "Yes")
+ uiutils.check(lambda: not vmrun.sensitive)
+
# Start offline snapshot
snapname = "offline-root"
win.find(snapname, "table cell").click()
diff --git a/ui/details.ui b/ui/details.ui
index 56a400966..ebf4f75bb 100644
--- a/ui/details.ui
+++ b/ui/details.ui
@@ -569,6 +569,11 @@
Falsestart
+
+
+ False
diff --git a/virtManager/config.py b/virtManager/config.py
index 43f8afb21..ec123bb9e 100644
--- a/virtManager/config.py
+++ b/virtManager/config.py
@@ -4,8 +4,6 @@
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
-import os
-
from gi.repository import Gio
from gi.repository import GLib
from gi.repository import Gtk
@@ -151,18 +149,25 @@ class vmmConfig(object):
"local_title": _("Locate existing storage"),
"dialog_type": Gtk.FileChooserAction.SAVE,
"choose_button": Gtk.STOCK_OPEN,
+ "gsettings_key": "image",
+ },
+
+ CONFIG_DIR_SCREENSHOT: {
+ "gsettings_key": "screenshot",
},
CONFIG_DIR_ISO_MEDIA: {
"enable_create": False,
"storage_title": _("Locate ISO media volume"),
"local_title": _("Locate ISO media"),
+ "gsettings_key": "media",
},
CONFIG_DIR_FLOPPY_MEDIA: {
"enable_create": False,
"storage_title": _("Locate floppy media volume"),
"local_title": _("Locate floppy media"),
+ "gsettings_key": "media",
},
CONFIG_DIR_FS: {
@@ -367,11 +372,9 @@ class vmmConfig(object):
def on_keys_combination_changed(self, cb):
return self.conf.notify_add("/console/grab-keys", cb)
- # This key is not intended to be exposed in the UI yet
+ # This key is not intended to be exposed in the UI yet (maybe ever)
def get_keyboard_grab_default(self):
return self.conf.get("/console/grab-keyboard")
- def set_keyboard_grab_default(self, val):
- self.conf.set("/console/grab-keyboard", val)
def on_keyboard_grab_default_changed(self, cb):
return self.conf.notify_add("/console/grab-keyboard", cb)
@@ -422,8 +425,6 @@ class vmmConfig(object):
# Libguestfs VM inspection
- def on_libguestfs_inspect_vms_changed(self, cb):
- return self.conf.notify_add("/enable-libguestfs-vm-inspection", cb)
def get_libguestfs_inspect_vms(self):
if self.CLITestOptions.config_libguestfs:
return True
@@ -439,9 +440,7 @@ class vmmConfig(object):
return 120
def get_stats_update_interval(self):
interval = self.conf.get("/stats/update-interval")
- if interval < 1:
- return 1
- return interval
+ return max(interval, 1)
def set_stats_update_interval(self, interval):
self.conf.set("/stats/update-interval", interval)
def on_stats_update_interval_changed(self, cb):
@@ -482,20 +481,16 @@ class vmmConfig(object):
def get_console_accels(self):
console_pref = self.conf.get("/console/enable-accels")
if console_pref is None:
- console_pref = False
+ console_pref = False # pragma: no cover
return console_pref
def set_console_accels(self, pref):
self.conf.set("/console/enable-accels", pref)
- def on_console_scaling_changed(self, cb):
- return self.conf.notify_add("/console/scaling", cb)
def get_console_scaling(self):
return self.conf.get("/console/scaling")
def set_console_scaling(self, pref):
self.conf.set("/console/scaling", pref)
- def on_console_resizeguest_changed(self, cb):
- return self.conf.notify_add("/console/resize-guest", cb)
def get_console_resizeguest(self):
val = self.conf.get("/console/resize-guest")
if val == -1:
@@ -513,21 +508,11 @@ class vmmConfig(object):
def get_details_show_toolbar(self):
res = self.conf.get("/details/show-toolbar")
if res is None:
- res = True
+ res = True # pragma: no cover
return res
def set_details_show_toolbar(self, state):
self.conf.set("/details/show-toolbar", state)
- # VM details default size
- def get_details_window_size(self):
- w = self.conf.get("/details/window_width")
- h = self.conf.get("/details/window_height")
- return (w, h)
- def set_details_window_size(self, w, h):
- self.conf.set("/details/window_width", w)
- self.conf.set("/details/window_height", h)
-
-
# New VM preferences
def get_new_vm_sound(self):
return self.conf.get("/new-vm/add-sound")
@@ -537,7 +522,7 @@ class vmmConfig(object):
def get_graphics_type(self, raw=False):
ret = self.conf.get("/new-vm/graphics-type")
if ret not in ["system", "vnc", "spice"]:
- ret = "system"
+ ret = "system" # pragma: no cover
if ret == "system" and not raw:
return self.default_graphics_from_config
return ret
@@ -547,9 +532,7 @@ class vmmConfig(object):
def get_add_spice_usbredir(self, raw=False):
ret = self.conf.get("/new-vm/add-spice-usbredir")
if ret not in ["system", "yes", "no"]:
- ret = "system"
- if not raw and self.get_graphics_type() != "spice":
- return "no"
+ ret = "system" # pragma: no cover
if ret == "system" and not raw:
return self.default_add_spice_usbredir
return ret
@@ -559,7 +542,7 @@ class vmmConfig(object):
def get_default_storage_format(self, raw=False):
ret = self.conf.get("/new-vm/storage-format")
if ret not in ["default", "raw", "qcow2"]:
- ret = "default"
+ ret = "default" # pragma: no cover
if ret == "default" and not raw:
return self.default_storage_format_from_config
return ret
@@ -570,7 +553,7 @@ class vmmConfig(object):
ret = self.conf.get("/new-vm/cpu-default")
if ret not in DomainCpu.SPECIAL_MODES:
- ret = DomainCpu.SPECIAL_MODE_APP_DEFAULT
+ ret = DomainCpu.SPECIAL_MODE_APP_DEFAULT # pragma: no cover
return ret
def set_default_cpu_setting(self, val):
self.conf.set("/new-vm/cpu-default", val.lower())
@@ -579,15 +562,13 @@ class vmmConfig(object):
# URL/Media path history
def _url_add_helper(self, gsettings_path, url):
maxlength = 10
- urls = self.conf.get(gsettings_path)
- if urls is None:
- urls = []
+ urls = self.conf.get(gsettings_path) or []
if urls.count(url) == 0 and len(url) > 0 and not url.isspace():
# The url isn't already in the list, so add it
urls.insert(0, url)
if len(urls) > maxlength:
- del urls[len(urls) - 1]
+ del urls[len(urls) - 1] # pragma: no cover
self.conf.set(gsettings_path, urls)
def add_container_url(self, url):
@@ -613,7 +594,7 @@ class vmmConfig(object):
current_list = self.get_perms_fix_ignore() or []
for path in pathlist:
if path in current_list:
- continue
+ continue # pragma: no cover
current_list.append(path)
self.conf.set("/paths/perms-fix-ignore", current_list)
def get_perms_fix_ignore(self):
@@ -654,9 +635,7 @@ class vmmConfig(object):
return ((uris is not None) and (uri in uris))
def set_conn_autoconnect(self, uri, val):
- uris = self.conf.get("/connections/autoconnect")
- if uris is None:
- uris = []
+ uris = self.conf.get("/connections/autoconnect") or []
if not val and uri in uris:
uris.remove(uri)
elif val and uri not in uris:
@@ -666,36 +645,23 @@ class vmmConfig(object):
# Default directory location dealings
- def _get_default_dir_key(self, _type):
- if (_type in [self.CONFIG_DIR_ISO_MEDIA,
- self.CONFIG_DIR_FLOPPY_MEDIA]):
- return "media"
- if (_type in [self.CONFIG_DIR_IMAGE,
- self.CONFIG_DIR_SCREENSHOT]):
- return _type
- return None
-
def get_default_directory(self, conn, _type):
ignore = conn
- key = self._get_default_dir_key(_type)
+ browsedata = self.browse_reason_data.get(_type, {})
+ key = browsedata.get("gsettings_key", None)
path = None
if key:
path = self.conf.get("/paths/%s-default" % key)
- if not path:
- if (_type == self.CONFIG_DIR_IMAGE or
- _type == self.CONFIG_DIR_ISO_MEDIA or
- _type == self.CONFIG_DIR_FLOPPY_MEDIA):
- path = os.getcwd()
-
log.debug("directory for type=%s returning=%s", _type, path)
return path
def set_default_directory(self, folder, _type):
- key = self._get_default_dir_key(_type)
+ browsedata = self.browse_reason_data.get(_type, {})
+ key = browsedata.get("gsettings_key", None)
if not key:
- return
+ return # pragma: no cover
log.debug("saving directory for type=%s to %s", key, folder)
self.conf.set("/paths/%s-default" % key, folder)
diff --git a/virtManager/delete.py b/virtManager/delete.py
index af97a6fc1..1d901f7c8 100644
--- a/virtManager/delete.py
+++ b/virtManager/delete.py
@@ -342,8 +342,7 @@ class vmmDeleteStorage(_vmmDeleteBase):
# Try to hot remove
detach_err = ()
try:
- if vm.is_active():
- vm.detach_device(devobj)
+ vm.detach_device(devobj)
except Exception as e:
log.debug("Device could not be hotUNplugged: %s", str(e))
detach_err = (str(e), "".join(traceback.format_exc()))
diff --git a/virtManager/details/details.py b/virtManager/details/details.py
index 8a9f32539..65c7fa558 100644
--- a/virtManager/details/details.py
+++ b/virtManager/details/details.py
@@ -683,7 +683,7 @@ class vmmDetails(vmmGObjectUI):
warn_icon.set_tooltip_text(
_("Libvirt or hypervisor does not support UEFI."))
elif not uefipaths:
- warn_icon.set_tooltip_text(
+ warn_icon.set_tooltip_text( # pragma: no cover
_("Libvirt did not detect any UEFI/OVMF firmware image "
"installed on the host."))
@@ -982,7 +982,7 @@ class vmmDetails(vmmGObjectUI):
pagetype = self._get_hw_row()[HW_LIST_COL_TYPE]
if pagetype is None:
- return
+ return # pragma: no cover
if self.widget("config-apply").get_sensitive():
# Apply button sensitive means user is making changes, don't
@@ -1046,6 +1046,10 @@ class vmmDetails(vmmGObjectUI):
self.vm, self.err, devobj)
if not success:
return
+
+ # This call here means when the vm config changes and triggers
+ # refresh event, the UI page will be updated, rather than leaving
+ # it untouched because it thinks changes are in progress
self._disable_apply()
def _remove_disk(self, disk):
@@ -1233,7 +1237,7 @@ class vmmDetails(vmmGObjectUI):
if new_idx < 0 or new_idx >= len(boot_order):
# Somehow we went out of bounds
- return
+ return # pragma: no cover
boot_list = self.widget("boot-list")
model = boot_list.get_model()
@@ -1814,19 +1818,17 @@ class vmmDetails(vmmGObjectUI):
# Machine settings
machtype = self.vm.get_machtype() or _("Unknown")
+ self.widget("machine-type-label").set_text(machtype)
if self.widget("machine-type").is_visible():
uiutil.set_list_selection(
self.widget("machine-type"), machtype)
- elif self.widget("machine-type-label").is_visible():
- self.widget("machine-type-label").set_text(machtype)
# Chipset
chipset = _chipset_label_from_machine(machtype)
+ self.widget("overview-chipset-label").set_text(chipset)
if self.widget("overview-chipset").is_visible():
uiutil.set_list_selection(
self.widget("overview-chipset"), chipset)
- elif self.widget("overview-chipset-label").is_visible():
- self.widget("overview-chipset-label").set_text(chipset)
def _refresh_os_page(self):
self._os_list.select_os(self.vm.xmlobj.osinfo)
@@ -2165,7 +2167,7 @@ class vmmDetails(vmmGObjectUI):
typelabel = _("Console Device")
elif char_type == "channel":
typelabel = _("Channel Device")
- else:
+ else: # pragma: no cover
typelabel = _("%s Device") % char_type.capitalize()
if (target_port is not None and
diff --git a/virtManager/lib/inspection.py b/virtManager/lib/inspection.py
index a93aa6ae3..2e67b6381 100644
--- a/virtManager/lib/inspection.py
+++ b/virtManager/lib/inspection.py
@@ -19,10 +19,13 @@ def _inspection_error(_errstr):
return data
-def _make_fake_data():
+def _make_fake_data(vm):
"""
Return fake vmmInspectionData for use with the test driver
"""
+ if not vm.xmlobj.devices.disk:
+ return _inspection_error("Fake test error no disks")
+
data = vmmInspectionData()
data.os_type = "test_os_type"
data.distro = "test_distro"
@@ -324,7 +327,7 @@ class vmmInspection(vmmGObject):
return _inspection_error(
_("Cannot inspect VM on remote connection"))
if conn.is_test():
- return _make_fake_data()
+ return _make_fake_data(vm)
return _perform_inspection(conn, vm)
diff --git a/virtManager/object/domain.py b/virtManager/object/domain.py
index bc5ad6ecc..feccfc6ad 100644
--- a/virtManager/object/domain.py
+++ b/virtManager/object/domain.py
@@ -276,8 +276,9 @@ class _vmmDomainSetTimeThread(vmmGObject):
# Only run the API for qemu and test drivers, they are the only ones
# that support it. This will save spamming logs with error output.
- if not self._domain.conn.is_qemu() and not self._domain.conn.is_test():
- return
+ if (not self._domain.conn.is_qemu() and
+ not self._domain.conn.is_test()):
+ return # pragma: no cover
# For qemu, only run the API if the VM has the qemu guest agent in
# the XML.
@@ -304,30 +305,32 @@ class _vmmDomainSetTimeThread(vmmGObject):
self._thread = None
self._do_cancel.clear()
+ def _wait_for_agent(self):
+ # Setting time of a qemu domain can only work if an agent is
+ # defined and online. We only get here if one is defined. So wait
+ # for it to come online now.
+ waited = 0
+ while waited < self._maxwait and not self._domain.agent_ready():
+ if waited == 0:
+ log.debug("Waiting for qemu guest agent to come online...")
+
+ # sleep some time and potentially abort
+ if self._do_cancel.wait(self._sleep):
+ return
+
+ waited += self._sleep
+
+ if not self._domain.agent_ready(): # pragma: no cover
+ log.debug("Giving up on qemu guest agent for time sync")
+ return
+
def _do_loop(self):
"""
Run the domain's set time operation. Potentially wait for a guest agent
to come online beforehand.
"""
if self._domain.conn.is_qemu():
- # Setting time of a qemu domain can only work if an agent is
- # defined and online. We only get here if one is defined. So wait
- # for it to come online now.
- waited = 0
- while waited < self._maxwait and not self._domain.agent_ready():
- if waited == 0:
- log.debug("Waiting for qemu guest agent to come online...")
-
- # sleep some time and potentially abort
- if self._do_cancel.wait(self._sleep):
- return
-
- waited += self._sleep
-
- if not self._domain.agent_ready():
- log.debug("Giving up on qemu guest agent for time sync")
- return
-
+ self._wait_for_agent()
self._domain.set_time()
def _cleanup(self):
@@ -369,6 +372,8 @@ class vmmDomain(vmmLibvirtObject):
for snap in self._snapshot_list or []:
snap.cleanup()
self._snapshot_list = None
+ self._set_time_thread.cleanup()
+ self._set_time_thread = None
vmmLibvirtObject._cleanup(self)
def _init_libvirt_state(self):
@@ -556,7 +561,7 @@ class vmmDomain(vmmLibvirtObject):
if new_nvram:
try:
new_nvram.get_vol_object().delete(0)
- except Exception as warn:
+ except Exception as warn: # pragma: no cover
log.debug("rename failed and new nvram was not "
"removed: '%s'", warn)
raise error
@@ -564,7 +569,7 @@ class vmmDomain(vmmLibvirtObject):
if new_nvram:
try:
old_nvram.get_vol_object().delete(0)
- except Exception as warn:
+ except Exception as warn: # pragma: no cover
log.debug("old nvram file was not removed: '%s'", warn)
self.define_overview(nvram=new_nvram.path)
@@ -1059,7 +1064,9 @@ class vmmDomain(vmmLibvirtObject):
def job_info(self):
if self.conn.is_test():
return testmock.fake_job_info()
- return self._backend.jobInfo()
+ # It's tough to hit this via uitests because it depends
+ # on the job lasting more than a second
+ return self._backend.jobInfo() # pragma: no cover
def abort_job(self):
self._backend.abortJob()
@@ -1168,7 +1175,7 @@ class vmmDomain(vmmLibvirtObject):
self._backend.setTime(time={"seconds": seconds,
"nseconds": nseconds})
log.debug("Successfully set guest time")
- except Exception as e:
+ except Exception as e: # pragma: no cover
log.debug("Failed to set time: %s", e)
def _async_set_time(self):
@@ -1256,7 +1263,7 @@ class vmmDomain(vmmLibvirtObject):
consoles = self.xmlobj.devices.console
if not consoles:
- return False
+ return False # pragma: no cover
console = consoles[0]
if (console.type == serial.type and
diff --git a/virtManager/vmwindow.py b/virtManager/vmwindow.py
index 9c292cef5..dab6c2085 100644
--- a/virtManager/vmwindow.py
+++ b/virtManager/vmwindow.py
@@ -462,8 +462,8 @@ class vmmVMWindow(vmmGObjectUI):
vmmenu.VMActionUI.resume(self, self.vm)
def control_vm_menu(self, src_ignore):
- can_usb = bool(self.console.details_viewer_has_usb_redirection() and
- self.vm.has_spicevmc_type_redirdev())
+ can_usb = bool(self.vm.has_spicevmc_type_redirdev() and
+ self.console.details_viewer_has_usb_redirection())
self.widget("details-menu-usb-redirection").set_sensitive(can_usb)
def control_vm_run(self, src_ignore):