This project has been moved to https://github.com/jirutka/qemu-openrc.
Last active
May 22, 2016 13:12
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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" | |
# |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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}" | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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