- cli: Add basic --audio type=XXX,id=Y support (RHEL-17435) - virtinst: unify detection of duplicate console when removing device (RHEL-17435) - virtinst: fix compare for audio devices (RHEL-17435) - testsuite: add test-spice vm definition (RHEL-17435) - virtinst: remove spice devices when removing last spice graphics (RHEL-17435) - guest: add convert_to_vnc() (RHEL-17435) - guest: remove spiceport devices when spice is removed (RHEL-17435) - guest: convert_to_vnc: convert video device (RHEL-17435) - virt-xml: Add `--edit --convert-to-vnc` (RHEL-17435) Resolves: RHEL-17435
398 lines
13 KiB
Diff
398 lines
13 KiB
Diff
From a6f53b7da4ac6ff0139e7a130ba875a61a877617 Mon Sep 17 00:00:00 2001
|
|
Message-ID: <a6f53b7da4ac6ff0139e7a130ba875a61a877617.1737975657.git.phrdina@redhat.com>
|
|
From: Pavel Hrdina <phrdina@redhat.com>
|
|
Date: Tue, 17 Sep 2024 10:02:59 -0400
|
|
Subject: [PATCH] guest: add convert_to_vnc()
|
|
|
|
From: Cole Robinson <crobinso@redhat.com>
|
|
|
|
This is the beginnings of support for a `virt-xml --convert-to-vnc`
|
|
option. Take an existing VM, strip out most of the previous graphics
|
|
config, and add VNC graphics.
|
|
|
|
We try to convert over some of the shared graphic bits, like listen
|
|
and port settings, if they were previously specified.
|
|
|
|
If spice GL was enabled, we convert to egl-headless config
|
|
|
|
Signed-off-by: Cole Robinson <crobinso@redhat.com>
|
|
(cherry picked from commit 229b905053f3d4bc17e7ad0f8d3fc2c3f23c47cd)
|
|
|
|
Conflicts:
|
|
tests/test_xmlparse.py
|
|
virtinst/guest.py
|
|
|
|
https://issues.redhat.com/browse/RHEL-17435
|
|
|
|
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
|
|
---
|
|
.../data/xmlparse/convert-to-vnc-empty-in.xml | 13 +++
|
|
.../xmlparse/convert-to-vnc-empty-out.xml | 13 +++
|
|
.../xmlparse/convert-to-vnc-has-vnc-in.xml | 31 +++++++
|
|
.../xmlparse/convert-to-vnc-has-vnc-out.xml | 22 +++++
|
|
.../convert-to-vnc-spice-devices-in.xml | 30 +++++++
|
|
.../convert-to-vnc-spice-devices-out.xml | 22 +++++
|
|
.../convert-to-vnc-spice-manyopts-in.xml | 20 +++++
|
|
.../convert-to-vnc-spice-manyopts-out.xml | 20 +++++
|
|
tests/test_xmlparse.py | 14 +++
|
|
virtinst/guest.py | 88 ++++++++++++++++++-
|
|
10 files changed, 269 insertions(+), 4 deletions(-)
|
|
create mode 100644 tests/data/xmlparse/convert-to-vnc-empty-in.xml
|
|
create mode 100644 tests/data/xmlparse/convert-to-vnc-empty-out.xml
|
|
create mode 100644 tests/data/xmlparse/convert-to-vnc-has-vnc-in.xml
|
|
create mode 100644 tests/data/xmlparse/convert-to-vnc-has-vnc-out.xml
|
|
create mode 100644 tests/data/xmlparse/convert-to-vnc-spice-devices-in.xml
|
|
create mode 100644 tests/data/xmlparse/convert-to-vnc-spice-devices-out.xml
|
|
create mode 100644 tests/data/xmlparse/convert-to-vnc-spice-manyopts-in.xml
|
|
create mode 100644 tests/data/xmlparse/convert-to-vnc-spice-manyopts-out.xml
|
|
|
|
diff --git a/tests/data/xmlparse/convert-to-vnc-empty-in.xml b/tests/data/xmlparse/convert-to-vnc-empty-in.xml
|
|
new file mode 100644
|
|
index 000000000..bc370a8a2
|
|
--- /dev/null
|
|
+++ b/tests/data/xmlparse/convert-to-vnc-empty-in.xml
|
|
@@ -0,0 +1,13 @@
|
|
+<domain type='qemu'>
|
|
+ <name>convert-me</name>
|
|
+ <memory unit='KiB'>8388608</memory>
|
|
+ <currentMemory unit='KiB'>2097152</currentMemory>
|
|
+ <vcpu placement='static'>2</vcpu>
|
|
+ <os>
|
|
+ <type arch='i686'>hvm</type>
|
|
+ <boot dev='hd'/>
|
|
+ </os>
|
|
+ <devices>
|
|
+ </devices>
|
|
+</domain>
|
|
+
|
|
diff --git a/tests/data/xmlparse/convert-to-vnc-empty-out.xml b/tests/data/xmlparse/convert-to-vnc-empty-out.xml
|
|
new file mode 100644
|
|
index 000000000..8612a6567
|
|
--- /dev/null
|
|
+++ b/tests/data/xmlparse/convert-to-vnc-empty-out.xml
|
|
@@ -0,0 +1,13 @@
|
|
+<domain type="qemu">
|
|
+ <name>convert-me</name>
|
|
+ <memory unit="KiB">8388608</memory>
|
|
+ <currentMemory unit="KiB">2097152</currentMemory>
|
|
+ <vcpu placement="static">2</vcpu>
|
|
+ <os>
|
|
+ <type arch="i686">hvm</type>
|
|
+ <boot dev="hd"/>
|
|
+ </os>
|
|
+ <devices>
|
|
+ <graphics type="vnc" port="-1"/>
|
|
+ </devices>
|
|
+</domain>
|
|
diff --git a/tests/data/xmlparse/convert-to-vnc-has-vnc-in.xml b/tests/data/xmlparse/convert-to-vnc-has-vnc-in.xml
|
|
new file mode 100644
|
|
index 000000000..29ee53d4c
|
|
--- /dev/null
|
|
+++ b/tests/data/xmlparse/convert-to-vnc-has-vnc-in.xml
|
|
@@ -0,0 +1,31 @@
|
|
+<domain type="kvm">
|
|
+ <name>convert-me</name>
|
|
+ <memory>2097152</memory>
|
|
+ <currentMemory>2097152</currentMemory>
|
|
+ <vcpu>2</vcpu>
|
|
+ <os>
|
|
+ <type arch="x86_64" machine="q35">hvm</type>
|
|
+ <boot dev="network"/>
|
|
+ </os>
|
|
+ <features>
|
|
+ <acpi/>
|
|
+ <apic/>
|
|
+ <vmport state="off"/>
|
|
+ </features>
|
|
+ <devices>
|
|
+ <channel type="spicevmc">
|
|
+ <target type="virtio" name="com.redhat.spice.0"/>
|
|
+ </channel>
|
|
+ <graphics type="spice" port="-1" tlsPort="-1" autoport="yes">
|
|
+ <image compression="off"/>
|
|
+ </graphics>
|
|
+ <graphics type="vnc" port="5907"/>
|
|
+ <sound model="ich9"/>
|
|
+ <audio type='spice'/>
|
|
+ <video>
|
|
+ <model type="virtio"/>
|
|
+ </video>
|
|
+ <redirdev bus="usb" type="spicevmc"/>
|
|
+ <redirdev bus="usb" type="spicevmc"/>
|
|
+ </devices>
|
|
+</domain>
|
|
diff --git a/tests/data/xmlparse/convert-to-vnc-has-vnc-out.xml b/tests/data/xmlparse/convert-to-vnc-has-vnc-out.xml
|
|
new file mode 100644
|
|
index 000000000..113f70a1e
|
|
--- /dev/null
|
|
+++ b/tests/data/xmlparse/convert-to-vnc-has-vnc-out.xml
|
|
@@ -0,0 +1,22 @@
|
|
+<domain type="kvm">
|
|
+ <name>convert-me</name>
|
|
+ <memory>2097152</memory>
|
|
+ <currentMemory>2097152</currentMemory>
|
|
+ <vcpu>2</vcpu>
|
|
+ <os>
|
|
+ <type arch="x86_64" machine="q35">hvm</type>
|
|
+ <boot dev="network"/>
|
|
+ </os>
|
|
+ <features>
|
|
+ <acpi/>
|
|
+ <apic/>
|
|
+ <vmport state="off"/>
|
|
+ </features>
|
|
+ <devices>
|
|
+ <graphics type="vnc" port="5907"/>
|
|
+ <sound model="ich9"/>
|
|
+ <video>
|
|
+ <model type="virtio"/>
|
|
+ </video>
|
|
+ </devices>
|
|
+</domain>
|
|
diff --git a/tests/data/xmlparse/convert-to-vnc-spice-devices-in.xml b/tests/data/xmlparse/convert-to-vnc-spice-devices-in.xml
|
|
new file mode 100644
|
|
index 000000000..8c5c63bdf
|
|
--- /dev/null
|
|
+++ b/tests/data/xmlparse/convert-to-vnc-spice-devices-in.xml
|
|
@@ -0,0 +1,30 @@
|
|
+<domain type="kvm">
|
|
+ <name>convert-me</name>
|
|
+ <memory>2097152</memory>
|
|
+ <currentMemory>2097152</currentMemory>
|
|
+ <vcpu>2</vcpu>
|
|
+ <os>
|
|
+ <type arch="x86_64" machine="q35">hvm</type>
|
|
+ <boot dev="network"/>
|
|
+ </os>
|
|
+ <features>
|
|
+ <acpi/>
|
|
+ <apic/>
|
|
+ <vmport state="off"/>
|
|
+ </features>
|
|
+ <devices>
|
|
+ <channel type="spicevmc">
|
|
+ <target type="virtio" name="com.redhat.spice.0"/>
|
|
+ </channel>
|
|
+ <graphics type="spice" port="-1" tlsPort="-1" autoport="yes">
|
|
+ <image compression="off"/>
|
|
+ </graphics>
|
|
+ <sound model="ich9"/>
|
|
+ <audio type='spice'/>
|
|
+ <video>
|
|
+ <model type="virtio"/>
|
|
+ </video>
|
|
+ <redirdev bus="usb" type="spicevmc"/>
|
|
+ <redirdev bus="usb" type="spicevmc"/>
|
|
+ </devices>
|
|
+</domain>
|
|
diff --git a/tests/data/xmlparse/convert-to-vnc-spice-devices-out.xml b/tests/data/xmlparse/convert-to-vnc-spice-devices-out.xml
|
|
new file mode 100644
|
|
index 000000000..cc3fefabe
|
|
--- /dev/null
|
|
+++ b/tests/data/xmlparse/convert-to-vnc-spice-devices-out.xml
|
|
@@ -0,0 +1,22 @@
|
|
+<domain type="kvm">
|
|
+ <name>convert-me</name>
|
|
+ <memory>2097152</memory>
|
|
+ <currentMemory>2097152</currentMemory>
|
|
+ <vcpu>2</vcpu>
|
|
+ <os>
|
|
+ <type arch="x86_64" machine="q35">hvm</type>
|
|
+ <boot dev="network"/>
|
|
+ </os>
|
|
+ <features>
|
|
+ <acpi/>
|
|
+ <apic/>
|
|
+ <vmport state="off"/>
|
|
+ </features>
|
|
+ <devices>
|
|
+ <graphics type="vnc" port="-1"/>
|
|
+ <sound model="ich9"/>
|
|
+ <video>
|
|
+ <model type="virtio"/>
|
|
+ </video>
|
|
+ </devices>
|
|
+</domain>
|
|
diff --git a/tests/data/xmlparse/convert-to-vnc-spice-manyopts-in.xml b/tests/data/xmlparse/convert-to-vnc-spice-manyopts-in.xml
|
|
new file mode 100644
|
|
index 000000000..ebd20a56d
|
|
--- /dev/null
|
|
+++ b/tests/data/xmlparse/convert-to-vnc-spice-manyopts-in.xml
|
|
@@ -0,0 +1,20 @@
|
|
+<domain type='qemu'>
|
|
+ <name>convert-me</name>
|
|
+ <memory unit='KiB'>8388608</memory>
|
|
+ <currentMemory unit='KiB'>2097152</currentMemory>
|
|
+ <vcpu placement='static'>2</vcpu>
|
|
+ <os>
|
|
+ <type arch='i686'>hvm</type>
|
|
+ <boot dev='hd'/>
|
|
+ </os>
|
|
+ <clock offset='utc'/>
|
|
+ <devices>
|
|
+ <graphics type='spice' port='5907' tlsPort='5901' autoport='no' passwd='sercet' passwdValidTo='2011-05-31T16:11:22' connected='disconnect' keymap='de' listen='127.0.0.1'>
|
|
+ <listen type='socket' socket='/tmp/spice.sock'/>
|
|
+ <listen type='address' address='127.0.0.1'/>
|
|
+ <gl enable='yes' rendernode='/dev/my/rendernode'/>
|
|
+ </graphics>
|
|
+ <graphics type='sdl'/>
|
|
+ </devices>
|
|
+</domain>
|
|
+
|
|
diff --git a/tests/data/xmlparse/convert-to-vnc-spice-manyopts-out.xml b/tests/data/xmlparse/convert-to-vnc-spice-manyopts-out.xml
|
|
new file mode 100644
|
|
index 000000000..c98c63830
|
|
--- /dev/null
|
|
+++ b/tests/data/xmlparse/convert-to-vnc-spice-manyopts-out.xml
|
|
@@ -0,0 +1,20 @@
|
|
+<domain type="qemu">
|
|
+ <name>convert-me</name>
|
|
+ <memory unit="KiB">8388608</memory>
|
|
+ <currentMemory unit="KiB">2097152</currentMemory>
|
|
+ <vcpu placement="static">2</vcpu>
|
|
+ <os>
|
|
+ <type arch="i686">hvm</type>
|
|
+ <boot dev="hd"/>
|
|
+ </os>
|
|
+ <clock offset="utc"/>
|
|
+ <devices>
|
|
+ <graphics type="vnc" port="5907" keymap="de" listen="127.0.0.1" passwd="sercet" passwdValidTo="2011-05-31T16:11:22">
|
|
+ <listen type="socket" socket="/tmp/spice.sock"/>
|
|
+ <listen type="address" address="127.0.0.1"/>
|
|
+ </graphics>
|
|
+ <graphics type="egl-headless">
|
|
+ <gl rendernode="/dev/my/rendernode"/>
|
|
+ </graphics>
|
|
+ </devices>
|
|
+</domain>
|
|
diff --git a/tests/test_xmlparse.py b/tests/test_xmlparse.py
|
|
index ac2fb38d2..e11d15d07 100644
|
|
--- a/tests/test_xmlparse.py
|
|
+++ b/tests/test_xmlparse.py
|
|
@@ -1135,3 +1135,17 @@ def testControllerAttachedDevices():
|
|
|
|
# Little test for DeviceAddress.pretty_desc
|
|
assert devs[-1].address.pretty_desc() == "0:0:0:3"
|
|
+
|
|
+
|
|
+def testConvertToVNC():
|
|
+ conn = utils.URIs.openconn(utils.URIs.kvm_x86)
|
|
+
|
|
+ def _test(filename_base):
|
|
+ guest, outfile = _get_test_content(conn, filename_base)
|
|
+ guest.convert_to_vnc()
|
|
+ _alter_compare(conn, guest.get_xml(), outfile)
|
|
+
|
|
+ _test("convert-to-vnc-empty")
|
|
+ _test("convert-to-vnc-spice-devices")
|
|
+ _test("convert-to-vnc-spice-manyopts")
|
|
+ _test("convert-to-vnc-has-vnc")
|
|
diff --git a/virtinst/guest.py b/virtinst/guest.py
|
|
index 7aa62be49..93e71a149 100644
|
|
--- a/virtinst/guest.py
|
|
+++ b/virtinst/guest.py
|
|
@@ -706,6 +706,84 @@ class Guest(XMLBuilder):
|
|
self.vcpus = self.cpu.vcpus_from_topology()
|
|
self.cpu.set_topology_defaults(self.vcpus)
|
|
|
|
+ def _convert_spice_gl_to_egl_headless(self):
|
|
+ if not self.has_spice():
|
|
+ return
|
|
+
|
|
+ spicedev = [g for g in self.devices.graphics if g.type == "spice"][0]
|
|
+ if not spicedev.gl:
|
|
+ return
|
|
+
|
|
+ dev = DeviceGraphics(self.conn)
|
|
+ dev.type = "egl-headless"
|
|
+ dev.set_defaults(self.conn)
|
|
+ if spicedev.rendernode:
|
|
+ dev.rendernode = spicedev.rendernode
|
|
+ self.add_device(dev)
|
|
+
|
|
+ def _convert_to_vnc_graphics(self):
|
|
+ """
|
|
+ If there's already VNC graphics configured, we leave it intact,
|
|
+ but rip out all evidence of other graphics devices.
|
|
+
|
|
+ If there's other non-VNC, non-egl-headless configured, we try to
|
|
+ inplace convert the first device we encounter.
|
|
+
|
|
+ If there's no graphics configured, set up a default VNC config.`
|
|
+ """
|
|
+ vnc_devs = [g for g in self.devices.graphics if g.type == "vnc"]
|
|
+ # We ignore egl-headless, it's not a true graphical frontend
|
|
+ other_devs = [g for g in self.devices.graphics if
|
|
+ g.type != "vnc" and g.type != "egl-headless"]
|
|
+
|
|
+ # Guest already had a vnc device.
|
|
+ # Remove all other devs and we are done
|
|
+ if vnc_devs:
|
|
+ for g in other_devs:
|
|
+ self.remove_device(g)
|
|
+ return
|
|
+
|
|
+ # We didn't find any non-vnc device to convert.
|
|
+ # Add a vnc device with default config
|
|
+ if not other_devs:
|
|
+ dev = DeviceGraphics(self.conn)
|
|
+ dev.type = dev.TYPE_VNC
|
|
+ dev.set_defaults(self.conn)
|
|
+ self.add_device(dev)
|
|
+ return
|
|
+
|
|
+ # Convert the pre-existing graphics device to vnc
|
|
+ # Remove the rest
|
|
+ dev = other_devs.pop(0)
|
|
+ srcdev = DeviceGraphics(self.conn, dev.get_xml())
|
|
+ for g in other_devs:
|
|
+ self.remove_device(g)
|
|
+
|
|
+ dev.clear()
|
|
+ dev.type = dev.TYPE_VNC
|
|
+ dev.keymap = srcdev.keymap
|
|
+ dev.port = srcdev.port
|
|
+ dev.autoport = srcdev.autoport
|
|
+ dev.passwd = srcdev.passwd
|
|
+ dev.passwdValidTo = srcdev.passwdValidTo
|
|
+ dev.listen = srcdev.listen
|
|
+ for listen in srcdev.listens:
|
|
+ srcdev.remove_child(listen)
|
|
+ dev.add_child(listen)
|
|
+ dev.set_defaults(self)
|
|
+
|
|
+ def convert_to_vnc(self):
|
|
+ """
|
|
+ Convert existing XML to have one VNC graphics connection.
|
|
+ """
|
|
+ self._convert_spice_gl_to_egl_headless()
|
|
+
|
|
+ # Rip out spice graphics devices unconditionally.
|
|
+ # Could be necessary if XML is in broken state.
|
|
+ self._force_remove_spice_devices()
|
|
+
|
|
+ self._convert_to_vnc_graphics()
|
|
+
|
|
def set_defaults(self, _guest):
|
|
self.set_capabilities_defaults()
|
|
|
|
@@ -1061,10 +1139,12 @@ class Guest(XMLBuilder):
|
|
if redirdev.type == "spicevmc":
|
|
self.devices.remove_child(redirdev)
|
|
|
|
- def _remove_spice_devices(self, rmdev):
|
|
- if rmdev.DEVICE_TYPE != "graphics" or self.has_spice():
|
|
- return
|
|
-
|
|
+ def _force_remove_spice_devices(self):
|
|
self._remove_spice_audio()
|
|
self._remove_spice_channels()
|
|
self._remove_spice_usbredir()
|
|
+
|
|
+ def _remove_spice_devices(self, rmdev):
|
|
+ if rmdev.DEVICE_TYPE != "graphics" or self.has_spice():
|
|
+ return
|
|
+ self._force_remove_spice_devices()
|
|
--
|
|
2.48.1
|