Topic: tech myref prev next
tech myref > QEMU
Create a pre-allocated (rather than sparse) disk image;
qemu-img create loc/test.img 4G
A four gigabyte disk image will be sufficient for a Debian installation. Start a virtual machine, with a VNC server;
qemu-system-x86_64 \
-display vnc=172.xx.xx.xx:1 \
-cdrom debian-12.0.0-amd64-netinst.iso \
-drive file=loc/test.img,format=raw \
-m 8G \
-smp 6 \
-machine accel=kvm
On Ubuntu, remove the default systemd unit for QEMU, which links to
/dev/null
;
systemctl unmask qemu@
Multiple virtual machines can be managed and configured to start on boot with
systemd units. Save the following, generic, QEMU systemd unit as
/etc/systemd/system/qemu@.service
;
[Unit]
Description=QEMU
[Service]
EnvironmentFile=/etc/qemu/vm/%i
ExecStart=sudo qemu-system-x86_64 -name %i -monitor unix:/run/qemu-%i-monitor,server,nowait $args
ExecStop=/bin/sh -c 'echo system_powerdown | nc -U /run/qemu-%i-monitor'
TimeoutStopSec=60
KillMode=none
[Install]
WantedBy=multi-user.target
Create an environment file for each virtual machine. Specify the graphics,
memory, number of CPU’s, acceleration type (KVM), CPU limit, disk drive and
network interfaces. In particular, do not leave out the -nographic
option,
as QEMU, by default, tries to open a GTK window. For instance, the following
is saved to /etc/qemu/vm/tuff
;
args="\
-nographic \
-m 6G \
-smp 2 \
-machine accel=kvm \
-cpu max \
-drive file=/mnt/vmd/72-tuff.img,format=raw \
-nic bridge,br=br4,model=virtio,mac=00:11:00:11:00:72 "
Start the virtual machine, and optionally install it;
systemctl start qemu@tuff
systemctl enable qemu@tuff
Physical network interfaces and VLANs can be bridged in order to make them available to QEMU virtual machines. The process differs between Debian and Ubuntu, because the latter uses Netplan to manage networking.
(This bit isn’t fully tested - yet!)
Make sure that both the vlan
and bridge-utils
packages are installed.
Debian reads from the /etc/network/interfaces
file to configure physical
interfaces, brdiges an VLANs. To split the configuration for each interface
into its own file, use source-directory
from the /etc/network/interfaces
file;
source-directory /etc/network/interfaces.d
Configuration for the physical interface may be managed by dhcpcd
. If this
is the case, for instance in Raspbian, IP can be configured by editing the
/etc/dhcpcd.conf
file;
interface eth0
static ip_address=172.27.3.60/24
static routers=172.27.3.1
static domain_name_servers=172.27.3.1
Add VLAN interfaces as required, to files in /etc/network/interfaces.d
;
auto eth0.2
iface eth0.2 inet manual
vlan-raw-device eth0
Add bridge interfaces in a similar way;
auto br4
iface br4 inet static
address 172.27.4.60/24
bridge_ports eth0.4
Here is a complete set of interfaces, which can be used as
/etc/network/interfaces
, or split out into multiple files;
auto lo
iface lo inet loopback
allow-hotplug enp2s0
iface enp2s0 inet manual
auto br2
iface br2 inet static
bridge_ports enp2s0.2
address 172.27.2.46/24
gateway 172.27.2.1
nameserver 172.27.2.1
auto br3
iface br3 inet static
bridge_ports enp2s0
address 172.27.3.46/24
auto br5
iface br5 inet static
bridge_ports enp2s0.5
address 172.27.5.46/24
auto enp2s0.2
iface enp2s0.2 inet manual
vlan-raw-device enp2s0
auto enp2s0.5
iface enp2s0.5 inet manual
vlan-raw-device enp2s0
First, stop Ubuntu from delegating network management to NetworkManager. Edit /etc/netplan/01-network-manager-all.yaml
and comment out every line;
# Let NetworkManager manage all devices on this system
#network:
# version: 2
# renderer: NetworkManager
Create a new file for the local network configuration, for example,
/etc/netplan/local.yaml
. In this file, list physical interfaces under
ethernets
, and create VLANs and bridges as required.
The Netplan preamble;
network:
version: 2
renderer: networkd
The physical interface, eno1
, with empty braces to signify no additional
configuration for this interface;
ethernets:
eno1:
{}
A VLAN configured on the physical interface. Note that, for the same VLAN id to exist on multiple physical interfaces, it must be created once per interface. This is at odds to the way in which network switches are configured;
vlans:
vlan.5.eno1:
id: 5
link: eno1
Create a bridge for the native VLAN on the physical network interface;
bridges:
br3:
interfaces: [eno1]
dhcp4: yes
dhcp6: no
Create another bridge for the VLAN on the physical network interface;
br5:
interfaces: [vlan.5.eno1]
addresses: [172.27.5.64/24]
dhcp4: no
dhcp6: no
Additional interfaces can be added to bridges. For instance, a VLAN can be ‘trunked’ between two physical network interfaces, by creating a bridge containing two VLAN interfaces.
Putting all of the above together, we have a fully functional Netplan file;
network:
version: 2
renderer: networkd
ethernets:
eno1:
wakeonlan: true
vlans:
vlan.5:
id: 5
link: eno1
bridges:
br3:
interfaces: [eno1]
dhcp4: yes
dhcp6: no
br5:
interfaces: [vlan.5]
addresses: [172.27.5.64/24]
dhcp4: no
dhcp6: no
Activate the new Netplan configuration with these commands;
sudo netplan generate
sudo netplan apply
Once the bridges are created and, hopefulyl, tested, they can be added to virtual machines as NICs. Add something like the following to the QEMU command line options, substituting the desired bridge interface and hardcoded MAC address;
-nic bridge,br=br4,model=virtio,mac=00:11:00:11:00:72
Each bridge used by any QEMU virtual machine must be explicitly allowed by
QEMU. Edit the /etc/qemu/bridge.conf
file and add a line for each bridge;
allow br4
It is desired to shrink a QEMU image file to better fit the contents of the image. It is assumed that the image contains an MBR partition table with three partitions; a root filesystem (Linux) partition, and extended partition, and a swap partition. The extended and swap partitions will be deleted and the primary Linux partition will be shrunk, then extended to fill the filesystem.
To accomplish this, the QEMU image file is attached to a loopback device. The
partition table is loaded, and the ext filesystem is shrunk it its minimum
size. The QEMU image file is then resized, deleting any data at the end of the
file. The partition table is edited, to delete the extended and swap
partitions, and set the size of the root Linux partition to fill the entire
image file. The ext filesystem is then expanded to fit the extent of the new
partition. Finally, the swap partition is disabled in the guest operating
system by removing it from the initramfs
configuration, rebuilding the
initramfs, and removing the reference to the swap partition from /etc/fstab
.
When following this guide for the first time, it is likely that kpartx
will
need to be installed;
apt install kpartx
First, identify the first available loopback device. This will be of the form
/dev/loopX
, where X is a number;
losetup -f
Attach the QEMU image file to the loopback device;
losetup /dev/loopX loc/image.img
Read the partitions from the loopback device;
kpartx -a /dev/loopX
Resize the ext partition;
e2fsck -f /dev/mapper/loopXp1
resize2fs -pM /dev/mapper/loopXp1
Shrink the QEMU image;
kpartx -d /dev/loopX
losetup -d /dev/loopX
qemu-img resize --shrink loc/image.img 10G
losetup /dev/loopX loc/image.img
Shrink the partition in the partition table. From within fdisk
, delete all
three partitions (the primary Linux partition, the swap partition, and the
extended partition), then recreate the primary Linux partition with the desired
size;
fdisk /dev/loopX
Resize the ext filesystem again, to fill the partition;
kpartx -a /dev/loopX
resize2fs -p /dev/mapper/loopXp1
Start the virtual machine;
kpartx -d /dev/loopX
losetup -d /dev/loopX
qemu-system-x86_64 -display vnc=172.xx.xx.xx:1 -drive file=loc/image.img \
-m 1G -smp 2 -machine accel=kvm
Connect to the virtual machine’s VNC console. It will print errors on boot. These errors will be fixed in the next step.
The virtual machine will have a broken initramfs. Fix this from inside the virtual machine, by removing the swap partition reference, and rebuilding the initramfs. Assuming the virtual machine is running Debian;
rm /etc/initramfs-tools/conf.d/resume
PATH=$PATH:/sbin dpkg-reconfigure initramfs-tools
Finally, edit /etc/fstab
, and remove the reference to the swap partition.
vim /etc/fstab
The virtual machine should now boot cleanly, albeit without a swap partition.