summaryrefslogtreecommitdiff
path: root/block-dmmd
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-10-12 04:00:49 +0000
committerCoprDistGit <infra@openeuler.org>2023-10-12 04:00:49 +0000
commitc22f60e6e55f1bf300dd76d2222a93911f3b2bb2 (patch)
treeef665e7018377f53612ac2751dcaea35a1c587b6 /block-dmmd
parent39a4763249cd6289e5019acfe0c98dbb169f5f2e (diff)
automatic import of xenopeneuler22.03_LTS
Diffstat (limited to 'block-dmmd')
-rw-r--r--block-dmmd384
1 files changed, 384 insertions, 0 deletions
diff --git a/block-dmmd b/block-dmmd
new file mode 100644
index 0000000..58534f8
--- /dev/null
+++ b/block-dmmd
@@ -0,0 +1,384 @@
+#! /bin/bash
+
+# Usage: block-dmmd [add args | remove args]
+#
+# the dmmd device syntax (in xl commands/configs) is something like:
+# script=block-dmmd,md;/dev/md0;md;/dev/md1;lvm;/dev/vg1/lv1
+# or
+# script=block-dmmd,lvm;/dev/vg1/lv1;lvm;/dev/vg1/lv2;md;/dev/md0
+# device pairs (type;dev) are processed in order, with the last device
+# assigned to the VM
+#
+# Note - When using the libxl stack, the "script=block-dmmd" option
+# is required. See man xl-disk-configuration(5) for more information.
+#
+# md devices can optionally:
+# specify a config file through:
+# md;/dev/md100(/var/xen/config/mdadm.conf)
+# use an array name (mdadm -N option):
+# md;My-MD-name;lvm;/dev/vg1/lv1
+#
+# Completely expressive syntax should be similar to:
+# "format=raw, vdev=xvdb, access=rw, script=block-dmmd, \
+# target=md;/dev/md0(/etc/mdadm.conf);lvm;/dev/vg1/lv1"
+#
+##
+# History:
+# 2017-07-10, mlatimer@suse.com:
+# Modification to use syslog for progress messages by ldevulder@suse.com
+# 2017-06-12, mlatimer@suse.com:
+# Merge LVM improvements by loic.devulder@mpsa.com
+# Document libxl "script=block-dmmd" syntax in examples
+# Remove xm/xend references (e.g. parsed_timeout from xend-config.sxp)
+# 2016-05-27, mlatimer@suse.com:
+# Merge improvements by loic.devulder@mpsa.com. Highlights include:
+# - Re-write and simplification to speed up the script!
+# - Add some (useful) logging messages and comments
+# Minor tweaks and logging improvements
+# 2016-05-26, mlatimer@suse.com:
+# Verify MD activation if mdadm returns 2
+# 2016-05-20, mlatimer@suse.com:
+# Strip leading "dmmd:" if present in xenstore params value
+# 2013-07-03, loic.devulder@mpsa.com:
+# Partial rewrite of the script for supporting MD activation by name
+# 2009-06-09, mh@novell.com:
+# Emit debugging messages into a temporary file; if no longer needed,
+# just comment the exec I/O redirection below
+# Make variables used in functions local to avoid global overridings
+# Use vgscan and vgchange where required
+# Use the C locale to avoid dealing with localized messages
+# Assign output from assembling an MD device to a variable to aid
+# debugging
+
+# We do not want to deal with localized messages
+# We use LC_ALL because LC_ALL superse LANG
+# But we also use LANG because some applications may still use LANG...
+export LC_ALL=C
+export LANG=${LC_ALL}
+
+# Loading common libraries
+. $(dirname $0)/block-common.sh
+
+# Constants
+typeset -rx MDADM_BIN=/sbin/mdadm
+typeset -rx LVCHANGE_BIN=/sbin/lvchange
+typeset -rx PVSCAN_BIN=/sbin/pvscan
+typeset -rx VGSCAN_BIN=/sbin/vgscan
+typeset -rx VGCHANGE_BIN=/sbin/vgchange
+typeset -rx CLVMD_BIN=/usr/sbin/clvmd
+typeset -rx DATE_SEC="date +%s"
+
+# We check for errors ourselves
+set +e
+
+function reload_clvm()
+{
+ # If we are in cluster mode
+ if ps -e | grep -q [c]lvmd 2>/dev/null; then
+ # Logging message
+ log info "Synchronizing cLVM..."
+
+ # Synchronize cLVM
+ ${CLVMD_BIN} -R > /dev/null 2>&1 \
+ || return 1
+ fi
+
+ return 0
+}
+
+function run_mdadm()
+{
+ local mdadm_cmd=$1
+ local msg
+ local rc
+
+ msg="$(${MDADM_BIN} ${mdadm_cmd} 2>&1)"
+ rc=$?
+ case "${msg}" in
+ *"has been started"* | *"already active"*)
+ return 0
+ ;;
+ *"is already in use"*)
+ # Hmm, might be used by another device in this domU
+ # Leave it to upper layers to detect a real error
+ return 2
+ ;;
+ *)
+ return ${rc}
+ ;;
+ esac
+
+ # Normally we should not get here, but if this happens
+ # we have to return an error
+ return 1
+}
+
+function activate_md()
+{
+ # Make it explicitly local
+ local par=$1
+ local cfg dev dev_path rc t mdadm_opts
+
+ if [[ ${par} == ${par%%(*} ]]; then
+ # No configuration file specified
+ dev=${par}
+ cfg=""
+ else
+ dev=${par%%(*}
+ t=${par#*(}
+ cfg="-c ${t%%)*}"
+ fi
+
+ # Looking for device name or aliase
+ if [[ ${dev:0:1} == / ]]; then
+ dev_path=${dev%/*}
+ mdadm_opts=""
+ else
+ dev_path=/dev/md
+ mdadm_opts="-s -N"
+ fi
+
+ # Logging message
+ log info "Activating MD device ${dev}..."
+
+ # Is MD device already active?
+ # We need to use full path name, aliase is not possible...
+ if [ -e ${dev_path}/${dev##*/} ]; then
+ ${MDADM_BIN} -Q -D ${dev_path}/${dev##*/} 2>/dev/null \
+ | grep -iq state.*\:.*inactive || return 0
+ fi
+
+ # Activate MD device
+ run_mdadm "-A ${mdadm_opts} ${dev} ${cfg}"
+ rc=$?
+
+ # A return code of 2 can indicate the array configuration was incorrect
+ if [[ ${rc} == 2 ]]; then
+ # Logging message
+ log info "Verifying MD device ${dev} activation..."
+
+ # If the array is active, return 0, otherwise return an error
+ ${MDADM_BIN} -Q -D ${dev_path}/${dev##*/} &>/dev/null && return 0 \
+ || return 1
+ fi
+
+ return ${rc}
+}
+
+function deactivate_md()
+{
+ local par=$1
+ local dev
+
+ if [[ ${par} == ${par%%(*} ]]; then
+ # No configuration file specified
+ dev=${par}
+ else
+ dev=${par%%(*}
+ fi
+
+ # Looking for device name or aliase
+ if [[ ${dev:0:1} == / ]]; then
+ dev_path=${dev%/*}
+ else
+ dev_path=/dev/md
+ fi
+
+ # Logging message
+ log info "Deactivating MD device ${dev}..."
+
+ # We need the device name only while deactivating
+ ${MDADM_BIN} -S ${dev_path}/${dev##*/} > /dev/null 2>&1
+
+ return $?
+}
+
+function lvm_action()
+{
+ local action=$1
+ local dev=$2
+ local run_timeout=90
+ local end_time
+
+ # Logging message
+ log info "${action} LVM device ${dev}..."
+
+ # Set end_time for the loop
+ (( end_time = $(${DATE_SEC}) + run_timeout ))
+
+ while true; do
+ # Action depends of what the user asks
+ if [[ ${action} == activate ]]; then
+ # First scan for PVs and VGs
+ # We need this for using MD device as PV
+ ${PVSCAN_BIN} > /dev/null 2>&1
+
+ ${LVCHANGE_BIN} -aey ${dev} > /dev/null 2>&1 \
+ && [[ -e ${dev} ]] \
+ && return 0
+ elif [[ ${action} == deactivate ]]; then
+ ${LVCHANGE_BIN} -aen ${dev} > /dev/null 2>&1 \
+ && return 0
+
+ # If the LV is already deactivated we may be in an infinite loop
+ # So we need to test if the LV is still present
+ [[ -e ${dev} ]] || return 0
+ fi
+
+ # It seems that we had a problem during lvchange
+ # If we are in a cluster the problem may be due to a cLVM locking bug,
+ # so try to reload it
+ reload_clvm
+
+ # If it takes too long we need to return an error
+ if (( $(${DATE_SEC}) >= end_time )); then
+ log err "Failed to ${action} $1 within ${run_timeout} seconds"
+ return 1
+ fi
+
+ # Briefly sleep before restarting the loop
+ sleep 0.1
+
+ done
+
+ # Normally we should not get here, but if this happens
+ # we have to return an error
+ return 1
+}
+
+# Variables
+typeset command=$1
+typeset BP=100
+typeset SP=${BP}
+typeset VBD
+typeset -a stack
+
+function push()
+{
+ local value="$1"
+
+ [[ -n "${value}" ]] \
+ && stack[$((--SP))]="${value}"
+
+ return 0
+}
+
+function pop()
+{
+ [[ "${SP}" != "${BP}" ]] \
+ && VBD=${stack[$((SP++))]} \
+ || VBD=""
+
+ return 0
+}
+
+function activate_dmmd()
+{
+ case "$1" in
+ "md")
+ activate_md $2
+ return $?
+ ;;
+ "lvm")
+ lvm_action activate $2
+ return $?
+ ;;
+ esac
+
+ # Normally we should not get here, but if this happens
+ # we have to return an error
+ return 1
+}
+
+function deactivate_dmmd()
+{
+ case "$1" in
+ "md")
+ deactivate_md $2
+ return $?
+ ;;
+ "lvm")
+ lvm_action deactivate $2
+ return $?
+ ;;
+ esac
+
+ # Normally we should not get here, but if this happens
+ # we have to return an error
+ return 1
+}
+
+function cleanup_stack()
+{
+ while true; do
+ pop
+ [[ -z "${VBD}" ]] && break
+ deactivate_dmmd ${VBD}
+ done
+}
+
+function parse_par()
+{
+ # Make these vars explicitly local
+ local ac par rc s t
+
+ ac=$1
+ par="$2"
+
+ par="${par};"
+ while true; do
+ t=${par%%;*}
+
+ [[ -z "${t}" ]] && return 0
+ par=${par#*;}
+
+ s=${par%%;*}
+ [[ -z "${s}" ]] && return 1
+ par=${par#*;}
+
+ if [[ "${ac}" == "activate" ]]; then
+ activate_dmmd ${t} ${s} \
+ || return 1
+ fi
+ push "${t} ${s}"
+ done
+}
+
+case "${command}" in
+ "add")
+ p=$(xenstore-read ${XENBUS_PATH}/params) || true
+ claim_lock "dmmd"
+ dmmd=${p#dmmd:}
+
+ if ! parse_par activate "${dmmd}"; then
+ cleanup_stack
+ release_lock "dmmd"
+ exit 1
+ fi
+
+ lastparam=${dmmd##*;}
+ usedevice=${lastparam%(*}
+ xenstore-write ${XENBUS_PATH}/node "${usedevice}"
+ write_dev "${usedevice}"
+ release_lock "dmmd"
+
+ exit 0
+ ;;
+
+ "remove")
+ p=$(xenstore-read ${XENBUS_PATH}/params) || true
+ claim_lock "dmmd"
+ dmmd=${p#dmmd:}
+
+ parse_par noactivate "${dmmd}"
+
+ cleanup_stack
+ release_lock "dmmd"
+
+ exit 0
+ ;;
+esac
+
+# Normally we should not get here, but if this happens
+# we have to return an error
+return 1