#!/bin/bash #EuryBOX vm functions file #Desc: rename a VM through libvirt #1 arg required: vm_name eurybox_vm_rename () { local NAME=$1 local STATUS local DISKS local DISKS_NUM local NOW=$(date +"%Y_%m_%d@%H_%M_%S") local TMP_DESC="${EURYBOX_TMP_FOLDER}/${NAME}_${NOW}" local RENAME_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS list --all | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1` STATUS=$? if [[ $STATUS -eq 0 ]] then if [[ $RENAME_OUT == "" ]] then eurybox_display_message warning VM "Rename not possible on non-present vm: $NAME" else RENAME_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS list | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1` if [[ !($RENAME_OUT == "") ]] then eurybox_display_message warning VM "Forcing stop of running vm: $NAME" RENAME_OUT=`sudo sh -c "virsh $EURYBOX_VIRSH_OPTIONS destroy $NAME" 2>&1` fi eurybox_export_vm_config $NAME $TMP_DESC DISKS=( $(sudo virsh $EURYBOX_VIRSH_OPTIONS domblklist $NAME | awk '($2 != "-") {print $2}') ) STATUS=$? if [[ !($STATUS -eq 0) ]] then eurybox_display_message error VM "Error on VM description dump: $NAME - error: $STATUS:\n$DISKS" else if [[ !($DISKS = "") ]] then DISKS_NUM=${#DISKS[@]} eurybox_display_message message VM "VM $NAME - $DISKS_NUM disk(s) found" for (( DISK_NUM=0;DISK_NUM<$DISKS_NUM;DISK_NUM++ )) do RENAME_OUT=`sudo mv ${DISKS[DISK_NUM]} ${DISKS[DISK_NUM]}_${NOW} 2>&1` STATUS=$? if [[ !($STATUS -eq 0) ]] then eurybox_display_message error VM "Error on VM disk rename: $NAME - ${DISKS[DISK_NUM]} - error $STATUS:\n$RENAME_OUT" else eurybox_display_message debug VM "VM $NAME - disk renamed: ${DISKS[DISK_NUM]} -> ${DISKS[DISK_NUM]}_${NOW}" 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` STATUS=$? if [[ !($STATUS -eq 0) ]] then eurybox_display_message error VM "Error on VM disk description update: $NAME - ${DISKS[DISK_NUM]} - error $STATUS:\n$RENAME_OUT" else sudo sh -c "echo \"$RENAME_OUT\" > $TMP_DESC" eurybox_display_message debug VM "VM $NAME - disk description renamed: ${DISKS[DISK_NUM]} -> ${DISKS[DISK_NUM]}_${NOW}" fi fi done else eurybox_display_message warning VM "No domain disk detected for VM $NAME" fi fi RENAME_OUT=`sudo sh -c "cat $TMP_DESC | awk '{ if (\\\$NF == \"\"name\"\") {print \"\"new_name\"\"} else { if (\\\$0 !~ //) {print \\\$0} } }' name=$NAME new_name=${NAME}_${NOW}" 2>&1` STATUS=$? if [[ !($STATUS -eq 0) ]] then eurybox_display_message error VM "Error on VM domain name description updated: $NAME - error $STATUS:\n$RENAME_OUT" else RENAME_OUT=`sudo sh -c "echo \"$RENAME_OUT\" > $TMP_DESC" 2>&1` STATUS=$? if [[ !($STATUS -eq 0) ]] then eurybox_display_message error RENAME "VM $NAME - domain name description update failed - error $STATUS:\n$RENAME_OUT" else eurybox_display_message debug RENAME "VM $NAME - domain name description updated: $NAME -> ${NAME}_${NOW}" fi RENAME_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS undefine $NAME 2>&1` STATUS=$? if [[ !($STATUS -eq 0) ]] then eurybox_display_message error VM "Error on VM domain name undefine: $NAME - error $STATUS:\n$RENAME_OUT" else RENAME_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS define $TMP_DESC 2>&1` STATUS=$? if [[ !($STATUS -eq 0) ]] then eurybox_display_message error VM "Error on VM domain name define: $TMP_DESC - error $STATUS:\n$RENAME_OUT" else eurybox_display_message message VM "VM renamed $NAME -> ${NAME}_${NOW}" fi fi fi fi else eurybox_display_message error VM "Virsh call issue - error $STATUS:\$RENAME_OUT" fi } #Desc: shutdown a VM through libvirt ACPI emulation (doesn't work for OS without ACPI support) #1 arg required: vm_name eurybox_vm_shutdown_acpi () { local NAME=$1 local STATUS local VIRSH_OUT #Waiting for the VM to be stopped local EURYBOX_VM_NAME local EURYBOX_VM_STATE=1 local EURYBOX_VM_STOPPED=0 local NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE while [[ ( $EURYBOX_VM_STATE -eq 1 ) && !( $NB_TRY_LEFT -eq 0 ) ]] do EURYBOX_VM_NAME=`sudo virsh $EURYBOX_VIRSH_OPTIONS list | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1` if [[ -z "$EURYBOX_VM_NAME" ]] then EURYBOX_VM_STATE=0 else if [[ $EURYBOX_VM_STOPPED -eq 0 ]] then VIRSH_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS shutdown $NAME 2>&1` STATUS=$? if [[ !($STATUS -eq 0) ]] then NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 )) eurybox_display_message debug VM "VM $NAME - stop failed - error $STATUS:\n$VIRSH_OUT\nTrying again in ${EURYBOX_ERROR_TEMPORISATION_TIME} seconds / $NB_TRY_LEFT left" else EURYBOX_VM_STOPPED=1 eurybox_display_message message VM "Successfully initiated VM $NAME stop - waiting for vm poweroff" NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE fi else NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 )) eurybox_display_message debug VM "VM $NAME - still running - trying again in ${EURYBOX_ERROR_TEMPORISATION_TIME} seconds / $NB_TRY_LEFT left" fi sleep ${EURYBOX_ERROR_TEMPORISATION_TIME} fi done if [[ $NB_TRY_LEFT -eq 0 ]] then eurybox_display_message warning VM "VM $NAME - ACPI stop failed - VM still running after $EURYBOX_MAX_RETRY_ON_FAILURE:\n$EURYBOX_VM_NAME\n error $STATUS:\n$VIRSH_OUT\nForcing stop" VIRSH_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS destroy $NAME 2>&1` STATUS=$? if [[ !($STATUS -eq 0) ]] then eurybox_display_message error VM "VM $NAME - forced stop failed - error $STATUS:\n$VIRSH_OUT" else eurybox_display_message message VM "Successfully initiated VM $NAME forced stop" EURYBOX_VM_NAME=`sudo virsh $EURYBOX_VIRSH_OPTIONS list | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1` if [[ -z "$EURYBOX_VM_NAME" ]] then eurybox_display_message message VM "VM $NAME - forced stop OK" else eurybox_display_message error VM "VM $NAME - forced stop failed - VM still running:\n$EURYBOX_VM_NAME" fi fi else eurybox_display_message message VM "VM $NAME - ACPI stop OK" fi } #Desc: shutdown a VM through ssh connection #4 arg required: vm_name vm_host vm_user vm_port eurybox_vm_shutdown_ssh () { local NAME=$1 local HOST=$2 local USER=$3 local PORT=$4 local EURYBOX_VM_STATE=1 local EURYBOX_VM_STOPPED=0 local STATUS local EURYBOX_VM_NAME local SSH_OUT local VIRSH_OUT local NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE while [[ ( $EURYBOX_VM_STATE -eq 1 ) && !( $NB_TRY_LEFT -eq 0 ) ]] do EURYBOX_VM_NAME=`sudo virsh $EURYBOX_VIRSH_OPTIONS list | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1` if [[ -z "$EURYBOX_VM_NAME" ]] then EURYBOX_VM_STATE=0 else if [[ $EURYBOX_VM_STOPPED -eq 0 ]] then SSH_OUT=`ssh $EURYBOX_SSH_OPTIONS -p $PORT $USER@$HOST "halt -p >/dev/null &" 2>&1` STATUS=$? if [[ !($STATUS -eq 0) ]] then NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 )) eurybox_display_message debug VM "VM $NAME - SSH stop failed - trying again in ${EURYBOX_ERROR_TEMPORISATION_TIME} seconds:\n$SSH_OUT\n$NB_TRY_LEFT left" else EURYBOX_VM_STOPPED=1 eurybox_display_message debug VM "Successfully initiated vm $NAME stop - waiting for vm poweroff" NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE fi else NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 )) eurybox_display_message debug VM "VM $NAME - still running - trying again in ${EURYBOX_ERROR_TEMPORISATION_TIME} seconds:\n$EURYBOX_VM_NAME\n$NB_TRY_LEFT left" fi sleep ${EURYBOX_ERROR_TEMPORISATION_TIME} fi done if [[ $NB_TRY_LEFT -eq 0 ]] then eurybox_display_message warning VM "VM $NAME - SSH stop failed - VM still running after $EURYBOX_MAX_RETRY_ON_FAILURE\nForcing stop" VIRSH_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS destroy $NAME 2>&1` STATUS=$? if [[ !($STATUS -eq 0) ]] then eurybox_display_message error VM "VM $NAME - forced stop failed - error $STATUS:\n$VIRSH_OUT" else eurybox_display_message message VM "Successfully initiated VM $NAME forced stop" EURYBOX_VM_NAME=`sudo virsh $EURYBOX_VIRSH_OPTIONS list | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1` if [[ -z "$EURYBOX_VM_NAME" ]] then eurybox_display_message message VM "VM $NAME - forced stop OK" else eurybox_display_message error VM "VM $NAME - forced stop failed - VM still running:\n$EURYBOX_VM_NAME" fi fi else eurybox_display_message message VM "VM $NAME - SSH stop OK" fi } #Desc: start a VM through libvirt and check via ssh startup success #4 arg required: vm_name vm_host vm_user vm_port eurybox_vm_start () { local NAME=$1 local HOST=$2 local USER=$3 local PORT=$4 local STATUS local VM_OUT local EURYBOX_VM_AVAILABLE local VIRSH_OUT #Check if VM is operationnal (at network level) local EURYBOX_VM_STATE=0 local EURYBOX_VM_STARTED=0 local NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE while [[ ( $EURYBOX_VM_STATE -eq 0 ) && !( $NB_TRY_LEFT -eq 0 ) ]] do EURYBOX_VM_AVAILABLE=`ssh $EURYBOX_SSH_OPTIONS -p $PORT $USER@$HOST "touch eurybox_check_ssh_ok" 2>&1` STATUS=$? if [[ $STATUS -eq 0 ]] then EURYBOX_VM_STATE=1 else if [[ $EURYBOX_VM_STARTED -eq 0 ]] then VIRSH_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS start $NAME 2>&1` STATUS=$? if [[ !($STATUS -eq 0) ]] then VM_OUT=`sudo virsh $EURYBOX_VIRSH_OPTIONS list | awk '{ if ($2 == name) {print $2} }' name=$NAME 2>&1` if [[ -z "$VM_OUT" ]] then NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 )) eurybox_display_message debug VM "Error on vm $NAME start - trying again in ${EURYBOX_ERROR_TEMPORISATION_TIME} seconds:\n$VIRSH_OUT\n$NB_TRY_LEFT left" else eurybox_display_message debug VM "VM $NAME already running - waiting for network contact" EURYBOX_VM_STARTED=1 NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE fi else EURYBOX_VM_STARTED=1 eurybox_display_message debug VM "Successfully initiated vm $NAME start - waiting for network contact" NB_TRY_LEFT=$EURYBOX_MAX_RETRY_ON_FAILURE fi else NB_TRY_LEFT=$(( $NB_TRY_LEFT - 1 )) eurybox_display_message debug VM "VM $NAME - still unreachable - trying again in ${EURYBOX_ERROR_TEMPORISATION_TIME} seconds\n$EURYBOX_VM_AVAILABLE\n$NB_TRY_LEFT left" fi sleep ${EURYBOX_ERROR_TEMPORISATION_TIME} fi done if [[ $NB_TRY_LEFT -eq 0 ]] then eurybox_display_message warning VM "VM $NAME - start failed - no network contact after $EURYBOX_MAX_RETRY_ON_FAILURE:\n${EURYBOX_VM_AVAILABLE}" else eurybox_display_message message VM "VM $NAME - start OK" fi }