How to Define a Libvirt Domain from XML Without Auto-starting the VM


2 views

When working with libvirt, the virsh create command immediately launches the VM after parsing the XML configuration. This behavior becomes problematic when:

  • You need to pre-define multiple VMs for batch operations
  • Your automation scripts expect stopped domain states
  • You want to validate configurations before execution

Instead of create, use the define command:

virsh define centos63.xml

This will:

  • Parse and validate the XML
  • Register the domain configuration with libvirt
  • Leave the domain in shut off state

Here's a complete example with error handling:

# Validate XML first (optional)
virt-xml-validate centos63.xml

# Define the domain
if virsh define centos63.xml; then
    echo "Domain defined successfully"
    # Check state
    virsh list --all | grep centos63
else
    echo "Domain definition failed" >&2
    exit 1
fi
Command Action VM State After
virsh create Starts transient VM Running
virsh define Creates persistent config Shut off

Combine with other virsh commands for powerful automation:

# Bulk define from template
for i in {1..5}; do
    sed "s/VMNAME/web-node-$i/" template.xml > temp.xml
    virsh define temp.xml
    rm temp.xml
done

# Start later with precise control
virsh start centos63 --paused  # Start in paused state
  • Use virt-xml-validate to catch syntax errors early
  • Check permissions in /etc/libvirt/qemu/ for persistent storage
  • For transient domains, virsh create is still the right choice

When managing virtual machines with libvirt, you might encounter situations where you need to import domain XML configurations without triggering immediate VM startup. The standard virsh create command automatically boots the domain, which isn't always desirable - especially when preparing templates, testing configurations, or integrating with automation scripts.

Libvirt provides the perfect alternative with the virsh define command:

virsh define centos63.xml

This command:

  • Parses and validates the XML configuration
  • Registers the domain with libvirt
  • Sets the domain to inactive state by default
  • Generates persistent configuration (unlike virsh create which creates temporary domains)

Here are some common scenarios where this approach shines:

# Batch import multiple domain definitions
for xml in /path/to/vm_configs/*.xml; do
  virsh define "$xml"
done

# Verify domain exists but isn't running
virsh list --all | grep my_vm

# Later start the VM when needed
virsh start my_vm

For development and testing, you can combine this with other libvirt commands:

# Define the domain
virsh define test_vm.xml

# Dump the current config for editing
virsh dumpxml test_vm > test_vm_modified.xml

# Edit the XML file
vim test_vm_modified.xml

# Redefine with changes
virsh define test_vm_modified.xml

When working with configuration management systems like Ansible:

- name: Define libvirt domain without starting
  community.libvirt.virt:
    command: define
    xml: "{{ lookup('file', 'vm_config.xml') }}"
    name: my_vm

This approach gives you complete control over when and how domains are activated while maintaining all the benefits of libvirt management.