Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Live migration for kvm-ssh #5119

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/tm_mad/fs_lvm/postmigrate
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ fi

. $TMCOMMON

XPATH="$(dirname $0)/../../datastore/xpath.rb --stdin"
SHARED=$(awk 'gsub(/[\0]/, x)' \
<( onedatastore show $DSID -x | $XPATH /DATASTORE/TEMPLATE/SHARED ))

CMD=$(cat <<EOF
set -ex -o pipefail
$SYNC
Expand All @@ -56,6 +60,10 @@ CMD=$(cat <<EOF
fi
fi
done

if [ "$SHARED" != "YES" ]; then
rm -rf "$DST_PATH"
fi
EOF
)

Expand Down
13 changes: 9 additions & 4 deletions src/tm_mad/fs_lvm/premigrate
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,26 @@ fi
CMD=$(cat <<EOF
set -ex -o pipefail
$SYNC
$SUDO $LVSCAN
$SUDO $LVSCAN > /dev/null

for disk in \$(ls ${DST_PATH}/disk.*); do
if [ -L "\$disk" ]; then
DEVICE=\$(readlink "\$disk")

if echo "\$DEVICE" | grep -q '^/dev/vg-one'; then
$SUDO $LVCHANGE -ay \$DEVICE
echo "$SUDO $LVCHANGE -ay \$DEVICE; "
fi
fi
done
EOF
)

ssh_exec_and_log $DST_HOST "$CMD" \
"Error running fs_lvm premigrate"
TODO=$(ssh $SRC_HOST "$CMD")

if [ -n "$TODO" ]; then

ssh_exec_and_log $DST_HOST "$TODO" \
"Error running fs_lvm premigrate"
fi

migrate_other "$@"
76 changes: 48 additions & 28 deletions src/vmm_mad/remotes/kvm/migrate
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ is_readonly() {
local DOMAIN=$1
local DISK=$2

READ_ONLY=$(virsh --connect $LIBVIRT_URI dumpxml $DOMAIN | \
$XPATH --stdin --subtree \
"//domain/devices/disk[source/@file='$DISK']/readonly")
READ_ONLY=$(awk 'gsub(/[\0]/, x)' \
<( virsh --connect $LIBVIRT_URI dumpxml $DOMAIN | \
$XPATH --stdin --subtree \
"//domain/devices/disk[source/@file='$DISK']/readonly"))

[ "$READ_ONLY" = '<readonly/>' ]
}
Expand All @@ -41,8 +42,8 @@ get_size_and_format_of_disk_img() {
local QEMU_IMG_PATH="$1"
local PARAM="$2"

if [ ! -f "$QEMU_IMG_PATH" ]; then
# assume network disk
if [ -L "$QEMU_IMG_PATH" ]; then
# symlink, assume network disk
echo unknown network-disk
return
fi
Expand All @@ -69,11 +70,6 @@ create_target_disk_img() {
local DEST_HOST=$1
local QEMU_IMG_PATH="$2"
local SIZE="$3"
local IMG_DIR=$(dirname "$QEMU_IMG_PATH")

ssh_monitor_and_log "$DEST_HOST" \
"mkdir -v -p '$IMG_DIR'" \
"Failed to make remote directory for $QEMU_IMG_PATH image"

ssh_monitor_and_log "$DEST_HOST" \
"qemu-img create -f qcow2 '$QEMU_IMG_PATH' '$SIZE'" \
Expand All @@ -84,14 +80,15 @@ STDIN=$(cat -)
DEPLOY_ID=$1
DEST_HOST=$2
DISKS=$(virsh --connect $LIBVIRT_URI domblklist "$DEPLOY_ID" \
| tail -n+3 | awk '{print $2}' | tr '\n' ' ')
| tail -n+3 | grep -v "^$" | awk '{print $1 "," $2}')


unset i j XPATH_ELEMENTS
while IFS= read -r -d '' element; do
XPATH_ELEMENTS[i++]="$element"
done < <(echo $STDIN| $XPATH \
/VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/SHARED \
/VMM_DRIVER_ACTION_DATA/DISK_TARGET_PATH)
/VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/SHARED \
/VMM_DRIVER_ACTION_DATA/DISK_TARGET_PATH)

SHARED="${XPATH_ELEMENTS[j++]}"
VM_DIR="${XPATH_ELEMENTS[j++]}"
Expand Down Expand Up @@ -122,29 +119,47 @@ else
exit 1
fi

for DISK in $DISKS; do
read -r SIZE FORMAT <<<"$(get_size_and_format_of_disk_img "$DISK" "$QEMU_IMG_PARAM")"
ssh_monitor_and_log "$DEST_HOST" "mkdir -p '$VM_DIR'" \
"Failed to make remote directory $VM_DIR image"

MIGRATE_DISKS=""

for DISK_STR in $DISKS; do
DISK_DEV=${DISK_STR/,*/}
DISK_PATH=${DISK_STR/*,/}

read -r SIZE FORMAT <<<"$(get_size_and_format_of_disk_img "$DISK_PATH" "$QEMU_IMG_PARAM")"

if [ "$FORMAT" = "raw" ]; then
if ! is_readonly $DEPLOY_ID $DISK; then
RAW_DISKS+=" $DISK"
if ! is_readonly $DEPLOY_ID $DISK_PATH; then
RAW_DISKS+=" $DISK_PATH"
MIGRATE_DISKS+="${DISK_DEV},"
fi

# do initial rsync
exec_and_log "rsync $DISK $DEST_HOST:$DISK" \
"Failed to rsync disk $DISK to $DEST_HOST:$DISK"
multiline_exec_and_log "tar -cSf - $DISK_PATH | ssh $DEST_HOST 'tar xSf - -C / '" \
"Failed to rsync disk $DISK_PATH to $DEST_HOST:$DISK_PATH"

elif [ "$FORMAT" = "qcow2" ] && [ ! -L "$DISK_PATH" ]; then
create_target_disk_img "$DEST_HOST" "$DISK_PATH" "$SIZE"
MIGRATE_DISKS+="${DISK_DEV},"

elif [ "$FORMAT" = "qcow2" ]; then
create_target_disk_img "$DEST_HOST" "$DISK" "$SIZE"

elif [ "$FORMAT" = "network-disk" ]; then
true # skip
fi

# copy disk snapshots
if [[ -d "${DISK}.snap" ]]; then
DISK_DIR=$(dirname "$DISK")
exec_and_log "rsync -r ${DISK}.snap $DEST_HOST:$DISK_DIR" \
"Failed to rsync disk snapshot ${DISK}.snap to $DEST_HOST:$DISK_DIR"
if [ -d "${DISK_PATH}.snap" ] || [ -L "${DISK_PATH}.snap" ]; then
multiline_exec_and_log "tar -cSf - $DISK_PATH.snap | ssh $DEST_HOST 'tar xSf - -C / '" \
"Failed to rsync disk snapshot ${DISK_PATH}.snap to $DEST_HOST"
fi

# recreate symlinks
if [ -L "$DISK_PATH" ]; then
LINK_TARGET=$(readlink $DISK_PATH)
ssh_exec_and_log "$DEST_HOST" "ln -s \"$LINK_TARGET\" \"$DISK_PATH\"" \
"Faild to create symlink $DISK_PATH -> $LINK_TARGET on $DEST_HOST"
fi
done

Expand All @@ -166,16 +181,21 @@ else
fi

for DISK in $RAW_DISKS; do
exec_and_log "rsync $DISK $DEST_HOST:$DISK" \
multiline_exec_and_log "tar -cSf - $DISK | ssh $DEST_HOST 'tar xSf - -C / '" \
"Failed to rsync disk $DISK to $DEST_HOST:$DISK"
done
fi

# Enumerate disks to copy, remove trailing comma
if [ -n "$MIGRATE_DISKS" ]; then
DISK_OPTS="--copy-storage-all --migrate-disks ${MIGRATE_DISKS::-1}"
fi

virsh --connect $LIBVIRT_URI migrate \
--live $MIGRATE_OPTIONS $DEPLOY_ID $QEMU_PROTOCOL://$DEST_HOST/system \
--copy-storage-all
RC=$?
$DISK_OPTS

RC=$?
# remote domfsthaw/resume, give it time
if [ $RC -eq 0 ]; then
if [ "$FREEZE" = "yes" ]; then
Expand Down