virt-xml: add --edit --convert-to-q35

Wire up guest.convert_to_q35 to the CLI. We add one suboptions,
`num_pcie_root_ports=X`, matching the pre-existing
`--controller num_pcie_root_ports=X` option

Nothing fancy here. See man page docs for details

Signed-off-by: Cole Robinson <crobinso@redhat.com>
This commit is contained in:
Cole Robinson 2024-09-19 13:23:27 -04:00
parent 454aad78a4
commit dd354e8b72
7 changed files with 292 additions and 0 deletions

View File

@ -197,6 +197,31 @@ GUEST OS OPTIONS
See virt-install(1) documentation for more details about ``--os-variant/--osinfo``
CONVERSION OPTIONS
==================
``--convert-to-q35``
^^^^^^^^^^^^^^^^^^^^
**Syntax:** ``--convert-to-q35`` [OPTIONS]
Convert an existing VM config from PC/i440FX to Q35 machine type.
This largely consists of:
* Convert device topology from PCI to PCIe
* Convert any IDE storage to SATA
You may need to make config changes inside the VM to handle this as well.
For example, Windows 10 may not find the boot device after IDE to SATA conversion.
But booting into safe mode once may fix it.
Sub options are:
``num_pcie_root_ports=NUM``
Control the number of default ``pcie-root-port`` controller devices
we add to the VM by default.
XML OPTIONS
===========

View File

@ -0,0 +1,72 @@
<currentMemory unit="KiB">4194304</currentMemory>
<vcpu placement="static">2</vcpu>
<os>
- <type arch="x86_64" machine="pc-i440fx-8.2">hvm</type>
+ <type arch="x86_64" machine="q35">hvm</type>
<boot dev="hd"/>
</os>
<devices>
@@
<disk type="file" device="disk">
<driver name="qemu" type="raw"/>
<source file="/my/fake/disk"/>
- <target dev="hda" bus="ide"/>
- <address type="drive" controller="0" bus="0" target="0" unit="0"/>
+ <target dev="sda" bus="sata"/>
</disk>
- <controller type="usb" index="0" model="qemu-xhci" ports="15">
- <address type="pci" domain="0x0000" bus="0x00" slot="0x05" function="0x0"/>
- </controller>
- <controller type="pci" index="0" model="pci-root"/>
- <controller type="ide" index="0">
- <address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x1"/>
- </controller>
- <controller type="virtio-serial" index="0">
- <address type="pci" domain="0x0000" bus="0x00" slot="0x06" function="0x0"/>
- </controller>
+ <controller type="usb" index="0" model="qemu-xhci" ports="15"/>
+ <controller type="virtio-serial" index="0"/>
<interface type="network">
<mac address="52:54:00:0f:b2:90"/>
<source network="default"/>
- <model type="e1000"/>
- <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0"/>
+ <model type="e1000e"/>
</interface>
<serial type="pty">
<target type="isa-serial" port="0">
@@
<listen type="address"/>
<image compression="off"/>
</graphics>
- <sound model="ich6">
- <address type="pci" domain="0x0000" bus="0x00" slot="0x04" function="0x0"/>
- </sound>
+ <sound model="ich9"/>
<audio id="1" type="spice"/>
<video>
<model type="qxl" ram="65536" vram="65536" vgamem="16384" heads="1" primary="yes"/>
- <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0"/>
</video>
<redirdev bus="usb" type="spicevmc">
<address type="usb" bus="0" port="2"/>
@@
<redirdev bus="usb" type="spicevmc">
<address type="usb" bus="0" port="3"/>
</redirdev>
- <memballoon model="virtio">
- <address type="pci" domain="0x0000" bus="0x00" slot="0x07" function="0x0"/>
- </memballoon>
+ <memballoon model="virtio"/>
+ <controller type="pci" model="pcie-root"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
</devices>
</domain>
Domain 'convert-me' defined successfully.

View File

@ -0,0 +1,79 @@
<currentMemory unit="KiB">4194304</currentMemory>
<vcpu placement="static">2</vcpu>
<os>
- <type arch="x86_64" machine="pc-i440fx-8.2">hvm</type>
+ <type arch="x86_64" machine="q35">hvm</type>
<boot dev="hd"/>
</os>
<devices>
@@
<disk type="file" device="disk">
<driver name="qemu" type="raw"/>
<source file="/my/fake/disk"/>
- <target dev="hda" bus="ide"/>
- <address type="drive" controller="0" bus="0" target="0" unit="0"/>
+ <target dev="sda" bus="sata"/>
</disk>
- <controller type="usb" index="0" model="qemu-xhci" ports="15">
- <address type="pci" domain="0x0000" bus="0x00" slot="0x05" function="0x0"/>
- </controller>
- <controller type="pci" index="0" model="pci-root"/>
- <controller type="ide" index="0">
- <address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x1"/>
- </controller>
- <controller type="virtio-serial" index="0">
- <address type="pci" domain="0x0000" bus="0x00" slot="0x06" function="0x0"/>
- </controller>
+ <controller type="usb" index="0" model="qemu-xhci" ports="15"/>
+ <controller type="virtio-serial" index="0"/>
<interface type="network">
<mac address="52:54:00:0f:b2:90"/>
<source network="default"/>
- <model type="e1000"/>
- <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0"/>
+ <model type="e1000e"/>
</interface>
<serial type="pty">
<target type="isa-serial" port="0">
@@
<listen type="address"/>
<image compression="off"/>
</graphics>
- <sound model="ich6">
- <address type="pci" domain="0x0000" bus="0x00" slot="0x04" function="0x0"/>
- </sound>
+ <sound model="ich9"/>
<audio id="1" type="spice"/>
<video>
<model type="qxl" ram="65536" vram="65536" vgamem="16384" heads="1" primary="yes"/>
- <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0"/>
</video>
<redirdev bus="usb" type="spicevmc">
<address type="usb" bus="0" port="2"/>
@@
<redirdev bus="usb" type="spicevmc">
<address type="usb" bus="0" port="3"/>
</redirdev>
- <memballoon model="virtio">
- <address type="pci" domain="0x0000" bus="0x00" slot="0x07" function="0x0"/>
- </memballoon>
+ <memballoon model="virtio"/>
+ <controller type="pci" model="pcie-root"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
+ <controller type="pci" model="pcie-root-port"/>
</devices>
</domain>
Domain 'convert-me' defined successfully.

View File

@ -0,0 +1,79 @@
<domain type='kvm'>
<name>convert-me</name>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<libosinfo:os id="http://microsoft.com/win/10"/>
</libosinfo:libosinfo>
</metadata>
<memory unit='KiB'>4194304</memory>
<currentMemory unit='KiB'>4194304</currentMemory>
<vcpu placement='static'>2</vcpu>
<os>
<type arch='x86_64' machine='pc-i440fx-8.2'>hvm</type>
<boot dev='hd'/>
</os>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/my/fake/disk'/>
<target dev='hda' bus='ide'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<controller type='usb' index='0' model='qemu-xhci' ports='15'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='virtio-serial' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</controller>
<interface type='network'>
<mac address='52:54:00:0f:b2:90'/>
<source network='default'/>
<model type='e1000'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<serial type='pty'>
<target type='isa-serial' port='0'>
<model name='isa-serial'/>
</target>
</serial>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0'/>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>
<input type='tablet' bus='usb'>
<address type='usb' bus='0' port='1'/>
</input>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='spice' autoport='yes'>
<listen type='address'/>
<image compression='off'/>
</graphics>
<sound model='ich6'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</sound>
<audio id='1' type='spice'/>
<video>
<model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<redirdev bus='usb' type='spicevmc'>
<address type='usb' bus='0' port='2'/>
</redirdev>
<redirdev bus='usb' type='spicevmc'>
<address type='usb' bus='0' port='3'/>
</redirdev>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</memballoon>
</devices>
</domain>

View File

@ -1436,6 +1436,10 @@ c.add_compare("--connect %(URI-KVM-X86)s test-many-devices --build-xml --disk so
c.add_compare("test --add-device --network default --update --confirm", "update-succeed", env={"VIRTXML_TESTSUITE_UPDATE_IGNORE_FAIL": "1", "VIRTINST_TEST_SUITE_INCREMENT_MACADDR": "1"}, input_text="yes\nyes\n") # test hotplug success
c.add_compare("test --add-device --network default --update --confirm --no-define", "update-nodefine-succeed", env={"VIRTXML_TESTSUITE_UPDATE_IGNORE_FAIL": "1"}, input_text="yes\n") # test hotplug success without define
# --convert-* tests
c.add_compare("--connect %(URI-KVM-X86)s --print-diff --define --edit --convert-to-q35", "convert-to-q35", input_file=(_VIRTXMLDIR + "convert-to-q35-win10-in.xml"))
c.add_compare("--connect %(URI-KVM-X86)s --print-diff --define --edit --convert-to-q35 num_pcie_root_ports=7", "convert-to-q35-numports", input_file=(_VIRTXMLDIR + "convert-to-q35-win10-in.xml"))
# Regression testing for historical --add-device/--remove-device/--edit multi option handling
# Single `--edit` with multiple options are processed in sequence
c.add_compare("test --print-diff --define --edit --boot emulator=/foo --boot bootmenu.enable=yes", "multi-edit-boot-backcompat")

View File

@ -1324,6 +1324,8 @@ class VirtCLIParser(metaclass=_InitClass):
@cli_arg_name: The command line argument this maps to, so
"hostdev" for --hostdev
"""
OPTSTR_EMPTY = 1
guest_propname = None
remove_first = None
stub_none = True
@ -1419,6 +1421,8 @@ class VirtCLIParser(metaclass=_InitClass):
self.optstr = optstr
self.guest = guest
self.editing = editing
if self.optstr == self.OPTSTR_EMPTY:
self.optstr = ""
self.optdict = _parse_optstr_to_dict(self.optstr,
self._virtargs, xmlutil.listify(self.remove_first)[:])
@ -1651,6 +1655,29 @@ def _add_xpath_args(cls):
can_comma=True, lookup_cb=None, find_inst_cb=find_xpath_cb)
############################
# --convert-to-q35 parsing #
############################
class ParserConvertToQ35(VirtCLIParser):
cli_arg_name = "convert_to_q35"
supports_clearxml = False
@classmethod
def _virtcli_class_init(cls):
VirtCLIParser._virtcli_class_init_common(cls)
cls.add_arg("num_pcie_root_ports", "num_pcie_root_ports")
def parse(self, inst):
class ConvertToQ35Data:
num_pcie_root_ports = None
inst = ConvertToQ35Data()
super().parse(inst)
self.guest.convert_to_q35(**inst.__dict__)
########################
# --unattended parsing #
########################

View File

@ -485,6 +485,12 @@ def parse_args():
cli.add_os_variant_option(parser, virtinstall=False)
conv = parser.add_argument_group(_("Conversion options"))
cli.ParserConvertToQ35.register()
conv.add_argument("--convert-to-q35", nargs="?",
const=cli.VirtCLIParser.OPTSTR_EMPTY,
help=_("Convert an existing VM from PC/i440FX to Q35."))
g = parser.add_argument_group(_("XML options"))
cli.add_disk_option(g, editexample=True)
cli.add_net_option(g)