Last active
March 10, 2018 17:40
-
-
Save xenithorb/680d119eefcaa31cf4bebd6271079ec8 to your computer and use it in GitHub Desktop.
Move a libvirt VM from one host to another
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Usage: ./virsh_offline_vm_xfer.sh <domain> <host> | |
# | |
# Requirements | |
# 1. The same user on the local and remote machine that are able to sudo | |
# 2. Both normal users belong to the libvirt group respectively or have | |
# global libvirtd access. (can access qemu:///system) | |
# 3. Assumes image paths can remain identical during transfer | |
# | |
# Author: Michael Goodwin Date: 2017-05-12 | |
trap 'breakdown "$HOST"' EXIT SIGINT SIGQUIT SIGTERM | |
DOMAIN="$1" | |
HOST="$2" | |
LOCAL_LIBVIRT_URI="qemu:///system" | |
REMOTE_LIBVIRT_URI="qemu+ssh://${HOST}/system" | |
IMAGES_PATH="/var/lib/libvirt/images" | |
SUDOERS_PATH="/etc/sudoers.d/vmxfer_nopasswd" | |
CMD="/usr/bin/rsync" | |
push() { | |
virsh_xfer_xml() { | |
local domain="$1" | |
virsh -c "${LOCAL_LIBVIRT_URI}" dumpxml --migratable "$domain" \ | |
| virsh -c "${REMOTE_LIBVIRT_URI}" define /dev/stdin | |
} | |
get_image_path() { | |
local domain="$1" | |
virsh -c "${LOCAL_LIBVIRT_URI}" domblklist --details "$domain" \ | |
| awk '$1 == "file" && $2 == "disk" { print $NF }' | |
} | |
xfer_vm_image() { | |
local domain="$1" host="$2" path | |
get_image_path "$domain" | while read -r path; do | |
if [[ "$path" =~ ^/dev/mapper ]]; then | |
{ echo "Block devices not supported!"; exit 1; } | |
else | |
sudo rsync -aAXWPS --rsync-path='sudo rsync' \ | |
"$path" "${USER}@${host}:${IMAGES_PATH}" | |
fi | |
done | |
} | |
setup_sudo_nopasswd() { | |
local host="$1" cmd | |
cmd="$( sed 's|"||g' <<< "$CMD" )" | |
sudoers_docu=$( | |
cat <<-EOF | |
${USER} ALL=(root) NOPASSWD: ${cmd} | |
${USER} ALL=(root) NOPASSWD: /bin/rm -v ${SUDOERS_PATH} | |
EOF | |
) | |
if echo "${sudoers_docu}" | visudo -cf-; then | |
# | |
mkscript() { | |
base64 <<-EOF | |
#!/bin/sh | |
echo '${sudoers_docu}' > "${SUDOERS_PATH}" | |
if ! visudo -cf "${SUDOERS_PATH}"; then | |
rm -v "${SUDOERS_PATH}" | |
else | |
exit 1 | |
fi | |
EOF | |
} | |
# Places remote sudoers file for tar | |
remote_temp=$( | |
ssh -q "${USER}@${host}" -- ' | |
tempfile=$(mktemp) | |
base64 -d > "$tempfile" | |
echo "$tempfile"' < <(mkscript) | |
) | |
# Reads pw from tty to actually use sudo to | |
# execute the temporary sudoers script | |
ssh -tq "${USER}@${host}" -- "\ | |
sudo -- bash \"${remote_temp}\" | |
rm \"${remote_temp}\"" | |
else | |
exit 1 | |
fi | |
} | |
"$@" | |
} | |
breakdown() { | |
local host="$1" | |
ssh -q "${USER}@${host}" -- sudo -n -- "/bin/rm -v ${SUDOERS_PATH}" | |
} | |
push setup_sudo_nopasswd "$HOST" \ | |
&& push xfer_vm_image "$DOMAIN" "$HOST" \ | |
&& push virsh_xfer_xml "$DOMAIN" \ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment