KVM Hypervisor notes

Russell Bateman
22 September 2022
last update:


I installed this on Ubuntu Server 22.04.1 LTS.

Installation

I used KVM hypervisor: a beginner's guide. It was missing some steps and explanations which I will add.

# apt -y install bridge-utils cpu-checker libvirt-clients libvirt-daemon qemu qemu-kvm
. . .
$ kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used
# apt-get install virt-manager                     # this step was overlooked by the tutorial
# which virt-install
/usr/bin/virt-install

Set up a new virtual machine (VM)

Apparently, one way to test is to install and launch a copy of this OS itself which arrives from a remote location:

# virt-install --name ubuntu-guest --os-variant ubuntu20.04 --vcpus 2 --ram 2048 --location \
               --location http://ftp.ubuntu.com/ubuntu/dists/focal/main/installer-amd64/ \
               --network bridge=virbr0,model=virtio --graphics none \
               --extra-args='console=ttyS0,115200n8 serial'

When you do this, you see a TUI and things unfold pretty much as they do during a proper installation of Ubuntu 20.04. The installation complete, I looked at the network interface configuration to see if, as happens to the hosting operation system running VirtualBox, I could find the guest OS' IP address. Sure enough. Then I logged in via ssh:

$ ifconfig
        ...

virbr0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
        ether 52:54:00:94:67:a3  txqueuelen 1000  (Ethernet)
        RX packets 36935  bytes 2061031 (2.0 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 51072  bytes 412408442 (412.4 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

        ...
$ ssh 192.168.122.1
The authenticity of host '192.168.122.1 (192.168.122.1)' can't be established.
ED25519 key fingerprint is SHA256:WNU9rI1TVlhY8cbJ24dVc0mF2KgQcsetgpRyLOnSOX8.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.122.1' (ED25519) to the list of known hosts.
[email protected]'s password:
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-48-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Thu Sep 22 10:28:49 PM UTC 2022

  System load:  0.0615234375       Users logged in:          1
  Usage of /:   2.1% of 914.78GB   IPv4 address for docker0: 172.17.0.1
  Memory usage: 3%                 IPv4 address for enp0s25: 192.168.0.108
  Swap usage:   0%                 IPv4 address for enp0s25: 192.168.0.121
  Temperature:  39.0 C             IPv4 address for virbr0:  192.168.122.1
  Processes:    220

 * Super-optimized for small spaces - read how we shrank the memory
   footprint of MicroK8s to make it the smallest full K8s around.

   https://ubuntu.com/blog/microk8s-memory-optimisation

1 update can be applied immediately.
To see these additional updates run: apt list --upgradable


Last login: Thu Sep 22 22:28:49 2022 from 192.168.0.149
$

However, I immediately (and silently) lost my ssh session; I'll have to figure out what that's all about.

KVM/s filesystem presence

/var/lib/libvirt/
├── boot
├── dnsmasq
├── images       # where the VM image storage is kept (i.e.: the VM's diskspace)
├── qemu
└── sanlock

Using virsh to manage an existing (VM)

Apparently, this is done using the virsh command. First, list the VM to get its name:

# virsh list
 Id   Name           State
------------------------------
 2    ubuntu-guest   running

Before removing this VM, let's think about what would be important were we to have a truly complex KVM set-up.

# virsh dumpxml --domain vm-name
(lots of XML describing the VM)
# virsh dumpxml --domain ubuntu-guest | grep 'source file'
      <source file='/var/lib/libvirt/images/ubuntu-guest.qcow2' index='1'/>

Other useful commands:

Start a VM virsh start vm-name
Cause a VM to start automatically at boot (of the host OS) virsh autostart vm-name
Shut down a VM virsh shutdown vm-name
Halt a VM forcefully (when crashed or not responding) virsh destroy vm-name
Reboot a VM virsh reboot vm-name

Tearing down and removing an existing (VM)

Start by getting the VM's name.

# virsh list
 Id   Name           State
------------------------------
 2    ubuntu-guest   running

There's no way to remove the storage associated with a VM, so be sure to find out what that is and make a note of it:

# virsh dumpxml --domain ubuntu-guest | grep 'source file'
      <source file='/var/lib/libvirt/images/ubuntu-guest.qcow2' index='1'/>

How to delete the VM:

# virsh undefine vm-name --remove-all-storage
# rm -rf filesystem-path

Following this, let's delete the VM we created (and spent the time installing—yikes!) and its filesystem storage. I don't need this VM; I only created it because the tutorial I was following did it. First, shut down the VM.

# virsh shutdown ubuntu-guest
Domain 'ubuntu-guest' is being shutdown
# virsh undefine ubuntu-guest --remove-all-storage
# virsh list
 Id   Name   State
--------------------
# rm -rf '/var/lib/libvirt/images/ubuntu-guest.qcow2'



Installing an .ova, the Cypress validator

How to use virt-v2v to convert a VirtualBox, Linux-based VM (thinking Cypress here) to KVM.

I'm going to work between my personal development host and a my headless Ubuntu Server 22.04.1. I'm following Convert and Deploy a VirtualBox VM to KVM.

  1. Transfer the .ova file to the host operating system.
    russ@tirion ~/Downloads $ scp Cypress.cypress_7.0.2_Public_VM.ova russ-microservices:/home/russ/Downloads
    Cypress.cypress_7.0.2_Public_VM.ova                                                   100% 2489MB  92.6MB/s   00:26
    
  2. Install virt-v2v on the Ubuntu server:
    # apt-get install virt-v2v
    
  3. Begin the conversion thus:
    # virt-v2v -i ova /home/russ/Downloads/Cypress.cypress_7.0.2_Public_VM.ova \  # (path to the image created on a different hypervisor)
               -o  libvirt -of qcow2  \                                           # (outputs libvirt VM in qcow2 file format)
               -os default            \                                           # (places the VM in the default KVM storage pool)
               -n  default                                                        # (configures the VM with the default virtual network)
    [   0.0] Opening the source -i ova /home/russ/Downloads/Cypress.cypress_7.0.2_Public_VM.ova
    [  23.7] Creating an overlay to protect the source from being modified
    [  23.9] Opening the overlay
    [  30.9] Inspecting the overlay
    [  32.9] Checking for sufficient free disk space in the guest
    [  32.9] Estimating space required on target for each disk
    [  32.9] Converting Ubuntu 18.04.6 LTS to run on KVM
    virt-v2v: warning: could not determine a way to update the configuration of Grub2
    virt-v2v: This guest has virtio drivers installed.
    [  61.4] Mapping filesystem data to avoid copying unused and blank areas
    [  62.5] Closing the overlay
    [  62.7] Assigning disks to buses
    [  62.7] Checking if the guest needs BIOS or UEFI to boot
    [  62.7] Initializing the target -o libvirt -os default
    [  62.8] Copying disk 1/1 to /var/lib/libvirt/images/Cypress.cypress_7.0.2_Public_VM-sda (qcow2)
        (100.00/100%)
    [  85.9] Creating output metadata
    [  85.9] Finishing off
    # virsh list --all                                                            # (Just so you know...)
     Id   Name   State
    --------------------
     -    Cypress.cypress_7.0.2_Public_VM   shut off
    
    
  4. Now it's time to review the newly imported VM's networking settings for accuracy. Here we see the original network values from the hypervisor where the image was crafted.
    # virsh domiflist Cypress.cypress_7.0.2_Public_VM
     Interface   Type     Source   Model    MAC
    -----------------------------------------------------------
     -           bridge   nat      virtio   52:54:00:81:69:ef
    
    
  5. Likely, these settings must be corrected (since this is a different host). First, remove the existing virtual network interface.
    # virsh detach-interface Cypress.cypress_7.0.2_Public_VM \
            --type   bridge            \
            --mac    52:54:00:81:69:ef \
            --config
    Interface detached successfully
    
  6. Now obtain a list of virtual networds available. This is the default virtual network configured for KVM.
    # virsh net-list --all
     Name      State    Autostart   Persistent
    --------------------------------------------
     default   active   yes         yes
    
  7. Get details about the default network:
    # virsh net-dumpxml default
    <network>
      <name>default</name>
      <uuid>8119de66-568f-4d8b-853c-64c7fdd74e97</uuid>
      <forward mode='nat'>
        <nat>
          <port start='1024' end='65535'/>
        </nat>
      </forward>
      <bridge name='virbr0' stp='on' delay='0'/>
      <mac address='52:54:00:94:67:a3'/>
      <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>
    
  8. Attach this network to the new VM:
    # virsh attach-interface Cypress.cypress_7.0.2_Public_VM \
            --type network   \
            --source default \
            --config
    Interface attached successfully
    
  9. At this point, before the VM is launched, any packages may be installed, and configuration files edited, made possible using virt-customize. See man virt-customize.

  10. The VM may now be launched:
    # virsh start Cypress.cypress_7.0.2_Public_VM
    error: Failed to start domain 'Cypress.cypress_7.0.2_Public_VM'
    error: internal error: process exited while connecting to monitor: 2022-09-23T20:11:20.131284Z qemu-system-x86_64: \
        -blockdev {"driver":"file","filename":"/var/lib/libvirt/images/Cypress.cypress_7.0.2_Public_VM-sda",\
         "node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}: \
        Could not open '/var/lib/libvirt/images/Cypress.cypress_7.0.2_Public_VM-sda': Permission denied
    # virsh list --all
     Id   Name                              State
    --------------------------------------------------
     -    Cypress.cypress_7.0.2_Public_VM   shut off
    
    

SELinux or AppArmor issues...

Decidedly, there's more to do. I believe the problem above, if running on CentOS (Red Hat), would be an SELinux issue. On Ubuntu, the present case, it's an AppArmor issue and I have not yet found a solution (though I have tried several). The trick is mainstreaming libvirt's use by a dedicated user or group or carefully exempting it from scrutiny.

(No, I do not understand why the Ubuntu guest OS VM installed and ran without this problem.)

I'll have to get back to this. One obstacle is that the Cypress validator is no longer particularly useful (as it once was) even when it can be got to run. It's child's play to do that using VirtualBox, but then the troubles only begin. So, I lack motivation.




Install software for remote virtualization management

# kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used
# apt-get update
# apt-get install qemu-kvm libvirt-daemon-system
# adduser russ libvirt                             # adds me to this group

At this point, it's ready to get a guest OS installed. The point is to be able to do this from a remote host, ostensibly with a GUI. In particular, I have an .ova image for the Cypress 7 VM. I'm going to try that remotely.