Highly Available and Scalable Information System
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

eurybox.functions.vm 9.7 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #!/bin/bash
  2. #EuryBOX vm functions file
  3. #Desc: rename a VM through libvirt
  4. #1 arg required: vm_name
  5. eurybox_vm_rename ()
  6. {
  7. local NAME=$1
  8. local STATUS
  9. local DISKS
  10. local DISKS_NUM
  11. local NOW=$(date +"%Y_%m_%d@%H_%M_%S")
  12. local TMP_DESC="${EURYBOX_TMP_FOLDER}/${NAME}_${NOW}"
  13. local RENAME_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS list --all | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1`
  14. STATUS=$?
  15. if [[ $STATUS -eq 0 ]]
  16. then
  17. if [[ $RENAME_OUT == "" ]]
  18. then
  19. eurybox_display_message warning VM "Rename not possible on non-present vm: $NAME"
  20. else
  21. RENAME_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS list | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1`
  22. if [[ !($RENAME_OUT == "") ]]
  23. then
  24. eurybox_display_message warning VM "Forcing stop of running vm: $NAME"
  25. RENAME_OUT=`sudo sh -c "virsh $EURYBOX_VIRSH_OPTIONS destroy $NAME" 2>&1`
  26. fi
  27. eurybox_export_vm_config $NAME $TMP_DESC
  28. DISKS=( $(sudo virsh $EURYBOX_VIRSH_OPTIONS domblklist $NAME | awk '($2 != "-") {print $2}') )
  29. STATUS=$?
  30. if [[ !($STATUS -eq 0) ]]
  31. then
  32. eurybox_display_message error VM "Error on VM description dump: $NAME - error: $STATUS:\n$DISKS"
  33. else
  34. if [[ !($DISKS = "") ]]
  35. then
  36. DISKS_NUM=${#DISKS[@]}
  37. eurybox_display_message message VM "VM $NAME - $DISKS_NUM disk(s) found"
  38. for (( DISK_NUM=0;DISK_NUM<$DISKS_NUM;DISK_NUM++ ))
  39. do
  40. RENAME_OUT=`sudo mv ${DISKS[DISK_NUM]} ${DISKS[DISK_NUM]}_${NOW} 2>&1`
  41. STATUS=$?
  42. if [[ !($STATUS -eq 0) ]]
  43. then
  44. eurybox_display_message error VM "Error on VM disk rename: $NAME - ${DISKS[DISK_NUM]} - error $STATUS:\n$RENAME_OUT"
  45. else
  46. eurybox_display_message debug VM "VM $NAME - disk renamed: ${DISKS[DISK_NUM]} -> ${DISKS[DISK_NUM]}_${NOW}"
  47. RENAME_OUT=`sudo cat $TMP_DESC | awk '{ if($NF == "file=" sq disk_name sq "/>") { for(i=1; i<(NF); i++) { if(i==1) { disk=$i } else { disk=disk" "$i } } ; disk=disk" file=" sq disk_new_name sq "/>" ; print disk } else { print $0 } }' disk_name=${DISKS[DISK_NUM]} disk_new_name=${DISKS[DISK_NUM]}_${NOW} sq=\' 2>&1`
  48. STATUS=$?
  49. if [[ !($STATUS -eq 0) ]]
  50. then
  51. eurybox_display_message error VM "Error on VM disk description update: $NAME - ${DISKS[DISK_NUM]} - error $STATUS:\n$RENAME_OUT"
  52. else
  53. sudo sh -c "echo \"$RENAME_OUT\" > $TMP_DESC"
  54. eurybox_display_message debug VM "VM $NAME - disk description renamed: ${DISKS[DISK_NUM]} -> ${DISKS[DISK_NUM]}_${NOW}"
  55. fi
  56. fi
  57. done
  58. else
  59. eurybox_display_message warning VM "No domain disk detected for VM $NAME"
  60. fi
  61. fi
  62. RENAME_OUT=`sudo sh -c "cat $TMP_DESC | awk '{ if (\\\$NF == \"<name>\"name\"</name>\") {print \"<name>\"new_name\"</name>\"} else { if (\\\$0 !~ /<uuid>/) {print \\\$0} } }' name=$NAME new_name=${NAME}_${NOW}" 2>&1`
  63. STATUS=$?
  64. if [[ !($STATUS -eq 0) ]]
  65. then
  66. eurybox_display_message error VM "Error on VM domain name description updated: $NAME - error $STATUS:\n$RENAME_OUT"
  67. else
  68. RENAME_OUT=`sudo sh -c "echo \"$RENAME_OUT\" > $TMP_DESC" 2>&1`
  69. STATUS=$?
  70. if [[ !($STATUS -eq 0) ]]
  71. then
  72. eurybox_display_message error RENAME "VM $NAME - domain name description update failed - error $STATUS:\n$RENAME_OUT"
  73. else
  74. eurybox_display_message debug RENAME "VM $NAME - domain name description updated: $NAME -> ${NAME}_${NOW}"
  75. fi
  76. RENAME_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS undefine $NAME 2>&1`
  77. STATUS=$?
  78. if [[ !($STATUS -eq 0) ]]
  79. then
  80. eurybox_display_message error VM "Error on VM domain name undefine: $NAME - error $STATUS:\n$RENAME_OUT"
  81. else
  82. RENAME_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS define $TMP_DESC 2>&1`
  83. STATUS=$?
  84. if [[ !($STATUS -eq 0) ]]
  85. then
  86. eurybox_display_message error VM "Error on VM domain name define: $TMP_DESC - error $STATUS:\n$RENAME_OUT"
  87. else
  88. eurybox_display_message message VM "VM renamed $NAME -> ${NAME}_${NOW}"
  89. fi
  90. fi
  91. fi
  92. fi
  93. else
  94. eurybox_display_message error VM "Virsh call issue - error $STATUS:\$RENAME_OUT"
  95. fi
  96. }
  97. #Desc: shutdown a VM through libvirt ACPI emulation (doesn't work for OS without ACPI support)
  98. #1 arg required: vm_name
  99. eurybox_vm_shutdown_acpi ()
  100. {
  101. local NAME=$1
  102. local STATUS
  103. #Waiting for the VM to be stopped
  104. local EURYBOX_VM_NAME
  105. local EURYBOX_VM_STATE=1
  106. local EURYBOX_VM_STOPPED=0
  107. local NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE
  108. while [[ ( $EURYBOX_VM_STATE -eq 1 ) && !( $NB_TRY_LEFT -eq 0 ) ]]
  109. do
  110. EURYBOX_VM_NAME=`sudo virsh $EURYBOX_VIRSH_OPTIONS list | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1`
  111. if [[ -z "$EURYBOX_VM_NAME" ]]
  112. then
  113. EURYBOX_VM_STATE=0
  114. else
  115. if [[ $EURYBOX_VM_STOPPED -eq 0 ]]
  116. then
  117. sudo virsh $EURYBOX_VIRSH_OPTIONS shutdown $NAME
  118. STATUS=$?
  119. if [[ !($STATUS -eq 0) ]]
  120. then
  121. eurybox_display_message warning VM "Error on vm $NAME stop - trying again in 5 seconds / $NB_TRY_LEFT left"
  122. NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 ))
  123. else
  124. EURYBOX_VM_STOPPED=1
  125. eurybox_display_message message VM "Successfully initiated vm $NAME stop - waiting for vm poweroff"
  126. NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE
  127. fi
  128. else
  129. NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 ))
  130. eurybox_display_message debug VM "VM $NAME - still running - trying again in 5 seconds / $NB_TRY_LEFT left"
  131. fi
  132. sleep 5
  133. fi
  134. done
  135. if [[ $NB_TRY_LEFT -eq 0 ]]
  136. then
  137. eurybox_display_message error VM "VM $NAME - stop failed - VM still running after $EURYBOX_MAX_RETRY_ON_FAILURE: $EURYBOX_VM_NAME"
  138. else
  139. eurybox_display_message message VM "VM $NAME - stop OK"
  140. fi
  141. }
  142. #Desc: shutdown a VM through ssh connection
  143. #4 arg required: vm_name vm_host vm_user vm_port
  144. eurybox_vm_shutdown_ssh ()
  145. {
  146. local NAME=$1
  147. local HOST=$2
  148. local USER=$3
  149. local PORT=$4
  150. local EURYBOX_VM_STATE=1
  151. local EURYBOX_VM_STOPPED=0
  152. local STATUS
  153. local EURYBOX_VM_NAME
  154. local SSH_OUT
  155. local NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE
  156. while [[ ( $EURYBOX_VM_STATE -eq 1 ) && !( $NB_TRY_LEFT -eq 0 ) ]]
  157. do
  158. EURYBOX_VM_NAME=`sudo virsh $EURYBOX_VIRSH_OPTIONS list | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1`
  159. if [[ -z "$EURYBOX_VM_NAME" ]]
  160. then
  161. EURYBOX_VM_STATE=0
  162. else
  163. if [[ $EURYBOX_VM_STOPPED -eq 0 ]]
  164. then
  165. SSH_OUT=`ssh $EURYBOX_SSH_OPTIONS -p $PORT $USER@$HOST "halt -p >/dev/null &" 2>&1`
  166. STATUS=$?
  167. if [[ !($STATUS -eq 0) ]]
  168. then
  169. eurybox_display_message warning VM "VM $NAME - stop failed - trying again in 5 seconds:\n$SSH_OUT\n$NB_TRY_LEFT left"
  170. NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 ))
  171. else
  172. EURYBOX_VM_STOPPED=1
  173. eurybox_display_message message VM "Successfully initiated vm $NAME stop - waiting for vm poweroff"
  174. NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE
  175. fi
  176. else
  177. NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 ))
  178. eurybox_display_message debug VM "VM $NAME - still running - trying again in 5 seconds:\n$EURYBOX_VM_NAME\n$NB_TRY_LEFT left"
  179. fi
  180. sleep 5
  181. fi
  182. done
  183. if [[ $NB_TRY_LEFT -eq 0 ]]
  184. then
  185. eurybox_display_message error VM "VM $NAME - stop failed - VM still running after $EURYBOX_MAX_RETRY_ON_FAILURE:\n$EURYBOX_VM_NAME"
  186. else
  187. eurybox_display_message message VM "VM $NAME - stop OK"
  188. fi
  189. }
  190. #Desc: start a VM through libvirt and check via ssh startup success
  191. #4 arg required: vm_name vm_host vm_user vm_port
  192. eurybox_vm_start ()
  193. {
  194. local NAME=$1
  195. local HOST=$2
  196. local USER=$3
  197. local PORT=$4
  198. local STATUS
  199. local VM_OUT
  200. local EURYBOX_VM_AVAILABLE
  201. local VIRSH_OUT
  202. #Check if VM is operationnal (at network level)
  203. local EURYBOX_VM_STATE=0
  204. local EURYBOX_VM_STARTED=0
  205. local NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE
  206. while [[ ( $EURYBOX_VM_STATE -eq 0 ) && !( $NB_TRY_LEFT -eq 0 ) ]]
  207. do
  208. EURYBOX_VM_AVAILABLE=`ssh $EURYBOX_SSH_OPTIONS -p $PORT $USER@$HOST "touch eurybox_check_ssh_ok" 2>&1`
  209. STATUS=$?
  210. if [[ $STATUS -eq 0 ]]
  211. then
  212. EURYBOX_VM_STATE=1
  213. else
  214. if [[ $EURYBOX_VM_STARTED -eq 0 ]]
  215. then
  216. VIRSH_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS start $NAME 2>&1`
  217. STATUS=$?
  218. if [[ !($STATUS -eq 0) ]]
  219. then
  220. VM_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS list | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1`
  221. if [[ -z "$VM_OUT" ]]
  222. then
  223. eurybox_display_message warning VM "Error on vm $NAME start - trying again in 5 seconds:\n$VIRSH_OUT\n$NB_TRY_LEFT left"
  224. NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 ))
  225. else
  226. eurybox_display_message debug VM "VM $NAME already running - waiting for network contact"
  227. EURYBOX_VM_STARTED=1
  228. NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE
  229. fi
  230. else
  231. EURYBOX_VM_STARTED=1
  232. eurybox_display_message debug VM "Successfully initiated vm $NAME start - waiting for network contact"
  233. NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE
  234. fi
  235. else
  236. NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 ))
  237. eurybox_display_message debug VM "VM $NAME - still unreachable - trying again in 5 seconds\n$EURYBOX_VM_AVAILABLE\n$NB_TRY_LEFT left"
  238. fi
  239. sleep 5
  240. fi
  241. done
  242. if [[ $NB_TRY_LEFT -eq 0 ]]
  243. then
  244. eurybox_display_message error VM "VM $NAME - start failed - no network contact after $EURYBOX_MAX_RETRY_ON_FAILURE"
  245. else
  246. eurybox_display_message debug VM "VM $NAME - start OK"
  247. fi
  248. }