virt-manager/tests/uitests/test_clonevm.py

253 lines
8.4 KiB
Python
Raw Normal View History

2024-05-17 13:37:53 +08:00
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
import os
import tests.utils
from . import lib
class _CloneRow:
"""
Helper class for interacting with the clone row
"""
def __init__(self, *args):
self.chkcell = args[2]
self.txtcell = args[5]
self.is_cloneable = self.chkcell.showing
self.is_share_requested = (
not self.is_cloneable or not self.chkcell.checked)
self.is_clone_requested = not self.is_share_requested
def check_in_text(self, substr):
lib.utils.check(lambda: substr in self.txtcell.text)
def select(self):
self.txtcell.click()
def _get_all_rows(win):
slist = win.find("storage-list")
def pred(node):
return node.roleName == "table cell"
cells = slist.findChildren(pred, isLambda=True)
idx = 0
rows = []
cellcount = 6
while idx < len(cells):
rows.append(_CloneRow(*cells[idx:idx + cellcount]))
idx += cellcount
# Skip the next row which is always a separator
idx += cellcount
return rows
##############################################
# UI tests for virt-manager's CloneVM wizard #
##############################################
def testCloneSimple(app):
# Disable predictable so UUID generation doesn't collide
uri = tests.utils.URIs.test_full.replace(",predictable", "")
app.uri = uri
# Clone 'test-clone-simple' which is the most basic case
# Cancel, and reopen
win = app.manager_open_clone("test-clone-simple")
win.find("Cancel", "push button").click()
lib.utils.check(lambda: not win.showing)
# Do default clone
win = app.manager_open_clone("test-clone-simple")
rows = _get_all_rows(win)
assert len(rows) == 1
assert rows[0].is_clone_requested
rows[0].check_in_text("test-clone-simple.img")
win.find("Clone", "push button").click()
lib.utils.check(lambda: not win.showing)
# Check path was generated correctly
win = app.manager_open_clone("test-clone-simple-clone")
rows = _get_all_rows(win)
assert len(rows) == 1
assert rows[0].is_clone_requested
rows[0].check_in_text("test-clone-simple-clone.img")
# Share storage and deal with warnings
rows[0].chkcell.click()
rows[0].check_in_text("Share disk with")
# Do 'cancel' first
win.find("Clone", "push button").click()
app.click_alert_button("cause data to be overwritten", "Cancel")
lib.utils.check(lambda: win.active)
win.find("Clone", "push button").click()
app.click_alert_button("cause data to be overwritten", "OK")
lib.utils.check(lambda: not win.active)
# Verify the new VM shared storage
win = app.manager_open_clone("test-clone-simple-clone1")
rows = _get_all_rows(win)
assert len(rows) == 1
rows[0].check_in_text("test-clone-simple-clone.img")
def testCloneMulti(app):
# Clone 'test-clone', check some results, make sure clone works
manager = app.topwin
manager.window_maximize()
# Shutdown this VM to prep for later
manager.find("test-many-devices").click()
sbutton = manager.find("Shut Down", "push button")
sbutton.click()
lib.utils.check(lambda: not sbutton.sensitive)
# Do a basic clone
win = app.manager_open_clone("test-clone")
win.find("Clone", "push button").click()
lib.utils.check(lambda: not win.showing)
manager.find("test-clone1", "table cell")
# Check test-many-devices which will not work, but confirm
# it errors gracefully
win = app.manager_open_clone("test-many-devices")
win.find("Clone", "push button").click()
app.click_alert_button("relative.sock", "Cancel")
# Ensure disconnecting will close the dialog
manager.grab_focus()
app.manager_conn_disconnect("test testdriver.xml")
lib.utils.check(lambda: not win.showing)
def testCloneStorageChange(app):
# Disable predictable so UUID generation doesn't collide
uri = tests.utils.URIs.test_full.replace(",predictable", "")
app.uri = uri
# Trigger some error handling scenarios
win = app.manager_open_clone("test-clone-simple")
newname = "test-aaabbb"
win.find("Name:", "text").set_text(newname)
win.find("Clone", "push button").click()
lib.utils.check(lambda: not win.showing)
win = app.manager_open_clone(newname)
row = _get_all_rows(win)[0]
row.check_in_text(newname)
oldnewname = newname
newname = "test-aaazzzzbbb"
win.find("Name:", "text").set_text(newname)
row.select()
win.find("Details", "push button").click()
stgwin = app.root.find("Change storage path", "dialog")
pathtxt = stgwin.find(None, "text", "New Path:")
lib.utils.check(lambda: newname in pathtxt.text)
stgwin.find("Browse", "push button").click()
app.select_storagebrowser_volume("pool-dir", "iso-vol")
lib.utils.check(lambda: "iso-vol" in pathtxt.text)
stgwin.find("OK").click()
app.click_alert_button("overwrite the existing", "No")
lib.utils.check(lambda: stgwin.showing)
stgwin.find("OK").click()
app.click_alert_button("overwrite the existing", "Yes")
lib.utils.check(lambda: not stgwin.showing)
# Can't clone onto existing storage volume
win.find("Clone", "push button").click()
app.click_alert_button(".*Clone onto existing.*", "Close")
# Reopen dialog and request to share it
win.find("Details", "push button").click()
stgwin = app.root.find("Change storage path", "dialog")
chkbox = stgwin.find("Create a new", "check")
lib.utils.check(lambda: chkbox.checked)
chkbox.click()
# Cancel and reopen, confirm changes didn't stick
stgwin.find("Cancel").click()
lib.utils.check(lambda: not stgwin.showing)
win.find("Details", "push button").click()
stgwin = app.root.find("Change storage path", "dialog")
chkbox = stgwin.find("Create a new", "check")
lib.utils.check(lambda: chkbox.checked)
# Requesting sharing again and exit
chkbox.click()
stgwin.find("OK").click()
lib.utils.check(lambda: not stgwin.active)
# Finish install, verify storage was shared
win.find("Clone", "push button").click()
app.click_alert_button("cause data to be overwritten", "OK")
lib.utils.check(lambda: not win.active)
win = app.manager_open_clone(newname)
row = _get_all_rows(win)[0].check_in_text(oldnewname)
def testCloneError(app):
# Trigger some error handling scenarios
win = app.manager_open_clone("test-clone-full")
win.find("Clone", "push button").click()
app.click_alert_button("not enough free space", "Close")
win.window_close()
win = app.manager_open_clone("test-clone-simple")
badname = "test/foo"
win.find("Name:", "text").set_text(badname)
rows = _get_all_rows(win)
rows[0].chkcell.click()
rows[0].check_in_text("Share disk with")
win.find("Clone", "push button").click()
win.find("Clone", "push button").click()
app.click_alert_button("cause data to be overwritten", "OK")
app.click_alert_button(badname, "Close")
lib.utils.check(lambda: win.active)
def testCloneNonmanaged(app):
# Verify unmanaged clone actual works
import tempfile
tmpsrc = tempfile.NamedTemporaryFile()
tmpdst = tempfile.NamedTemporaryFile()
open(tmpsrc.name, "w").write(__file__)
app.open(xmleditor_enabled=True)
manager = app.topwin
win = app.manager_open_details("test-clone-simple")
win.find("IDE Disk 1", "table cell").click()
win.find("XML", "page tab").click()
xmleditor = win.find("XML editor")
origpath = "/pool-dir/test-clone-simple.img"
newpath = tmpsrc.name
xmleditor.set_text(xmleditor.text.replace(origpath, newpath))
win.find("config-apply").click()
win.find("Details", "page tab").click()
disksrc = win.find("disk-source-path")
lib.utils.check(lambda: disksrc.text == newpath)
win.window_close()
lib.utils.check(lambda: manager.active)
win = app.manager_open_clone("test-clone-simple")
row = _get_all_rows(win)[0]
row.check_in_text(tmpsrc.name)
row.select()
win.find("Details", "push button").click()
stgwin = app.root.find("Change storage path", "dialog")
pathtxt = stgwin.find(None, "text", "New Path:")
os.unlink(tmpdst.name)
pathtxt.set_text(tmpdst.name)
stgwin.find("OK").click()
win.find("Clone", "push button").click()
lib.utils.check(lambda: not win.active)
lib.utils.check(lambda: os.path.exists(tmpdst.name))
assert open(tmpsrc.name).read() == open(tmpdst.name).read()