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.