KVM-QEMU HOWTO

This article presents a step-by-step guide on how to compile and boot kvm and Qemu.

References

  1. https://help.ubuntu.com/community/KVM/Installation
  2. http://wiki.qemu-project.org/Main_Page

Install KVM

Make sure that your CPU supports hardware virtualization.
egrep -c '(vmx|svm)' /proc/cpuinfo

If 0 it means that your CPU doesn't support hardware virtualization. If 1 or more it does - but you still need to make sure that virtualization is enabled in the BIOS.

Install KVM packages
sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils
Make sure your Ubuntu username is added to the group libvirtd
sudo adduser `id -un` libvirtd

Note: Because I focus on the NVMes SSD performance evaluation, the networking is not necessary and is not mentioned here.

Compile Qemu [Optional]

Actually, Qemu is installed when installing KVM. In the field of virtualizaton, Qemu is usually modified for specific usage. The executable file of Qemu is located at /usr/bin, by default.

$ which is qemu-system-x86_64
/usr/bin/qemu-system-x86_64
Download Qemu repository
$ git clone https://github.com/qemu/qemu.git
Configure Qemu
$ cd qemu
$ git submodule update --init dtc
$ ./configure --prefix=/usr/local \
    -- enable-kvm \
    -- target-list=x86_64-softmmu
$ make -j8
$ make install [OPTIONAL]
  • --prefix represents the location where Qemu is installed, /usr is default, and we choose /usr/local to avoid overlapping and keep both.
  • enable-kvm enables KVM support.
  • -- target-list specify the compile target, wo only need x86_64-softmmu.
  • make install is not necessary, for me, I prefer not to make install. When running the Qemu compiled by myself, command /path/to/qemu/x86_64-softmmu/qemu-system-x86_64 -m 1024 -cpu host -hda guest.img ...... specifies the detailed path of Qemu executable file.

Boot Example

Here is an example script for booting the kvm guest, which can be considered as a template.

$ cat kvm-install.sh
#! /bin/bash

/usr/bin/qemu-system-x86_64 \
    -m 1024 -smp 2 -M pc -name kvm-guest \
    -cpu host -enable-kvm -machine kernel_irqchip=on \
    -hda /path/to/guest.img \
    -cdrom /path/to/install.iso

$ cat kvm-boot.sh
#! /bin/bash

/usr/bin/qemu-system-x86_64 \
    -m 1024 -smp 2 -M pc -name kvm-guest \
    -cpu host -enable-kvm -machine kernel_irqchip=on \
    -hda /path/to/guest.img

$ cat kvm-boot-remotely.sh
#! /bin/bash

/usr/bin/qemu-system-x86_64 \
    -m 1024 -smp 2 -M pc -name kvm-guest \
    -cpu host -enable-kvm -machine kernel_irqchip=on \
    -hda /path/to/guest.img \
    -vnc :1

Networking

The lib bridge-utils already sets up virbr0 for you. If you want to customize, you can do as follows.

$ cat /etc/qemu-ifup

#!/bin/sh

if [ ! -n "$1" ];then
    echo "Error: no interface specified"
    exit 1
fi

for dev_inf in $(ip addr show |grep 'scope global'|awk '{print $NF;}')
do
    switch=$(brctl show |grep "^$dev_inf[[:space:]]"|awk '{print $1;}')
    if [ $switch ];then
        break
    fi
done

if [ ! "$switch" ];then
    echo "Error: no switch specified"
    exit 1
fi

tunctl -u root -t $1
ip link set $1 up
sleep 1s
brctl addif $switch $1
exit 0

$ chmod 775 /etc/qemu-ifup
$ cat crbr.sh

[[ -c /dev/kvm ]] && TARGET_BRG=sw0
[[ -d /dev/xen ]] && TARGET_BRG=xenbr0

func_install_brctl()
{
    which brctl 2>&1>/dev/null
    local miss_brctl=$?
    [[ $miss_brctl -eq 0 ]] && return

    local TYPE_UNKNOW=0 TYPE_YUM=1 TYPE_APT=2
    local install_type=TYPE_UNKNOW install_cmd
    which yum 2>&1>/dev/null
    [[ $? -eq 0 ]] && install_type=$TYPE_YUM
    which apt-get 2>&1>/dev/null
    [[ $? -eq 0 ]] && install_type=$TYPE_APT

    case $install_type in
        $TYPE_YUM)  install_cmd="yum install -y bridge-utils"   ;;
        $TYPE_APT)  install_cmd="apt-get install -y --force-yes bridge-utils"   ;;
        *)          echo "Miss tool to install tools" && exit   ;;
    esac

    $install_cmd
}

func_route_fix()
{
    local dup_route=$(ip route list|grep -v 'default via'|sed -n 's/.*[^0-9]\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p'|uniq -dc)
    [[ ! "$dup_route" ]] && echo "Current route is health" && return
    echo "Catch duplicate route, start fix route process"
    echo "Shutdown bridge $1"
    ip addr flush $1
    echo "Shutdown ethernet $2"
    ip addr flush $2
    echo "Kill dhclient"
    pkill -f "dhclient $1"
    echo "Turn on bridge $1"
    ip link set dev $1 up
    echo "Assign IP to $TARGET_BRG"
    dhclient $1
    echo "Route fix process finished"
}

func_setup_bridge()
{
    local brg_name=$(brctl show|grep "^$TARGET_BRG[[:space:]]") dev_inf
    if [ "$brg_name" ];then
        echo "$TARGET_BRG exsit"
    else
        echo "Miss $TARGET_BRG, detect bridge effect"
        for dev_inf in $(ip addr show |grep 'scope global'|awk '{print $NF;}')
        do
            brg_name=$(brctl show |grep "^$dev_inf[[:space:]]"|awk '{print $1;}')
            if [ "$brg_name" ];then
                dev_inf=$(brctl show $brg_name|sed -n '2p'|awk '{print $4;}')
                echo "Already active bridge: $brg_name combine with $dev_inf, please manual check bridge create "
                return
            fi
        done
        echo "Create $TARGET_BRG"
        brctl addbr $TARGET_BRG
    fi

    dev_inf=$(brctl show $TARGET_BRG|sed -n '2p'|awk '{print $4;}')
    if [ "$dev_inf" ];then
        echo "Already combine $dev_inf with $TARGET_BRG"
        func_route_fix $TARGET_BRG $dev_inf
    else
        while [ true ]
        do
            dev_inf=$(ip addr show |grep 'scope global'|awk '{print $NF;}'|head -n 1)
            [[ "$dev_inf" ]] && break
            sleep 5s
        done
        echo "Shutdown interface $dev_inf"
        ip addr flush dev $dev_inf
        echo "Combine $dev_inf with $TARGET_BRG"
        brctl addif $TARGET_BRG $dev_inf
        echo "Turn on $TARGET_BRG"
        ip link set dev $TARGET_BRG up
    fi

    local ip_assign=$(ps -ef|grep "dhclient $TARGET_BRG"|grep -v 'grep')
    if [ "$ip_assign" ];then
        echo "Already assign ip to $TARGET_BRG"
    else
        echo "Assign IP to $TARGET_BRG"
        dhclient $TARGET_BRG
    fi
}

func_install_brctl
func_setup_bridge
$ cat boot-with-networing.sh

/usr/bin/qemu-system-x86_64 \
    -m 1024 -smp 2 -M pc -name kvm-guest \
    -cpu host -enable-kvm -machine kernel_irqchip=on \
    -hda /path/to/guest.img \
    -net nic -net tap,script=/etc/qemu-ifup \
    -net nic,model=e1000,macaddr=00:DE:EF:12:34:5D

There are other available network setup as follows.

-net nic,model=virtio,vlan=0,macaddr=00:16:3e:00:01:01 
-net tap,vlan=0,script=/root/ifup-br0,downscript=/root/ifdown-br0 
-net nic,model=virtio,vlan=1,macaddr=00:16:3e:00:01:02 
-net tap,vlan=1,script=/root/ifup-br1,downscript=/root/ifdown

results matching ""

    No results matching ""