Skip to content
Published on

How VMI Spec Gets Converted to libvirt Domain XML

Authors

Introduction

Users declare VMIs in Kubernetes-style YAML. But libvirt and QEMU ultimately execute guests based on domain spec and XML. Therefore KubeVirt needs a critically important translation layer that bridges these two worlds. This role is filled by pkg/virt-launcher/virtwrap/converter.

The core question of this article is: What process does a VMI spec go through to become libvirt domain XML?

Conversion Is Not Simple Field Copying

At first, it seems like spec.domain.cpu would simply copy to the libvirt CPU field, and spec.domain.devices.disks to libvirt disk entries. But in reality, it is much more complex.

The reasons are threefold:

  1. Guest device names must be calculated
  2. Actual disk paths prepared in the Pod must be found
  3. Policies like architecture, virtio model, security, and migration must be reflected

In other words, the converter is not a serialization layer but a policy-inclusive transformer.

Key Entry Points

The most important function names in converter.go are:

  • Convert_v1_VirtualMachineInstance_To_api_Domain
  • Convert_v1_Disk_To_api_Disk
  • Convert_v1_Volume_To_api_Disk
  • Convert_v1_BlockSize_To_api_BlockIO

Just from these names, the structure is visible. The ultimate goal is to convert the entire VMI to api.Domain, and within that, detailed conversion functions for disk, volume, block IO, CPU, NIC, etc. are called hierarchically.

Why api.Domain Is Important

Within KubeVirt, api.Domain is close to a canonical intermediate representation for guest execution.

  • VMI is a Kubernetes-friendly declarative model
  • api.Domain is a libvirt-friendly execution model
  • It can ultimately be XML marshalled

In other words, api.Domain serves as an "intermediate language for virtualization" within KubeVirt.

What Happens in Disk Conversion

Looking at Convert_v1_Disk_To_api_Disk, you can see much beyond simple mapping.

1. Device Name Calculation by Bus

Target bus and device names differ depending on virtio, scsi, cdrom, or lun. For example, virtio disks get guest-visible names like vda, vdb.

2. PCI Address Verification

For some bus types, assigning arbitrary PCI addresses is not allowed. The converter applies these constraints.

3. Shareable, Cache, Discard Policy Application

For shared disks, cache must be none, etc. -- it's not simply copying YAML values but checking combination constraints.

4. Boot Order and Alias Addition

Guest boot order and user-defined aliases are also created during the conversion process.

In other words, looking at just one disk, the converter is not a simple serializer but a guest hardware model designer.

Why Volumes and Disks Are Separated

In the Kubernetes-side VMI spec, volumes and disks are separated:

  • volumes: what is the data source
  • disks: what device to attach to the guest

For example, the same PVC can be:

  • Attached as a regular disk
  • Exposed like a cdrom
  • Given a different boot order

The converter combines these two to calculate "which libvirt disk to attach this source to the guest as."

Why Conversion Context Is Needed

Looking at convertertypes.ConverterContext types, you can see the converter is not a simple stateless function. Conversion requires surrounding context.

Typically the following information is included in the context:

  • Architecture
  • Whether emulation is allowed
  • Hypervisor device availability
  • Whether PVC is block or filesystem
  • Disk creator
  • Launch security options
  • Whether to use virtio transitional model

This means that even for the same VMI spec, the final domain spec can differ depending on node architecture and execution environment.

Network and CPU Are Converted the Same Way

Disks are not special alone. NICs, CPU topology, NUMA, launch security, EFI, iothreads, etc. are also converted by the converter into libvirt domain representation.

For example:

  • Dedicated CPU changes pinning-related fields
  • Enabling launch security adds options like IOMMU
  • Changing architecture changes machine type and some device representations

In other words, the converter is responsible for the entire guest hardware configuration.

When Is Domain XML Completed

Practically, understand it in this order:

  1. VMI spec is read.
  2. The converter creates api.Domain.
  3. If needed, hooks or sidecars additionally modify the domain spec.
  4. The final domain XML is delivered to libvirt.
  5. libvirt executes QEMU based on this.

Therefore, if you want to know "why a certain guest device looks that way," you almost always need to start by reading the converter.

Why Domain XML Is Revisited During Migration

live-migration-source.go contains logic like migratableDomXML. During migration, the source domain XML cannot be passed as-is -- metadata may need to be cleaned up or disk file paths may need to be modified to match the target side's paths.

In other words, domain XML is not important just once right before launch:

  • At initial boot
  • During migration
  • During some hotplug and target preparation

It continues to be used as a core data structure at multiple stages.

Why This Layer Is the Key to Debugging

Many problems arise somewhere between YAML and QEMU. That middle ground is the converter.

It Explains Problems Like

  • Why guest disk names are different from expected
  • Why certain option combinations are rejected
  • Why a different model was used instead of virtio
  • Why disk paths are changed again during migration

If the launcher Pod is alive and there's a failure at the libvirt define stage, the converter result should be the first suspect.

Common Misconceptions

Misconception 1: VMI Spec Is Almost the Same as libvirt XML

No. VMI spec is a Kubernetes declarative model, and libvirt XML is a hypervisor execution model. There are many policies between them that KubeVirt must interpret.

Misconception 2: Disks Just Need the Volume Path to Be Correct

No. Guest-visible attributes like bus, boot order, discard, cache, reservation, and block size are all important.

Misconception 3: The Converter Is Only Important Once at Launch

No. During migration, hotplug, and target preparation, domain spec and XML transformations become important again.

Conclusion

KubeVirt's converter is the most important intermediate layer that translates VMI spec into the libvirt domain model. This layer is not simple field copying but reflects guest hardware model, execution environment, security options, and migration constraints together. So to deeply understand KubeVirt, the package you must read right after the controller is pkg/virt-launcher/virtwrap/converter.

In the next article, we will look at how these conversion results meet actual storage sources, and through what paths PVCs, DataVolumes, container disks, and hotplug disks attach to the guest.