Copy a virtual machine image from a virtual machine template:
root@host:~# cp <path to vm template file> <path to new vm image file>
or create a new image file:
root@host:~# qemu-img create -f <type> -o <options> <path to new vm image file> <size>
E.g. a QCOW2 image file with a size of 2GB:
root@host:~# qemu-img create -f qcow2 -o lazy_refcounts=on slave1.qcow2 2G
Create a virtual machine description file:
<domain type='kvm'> <name>VMNAME</name> <memory unit='KiB'>MEMORY</memory> <vcpu placement='static'>CPUS</vcpu> <os> <type arch='x86_64' machine='pc-i440fx-2.1'>hvm</type> <boot dev='hd'/> </os> <features> <acpi/> <apic/> <pae/> </features> <cpu mode='custom' match='exact'/> <clock offset='utc'> <timer name='rtc' tickpolicy='catchup'/> <timer name='pit' tickpolicy='delay'/> <timer name='hpet' present='no'/> </clock> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <pm> <suspend-to-mem enabled='no'/> <suspend-to-disk enabled='no'/> </pm> <devices> <emulator>/usr/bin/kvm</emulator> <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='PATHTOVMIMAGE'/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </disk> <controller type='pci' index='0' model='pci-root'/> <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> </controller> <controller type='virtio-serial' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </controller> <interface type='network'> <source network='NETWORK'/> <model type='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </interface> <console type='pty'> <target type='virtio' port='0'/> </console> <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> <graphics type='vnc' port='-1' autoport='yes'/> <video> <model type='cirrus' vram='9216' heads='1'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </video> <memballoon model='virtio'> <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> </memballoon> </devices> </domain>
Replace VMNAME
, MEMORY
, CPUS
, PATHTOVMIMAGE
and NETWORK
, with the appropriate values and save the virtual machine description file as <VMNAME>.xml
.
With the virtual machine description file, define a virtual machine:
root@host:~# virsh define <VMNAME>.xml root@host:~# virsh autostart <VMNAME>
Networking:
Private bridge, with access to networks outside of the KVM host for the virtual machines via NAT on the KVM host:
Create a virtual network description file:
<network connections='1'> <name>default</name> <forward mode='nat'> <nat> <port start='1024' end='65535'/> </nat> </forward> <bridge name='virbr0' stp='on' delay='0'/> <ip address='192.168.122.1' netmask='255.255.255.0'> <dhcp> <range start='192.168.122.2' end='192.168.122.254'/> </dhcp> </ip> </network>
Replace the IP addresses and the netmask with the appropriate values for the network environment and save the virtual network description file as network-default.xml
With the virtual network description file, define a virtual network:
root@host:~# virsh net-define network-default.xml root@host:~# virsh net-autostart default root@host:~# virsh autostart default
Optional: Add entries for each virtual machine to the file /etc/hosts
on the KVM server if network access from the KVM server to the virtual machine is required.
Gather the MAC address for each virtual machine interface:
root@host:~# virsh dumpxml <VMNAME> | egrep "<mac " <mac address='52:54:00:5a:3d:f0'/>
For each virtual machine insert a static entry to the virtual network. This will be used to map each virtual machines MAC address to a IP address via DHCP:
root@host:~# virsh net-update default add ip-dhcp-host "<host mac='MAC' name='HOSTNAME' ip='IPADDRESS' />" --live --config
Replace MAC
, HOSTNAME
and IPADDRESS
with the appropriate values for each virtual machine.
Restart the libvirt service on the KVM host:
root@host:~# systemctl restart libvirtd.service
This will have created a virtual network in the form of a Linux bridge:
root@host:~# brctl show bridge name bridge id STP enabled interfaces virbr0 8000.fe54005a3df0 yes
It will also have inserted appropriate IPtables NAT rules into the FORWARD
chain:
root@host:~# iptables -nL [...] Chain FORWARD (policy DROP) target prot opt source destination ACCEPT all -- 0.0.0.0/0 192.168.122.0/24 ctstate RELATED,ESTABLISHED ACCEPT all -- 192.168.122.0/24 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable [...]
In order to forward packets from and to the virtual machines, IP forwarding must also be enabled on the KVM host:
root@host:~# sysctl net.ipv4.ip_forward net.ipv4.ip_forward = 1
Start the virtual machine:
root@host:~# virsh start <VMNAME>
If the virtual machine was copied from a template and virtual machine networking is done with a private bridge and NAT, the hostname inside the virtual machine is currently still the wrong one in order to match the definition for a successful DHCP request. On the first boot of the virtual machine, the hostname needs to be changed via a login on the virtual machine console. See Debian - Necessary Changes After Cloning A System for the necessary steps. Afterwards the virtual machine should get an IP address assigned via DHCP.