From d31a16c435e497f320ccfa880122dff963f151a7 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 23 Aug 2018 20:07:28 -0400 Subject: Organize in to an installable package --- .gitignore | 5 +++ Makefile | 73 ++++++++++++++++++++++++++++++++++++++++++++ README.md | 9 ++++++ conf.d/qemu.d/beefcake | 39 ----------------------- conf.d/qemu.d/qemutest | 7 ----- conf.d/qemu.d/testbox | 10 ------ examples/beefcake | 39 +++++++++++++++++++++++ examples/qemutest | 7 +++++ examples/testbox | 10 ++++++ qemu.in | 37 ++++++++++++++++++++++ qemu@.service.in | 16 ++++++++++ systemd/system/qemu | 37 ---------------------- systemd/system/qemu@.service | 16 ---------- write-ifchanged | 26 ++++++++++++++++ 14 files changed, 222 insertions(+), 109 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md delete mode 100644 conf.d/qemu.d/beefcake delete mode 100644 conf.d/qemu.d/qemutest delete mode 100644 conf.d/qemu.d/testbox create mode 100644 examples/beefcake create mode 100644 examples/qemutest create mode 100644 examples/testbox create mode 100755 qemu.in create mode 100644 qemu@.service.in delete mode 100755 systemd/system/qemu delete mode 100644 systemd/system/qemu@.service create mode 100755 write-ifchanged diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8c156ea --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/qemu +/qemu@.service +.var.* +.tmp.* +*.tmp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f3e2a11 --- /dev/null +++ b/Makefile @@ -0,0 +1,73 @@ +# Copyright (C) 2016-2018 Luke Shumaker +# SPDX-License-Identifier: AGPL-3.0-or-later + +# GNU standard settings +prefix = /usr/local +exec_prefix = $(prefix) +bindir = $(exec_prefix)/bin +localstatedir = $(prefix)/var +runstatedir = $(or $(shell systemd-path system-runtime 2>/dev/null),$(localstatedir)/run) +sysconfdir = $(prefix)/etc + +# systemd settings +rootprefix = $(prefix) +systemunitdir = $(or $(shell pkg-config --variable=systemdsystemunitdir systemd 2>/dev/null),$(rootprefix)/lib/systemd/system) + +# other +pkgconfdir = $(sysconfdir)/conf.d/qemu.d +BINPROG = $(bindir)/qemu +SOCAT = /bin/socat + +outdir = . +srcdir = . + +#### + +files.out.all += qemu qemu@.service + +files.sys.all += $(BINPROG) +files.sys.all += $(systemunitdir)/qemu@.service +files.sys.all += $(pkgconfdir) + +var = $(patsubst ./%,%,$(outdir)/.var.) + +all: $(addprefix $(outdir)/,$(files.out.all)) +clean: + rm -f -- $(addprefix $(outdir)/,$(files.out.all)) +install: $(addprefix $(DESTDIR),$(files.sys.all)) +.PHONY: all clean install +.SECONDARY: +.DELETE_ON_ERROR: + +$(outdir)/qemu: $(var)runstatedir $(var)pkgconfdir +$(outdir)/qemu@.service: $(var)runstatedir $(var)BINPROG $(var)SOCAT +$(outdir)/%: $(srcdir)/%.in + sed $(foreach v,$(patsubst $(var)%,%,$(filter $(var)%,$^)),-e 's|@$v@|$($v)|g') < $< > $@ + +$(DESTDIR)$(BINPROG): $(outdir)/qemu + install -DTm755 $< $@ +$(DESTDIR)$(systemunitdir)/%: $(outdir)/% + install -DTm644 $< $@ +$(DESTDIR)$(pkgconfdir): $(wildcard $(srcdir)/examples/*) + install -Dm644 -t $@ -- $^ + test -d $@ + touch $@ + +#### + +# Magic to depend on the value of variables + +.PHONY: FORCE +$(var)%: FORCE + @printf '%s' $(call quote.shell,$($*)) | sed 's/^/#/' | ./write-ifchanged $@ +-include $(wildcard $(var)*) + +define at.nl + + +endef + +# I put this as the last line in the file because it confuses Emacs +# syntax highlighting and makes the remainder of the file difficult to +# edit. +quote.shell = $(subst $(at.nl),'$$'\n'','$(subst ','\'',$1)') diff --git a/README.md b/README.md new file mode 100644 index 0000000..d10fa6b --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +A tiny libvirtd alternative that integrates better with systemd + +Requirements: + + - QEMU + - GNU Bash 4.4+ + - numactl + - socat + - taskset (from util-linux) diff --git a/conf.d/qemu.d/beefcake b/conf.d/qemu.d/beefcake deleted file mode 100644 index 21b7e74..0000000 --- a/conf.d/qemu.d/beefcake +++ /dev/null @@ -1,39 +0,0 @@ -#!/hint/bash - -system=x86_64 -args=( - -no-user-config - -no-reboot # let the systemd supervisor know we're restarting - - -machine accel=kvm - - # RAM: 16 GiB per NUMA node, but leave 1 GiB per node for QEMU itself - -m $((30*1024)) - -object memory-backend-ram,id=ram0,prealloc=on,size=$((15*1024**3)),host-nodes=0,policy=bind - -object memory-backend-ram,id=ram1,prealloc=on,size=$((15*1024**3)),host-nodes=1,policy=bind - # CPU: 1 socket / 8 cores-per-node / 2 threads-per-core = total of 16 CPUs - # Except that it's AMD, and QEMU thinks all threads are Intel HT, so turn off threads - # The distance between the two nodes is '16' - -smp sockets=1,cores=16,threads=1,cpus=16 - -numa node,nodeid=0,memdev=ram0,cpus=0-7 - -numa node,nodeid=1,memdev=ram1,cpus=8-15 - -numa dist,src=0,dst=1,val=16 - - -uuid 4c42bd65-6ad5-456d-8b76-758ecb795e21 - -drive media=disk,file=/dev/vg_build64/lv_beefcake_root,format=raw,if=virtio - -drive media=disk,file=/dev/vg_build64/lv_beefcake_home,format=raw,if=virtio - -drive media=disk,file=/dev/vg_build64/lv_beefcake_data,format=raw,if=virtio - -drive media=disk,file=/dev/vg_build64/lv_beefcake_chroots,format=raw,if=virtio - #-cdrom /mnt/media/Operating_Systems/unix/Linux-based/Arch-based/Parabola/parabola-2017.05.28-dual.iso - -boot menu=on,order=dc - - -writeconfig /tmp/beefcake.cfg -) - -numactl=( - --membind=0,1 - --cpunodebind=0,1 -) -for i in {0..15}; do - vcpu2cpulist[$i]=$i -done diff --git a/conf.d/qemu.d/qemutest b/conf.d/qemu.d/qemutest deleted file mode 100644 index 04d9046..0000000 --- a/conf.d/qemu.d/qemutest +++ /dev/null @@ -1,7 +0,0 @@ -#!/hint/bash - -system=x86_64 -args=( - -machine accel=kvm -m 5G - -drive media=disk,file=/dev/vg_build64/lv_qemutest_root,format=raw,if=virtio -) diff --git a/conf.d/qemu.d/testbox b/conf.d/qemu.d/testbox deleted file mode 100644 index 6e76886..0000000 --- a/conf.d/qemu.d/testbox +++ /dev/null @@ -1,10 +0,0 @@ -#!/hint/bash - -system=x86_64 -args=( - -machine accel=kvm - -m 5G - -cdrom /mnt/media/Operating_Systems/unix/Linux-based/Arch-based/Parabola/parabola-2017.05.28-dual.iso - -boot menu=on,order=dc - -writeconfig /tmp/testbox.cfg -) diff --git a/examples/beefcake b/examples/beefcake new file mode 100644 index 0000000..21b7e74 --- /dev/null +++ b/examples/beefcake @@ -0,0 +1,39 @@ +#!/hint/bash + +system=x86_64 +args=( + -no-user-config + -no-reboot # let the systemd supervisor know we're restarting + + -machine accel=kvm + + # RAM: 16 GiB per NUMA node, but leave 1 GiB per node for QEMU itself + -m $((30*1024)) + -object memory-backend-ram,id=ram0,prealloc=on,size=$((15*1024**3)),host-nodes=0,policy=bind + -object memory-backend-ram,id=ram1,prealloc=on,size=$((15*1024**3)),host-nodes=1,policy=bind + # CPU: 1 socket / 8 cores-per-node / 2 threads-per-core = total of 16 CPUs + # Except that it's AMD, and QEMU thinks all threads are Intel HT, so turn off threads + # The distance between the two nodes is '16' + -smp sockets=1,cores=16,threads=1,cpus=16 + -numa node,nodeid=0,memdev=ram0,cpus=0-7 + -numa node,nodeid=1,memdev=ram1,cpus=8-15 + -numa dist,src=0,dst=1,val=16 + + -uuid 4c42bd65-6ad5-456d-8b76-758ecb795e21 + -drive media=disk,file=/dev/vg_build64/lv_beefcake_root,format=raw,if=virtio + -drive media=disk,file=/dev/vg_build64/lv_beefcake_home,format=raw,if=virtio + -drive media=disk,file=/dev/vg_build64/lv_beefcake_data,format=raw,if=virtio + -drive media=disk,file=/dev/vg_build64/lv_beefcake_chroots,format=raw,if=virtio + #-cdrom /mnt/media/Operating_Systems/unix/Linux-based/Arch-based/Parabola/parabola-2017.05.28-dual.iso + -boot menu=on,order=dc + + -writeconfig /tmp/beefcake.cfg +) + +numactl=( + --membind=0,1 + --cpunodebind=0,1 +) +for i in {0..15}; do + vcpu2cpulist[$i]=$i +done diff --git a/examples/qemutest b/examples/qemutest new file mode 100644 index 0000000..04d9046 --- /dev/null +++ b/examples/qemutest @@ -0,0 +1,7 @@ +#!/hint/bash + +system=x86_64 +args=( + -machine accel=kvm -m 5G + -drive media=disk,file=/dev/vg_build64/lv_qemutest_root,format=raw,if=virtio +) diff --git a/examples/testbox b/examples/testbox new file mode 100644 index 0000000..6e76886 --- /dev/null +++ b/examples/testbox @@ -0,0 +1,10 @@ +#!/hint/bash + +system=x86_64 +args=( + -machine accel=kvm + -m 5G + -cdrom /mnt/media/Operating_Systems/unix/Linux-based/Arch-based/Parabola/parabola-2017.05.28-dual.iso + -boot menu=on,order=dc + -writeconfig /tmp/testbox.cfg +) diff --git a/qemu.in b/qemu.in new file mode 100755 index 0000000..566cacf --- /dev/null +++ b/qemu.in @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +shopt -s lastpipe +set -euE -o pipefail + +declare -A vcpu2cpulist +numactl=() +source "@pkgconfdir@/$1" +args+=( + -name "$1",debug-threads=on + -pidfile "@runstatedir@/qemu-$1/pid" + -vnc unix:"@runstatedir@/qemu-$1/vnc.sock" + -monitor unix:"@runstatedir@/qemu-$1/monitor.sock",server,nowait + -serial file:"/dev/stdout" + -daemonize +) + +{ + numactl "${numactl[@]}" -- qemu-system-"${system}" "${args[@]}" + + if [[ ${vcpu2cpulist+${#vcpu2cpulist[@]}} -gt 0 ]]; then + declare -A vcpu2tid + while read -r line; do + if [[ $line != ?' CPU #'*:*thread_id=* ]]; then + continue + fi + vcpu=${line#?' CPU #'}; vcpu=${vcpu%%:*} + tid=${line#thread_id=}; tid=${tid%% *} + vcpu2tid[$vcpu]=$tid + done < <(socat STDIO UNIX-CONNECT:"@runstatedir@/qemu-$1/monitor.sock" <<<'info cpus') + + for vcpu in "${!vcpu_pins[@]}"; do + taskset --cpu-list --pid -- "${vcpu2cpulist[@]}" "${vcpu2tid[$vcpu]}" + done + fi + + systemd-notify --ready +} | exec cat diff --git a/qemu@.service.in b/qemu@.service.in new file mode 100644 index 0000000..000419e --- /dev/null +++ b/qemu@.service.in @@ -0,0 +1,16 @@ +[Unit] +Description=Virtual Machine %I +Documentation=man:qemu(1) +PartOf=machines.target +Before=machines.target + +[Service] +Type=notify +NotifyAccess=all +RuntimeDirectory=qemu-%I +PIDFile=@runstatedir@/qemu-%I/pid +ExecStart=@BINPROG@ %I +ExecStop=@SOCAT@ SYSTEM:'echo system_powerdown; sleep infinity' UNIX-CONNECT:@runstatedir@/qemu-%I/monitor.sock + +[Install] +WantedBy=machines.target diff --git a/systemd/system/qemu b/systemd/system/qemu deleted file mode 100755 index ad58ae3..0000000 --- a/systemd/system/qemu +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash -shopt -s lastpipe -set -euE -o pipefail - -declare -A vcpu2cpulist -numactl=() -source "/etc/conf.d/qemu.d/$1" -args+=( - -name "$1",debug-threads=on - -pidfile "/run/qemu-$1/pid" - -vnc unix:"/run/qemu-$1/vnc.sock" - -monitor unix:"/run/qemu-$1/monitor.sock",server,nowait - -serial file:"/dev/stdout" - -daemonize -) - -{ - numactl "${numactl[@]}" -- qemu-system-"${system}" "${args[@]}" - - if [[ ${vcpu2cpulist+${#vcpu2cpulist[@]}} -gt 0 ]]; then - declare -A vcpu2tid - while read -r line; do - if [[ $line != ?' CPU #'*:*thread_id=* ]]; then - continue - fi - vcpu=${line#?' CPU #'}; vcpu=${vcpu%%:*} - tid=${line#thread_id=}; tid=${tid%% *} - vcpu2tid[$vcpu]=$tid - done < <(socat STDIO UNIX-CONNECT:"/run/qemu-$1/monitor.sock" <<<'info cpus') - - for vcpu in "${!vcpu_pins[@]}"; do - taskset --cpu-list --pid -- "${vcpu2cpulist[@]}" "${vcpu2tid[$vcpu]}" - done - fi - - systemd-notify --ready -} | exec cat diff --git a/systemd/system/qemu@.service b/systemd/system/qemu@.service deleted file mode 100644 index 95cbefc..0000000 --- a/systemd/system/qemu@.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=Virtual Machine %I -Documentation=man:qemu(1) -PartOf=machines.target -Before=machines.target - -[Service] -Type=notify -NotifyAccess=all -RuntimeDirectory=qemu-%I -PIDFile=/run/qemu-%I/pid -ExecStart=/etc/systemd/system/qemu %I -ExecStop=/bin/socat SYSTEM:'echo system_powerdown; sleep infinity' UNIX-CONNECT:/run/qemu-%I/monitor.sock - -[Install] -WantedBy=machines.target diff --git a/write-ifchanged b/write-ifchanged new file mode 100755 index 0000000..bd702a8 --- /dev/null +++ b/write-ifchanged @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Copyright (C) 2015 Luke Shumaker +# SPDX-License-Identifier: AGPL-3.0-or-later +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +outfile=$1 +tmpfile="$(dirname "$outfile")/.tmp.${outfile##*/}.tmp" + +cat > "$tmpfile" || exit $? +if cmp -s "$tmpfile" "$outfile"; then + rm -f "$tmpfile" || : +else + mv -f "$tmpfile" "$outfile" +fi -- cgit v1.1-4-g5e80