KVM With Gentoo

Jan 29, 2019
7 min read
May 27, 2023 09:13 EEST

We use as distribution a gentoo system. The KVM will be installed on a raid1 (mirror) with LVM2. We use the standard procedure to install the gentoo system. I start the installation from an already running system (you can even boot from a boot CD, USB stick or any other linux live system).

The system where I will install is located on /dev/sda. We will start with one harddisk, the second harddisk will be plugged into the system after it is running fine the raid system will mirror the data automatically. The harddisk must be completely empty.

Prepare the harddisk

modprobe raid1
Raid Device /dev/sda missing Type
/dev/sda1 Bios boot partition Bios boot partition 1MiB
/dev/md0 Raid for Gentoo-KVM Raid for Gentoo-KVM Raid-1 (mirror)
parted /dev/sda
mklabel gpt
(say yes if parted asks you)
mkpart boot1 1MiB 2MiB
mkpart kvm1 2MiB 100%
set 1 bios_grub on
set 2 raid on
quit
mdadm --create /dev/md0 --level=mirror --raid-devices=2 /dev/sda1 missing
mdadm --grow /dev/md0 -b internal
pvcreate /dev/md0
vgcreate vg-kvm /dev/md0
lvcreate -L100M -nboot vg-kvm
lvcreate -L4GB -nswap vg-kvm
lvcreate -L30GB -nroot vg-kvm
mkfs.ext2 -L boot /dev/vg-kvm/boot
mkfs.ext4 -L root /dev/vg-kvm/root
mkswap /dev/vg-kvm/swap
swapon /dev/vg-kvm/swap
mount /dev/vg-kvm/root /mnt/gentoo/
mkdir /mnt/gentoo/boot
mount /dev/vg-kvm/boot /mnt/gentoo/boot/

Installation of Gentoo

Make sure you have the following use flags defined in /etc/portage/make.conf

USE="bindist mmx sse sse2 -ldap perl python lvm parted qemu virt-network avahi sasl audit nfs"
MAKEOPTS="-j5"
QEMU_SOFTMMU_TARGETS="i386 x86_64"
QEMU_USER_TARGETS="i386 x86_64"

Follow the normal gentoo install guide here: http://www.gentoo.org/doc/de/handbook/handbook-amd64.xml?part=1&chap=5

Some changes to the gentoo manual (all to be executed in the chroot environment):

  • Use lzo to compress kernel
  • Use Grub 2
  • Modify fstab to use labels
  • Build our own initramfs
echo "=sys-boot/grub-2*">>/etc/portage/package.keywords
echo "sys-boot/grub device-mapper">>/etc/portage/package.use
emerge -av grub lzop lvm2 mdadm genkernel
rc-update add lvm boot
rc-update add mdraid boot

Modify /etc/default/grub:

GRUB_CMDLINE_LINUX_DEFAULT="dolvm domdadm intel_iommu=on,igfx_off,pass-through vga=791 splash=silent,theme:gentoo console=tty1 quiet libata.ignore_hpa=1 cgroup_enable=memory swapaccount=1"

To build the initramfs use:

genkernel --lvm --mdadm --iscsi --disklabel --install initramfs

Setup fstab:

blkid
/dev/loop0: TYPE="squashfs"
/dev/sda2: UUID="9338e0f6-0ed2-8112-a0e2-840b4d9616de" UUID_SUB="fa5fb4fe-6f65-efe6-5cd3-21e7e6c42976" LABEL="Gentoo-20121221:0" TYPE="linux_raid_member"
/dev/md0: UUID="PoGeVn-q9Sb-T7YD-Ysro-oRDG-pB7f-tXRWzr" TYPE="LVM2_member"
/dev/sdb: LABEL="PENDRIVE" UUID="1105-224F" TYPE="vfat"
/dev/mapper/vg--kvm-boot: LABEL="boot" UUID="251d9d9e-2c38-41db-938d-e25ef56afd3a" TYPE="ext2"
/dev/mapper/vg--kvm-swap: UUID="9d77c5f7-ebc8-4a9d-afa9-cd215489aae8" TYPE="swap"
/dev/mapper/vg--kvm-root: LABEL="root" UUID="7702989f-02c0-48dd-b640-3a921797096b" TYPE="ext4"

Now edit the /etc/fstab based on the information:

UUID="251d9d9e-2c38-41db-938d-e25ef56afd3a"             /boot           ext2            noatime  1 2
UUID="7702989f-02c0-48dd-b640-3a921797096b"             /               ext3            noatime         0 1
UUID="9d77c5f7-ebc8-4a9d-afa9-cd215489aae8"             none            swap            sw              0 0

Install GRUB 2

mkdir /boot/grub2
grub-mkconfig -o /boot/grub/grub.cfg
grub-install /dev/sda

Configure KVM

Install required software:

emerge -av qemu usbutils bridge-utils usermode-utilities iptables macchanger virt-manager
rc-update add libvirtd default
gpasswd -a qemu kvm

Enable KSM:

echo "echo 1 > /sys/kernel/mm/ksm/run" >/etc/local.d/ksm.start
chmod +x /etc/local.d/ksm.start

Create certificates:

mkdir -p /tmp/certs
cd /tmp/certs

certtool --generate-privkey > cakey.pem
echo "cn = FM-Data" >ca.info
echo "ca" >>ca.info
echo "cert_signing_key" >>ca.info
certtool --generate-self-signed --load-privkey cakey.pem --template ca.info --outfile cacert.pem

mkdir -p /etc/pki/CA
cp cacert.pem /etc/pki/CA

certtool --generate-privkey > serverkey.pem
echo "organization = FM-Data" >server.info
echo "cn = kvm.idefix.lan" >>server.info
echo "tls_www_server" >>server.info
echo "encryption_key" >>server.info
echo "signing_key" >>server.info
certtool --generate-certificate --load-privkey serverkey.pem --load-ca-certificate cacert.pem --load-ca-privkey cakey.pem --template server.info --outfile servercert.pem

mkdir -p /etc/pki/libvirt/private
cp serverkey.pem /etc/pki/libvirt/private/
cp servercert.pem /etc/pki/libvirt/

certtool --generate-privkey > clientkey.pem
echo "country = DE" >client.info
echo "state = Bayern" >>client.info
echo "locality = Fuerstenfeldbruck" >>client.info
echo "organization = FM-Data" >>client.info
echo "cn = client1" >>client.info
echo "tls_www_client" >>client.info
echo "encryption_key" >>client.info
echo "signing_key" >>client.info
certtool --generate-certificate --load-privkey clientkey.pem --load-ca-certificate cacert.pem --load-ca-privkey cakey.pem --template client.info --outfile clientcert.pem

cp clientkey.pem /etc/pki/libvirt/private/clientkey.pem
cp clientcert.pem /etc/pki/libvirt/clientcert.pem

rm *

Network bridge: Edit vi /etc/conf.d/net

bridge_br0="eth0"
brctl_br0="setfd 0 sethello 0 stp off"
config_br0="dhcp"
cd /etc/init.d/
ln -s net.lo net.br0
rc-update del net.eth0
rc-update add net.br0 default

Enable PCI passthrough:

echo "options kvm allow_unsafe_assigned_interrupts=1" >kvm_iommu_map_guest.conf

Add Second Harddisk and Build Raid1

Install sgdisk:

emerge -av sys-apps/gptfdisk

Copy the GPT partition schema from the original disk to the new disk. The already existing disk is /dev/sda and the new disk is /dev/sdf:

sgdisk -R=/dev/sdf /dev/sda
sgdisk -G /dev/sdf
sgdisk -c 1:"boot2" /dev/sdf
sgdisk -c 2:"kvm2" /dev/sdf

See disk and raid information:

cat /proc/mdstat
blkid
/dev/sdf1: PARTLABEL="boot2" PARTUUID="bea234c8-ce71-4c23-8e67-7faf5d8e50d1"
/dev/sdf2: PARTLABEL="kvm2" PARTUUID="054de73e-7cd6-4c94-860b-3eda62cabc58"

Add the new disk to the raid:

mdadm -a /dev/md126 /dev/disk/by-partuuid/054de73e-7cd6-4c94-860b-3eda62cabc58 

Install boot manager:

grub2-install /dev/sdf

Install Gentoo as Guest

Download the install-amd64-minimal-20130207.iso and place it in the iso directory:

cd /mnt/isos/
wget http://distfiles.gentoo.org/releases/amd64/autobuilds/current-iso/default/20130207/install-amd64-minimal-20130207.iso

Now start virt-manager and we create there the new virtual machine. I created a lvm partition with 30GB and mounted the iso we downloaded. Then follow the normal gentoo installation guide or continue here.

Prepare Harddisk

fdisk /dev/sda
n
p
1
<ENTER>
+100M
n
p
2
<ENTER>
<ENTER>
t
2
8e
a
1
w
pvcreate /dev/sda2
vgcreate vg-knx /dev/sda2
lvcreate -L4GB -nswap vg-knx
lvcreate -l+100%FREE -nroot vg-knx
mkfs.ext2 -L boot /dev/sda1
mkfs.ext4 -L root /dev/vg-knx/root
mkswap -L swap /dev/vg-knx/swap
swapon /dev/vg-knx/swap
mount /dev/vg-knx/root /mnt/gentoo/
mkdir /mnt/gentoo/boot
mount /dev/sda1 /mnt/gentoo/boot
cd /mnt/gentoo

Install Gentoo

links http://www.gentoo.org/main/en/mirrors.xml
(download stage3 in releases/autobuilds/current-stage3/default/..../stage3-amd64....tar.bz2)
q
tar xjpf stage3-*.tar.bz2
echo 'MAKEOPTS="-j2"' >>etc/portage/make.conf
mirrorselect -i -o >> /mnt/gentoo/etc/portage/make.conf
mirrorselect -i -r -o >> /mnt/gentoo/etc/portage/make.conf
cp -L /etc/resolv.conf /mnt/gentoo/etc/
mount -t proc none /mnt/gentoo/proc
mount --rbind /sys /mnt/gentoo/sys
mount --rbind /dev /mnt/gentoo/dev
chroot /mnt/gentoo /bin/bash
source /etc/profile
export PS1="(chroot) $PS1"
mkdir /usr/portage
emerge-webrsync
eselect news list
eselect news read
eselect profile list
eselect profile set 3
emerge --sync --quiet
cp /usr/share/zoneinfo/Europe/Berlin /etc/localtime
echo "Europe/Berlin" > /etc/timezone
emerge =gentoo-sources-3.0.35 eix genkernel syslog-ng vixie-cron dhcpcd grub vim
rc-update add syslog-ng default
rc-update add vixie-cron default
rc-update add sshd default

Prepare the kernel

vi /etc/genkernel.conf
SYMLINK="yes"
MAKEOPTS="-j2"
LVM="yes"
DISKLABEL="yes"
BOOTLOADER="grub"

Compile the kernel now with:

cd /usr/src/linux
genkernel all

Configure the system

vi /etc/fstab
LABEL="boot"            /boot           ext2            noatime         1 2
LABEL="root"            /               ext4            noatime         0 1
LABEL="swap"            none            swap            sw              0 0

Configure hostname:

vi /etc/conf.d/hostname
hostname="knx.idefix.lan"

Configure network:

vi /etc/conf.d/net
config_eth0="dhcp"
cd /etc/init.d
ln -s net.lo net.eth0
rc-update add net.eth0 default

Locale settings:

vi /etc/conf.d/keymaps
vi /etc/locale.gen
en_US ISO-8859-1
en_US.UTF-8 UTF-8
de_DE ISO-8859-1
de_DE@euro ISO-8859-15
de_DE.UTF-8 UTF-8

locale-gen
vi /etc/env.d/02locale
LANG="de_DE.UTF-8"
LC_COLLATE="C"

env-update && source /etc/profile

Install grub

vi /boot/grub/grub.conf
default 0
timeout 0
splashimage=(hd0,0)/grub/splash.xpm.gz

title Gentoo Linux
root (hd0,0)
kernel /kernel real_root=/dev/vg-knx/root dolvm
initrd /initramfs
grep -v rootfs /proc/mounts > /etc/mtab
grub-install --no-floppy /dev/sda

Setup users

passwd
useradd -m -G users,wheel,audio -s /bin/bash idefix
passwd idefix

rm /stage3-*.tar.bz2*

Reboot the system

exit
cd
umount -l /mnt/gentoo/dev{/shm,/pts,}
umount -l /mnt/gentoo{/boot,/proc,}
reboot

Pass Cine-S2 to virtual machine

Find the device with:

lspci

we get:

...
04:00.0 Multimedia controller: Digital Devices GmbH Octopus LE DVB adapter
...

We search for the id of the card:

lspci -n |grep 04:00.0

We get:

04:00.0 0480: dd01:0003

Now we create a startup script to free the card before libvirt tries to start the virtual machine. For this we create a new start script and enable it:

cd /etc/init.d/
echo '#!/sbin/runscript' > pci_passthrough
echo "" >> pci_passthrough
echo "depend() {" >> pci_passthrough
echo "        before libvirtd" >> pci_passthrough
echo "}" >> pci_passthrough
echo "" >> pci_passthrough
echo "start () {" >> pci_passthrough
echo "        echo "dd01 0003" > /sys/bus/pci/drivers/pci-stub/new_id" >> pci_passthrough
echo "        echo 0000:04:00.0 >/sys/bus/pci/devices/0000\:04\:00.0/driver/unbind" >> pci_passthrough
echo "        echo 0000:04:00.0 >/sys/bus/pci/drivers/pci-stub/bind" >> pci_passthrough
echo "}" >> pci_passthrough
echo "" >> pci_passthrough
chmod +x pci_passthrough
rc-update add pci_passthrough default

If you reboot your system now, it frees the pci card with the given id before libvirt tries to start the virtual machines.

Snapshot and upgrade the guest, maybe roll back

We have now the following setup.

vgs
  VG           #PV #LV #SN Attr   VSize   VFree
  boot           1   3   0 wz--n- 148,95g      0
  vg-kvm         1   7   0 wz--n- 232,75g 120,30g
  videostorage   1   1   0 wz--n-   4,00t  20,00g
  LV      VG           Attr     LSize   Pool Origin Data%  Move Log Copy%  Convert
  root    boot         -wi-a---  30,00g
  swap    boot         -wi-a---   2,00g
  video1  boot         -wi-a--- 116,95g
  boot    vg-kvm       -wi-ao-- 100,00m
  freepbx vg-kvm       -wi-a---  19,53g
  iso     vg-kvm       -wi-ao--  10,00g
  knx     vg-kvm       -wi-ao--  29,30g
  root    vg-kvm       -wi-ao--  30,00g
  swap    vg-kvm       -wi-ao--   4,00g
  yavdr   vg-kvm       -wi-ao--  19,53g
  video0  videostorage -wi-ao--   3,98t

Create snapshot

We would like to create now a snapshot of the machine yavdr:

virsh shutdown yavdr

Wait till the virtual machine is shutdown completely. Check it with:

virsh list --all

Create the snapshot:

lvcreate -L4G -s -n /dev/vg-kvm/yavdr-snapshot /dev/vg-kvm/yavdr
virsh start yavdr

We can see the new snapshot now:

lvs vg-kvm
  LV             VG     Attr     LSize   Pool Origin Data%  Move Log Copy%  Convert
  boot           vg-kvm -wi-ao-- 100,00m
  freepbx        vg-kvm -wi-a---  19,53g
  iso            vg-kvm -wi-ao--  10,00g
  knx            vg-kvm -wi-ao--  29,30g
  root           vg-kvm -wi-ao--  30,00g
  swap           vg-kvm -wi-ao--   4,00g
  yavdr          vg-kvm owi-aos-  19,53g
  yavdr-snapshot vg-kvm swi-a-s-   4,00g      yavdr    0,05

Roll back to snapshot

We tested now some stuff and we see it does not work. Stop the virtual machine:

virsh destroy yavdr

Rollback the lvm to the snapshot (this will destroy the snapshot):

lvconvert --merge /dev/vg-kvm/yavdr-snapshot

Start the VM again:

virsh start yavdr

Destroy the snapshot

If everything is fine, destroy the snapshot:

lvremove /dev/vg-kvm/yavdr-snapshot

Related Posts