From d9f244c2a269ccefb2258f644aa8f856e0acf007 Mon Sep 17 00:00:00 2001 From: Marc Ponschab Date: Wed, 7 Sep 2016 15:06:34 +0200 Subject: [PATCH] use xmllint; select only valid drbd devices; retry when demote/promote fails --- README.md | 7 +++++-- qemu | 47 +++++++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index f0bff7a..64eada9 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,15 @@ guests when the guests are started or shut down. After installing it, the libvirt management daemon needs to be reloaded: /etc/init.d/libvirt-bin reload + +or, on systemd based systems + +systemctl restart libvirtd In order for the DRBD resources to be recognized as such, they need to be configured with the /dev/drbd/by-res/ path. -The script requires the xpath command from the libxml-xpath-perl -package. +The script requires the xmllint command from the libxml package. The latest version of the script is at https://github.com/ohitz/libvirt-drbd diff --git a/qemu b/qemu index 3b43177..a72899c 100755 --- a/qemu +++ b/qemu @@ -1,6 +1,7 @@ #!/bin/bash # # Copyright (C) 2014 Oliver Hitz +# Copyright (C) 2016 Marc Ponschab # # This script is a libvirt hook to automatically promote/demote DRBD # resources. @@ -12,18 +13,37 @@ # In order for the DRBD resources to be recognized as such, they need to # be configured with the /dev/drbd/by-res/ path. # -# The script requires the xpath command from the libxml-xpath-perl -# package. +# The script requires the xmllint command from the libxml package. # # The latest version of the script is at # https://github.com/ohitz/libvirt-drbd +# If qemu does't release the drbrd device immediately, make MAX_ATTEMPTS attemps after waiting SLEEP_BETWEEN_ATTEMPTS +MAX_ATTEMPTS=10; +SLEEP_BETWEEN_ATTEMPTS=1; + function cleanup() { if [ -n "$guest_cfg" ]; then rm -f $guest_cfg fi } +function selectDrbdDevices() { + xmllint --xpath "/domain/devices/disk/source[starts-with(@dev, '/dev/drbd/by-res/')]/@dev" $1; +} + +function setRole() { + role=$1; + resourceName=$(echo $2 | sed -e 's|^dev="/dev/drbd/by-res/\(.*\)"|\1|'); + for i in $(seq $MAX_ATTEMPTS); do + #echo "attempt $i: drbdadm $role $resourceName" >>/var/log/libvirt/hook-qemu.log + /sbin/drbdadm $role $resourceName && return; + sleep $SLEEP_BETWEEN_ATTEMPTS; + done + echo "$MAX_ATTEMPTS attempts executing \"drbdadm $role $resourceName failed, giving up.\"" >&2 + exit 1 +} + trap cleanup EXIT if [ "$#" -ne 4 ]; then @@ -44,15 +64,8 @@ prepare) # Read XML configuration on stdin. cat - > $guest_cfg - for dev in `xpath -q -e "/domain/devices/disk/source/@dev" $guest_cfg | cut -d \" -f 2`; do - drbd_resource=`echo $dev | sed 's|^/dev/drbd/by-res/||'` - if [ "x$drbd_resource" != "x$dev" ]; then - drbd_role="$(/sbin/drbdadm role $drbd_resource)" - drbd_lrole="${drbd_role%%/*}" - if [ "$drbd_lrole" != 'Primary' ]; then - /sbin/drbdadm primary $drbd_resource || exit 1 - fi - fi + for dev in $(selectDrbdDevices $guest_cfg); do + setRole primary $dev; done ;; release) @@ -61,17 +74,11 @@ release) # Read XML configuration on stdin. cat - > $guest_cfg - for dev in `xpath -q -e "/domain/devices/disk/source/@dev" $guest_cfg | cut -d \" -f 2`; do - drbd_resource=`echo $dev | sed 's|^/dev/drbd/by-res/||'` - if [ "x$drbd_resource" != "x$dev" ]; then - drbd_role="$(/sbin/drbdadm role $drbd_resource)" - drbd_lrole="${drbd_role%%/*}" - if [ "$drbd_lrole" = 'Primary' ]; then - /sbin/drbdadm secondary $drbd_resource || exit 1 - fi - fi + for dev in $(selectDrbdDevices $guest_cfg); do + setRole secondary $dev; done ;; esac exit 0 +