migrate: Add XML editor support

Allows the user to tweak the XML at the destination, which is already
something that libvirt supports

Signed-off-by: Cole Robinson <crobinso@redhat.com>
This commit is contained in:
Cole Robinson 2020-09-02 16:56:08 -04:00
parent 16ebab2230
commit 5e495ebd46
5 changed files with 551 additions and 486 deletions

View File

@ -102,7 +102,6 @@ class VMMMigrate(uiutils.UITestCase):
uiutils.check(lambda: not progwin.showing, timeout=5)
uiutils.check(lambda: not mig.showing)
def testMigrateConnMismatch(self):
# Add a possible target but disconnect it
self.app.uri = utils.URIs.test_default
@ -120,3 +119,35 @@ class VMMMigrate(uiutils.UITestCase):
mig.find("conn-combo").find("No usable", "menu item")
mig.keyCombo("<alt>F4")
uiutils.check(lambda: not mig.showing)
def testMigrateXMLEditor(self):
self.app.open(xmleditor_enabled=True)
manager = self.app.topwin
# Add an additional connection
self._add_conn("test:///default")
# Run it and check some values
vmname = "test-many-devices"
win = self._open_migrate(vmname)
win.find("address-text").set_text("TESTSUITE-FAKE")
# Create a new obj with XML edited name, verify it worked
newname = "aafroofroo"
win.find("XML", "page tab").click()
xmleditor = win.find("XML editor")
newtext = xmleditor.text.replace(
">%s<" % vmname, ">%s<" % newname)
xmleditor.set_text(newtext)
win.find("Migrate", "push button").click()
uiutils.check(lambda: not win.showing, timeout=10)
manager.find(newname, "table cell")
# Do standard xmleditor tests
win = self._open_migrate(vmname)
win.find("address-text").set_text("TESTSUITE-FAKE")
finish = win.find("Migrate", "push button")
self._test_xmleditor_interactions(win, finish)
win.find("Cancel", "push button").click()
uiutils.check(lambda: not win.visible)

View File

@ -265,7 +265,9 @@ def drag(win, x, y):
"""
Drag a window to the x/y coordinates
"""
win.click()
time.sleep(.5)
win.click_title()
time.sleep(.5)
clickX, clickY = _title_coordinates(win)
dogtail.rawinput.drag((clickX, clickY), (x, y))

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@ from .asyncjob import vmmAsyncJob
from .baseclass import vmmGObjectUI
from .connmanager import vmmConnectionManager
from .object.domain import vmmDomain
from .xmleditor import vmmXMLEditor
NUM_COLS = 3
@ -40,6 +41,12 @@ class vmmMigrateDialog(vmmGObjectUI):
vmmGObjectUI.__init__(self, "migrate.ui", "vmm-migrate")
self.vm = None
self._xmleditor = vmmXMLEditor(self.builder, self.topwin,
self.widget("details-box-align"),
self.widget("details-box"))
self._xmleditor.connect("xml-requested",
self._xmleditor_xml_requested_cb)
self.builder.connect_signals({
"on_vmm_migrate_delete_event": self._delete_event,
"on_migrate_cancel_clicked": self._cancel_clicked,
@ -58,6 +65,8 @@ class vmmMigrateDialog(vmmGObjectUI):
def _cleanup(self):
self.vm = None
self._xmleditor.cleanup()
self._xmleditor = None
@property
def _connobjs(self):
@ -147,6 +156,8 @@ class vmmMigrateDialog(vmmGObjectUI):
self.widget("migrate-temporary-label").get_tooltip_text())
def _reset_state(self):
self._xmleditor.reset_state()
title_str = _("<span size='large'>Migrate '%(vm)s'</span>") % {
"vm": xmlutil.xml_escape(self.vm.get_name()),
}
@ -348,6 +359,11 @@ class vmmMigrateDialog(vmmGObjectUI):
def _finish(self):
try:
xml = None
if self._xmleditor.is_xml_selected():
xml = self._xmleditor.get_xml()
log.debug("Using XML from xmleditor:\n%s", xml)
row = uiutil.get_list_selected_row(self.widget("migrate-dest"))
destlabel = row[COL_LABEL]
destconn = self._connobjs.get(row[COL_URI])
@ -378,7 +394,7 @@ class vmmMigrateDialog(vmmGObjectUI):
progWin = vmmAsyncJob(
self._async_migrate,
[self.vm, destconn, uri, tunnel, unsafe, temporary],
[self.vm, destconn, uri, tunnel, unsafe, temporary, xml],
self._finish_cb, [destconn],
_("Migrating VM '%s'") % self.vm.get_name(),
(_("Migrating VM '%(name)s' to %(host)s. This may take a while.") %
@ -398,7 +414,7 @@ class vmmMigrateDialog(vmmGObjectUI):
asyncjob.job_canceled = True # pragma: no cover
def _async_migrate(self, asyncjob,
origvm, origdconn, migrate_uri, tunnel, unsafe, temporary):
origvm, origdconn, migrate_uri, tunnel, unsafe, temporary, xml):
meter = asyncjob.get_meter()
srcconn = origvm.conn
@ -410,5 +426,12 @@ class vmmMigrateDialog(vmmGObjectUI):
log.debug("Migrating vm=%s from %s to %s", vm.get_name(),
srcconn.get_uri(), dstconn.get_uri())
vm.migrate(dstconn, migrate_uri, tunnel, unsafe, temporary,
vm.migrate(dstconn, migrate_uri, tunnel, unsafe, temporary, xml,
meter=meter)
################
# UI listeners #
################
def _xmleditor_xml_requested_cb(self, src):
self._xmleditor.set_xml(self.vm.xmlobj.get_xml())

View File

@ -1388,7 +1388,7 @@ class vmmDomain(vmmLibvirtObject):
def migrate(self, destconn, dest_uri=None,
tunnel=False, unsafe=False, temporary=False, meter=None):
tunnel=False, unsafe=False, temporary=False, xml=None, meter=None):
self._cancel_set_time()
self._install_abort = True
@ -1417,12 +1417,15 @@ class vmmDomain(vmmLibvirtObject):
params = {}
if dest_uri and not tunnel:
params[libvirt.VIR_MIGRATE_PARAM_URI] = dest_uri
if xml:
params[libvirt.VIR_MIGRATE_PARAM_DEST_XML] = xml
if self.conn.is_test() and "TESTSUITE-FAKE" in (dest_uri or ""):
# If using the test driver and a special URI, fake successful
# migration so we can test more of the migration wizard
time.sleep(3)
xml = self.get_xml_to_define()
if not xml:
xml = self.get_xml_to_define()
destconn.define_domain(xml).create()
self.delete()
elif tunnel: