We have some news to share for the request index beta feature. We’ve added more options to sort your requests, counters to the individual filters and documentation for the search functionality. Checkout the blog post for more details.

File block-dmmd of Package xen

#! /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
openSUSE Build Service is sponsored by