From 33a7588b99fde3e64db66e63697271ff224993f2 Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Wed, 30 Dec 2015 18:02:22 +0100 Subject: [PATCH] saving uncommitted changes in /etc prior to emerge run --- conf.d/libvirt-guests | 68 ++++++++++++ conf.d/libvirtd | 35 +------ init.d/libvirt-guests | 235 ++++++++++++++++++++++++++++++++++++++++++ init.d/libvirtd | 163 ++++++----------------------- 4 files changed, 339 insertions(+), 162 deletions(-) create mode 100644 conf.d/libvirt-guests create mode 100755 init.d/libvirt-guests diff --git a/conf.d/libvirt-guests b/conf.d/libvirt-guests new file mode 100644 index 00000000..ed2ce580 --- /dev/null +++ b/conf.d/libvirt-guests @@ -0,0 +1,68 @@ +# /etc/conf.d/libvirtd + +# LIBVIRT_URIS +# space separated list of libvirt URIs to communicate with to start/stop guests +# Valid values are anything that can be passed to 'virsh connect' + +#LIBVIRT_URIS="qemu:///system" + + +# LIBVIRT_SHUTDOWN +# Valid options: +# * managedsave - Performs a state save external to the VM (for hypervisors +# supporting this operation). qemu-kvm will stop the CPU +# and save off all state to a separate file. When the +# machine is started again, it will resume like nothing +# ever happened. This is guarenteed to always successfully +# stop your machine and restart it. +# +# * shutdown - Sends an ACPI shutdown (think of this as a request to +# your guest to shutdown). There is no way to distinguish +# between guests that are ignoring the shutdown request or +# are stuck or are taking a long time to shutdown. We will +# wait LIBVIRT_MAXWAIT seconds before yanking the power +# out. +# +# * destroy - Immediately stop all running guests. Use with caution as +# this can leave the guest in a corrupted state and might +# lead to data loss. +# + +#LIBVIRT_SHUTDOWN="managedsave" + + +# LIBVIRT_MAXWAIT +# Timeout in seconds until stopping a guest and "pulling the plug" on the +# guest +# Valid values are any integer over 0 + +#LIBVIRT_MAXWAIT="500" + + +# LIBVIRT_START +# If this value is set to 'no', then guests and networks that were shutdown +# by this script when it was stopped will not be started when it is started +# back up. +# Valid values are yes or no + +#LIBVIRT_START="yes" + + +# LIBVIRT_IGNORE_AUTOSTART +# If the VM is marked for autostart in its XML configuration then we won't +# save its start when the init script is stopped. The result is that when +# the init script starts back up, no attempt will be made to start the VM or +# confirm it is started. +# Valid values are yes or no + +#LIBVIRT_IGNORE_AUTOSTART="no" + + +# LIBVIRT_NET_SHUTDOWN +# If libvirtd created networks for you (e.g. NATed networks) then this init +# script will shut them down for you if this is set to 'yes'. Otherwise, +# the networks will be left running. For this option to be useful you must +# have enabled the 'virt-network' USE flag and have had libvirt create a +# NATed network for you. Valid values: 'yes' or 'no' + +#LIBVIRT_NET_SHUTDOWN="yes" diff --git a/conf.d/libvirtd b/conf.d/libvirtd index 48ab1252..c326531d 100644 --- a/conf.d/libvirtd +++ b/conf.d/libvirtd @@ -6,38 +6,13 @@ # for libvirtd, you may override this. Or if you only use libvirtd locally. rc_need="net" +# The termination timeout (start-stop-daemon parameter "retry") ensures +# that the service will be terminated within a given time (25 + 5 seconds +# per default) when you are stopping the service. +#LIBVIRTD_TERMTIMEOUT="TERM/25/KILL/5" + # LIBVIRTD_OPTS # You may want to add '--listen' to have libvirtd listen for tcp/ip connections # if you want to use libvirt for remote control # Please consult 'libvirtd --help' for more options #LIBVIRTD_OPTS="--listen" - -# LIBVIRTD_KVM_SHUTDOWN -# Valid options: -# * shutdown - Sends an ACPI shutdown (think when you tap the power button -# on your machine and it begins a graceful shutdown). If your -# VM ignores this, it will have the power yanked out from under -# it in LIBVIRTD_KVM_SHUTDOWN_MAXWAIT seconds. -# * managedsave - Performs a state save external to the VM. qemu-kvm will stop -# stop the CPU and save off all state to a separate file. When -# the machine is started again, it will resume like nothing ever -# happened. This is guarenteed to always successfully stop your -# machine and restart it. However it may take some time to finish. -# * none - No attempts will be made to stop any VMs. If you are restarting your -# machine the qemu-kvm process will be simply killed, which may result -# in your VMs having disk corruption. -LIBVIRTD_KVM_SHUTDOWN="managedsave" - -# LIBVIRTD_KVM_SHUTDOWN_MAXWAIT -# Timeout in seconds until stopping libvirtd and "pulling the plug" on the -# remaining VM's still in a running state -#LIBVIRTD_KVM_SHUTDOWN_MAXWAIT="500" - -# LIBVIRTD_KVM_NET_SHUTDOWN -# If libvirtd created networks for you (e.g. NATed networks) then this init -# script will shut them down for you if this is set to 'yes'. Otherwise, -# the networks will be left running once libvirt is shutdown. For this -# option to be useful you must have enabled the 'virt-network' USE flag and -# have had libvirt create a NATed network for you. -# Valid values: 'yes' or 'no' -#LIBVIRTD_KVM_NET_SHUTDOWN="yes" diff --git a/init.d/libvirt-guests b/init.d/libvirt-guests new file mode 100755 index 00000000..a8d65f89 --- /dev/null +++ b/init.d/libvirt-guests @@ -0,0 +1,235 @@ +#!/sbin/runscript + +description="Virtual Machine Management (libvirt) Guests" + +depend() { + need libvirtd +} + +# set the default to QEMU +[ -z "${LIBVIRT_URIS}" ] && LIBVIRT_URIS="qemu:///system" + +# default to suspending the VM via managedsave +case "${LIBVIRT_SHUTDOWN}" in + managedsave|shutdown|destroy) ;; + *) LIBVIRT_SHUTDOWN="managedsave" ;; +esac + +# default to 500 seconds +[ -z ${LIBVIRT_MAXWAIT} ] && LIBVIRT_MAXWAIT=500 + +gueststatefile="/var/lib/libvirt/libvirt-guests.state" +netstatefile="/var/lib/libvirt/libvirt-net.state" + +do_virsh() { + local hvuri=$1 + shift + + # if unset, default to qemu + [ -z ${hvuri} ] && hvuri="qemu:///system" + # if only qemu was supplied then correct the value + [ "xqemu" = x${hvuri} ] && hvuri="qemu:///system" + + # Silence errors because virsh always throws an error about + # not finding the hypervisor version when connecting to libvirtd + # lastly strip the blank line at the end + LC_ALL=C virsh -c ${hvuri} "$@" 2>/dev/null | head -n -1 +} + +libvirtd_dom_list() { + # Only work with domains by their UUIDs + local hvuri=$1 + shift + + do_virsh "${hvuri}" list --uuid $@ +} + +libvirtd_dom_count() { + local hvuri=$1 + shift + + libvirtd_dom_list "${hvuri}" $@ | wc -l +} + +libvirtd_net_list() { + # Only work with networks by their UUIDs + local hvuri=$1 + shift + + do_virsh "${hvuri}" net-list --uuid $@ +} + +libvirtd_net_count() { + local hvuri=$1 + shift + + libvirtd_net_list "${hvuri}" $@ | wc -l +} + +libvirtd_dom_stop() { + # stops all persistent or transient domains for a given URI + # $1 - uri + # $2 - persisent/transient + + local uri=$1 + local persist=$2 + local shutdown_type=${LIBVIRT_SHUTDOWN} + local counter=${LIBVIRT_MAXWAIT} + local dom_name= + local dom_as= + local dom_ids= + local uuid= + local dom_count= + + [ "${persist}" = "--transient" ] && shutdown_type="shutdown" + [ -n "${counter}" ] || counter=500 + + einfo " Shutting down domain(s) ..." + + # grab all persistent or transient domains running + dom_ids=$(libvirtd_dom_list ${uri} ${persist}) + + for uuid in ${dom_ids}; do + # Get the name + dom_name=$(do_virsh ${uri} domname ${uuid}) + einfo " ${dom_name}" + # Get autostart state + dom_as=$(do_virsh ${uri} dominfo ${uuid} | \ + awk '$1 == "Autostart:" { print $2 }') + + if [ "${persist}" = "--persistent" ]; then + # Save our running state only if LIBVIRT_IGNORE_AUTOSTART != yes + if [ "x${LIBVIRT_IGNORE_AUTOSTART}" = "xyes" ] && \ + [ ${dom_as} = "enabled" ]; then + : + else + echo "${uri} ${uuid}" >> ${gueststatefile} + fi + + fi + + # Now let's stop it + do_virsh "${uri}" ${shutdown_type} ${uuid} > /dev/null + + done + + dom_count="$(libvirtd_dom_count ${uri} ${persist})" + while [ ${dom_count} -gt 0 ] && [ ${counter} -gt 0 ] ; do + dom_count="$(libvirtd_dom_count ${uri} ${persist})" + sleep 1 + if [ "${shutdown_type}" = "shutdown" ]; then + counter=$((${counter} - 1)) + fi + echo -n "." + done + + if [ "${shutdown_type}" = "shutdown" ]; then + # grab all domains still running + dom_ids=$(libvirtd_dom_list ${uri} ${persist}) + for uuid in ${dom_ids}; do + dom_name=$(do_virsh ${uri} domname ${uuid}) + eerror " ${dom_name} forcibly stopped" + do_virsh "${uri}" destroy ${uuid} > /dev/null + done + fi +} + +libvirtd_net_stop() { + # stops all persistent or transient domains for a given URI + # $1 - uri + # $2 - persisent/transient + + local uri=$1 + local persist=$2 + local uuid= + local net_name= + + if [ "${LIBVIRT_NET_SHUTDOWN}" != "no" ]; then + + einfo " Shutting down network(s):" + for uuid in $(libvirtd_net_list ${uri} ${persist}); do + net_name=$(do_virsh ${uri} net-name ${uuid}) + einfo " ${net_name}" + + if [ "${persist}" = "--persistent" ]; then + # Save our running state + echo "${uri} ${uuid}" >> ${netstatefile} + + fi + + # Actually stop the network + do_virsh qemu net-destroy ${uuid} > /dev/null + done + + fi +} + +start() { + local uri= + local uuid= + local name= + + for uri in ${LIBVIRT_URIS}; do + do_virsh "${uri}" connect + if [ $? -ne 0 ]; then + eerror "Failed to connect to '${uri}'. Domains may not start." + fi + done + + [ ! -e "${netstatefile}" ] && touch "${netstatefile}" + [ ! -e "${gueststatefile}" ] && touch "${gueststatefile}" + + # if the user didn't want to start any guests up then respect their wish + [ "x${LIBVIRT_START}" = "xno" ] && return 0 + + # start networks + ebegin "Starting libvirt networks" + while read -r uri uuid + do + # ignore trash + [ -z "${uri}" ] || [ -z "${uuid}" ] && continue + + name=$(do_virsh "${uri}" net-name ${uuid}) + einfo " ${name}" + do_virsh "${uri}" net-start ${uuid} > /dev/null + done <"${netstatefile}" + eend 0 + + # start domains + ebegin "Starting libvirt domains" + while read -r uri uuid + do + # ignore trash + [ -z "${uri}" ] || [ -z "${uuid}" ] && continue + + name=$(do_virsh "${uri}" domname ${uuid}) + einfo " ${name}" + do_virsh "${uri}" start ${uuid} > /dev/null + done <"${gueststatefile}" + eend 0 +} + +stop() { + local counter= + local dom_name= + local net_name= + local dom_ids= + local uuid= + local dom_count= + + rm -f "${gueststatefile}" + [ $? -ne 0 ] && eerror "Unable to save domain state" + rm -f "${netstatefile}" + [ $? -ne 0 ] && eerror "Unable to save net state" + + for uri in ${LIBVIRT_URIS}; do + einfo "Stopping libvirt domains and networks for ${uri}" + + libvirtd_dom_stop "${uri}" "--persistent" + libvirtd_dom_stop "${uri}" "--transient" + libvirtd_net_stop "${uri}" "--persistent" + libvirtd_net_stop "${uri}" "--transient" + + einfo "Done stopping domains and networks for ${uri}" + done +} diff --git a/init.d/libvirtd b/init.d/libvirtd index 99e82585..97184e36 100755 --- a/init.d/libvirtd +++ b/init.d/libvirtd @@ -1,139 +1,38 @@ #!/sbin/runscript +# Copyright 1999-2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ description="Virtual Machine Management daemon (libvirt)" -extra_started_commands="reload halt" -description_halt="Stops the libvirt daemon without stopping your VMs" -description_reload="Restarts the libvirt daemon without stopping your VMs" - -depend() { - - use avahi-daemon dbus virtlockd - after ntp-client ntpd nfs nfsmount portmap rpc.statd iptables ip6tables ebtables corosync sanlock cgconfig xenconsoled -} - -libvirtd_virsh() { - local mode=$1 - shift - - # Silence errors because virsh always throws an error about - # not finding the hypervisor version when connecting to libvirtd - LC_ALL=C virsh -c ${mode}:///system "$@" 2>/dev/null -} - -libvirtd_dom_list() { - # Make sure that it wouldn't be confused if the domain name - # contains the word running. - libvirtd_virsh $1 list | awk '$3 == "running" { print $1 }' -} - -libvirtd_dom_count() { - # Make sure that it wouldn't be confused if the domain name - # contains the word running. - libvirtd_virsh $1 list | awk 'BEGIN { count = 0 } \ - $3 == "running" { count++ } \ - END { print count }' -} - -libvirtd_net_list() { - # The purpose of the awk is to avoid networks with 'active' in the name - libvirtd_virsh $1 net-list | awk '$2 == "active" { print $1 }' -} - -libvirtd_net_count() { - # The purpose of the awk is to avoid networks with 'active' in the name - libvirtd_virsh $1 net-list | awk 'BEGIN { count = 0 } \ - $2 == "active" { count++ } \ - END { print count }' -} +LIBVIRTD_OPTS=${LIBVIRTD_OPTS:-"${LIBVIRTD_OPTS}"} +LIBVIRTD_TIMEOUT=${LIBVIRTD_TERMTIMEOUT:-"TERM/25/KILL/5"} -start() { - # Test configuration directories in /etc/libvirt/ to be either not - # present or a directory, i.e. not a regular file, bug #532892 - for dir in lxc nwfilter qemu storage; do - if [ -f /etc/libvirt/$dir ]; then - eerror "/etc/libvirt/$dir was created as a regular file. It must be either" - eerror "a directory or not present for libvirtd to start up successfully." - return 1 - fi - done - - ebegin "Starting libvirtd" - start-stop-daemon --start \ - --env KRB5_KTNAME=/etc/libvirt/krb5.tab \ - --exec /usr/sbin/libvirtd -- -d ${LIBVIRTD_OPTS} - eend $? -} +command="/usr/sbin/libvirtd" +command_args="-d ${LIBVIRTD_OPTS}" +start_stop_daemon_args="--env KRB5_KTNAME=/etc/libvirt/krb5.tab" +pidfile="/var/run/libvirtd.pid" +retry="${LIBVIRTD_TERMTIMEOUT}" -stop() { - local counter= - local vm_name= - local net_name= - local dom_id= - - ebegin "Stopping libvirtd" - # try to shutdown all (KVM/Qemu) domains - if [ "${LIBVIRTD_KVM_SHUTDOWN}" != "none" ] \ - && [ "$(libvirtd_dom_count qemu)" != "0" ] ; then - - einfo " Shutting down domain(s):" - for dom_id in $(libvirtd_dom_list qemu) ; do - vm_name="$(libvirtd_virsh qemu domname ${dom_id} | head -n 1)" - einfo " ${vm_name}" - libvirtd_virsh qemu ${LIBVIRTD_KVM_SHUTDOWN} ${dom_id} > /dev/null - done - - if [ -n "${LIBVIRTD_KVM_SHUTDOWN_MAXWAIT}" ] ; then - counter="${LIBVIRTD_KVM_SHUTDOWN_MAXWAIT}" - else - counter=500 - fi - - if [ "${LIBVIRTD_KVM_SHUTDOWN}" = "shutdown" ]; then - einfo " Waiting ${counter} seconds while domains shutdown ..." - DOM_COUNT="$(libvirtd_dom_count qemu)" - while [ ${DOM_COUNT} -gt 0 ] && [ ${counter} -gt 0 ] ; do - DOM_COUNT="$(libvirtd_dom_count qemu)" - sleep 1 - counter=$((${counter} - 1)) - echo -n "." - done - fi - - if [ "$(libvirtd_dom_count qemu)" != "0" ] ; then - eerror " !!! Some guests are still running, stopping anyway" - fi - - fi - - if [ "${LIBVIRTD_KVM_NET_SHUTDOWN}" != "no" ] \ - && [ "$(libvirtd_net_count qemu)" != "0" ]; then - - einfo " Shutting down network(s):" - for net_name in $(libvirtd_net_list qemu); do - einfo " ${net_name}" - libvirtd_virsh qemu net-destroy ${net_name} > /dev/null - done - - if [ "$(libvirtd_net_count qemu)" != "0" ]; then - eerror " !!! Some networks are still active, stopping anyway" - fi - fi - - # Now actually stop the daemon - start-stop-daemon --stop --quiet --exec \ - /usr/sbin/libvirtd --pidfile=/var/run/libvirtd.pid - eend $? -} - -halt() { - ebegin "Stopping libvirtd without shutting down your VMs" - start-stop-daemon --stop --quiet --exec \ - /usr/sbin/libvirtd --pidfile=/var/run/libvirtd.pid - eend $? -} - -reload() { - halt - start +depend() { + + use avahi-daemon dbus virtlockd + after ntp-client ntpd nfs nfsmount portmap rpc.statd iptables ip6tables ebtables corosync sanlock cgconfig xenconsoled +} + +start_pre() { + # Test configuration directories in /etc/libvirt/ to be either not + # present or a directory, i.e. not a regular file, bug #532892 + local has_errors=0 + ebegin "Checking for suitable directories in \"/etc/libvirt\"" + + for dir in lxc nwfilter qemu storage; do + if [ -f /etc/libvirt/$dir ]; then + has_errors=1 + eerror "/etc/libvirt/$dir was created as a regular file. It must be either" + eerror "a directory or not present for libvirtd to start up successfully." + fi + done + + eend ${has_errors} "Please correct the error(s) above" } -- 2.39.5