libvirt-guests.initd 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #!/usr/bin/openrc-run
  2. description="Virtual Machine Management (libvirt) Guests"
  3. depend() {
  4. use libvirtd
  5. }
  6. # set the default to QEMU
  7. [ -z "${LIBVIRT_URIS}" ] && LIBVIRT_URIS="qemu:///system"
  8. # default to suspending the VM via managedsave
  9. case "${LIBVIRT_SHUTDOWN}" in
  10. managedsave|shutdown|destroy) ;;
  11. *) LIBVIRT_SHUTDOWN="managedsave" ;;
  12. esac
  13. # default to 500 seconds
  14. [ -z ${LIBVIRT_MAXWAIT} ] && LIBVIRT_MAXWAIT=500
  15. gueststatefile="/var/lib/libvirt/libvirt-guests.state"
  16. netstatefile="/var/lib/libvirt/libvirt-net.state"
  17. do_virsh() {
  18. local hvuri=$1
  19. shift
  20. # if unset, default to qemu
  21. [ -z ${hvuri} ] && hvuri="qemu:///system"
  22. # if only qemu was supplied then correct the value
  23. [ "xqemu" = x${hvuri} ] && hvuri="qemu:///system"
  24. # Silence errors because virsh always throws an error about
  25. # not finding the hypervisor version when connecting to libvirtd
  26. # lastly strip the blank line at the end
  27. LC_ALL=C virsh -c ${hvuri} "$@" 2>/dev/null | head -n -1
  28. }
  29. libvirtd_dom_list() {
  30. # Only work with domains by their UUIDs
  31. local hvuri=$1
  32. shift
  33. # The grep is to remove dom0 for xen domains. Otherwise we never hit 0
  34. do_virsh "${hvuri}" list --uuid $@ | grep -v 00000000-0000-0000-0000-000000000000
  35. }
  36. libvirtd_dom_count() {
  37. local hvuri=$1
  38. shift
  39. libvirtd_dom_list "${hvuri}" $@ | wc -l
  40. }
  41. libvirtd_net_list() {
  42. # Only work with networks by their UUIDs
  43. local hvuri=$1
  44. shift
  45. do_virsh "${hvuri}" net-list --uuid $@
  46. }
  47. libvirtd_net_count() {
  48. local hvuri=$1
  49. shift
  50. libvirtd_net_list "${hvuri}" $@ | wc -l
  51. }
  52. libvirtd_dom_stop() {
  53. # stops all persistent or transient domains for a given URI
  54. # $1 - uri
  55. # $2 - persisent/transient
  56. local uri=$1
  57. local persist=$2
  58. local shutdown_type=${LIBVIRT_SHUTDOWN}
  59. local counter=${LIBVIRT_MAXWAIT}
  60. local dom_name=
  61. local dom_as=
  62. local dom_ids=
  63. local uuid=
  64. local dom_count=
  65. [ "${persist}" = "--transient" ] && shutdown_type="shutdown"
  66. [ -n "${counter}" ] || counter=500
  67. einfo " Shutting down domain(s) ..."
  68. # grab all persistent or transient domains running
  69. dom_ids=$(libvirtd_dom_list ${uri} ${persist})
  70. for uuid in ${dom_ids}; do
  71. # Get the name
  72. dom_name=$(do_virsh ${uri} domname ${uuid})
  73. einfo " ${dom_name}"
  74. # Get autostart state
  75. dom_as=$(do_virsh ${uri} dominfo ${uuid} | \
  76. awk '$1 == "Autostart:" { print $2 }')
  77. if [ "${persist}" = "--persistent" ]; then
  78. # Save our running state only if LIBVIRT_IGNORE_AUTOSTART != yes
  79. if [ "x${LIBVIRT_IGNORE_AUTOSTART}" = "xyes" ] && \
  80. [ ${dom_as} = "enabled" ]; then
  81. :
  82. else
  83. echo "${uri} ${uuid}" >> ${gueststatefile}
  84. fi
  85. fi
  86. # Now let's stop it
  87. do_virsh "${uri}" ${shutdown_type} ${uuid} > /dev/null
  88. done
  89. dom_count="$(libvirtd_dom_count ${uri} ${persist})"
  90. while [ ${dom_count} -gt 0 ] && [ ${counter} -gt 0 ] ; do
  91. dom_count="$(libvirtd_dom_count ${uri} ${persist})"
  92. sleep 1
  93. if [ "${shutdown_type}" = "shutdown" ]; then
  94. counter=$((${counter} - 1))
  95. fi
  96. printf "."
  97. done
  98. if [ "${shutdown_type}" = "shutdown" ]; then
  99. # grab all domains still running
  100. dom_ids=$(libvirtd_dom_list ${uri} ${persist})
  101. for uuid in ${dom_ids}; do
  102. dom_name=$(do_virsh ${uri} domname ${uuid})
  103. eerror " ${dom_name} forcibly stopped"
  104. do_virsh "${uri}" destroy ${uuid} > /dev/null
  105. done
  106. fi
  107. }
  108. libvirtd_net_stop() {
  109. # stops all persistent or transient domains for a given URI
  110. # $1 - uri
  111. # $2 - persisent/transient
  112. local uri=$1
  113. local persist=$2
  114. local uuid=
  115. local net_name=
  116. if [ "${LIBVIRT_NET_SHUTDOWN}" != "no" ]; then
  117. einfo " Shutting down network(s):"
  118. for uuid in $(libvirtd_net_list ${uri} ${persist}); do
  119. net_name=$(do_virsh ${uri} net-name ${uuid})
  120. einfo " ${net_name}"
  121. if [ "${persist}" = "--persistent" ]; then
  122. # Save our running state
  123. echo "${uri} ${uuid}" >> ${netstatefile}
  124. fi
  125. # Actually stop the network
  126. do_virsh qemu net-destroy ${uuid} > /dev/null
  127. done
  128. fi
  129. }
  130. start() {
  131. local uri=
  132. local uuid=
  133. local name=
  134. for uri in ${LIBVIRT_URIS}; do
  135. do_virsh "${uri}" connect
  136. if [ $? -ne 0 ]; then
  137. eerror "Failed to connect to '${uri}'. Domains may not start."
  138. fi
  139. done
  140. [ ! -e "${netstatefile}" ] && touch "${netstatefile}"
  141. [ ! -e "${gueststatefile}" ] && touch "${gueststatefile}"
  142. # if the user didn't want to start any guests up then respect their wish
  143. [ "x${LIBVIRT_START}" = "xno" ] && return 0
  144. # start networks
  145. ebegin "Starting libvirt networks"
  146. while read -r uri uuid
  147. do
  148. # ignore trash
  149. [ -z "${uri}" ] || [ -z "${uuid}" ] && continue
  150. name=$(do_virsh "${uri}" net-name ${uuid})
  151. einfo " ${name}"
  152. do_virsh "${uri}" net-start ${uuid} > /dev/null
  153. done <"${netstatefile}"
  154. eend 0
  155. # start domains
  156. ebegin "Starting libvirt domains"
  157. while read -r uri uuid
  158. do
  159. # ignore trash
  160. [ -z "${uri}" ] || [ -z "${uuid}" ] && continue
  161. name=$(do_virsh "${uri}" domname ${uuid})
  162. einfo " ${name}"
  163. do_virsh "${uri}" start ${uuid} > /dev/null
  164. do_virsh "${uri}" domtime --sync ${uuid} > /dev/null
  165. done <"${gueststatefile}"
  166. eend 0
  167. }
  168. stop() {
  169. local counter=
  170. local dom_name=
  171. local net_name=
  172. local dom_ids=
  173. local uuid=
  174. local dom_count=
  175. rm -f "${gueststatefile}"
  176. [ $? -ne 0 ] && eerror "Unable to save domain state"
  177. rm -f "${netstatefile}"
  178. [ $? -ne 0 ] && eerror "Unable to save net state"
  179. for uri in ${LIBVIRT_URIS}; do
  180. einfo "Stopping libvirt domains and networks for ${uri}"
  181. libvirtd_dom_stop "${uri}" "--persistent"
  182. libvirtd_dom_stop "${uri}" "--transient"
  183. libvirtd_net_stop "${uri}" "--persistent"
  184. libvirtd_net_stop "${uri}" "--transient"
  185. einfo "Done stopping domains and networks for ${uri}"
  186. done
  187. }