Skip to content

Instantly share code, notes, and snippets.

@jirutka
Last active May 22, 2016 13:12
Show Gist options
  • Save jirutka/c2cc5dc9729443a2ff45 to your computer and use it in GitHub Desktop.
Save jirutka/c2cc5dc9729443a2ff45 to your computer and use it in GitHub Desktop.
OpenRC runscript for QEMU/KVM / Moved to https://github.com/jirutka/qemu-openrc
# Copyright 1999-2016 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# vim: set ft=sh:
###############################################################################
# YOU SHOULD NOT MODIFY THIS FILE! #
# #
# Create a copy named after the virtual machine you want to run #
# (with prefix "qemu.") and modify that instead (and remove this notice). #
###############################################################################
##
# This is example configuration for qemu-kvm runscript. It contain all
# user-definable variables with their default values. If the default value is
# suitable for you, then you can omit that variable in your VM config.
#
# Name of this VM. This is always derived from the runscript name
# (e.g. qemu.foo -> foo)!
#vm_name="${RC_SVCNAME#qemu.}"
# User to run the QEMU process.
#user="qemu"
# Group to run the QEMU process.
#group="qemu"
# Where to store the QEMU process PID.
#pidfile="/run/qemu/${vm_name}/qemu.pid"
# Where to redirect stdout/stderr of the QEMU process.
#logfile="/var/log/qemu/${vm_name}.log"
# How many seconds to wait after sending "system_shutdown" before force
# stopping the VM.
#shutdown_timeout=60
# How many CPU cores to allocate for the VM on startup.
#cpus="1"
# Maximum number of hotpluggable CPU cores, i.e. how many CPUs may be allocated
# for the VM after startup from the monitor console.
#cpus_max="$cpus"
# Amount of RAM to allocate for the VM on startup. Use suffix "M" or "G" for
# megabytes or gigabytes respectively.
#memory="1G"
# Maximum amount of RAM the VM can reach, i.e. how much memory may be allocated
# for the VM after startup from the monitor console. Use suffix "M" or "G" for
# megabytes or gigabytes respectively.
#memory_max="$memory"
# Number of memory slots for additional hotpluggable memory. If it's 0, then
# memory hotplug won't be enabled and the VM startup RAM will never increase.
# If $memory == $memory_max, then this is forced to 0.
#memory_slots=2
# Whether to use hugetlbfs mounted on $hugepages_path for the VM RAM.
#memory_hugepages="no"
# Mount point of the hugetlbfs.
#hugepages_path="/dev/hugepages"
# Start the RTC at the current UTC, or local time? Use "utc", or "localtime".
# Note: "localtime" is required for correct date in Windows.
#rtc_base="utc"
# Select type of VGA card to emulate. Valid values for type are: cirrus, std,
# vmware, qxl, tcx, cg3, and none. See option -vga in man qemu for more
# information.
#vga="std"
# Address to listen for VNC (TCP) connections.
#vnc_listen="0.0.0.0"
# VNC display number. If empty, then VNC will be disabled.
# Note: By convention the TCP port is 5900+$vnc_display.
#vnc_display=
# Password required for client connections on VNC. If empty, then password
# base authentication is disabled.
#vnc_password=
# Path of the QEMU monitor socket for this VM.
#monitor_socket="/run/qemu/${vm_name}/monitor.sock"
# See description below.
net0="bridge"
##
# Network interfaces
#
# You can specify up to 10 NICs using variables netX and netX_OPTION. For list
# of available options open man qemu and find -netdev.
#
# MAC address of the NIC is automatically generated from the VM name and
# sequence number of the NIC, so it's always the same for particular VM and NIC
# and it should be unique as well. You can override the MAC address with
# variable netX_mac.
#
# These NICs will use driver virtio-net-pci (requires virtio-net driver to be
# installed in the VM).
#
# Example:
# net0="bridge"
# net0_mac="52:54:12:34:56:78"
#
##
# Hard-drives
#
# You can specify up to 10 drives using variables diskX_OPTION. For list of
# available options open man qemu and find -drive.
#
# These drives will use driver scsi-disk connected to virtio-scsi-pci (requires
# virtio-scsi drivers to be installed in the VM).
#
# Example:
# disk0_file="/dev/mapper/${vm_name}-disk0"
# disk0_format="raw"
# disk0_cache="none"
#
# disk1_file="/var/lib/qemu/${vm_name}/disk0.qcow2"
# disk1_format="qcow2"
#
##
# CD-ROMs
#
# You can specify up to 10 cdrom drives using variables cdromX_file.
#
# These drives will use driver ide-cd connected to an emulated IDE controller
# (no virtio). This is slow, but doesn't require any special drivers in the VM.
#
# Example:
# cdrom0_file="/var/lib/qemu/virtio-win.iso"
#
#!/sbin/openrc-run
# Copyright 1999-2016 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
vm_name="${RC_SVCNAME#qemu.}"
: ${user:="qemu"}
: ${group:="qemu"}
: ${pidfile="/run/qemu/${vm_name}/qemu.pid"}
: ${logfile:="/var/log/qemu/${vm_name}.log"}
: ${shutdown_timeout:="60"}
: ${cpus:="1"}
: ${cpus_max:="$cpus"}
: ${memory:="1G"}
: ${memory_max:="$memory"}
: ${memory_slots:="2"}
: ${memory_hugepages:="no"}
: ${rtc_base:="utc"}
: ${vga:="std"}
: ${vnc_listen:="0.0.0.0"}
: ${hugepages_path:="/dev/hugepages"}
: ${monitor_socket:="/run/qemu/${vm_name}/monitor.sock"}
name="VM $vm_name"
describe="Qemu/KVM virtual machine \"$vm_name\""
describe_forcestop='Force stop the system'
describe_reset='Reset the system'
extra_commands='forcestop'
extra_started_commands='reset'
command='/usr/bin/qemu-system-x86_64'
command_args="
-name $vm_name,process=$vm_name
-nodefaults
-no-user-config
-cpu host
-enable-kvm
-realtime mlock=off
-rtc base=$rtc_base
-smp cpus=$cpus,maxcpus=$cpus_max
-balloon virtio
-vga $vga
-device virtio-rng-pci
-device virtio-scsi-pci,id=scsi
-monitor unix:$monitor_socket,server,nowait"
command_background='yes'
start_stop_daemon_args="
--user=$user
--wait=100
--stdout=$logfile
--stderr=$logfile"
depend() {
need net
}
start_pre() {
if [ "$RC_SVCNAME" = 'qemu-kvm' ]; then
eerror ''
eerror 'You are not supposed to run this runscript directly. Instead, you should'
eerror 'create a symlink for the VM you want to run as well as a copy of the'
eerror 'configuration file and modify it appropriately, like so:'
eerror ''
eerror ' ln -s qemu-kvm /etc/init.d/qemu.example'
eerror ' cp /etc/conf.d/qemu-kvm /etc/conf.d/qemu.example'
return 1
fi
if [ "$memory" = "$memory_max" ]; then
memory_slots="0"
fi
command_args_push "-m size=$memory,slots=$memory_slots,maxmem=$memory_max"
if yesno "$memory_hugepages"; then
command_args_push "-mem-path $hugepages_path"
fi
if [ -n "$vnc_display" ]; then
command_args_push "-display vnc=${vnc_listen}:${vnc_display}${vnc_password:+",password"}"
fi
command_args_push "$(net_args) $(disk_args) $(cdrom_args)"
if yesno "$EINFO_VERBOSE"; then
einfo "Command: $command $(echo $command_args)"
fi
local path; for path in "$pidfile" "$monitor_socket" "$logfile"; do
# checkpath doesn't create intermediate directories
mkdir -p "$(dirname "$path")"
checkpath -d -m 0750 -o $user:$group "$(dirname "$path")"
done
return 0
}
start_post() {
ewaitfile 5 "$monitor_socket" || {
eerror 'Monitor socket has not been created!'; return 0
}
if [ -n "$vnc_password" ]; then
virsh "set_password vnc $vnc_password" || eerror 'Failed to set VNC password!'
fi
}
stop() {
local count="$shutdown_timeout"
ebegin "Stopping $name"
virsh 'system_powerdown' || count=0
while ! $(status 1>/dev/null 2>&1) && [ $count -gt 0 ]; do
sleep 1
printf '.'
count=$(( count - 1 ))
done
echo ''
if [ $count -eq 0 ]; then
ewarn 'Failed to shutdown VM gracefully, stopping it with force'
start-stop-daemon --stop \
--quiet --retry 'SIGKILL/5' \
--pidfile "$pidfile" --exec "$command"
eend $?
else
eend 0
fi
}
stop_post() {
[ -S "$monitor_socket" ] && rm -f "$monitor_socket"
[ -f "$pidfile" ] && rm -f "$pidfile"
return 0
}
forcestop() {
ebegin "Force stopping $name"
start-stop-daemon --stop \
--quiet --retry 'SIGKILL/3' \
--pidfile "$pidfile" --exec "$command"
local _status="$?"
if [ $_status -eq 0 ]; then
if service_started "${RC_SVCNAME}"; then
mark_service_stopped "${RC_SVCNAME}"
fi
stop_post
fi
eend $_status
}
reset() {
ebegin "Reseting $name"
virsh 'system_reset'
eend $?
}
#-------------------------------- Helpers -------------------------------
command_args_push() {
command_args="$command_args $@"
}
disk_args() {
local idx opts
for idx in $(seq 0 9); do
# comma-separated key=value pairs; contains trailing comma if not empty
opts=$(set | sed -En "s/^disk${idx}_(.*)/\1/p" | tr $'\n' ',')
if [ -n "$opts" ]; then
echo "-drive id=hd${idx},${opts}media=disk,if=none"
echo "-device scsi-hd,drive=hd${idx},scsi-id=${idx}"
fi
done
}
cdrom_args() {
local idx file
for idx in $(seq 0 9); do
file=$(getval "cdrom${idx}_file")
if [ -n "$file" ]; then
echo "-drive id=cdr${idx},media=cdrom,if=none,file='$file',readonly,cache=none"
echo "-device ide-cd,drive=cdr${idx}"
fi
done
}
net_args() {
local idx netid netdev opts mac
for idx in $(seq 0 9); do
netid="net${idx}"
netdev=$(getval "$netid")
if [ -n "$netdev" ]; then
# comma-separated key=value pairs; contains trailing comma if not empty
opts=$(set | sed -En "s/^net${idx}_(.*)/\1/p" | grep -v '^mac=.*$')
echo "-netdev ${netdev},${opts}id=hostnet${idx}"
mac=$(getval ${netid}_mac "$(gen_macaddr ${vm_name}%${idx})")
echo "-device virtio-net-pci,id=${netid},netdev=hostnet${idx},mac=${mac}"
fi
done
}
virsh() {
local IFS=$'\n'
echo -e "$*" | socat - "UNIX-CONNECT:${monitor_socket}" 1>/dev/null
}
gen_macaddr() {
printf "$1" | md5sum | sed -E 's/^(..)(..)(..)(..).*$/52:54:\1:\2:\3:\4/'
}
getval() {
local var_name="$1"
local default="${2:-}"
eval "echo \${$var_name:-$default}"
}
#!/bin/sh
# vim: set ts=4:
if [ -z "$1" ]; then
echo "Usage: virsh <VM-NAME | SOCKET-PATH> [command ...]" 1>&2
exit 1
fi
case "$1" in
/*) socket_path="$1" ;;
*) socket_path="/run/qemu/$1/monitor.sock" ;;
esac
if [ ! -S "$socket_path" ]; then
echo "Error: QEMU monitor socket $socket_path does not exist!" 1>&2
exit 2
fi
if [ -n "$2" ]; then
IFS=$'\n'
shift
echo -e "$*" | socat - "UNIX-CONNECT:${socket_path}"
else
echo 'Connecting to QEMU monitor in interactive mode. Use Ctrl+O to exit.'
echo 'Note: command "quit" does not exit the monitor, but stops VM!'
echo ''
socat -,raw,echo=0,escape=0x0f "UNIX-CONNECT:${socket_path}"
fi
echo ''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment