Best practices for cloning /etc/libvirt/qemu XMLs?

I have a existing VM I am very happy with the hardware config for, but I would like to clone the XML and generate a new UUID for a separate VM without using virt-manager, as the virt-manager VM duplication feature is quite lacking and could clone some elements of the XML incorrectly.

Simply having an identical clone is not ideal, for when you do virsh define, the identical UUID screws everything up.

What are your best practices for keeping the hardware config of your XML and generating a new unique UUID with the least amount of hassle? Creating a new VM and copying and pasting seems like a roundabout way and requires more steps than simply a command to random seed a new UUID in the XML.

1 Like

I believe you can edit the UUID portion out, and libvirt will give you a new one when running define.

Could probably use a script to delete it, or just a few seconds in your favorite text editor.

Next thing I’m worried about is NVRAM files and if virsh define makes those as well after deleting the entries, along with what virt-manager adds to the XML for specific OS preparations. It would be nice to have a cheat sheet for OS prep quirks rather than have it buried in virt-manager. Again, virt-manager’s VM cloning wizard can mess up duplicating the XML.

Ahh good point! I don’t have much experience with EFI machines under libvirt. Also curious about the answer.

Depending on how much of the original VM you want to retain, invoking virt-clone with the appropriate parameters should do the trick

virt-clone is a command line tool for cloning existing virtual machine images using the libvirt hypervisor management library. It will copy the disk images of any existing virtual machine, and define a new guest with an identical virtual hardware configuration. Elements which require uniqueness will be updated to avoid a clash between old and new guests.

As an example:

The source VM

$ virsh dumpxml win10 | head -n17
<domain type='kvm'>
  <name>win10</name>
  <uuid>2a68f391-81c9-42c3-8e3d-02b3a84d098e</uuid>
  <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'>8388608</memory>
  <currentMemory unit='KiB'>8388608</currentMemory>
  <vcpu placement='static' current='1'>8</vcpu>
  <os>
    <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
    <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
    <nvram>/var/lib/libvirt/qemu/nvram/win10_VARS.fd</nvram>
    <boot dev='hd'/>
  </os>

Use the --auto-clone flag to clone everything and automatically re-populate unique elements

$ virt-clone --original win10 --auto-clone 
Allocating 'win10-clone.qcow2'             |  35 GB  00:03:06
Allocating 'win10-clone_VARS.fd'           | 128 kB  00:00:00

Clone 'win10-clone' created successfully.

The resulting VM

$ virsh dumpxml win10-clone | head -n17
<domain type='kvm'>
  <name>win10-clone</name>
  <uuid>2174449a-d509-46fe-acab-4903f22ece34</uuid>
  <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'>8388608</memory>
  <currentMemory unit='KiB'>8388608</currentMemory>
  <vcpu placement='static' current='1'>8</vcpu>
  <os>
    <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
    <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
    <nvram>/var/lib/libvirt/qemu/nvram/win10-clone_VARS.fd</nvram>
    <boot dev='hd'/>
  </os>

What I’m worried about is if virt-manager is just a frontend to that CLI. If it is, then they’re doing it wrong, and we need a cheat sheet for the correct way of doing it.

TL;DR
image

suspicious@virthost:~$ virt-clone --version
2.2.1
suspicious@virthost:~$ which virt-clone
/usr/bin/virt-clone
suspicious@virthost:~$ file $(!!)
file $(which virt-clone)
/usr/bin/virt-clone: POSIX shell script, ASCII text executable
suspicious@virthost:~$ cat !$
cat $(which virt-clone)
#!/bin/sh

exec "/usr/share/virt-manager/virt-clone" "$@"

/usr/share/virt-manager/virt-clone is a Python script which pulls the Cloner class, responsible for all the heavy lifting.

Looking from the other angle…

suspicious@virthost:~$ virt-manager --version
2.2.1
suspicious@virthost:~$ which virt-manager
/usr/bin/virt-manager
suspicious@virthost:~$ file $(!!)
file $(which virt-manager)
/usr/bin/virt-manager: POSIX shell script, ASCII text executable
suspicious@virthost:~$ cat !$
cat $(which virt-manager)
#!/bin/sh

exec "/usr/share/virt-manager/virt-manager" "$@"

/usr/share/virt-manager/virt-manager is another Python script which initalises the interface and wires up UI elements to underlying logic. Logic for the ‘Clone Virtual Machine’ dialog (defined with some XML) is controlled by clone.py which, as we’d hoped, instantiates the same Cloner class as virt-clone.

If that’s not enough for you, there are unit tests for the clone functionality which iterate over several potential cloning scenarios; no doubt built up over the long history of this project.

Beyond this, if you’ve got specific concerns, take it up with Cole :wink:

Huh, so we need a cheat sheet on how to do it correctly because the GUI virt-manager isn’t doing it right.

we can send a pull request with a fix to Cloner to virt-manager, … what’s not right … is gui not using --auto-clone?

It basically doesn’t respect custom PCI-E topology, reinvents the wheel when trying to clone CPU config, and yeah, doesn’t do a good job.

1 Like

Sounds like we’re getting into the weeds here. Anecdotally, I haven’t had any issues using virt-manager's clone functionality. Plus my quick dive into the code (primarily to sate my own curiosity) highlighted

  1. cloning via virt-manager and virt-clone is handled the same way
  2. there are unit tests in place that enforce expected behaviour

Either the way cloning behaves (through virt-manager or virt-clone) isn’t what you were expecting, or there’s a genuine bug in code. If there were more information to go on (XML dump, log files, screenshots, etc) no doubt someone here (or, better yet, the virt-manager issue tracker) could provide further assistance.

Without the specifics of your particular case, we’re at an impasse.