| #!/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 line |
| do |
| # tokenize the data |
| read -r uri uuid <<<"${line}" |
| # 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 line |
| do |
| # tokenize the data |
| read -r uri uuid <<<"${line}" |
| # 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 |
| } |