Stupid KVM Tricks

virt-install ubuntu16.04

Create the disk image

qemu-img create -f qcow2 /var/lib/libvirt/images/xenial.qcow2 20G

Command to run the install

virt-install \
    --name xenial \
    --ram 4096 \
    --disk path=/var/lib/libvirt/images/xenial.qcow2,size=20 \
    --vcpus 4 \
    --os-type linux \
    --os-variant ubuntu16.04 \
    --network bridge=br0 \
    --graphics none \
    --console pty,target_type=serial \
    --location ./ubuntu-16.04.3-server-amd64.iso \
    --extra-args 'console=ttyS0,115200n8 serial'

virt-install Arch Linux

The --extra-args option lets you use a serial console. But the --extra-args option only works if you also use an --location option. But the --location option can only be used with certain isos. So use --cdrom instead of --location, drop the --extra-args, and instruct the kernel to boot with a serial console with a parameter at the boot splash screen.

qemu-img create -f qcow2 /var/lib/libvirt/images/arch.qcow2 20G

virt-install --name arch --ram 4096 \
  --disk path=/var/lib/libvirt/images/arch.qcow2,size=20 \
  --vcpus 2 \
  --os-type linux \
  --os-variant ubuntu16.04 \ 
  --network bridge=virbr0 \
  --graphics none \ 
  --console pty,target_type=serial \
  --cdrom /var/lib/libvirt/images/archlinux-2018.02.01-x86_64.iso

the arch boot splash screen will appear in your terminal and you can tap the "tab" key to edit boot parameters

add "console=ttyS0" to kernel command line parameters

before

> .linux boot/x86_64/vmlinuz archisobasedir=arch archisolabel=ARCH_201802 initrd=boot/intel_ucode.img,boot/x86_64/archiso.img

after

> .linux boot/x86_64/vmlinuz archisobasedir=arch archisolabel=ARCH_201802 initrd=boot/intel_ucode.img,boot/x86_64/archiso.img console=ttyS0

arch boots ...
...
...
...

root@archiso ~ # lsblk
NAME  MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0   7:0    0  432M  1 loop /run/archiso/sfs/airootfs
sr0    11:0    1  539M  0 rom  /run/archiso/bootmnt
vda   254:0    0   20G  0 disk 
root@archiso ~ # 

Change the Network Interface

br0 gets addresses from the network router, but what if you want your vm to have be on the virbr0 192.168.122.0/24 subnet?

virsh edit xenial

And then 'J' all the way down to the bottom, change the interface name from br0 to virbr0,

virsh start xenial

and then look for the machine with nmap

nmap -sn 192.168.122.0/24

Clone the VM

In this case we don't have to pre-allocate the disk image because virt-clone will do that for us.

virt-clone --original xenial --name xenial-clone \
    --file /var/lib/libvirt/images/xenial-clone.qcow2

Clone the VM to another Machine

First dump the xml that defines the virtual machine.

virsh dumpxml xenial > xenial.xml

Then copy both xenial.xml and xenial.qcow2 to the new host machine. On the new kvm host you'll want to at least make sure your vm has the correct CPU architecture. The command to get a list of supported kvm cpu architectures is:

virsh cpu-models <arch>
# i.e.
virsh cpu-models x86_64

After you edit xenial.xml and update the correct cpu architecture, mv xenial.qcow2 to /var/lib/libvirt/images/, clone it. virt-clone will handle generating new mac addresses for the network interfaces.

  <cpu mode='custom' match='exact'>
    <model fallback='allow'>Haswell-noTSX</model>
  </cpu>
# i.e. change to above to
  <cpu mode='custom' match='exact'>
    <model fallback='allow'>SandyBridge</model>
  </cpu>

virt-clone --original-xml xenial.xml --name xenial-clone \
    --file /var/lib/libvirt/images/xenial-clone.qcow2

What is the os-type and os-variant type names?

osinfo-query os

misc

  • Start the vm virsh start xenial
  • List all the vms virsh list --all
  • Stop the vm virsh destroy xenial
  • Delete the vm virsh undefine xenial

virsh help

The virsh help command returns a long chart of help information. But each section has a keyword.

Take for instance the command virsh help monitor. From this we see the domiflist subcommand (among others). Unfortunately domifaddr doesn't seem to work on the Ubuntu:16.04 host, but there are other ways to find the ip address of a virtual machine.

So now if you want to see what host interface the vm xenial is attached to, type.

virsh domiflist xenial

which returns:

Interface  Type       Source     Model       MAC
-------------------------------------------------------
vnet1      bridge     virbr0     virtio      52:54:00:58:bf:75

So now we can find the address of virbr0 on the host machine.

ifconfig virbr0

which returns:

virbr0    Link encap:Ethernet  HWaddr 52:54:00:38:87:38  
          inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1351 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3037 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:232346 (232.3 KB)  TX bytes:502916 (502.9 KB)

and thus we know what subnet to scan with nmap to find the ip address of the vm

nmap -sn 192.168.122.0/24

Snapshots

Create snapshot of vm dcing

virsh snapshot-create-as --domain dcing --name dcing-snap0

But you don't need to name your snapshots because they are listed by time.

virsh snapshot-create --domain dcing

List snapshots for vm dcing

virsh snapshot-list --domain dcing

 Name                 Creation Time             State
------------------------------------------------------------
 1518366561           2018-02-11 08:29:21 -0800 shutoff
 dcing-snap0          2018-02-11 08:22:57 -0800 shutoff

Revert dcing to snap0

virsh snapshot-revert --domain dcing --snapshotname dcing-snap0

Delete snapshot

virsh snapshot-delete --domain dcing --snapshotname dcing-snap0