Two or more workstations on one computer - a free solution


This article discusses the idea and practical guide for creating a multi-user workstation (multiseat) using KVM virtualization, with the possibility of remote control via libvirt. Using this guide, it is possible to create two or more workplaces both in the office and at home, which may require the full use of the computer's graphics subsystem. Moreover, it is possible to implement simultaneously the operation of various operating systems Windows, Linux, Mac OS X on one system unit, the rest is to your taste.

Introduction


The desire to realize the possibility of sharing one computer, at least two people appeared a long time ago. The idea of ​​making at least two workplaces from a home or office computer was previously implemented mainly on the same operating system with all the attendant drawbacks. Difficulties arose especially when one person liked working in windows, and another in Linux and someone had to endure if the solution was implemented only through one OS. However, there were other difficulties.

Now computers have become more productive, the increase in the frequency of new processors has not pleased us for a long time, but on the other hand, the growth of cores has pleased us. And this means that we potentially already have several computers in one system unit. And this trend will only grow. The work of several people with one computer in a standard configuration will soon be quite popular in the market and is now available for sale.

Gentoo Installation


Training
Download the current livecd and boot.
Raise the network. What is the name of the network interface?
ifconfig
  eno1: flags=4163  mtu 1500

For those who like windows, configure the network so
net-setup eno1

I personally got used to the old fashioned way. Register your ip
ifconfig eno1 192.168.1.2/24

Set the default router
route add default gw 192.168.1.1

Specify our DNS
echo "nameserver 8.8.8.8" >> /etc/resolv.conf

Set a password for root
passwd root

Run ssh to continue the installation remotely
/etc/init.d/sshd start

From your favorite workplace, go to ssh
ssh root@192.168.1.186


Disk layout
It is assumed that you have one empty drive named / dev / sda
parted -a opt  /dev/sda
(parted) mklabel msdos

Create a download section. 150M with a very large margin. Maybe we will migrate sections in the GPT in the future and put EFI.
(parted) mkpart primary ext2 1 150M
(parted) set 1 boot on

We give everything else under lvm
(parted) mkpart primary 150M -1s
(parted) #Is this still acceptable to you? Yes/No? yes 
(parted) set 2 lvm on                                                     
(parted) quit

We need LVM in order to take snapshots of virtual machine disks, without stopping the system, for organizing backups. It will also be more convenient to change sections, add new ones.
Partitioning a disk for LVM. Put the sizes to your taste
pvcreate /dev/sda2
vgcreate vg /dev/sda2
lvcreate -L 1G -n root vg
lvcreate -L 1G -n tmp vg
lvcreate -L 5G -n var vg
lvcreate -L 10G -n usr vg

If LVM has already been configured, then you need to activate it
vgchange -ay

Format all sections
mkfs.ext2 /dev/sda1
mkfs.ext2 /dev/vg/tmp
for p in root var usr ; do mkfs.ext4 /dev/vg/$p ; done

Mount our future root partition
mount /dev/vg/root /mnt/gentoo

Create directories for the rest of the mount points
cd /mnt/gentoo
mkdir boot usr var tmp sys proc dev
chmod 1777 tmp

Mount the remaining sections
mount /dev/vg/usr /mnt/gentoo/usr
mount /dev/vg/tmp /mnt/gentoo/tmp
mount /dev/vg/var /mnt/gentoo/var
mount /dev/sda2 /mnt/gentoo/boot


Deploying the finished image and preparing for chroot
cd /mnt/gentoo

Download a fresh system (check the date in the file name)
wget http://mirror.yandex.ru/gentoo-distfiles/releases/amd64/current-stage3/stage3-amd64-nomultilib-20140123.tar.bz2

Take portage. Portage - a description of how to build and install the programs we need
wget http://mirror.yandex.ru/gentoo-distfiles/snapshots/portage-latest.tar.bz2 

Unpack it all
tar xvjpf stage3-amd64-nomultilib-20140123.tar.bz2
tar xvjf portage-latest.tar.bz2 -C /mnt/gentoo/usr 

Copy resolv.conf to the future root partition
cp /etc/resolv.conf /mnt/gentoo/etc/resolv.conf 

Mount system partitions
mount --rbind /dev /mnt/gentoo/dev
mount -t proc none /mnt/gentoo/proc
mount --rbind /sys /mnt/gentoo/sys

We get inside the created root partition (future system)
chroot /mnt/gentoo
env-update
source /etc/profile


We live in a new system
nano /etc/portage/make.conf

If necessary, then change CFLAGS - options for the compiler. Compiler options are almost standard, except for -march = native (instead of -march = i686), which requires the compiler to use all the features of the processor. If the task is to make iron an independent installation, then it is better not to use it, because when restored to a new hardware (possibly) will have to rebuild the whole world.
USE - lists globally the main options of the programs that will be installed.
If there are thin clients, add “spice” to the USE; if you need to forward USB ports of thin clients, add “usbredir”
CFLAGS="-O2 -pipe -march=native"
# количество процессов при сборке пакетов
MAKEOPTS="-j3"
USE="bindist mmx sse sse2 -ipv6 unicode device-mapper -X slang udev pulseaudio"
GENTOO_MIRRORS=http://mirror.yandex.ru/gentoo-distfiles/
SYNC="rsync://rsync.ru.gentoo.org/gentoo-portage"
LINGUAS="ru en" 

We will register our sections for auto-mount
cat > /etc/fstab << "EOF"
/dev/sda1 /boot ext2 noauto,noatime 1 2
/dev/vg/root / ext4 noatime 0 1 
/dev/vg/tmp /tmp ext2 noatime 0 0
/dev/vg/usr /usr ext4 noatime 0 0 
/dev/vg/var /var ext4 noatime 0 0
EOF

Update the portage tree
emerge --sync

If you need to change the profile, then just the time
eselect profile list
eselect profile set <цифра>

Create a network configuration file
cat > /etc/conf.d/net << "EOF"
config_eno1="null"
config_br0="192.168.1.2/24"
routes_br0="default via 192.168.1.1"
bridge_br0="eno1"
rc_net_br0_need="net.eno1"
ethtool_offload_eno1="gro off"
dns_domain="mydomain.ru"
dns_servers="8.8.8.8 8.8.4.4"
EOF
ln -s /etc/init.d/net.lo /etc/init.d/net.eno1
ln -s /etc/init.d/net.lo /etc/init.d/net.br0

Set root password
passwd root

Add yourself (testuser) as a user and set a password. Add users, wheel, audio to the groups
useradd -m -G users,wheel,audio -s /bin/bash testuser
passwd testuser

At the time of writing, qemu-1.7.1 has not yet been released, so we put two stars to pick up the development version
echo "app-emulation/qemu ** ~amd64" >>/etc/portage/package.accept_keywords

This flag is needed for pulseaudio to work as an independent process. Unfortunately, by default I was unable to get it working stably with libvirt using the variable “nographics_allow_host_audio = 1” in libvirtd.conf. Maybe you can do it?
echo "media-sound/pulseaudio -system-wide" >>/etc/portage/make.profile/package.use.mask
echo "media-sound/pulseaudio -dbus system-wide" >>/etc/portage/package.use 

We indicate that it will be necessary to collect new versions of packages
for p in sys-kernel/gentoo-sources app-emulation/libvirt sys-apps/dtc sys-firmware/seabios; do echo $p" ~amd64" >>/etc/portage/package.accept_keywords ; done 

Install the necessary programs. The -av switch allows you to see the build options; if something doesn’t work, you can enable the option in the USE variable, which is contained in the /etc/portage/make.conf file. app-misc / mc - if someone is comfortable
emerge -av gentoo-sources vixie-cron lvm2 genkernel syslog-ng iproute2 libvirt ethtool bridge-utils grub terminus-font radeon-ucode app-misc/mc

Add programs to startup
for s in sshd vixie-cron syslog-ng net.br0 libvirtd ; do rc-update add $s default; done

Let's build the Linux kernel, and in the sections
> Device Drivers> IOMMU Hardware Support> IOMMU Hardware Support
Mark all with asterisks
> Device Drivers> VFIO Non-Privileged userspace driver framework
Mark all with asterisks
> Device Drivers> Networking support> Universal TUN / TAP device driver support
Set asterisk.
Everything else to taste ;-)
genkernel --lvm --menuconfig all

Add the flag “dolvm” for LVM startup
nano /etc/default/grub
# пропишем переменную
GRUB_CMDLINE_LINUX="dolvm"

Install the Grub bootloader
grub2-install /dev/sda
grub2-mkconfig -o /boot/grub/grub.cfg

We configure localization
cat /usr/share/i18n/SUPPORTED | grep -E 'ru_RU|en_US' >> /etc/locale.gen && locale-gen

Copy the new timezone file to / etc / localtime
cp /usr/share/zoneinfo/Europe/Moscow /etc/localtime

Set up keyboard switching
nano /etc/conf.d/keymaps
# изменим параметры
dumpkeys_charset="utf8"
keymap="-u ru"

Let's write the background in the console
nano /etc/conf.d/consolefont
# изменим параметр
consolefont="cyr-sun16"

Message Localization
cat > /etc/env.d/02locale << "EOF"
LANG="ru_RU.UTF-8"
LC_ALL="ru_RU.UTF-8"
LANG="ru_RU.UTF-8"
LC_MESSAGES="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
EOF
env-update && source /etc/profile
rc-update add keymap default
rc-update add consolefont default


If necessary, you can update and rebuild packages with new USE flags
emerge -avuDN system world

Set host name
nano /etc/conf.d/hostname
hostname="testhost"

Edit / etc / hosts
nano /etc/hosts
127.0.0.1 localhost testhost testhost.mydomain.ru

We are overloaded, if everything is fine, then you are lucky ;-) Still, the hardware is different for everyone, maybe something will need to be included in the kernel.
If everything is bad, then we understand the documentation or use google. Documentation in Russian on the network is enough.

Customization


BIOS setup

We check that VT-d is enabled in BIOS, for “Z intel usb intel XHCI” for Z87 we need to disable it for forwarding USB controllers.

Sound setting

usermod -G kvm, audio, pulse-access -d / home / qemu qemu
usermod -G wheel, audio, pulse-access, users testuser
Run pulseaudio.
echo 'PULSEAUDIO_SHOULD_NOT_GO_SYSTEMWIDE="1"' >> /etc/conf.d/pulseaudio 
rc-update add pulseaudio default 
/etc/init.d/pulseaudio start
su - testuser 
# C помощью alsamixer выставляем требуемую громкость, если ММ то нажимаем М.
alsamixer
# обратно к root
exit
# сохраняем настройки громкости
/etc/init.d/alsasound save 
/etc/init.d/alsasound start
rc-update add alsasound default

Libvirt setup

In the file /etc/libvirt/qemu.conf we define the user from whom the virtual machines will be launched
user = "qemu"
group = "qemu"
# Если все будет плохо, то можно раскомментировать
# clear_emulator_capabilities = 0

At the time of writing the seabios article in gentoo 1.7.3, and we need a fresh one, so download and unpack it
cd /etc/libvirt 
wget http://code.coreboot.org/p/seabios/downloads/get/bios.bin-1.7.4.gz 
gzip -d bios.bin-1.7.4.gz


Create a helper script to forward devices
cat > /etc/libvirt/vfio-bind << "EOF"
#!/bin/sh
for dev in "$@"; do 
  vendor=$(cat /sys/bus/pci/devices/$dev/vendor) 
  device=$(cat /sys/bus/pci/devices/$dev/device)
  if [ -e /sys/bus/pci/devices/$dev/driver ]; then
    echo $dev > /sys/bus/pci/devices/$dev/driver/unbind
  fi                                                                                                         
  echo $vendor $device > /sys/bus/pci/drivers/vfio-pci/new_id
done
EOF
chmod +x /etc/libvirt/vfio-bind

Launch lspci and select the victim for manual forwarding
03:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Turks PRO [Radeon HD 6570/7570]
03:00.1 Audio device: Advanced Micro Devices, Inc. [AMD/ATI] Turks/Whistler HDMI Audio [Radeon HD 6000 Series
00:1a.0 USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB EHCI #2 (rev 04)

Create a script for forwarding a specific video card
cat > /etc/libvirt/bind-vga-1 << "EOF"
#!/bin/sh                                                                                                    
/etc/libvirt/vfio-bind 0000:03:00.0 0000:03:00.1                                                                    
# ставим права на группу 6. Найти можно здесь /sys/kernel/iommu_groups/6/devices
chown qemu /dev/vfio/6
EOF
chmod +x /etc/libvirt/bind-vga-1
# запускаем
/etc/libvirt/bind-vga-1
# создадим скрипт автозагрузки
cat > /etc/init.d/bind-vga-1 << "EOF"
#!/sbin/runscript                                                                                            
start() {
  ebegin "Starting vfio-bind"
  /etc/libvirt/bind-vga-1
  eend $? "Failed to start vfio-bind"
}
EOF
# если нужно, то в автозагрузку его
rc-update add bind-vga-1 default

Now create a section where the image of the virtual machine will lie
lvcreate -L70G -nwks1 vg

I have a car where the images of already prepared virtual machines with software are located, I hope you will have one. How to prepare the image I will write below.
ssh root@192.168.1.3 "dd if=/dev/vg_archive/windows7 bs=1M |gzip -" |gunzip - | dd of=/dev/vg/wks1 bs=1M

Domain setting


The following is the configuration file for the final working configuration with comments.

wks12811e544-bf4d-baf6-1135-ec5acd13999941451524145152hvm/etc/libvirt/bios.bin-1.7.4destroyrestartrestart/usr/bin/qemu-kvm
      
      -->
-->
-->

This configuration is written to the file /etc/libvirt/qemu/wks1.xml
Reread the configuration file
/etc/init.d/libvirtd restart

We start the domain
virsh start wks1
# если все будет хорошо, то можно в автозагрузку добавить
# virsh autostart wks1

Initial installation


For the initial installation, write the desired iso image and uncomment the cdrom section. We also remove all virtio settings and device forwarding 03: 00.0 - video and 00: 1a.0 usb controller. Turn on vnc access. After you install the system, you need to install the virtio driver in the guest OC. Drivers for windows.
Without drivers, everything works very slowly.

Famous ambushes


  • I met with the fact that without a full windows update the latest virtio drivers did not get up.
  • Before installing the virtio driver of the main disk, you need to connect a second empty disk with the already defined virtio type
    lvcreate -nzero -L1M
    


  • In windows, change the energy-saving settings -> set the sleep mode -> put the computer into sleep mode ->
    "never"


This script can be installed in crontab.
cat > /etc/libvirtd/shutdown_if_not_start.sh << "EOF"
#!/bin/sh                                                                                                    
LIST_VM=`virsh list | awk '{if($3=="running")print $2}'|wc -l`                                               
if [ ${LIST_VM} -ne  0 ] ; then                                                                              
  exit 0                                                                                                     
fi                                                                                                           
awk '{if(int($1)>300){exit 0}else{ exit 1}}' /proc/uptime                                                    
if [ $? -ne 0 ]; then                                                                                        
  exit 0                                                                                                     
fi                                                                                                           
/sbin/shutdown -h now
EOF
chmod +x /etc/libvirtd/shutdown_if_not_start.sh

Conclusion


It seems that he described the main points. Here you can find solutions if you have windows crashing into BSOD. If you will be organizing snapshots, do not forget to install the QEMU Guest Agent and learn how to work with it.
We have Apache on combat computers, through the script the user himself can perform actions from the VM from a neighboring computer or virtual machine. You can also implement the launch of virtualoks via a USB key.
I am sure that someone will be able to improve this configuration. Please write about this in a comment to help others.
This configuration can be shared and distributed to other machines, as well as guest OC images. Do not forget, after deploying the host image, to correct addresses, hostnames, interfaces and generate ssh keys.
About spice and ARM, if it is interesting, I will write separately.

Also popular now: