File block-dmmd of Package xen

#! /bin/bash

# Usage: block-dmmd [add args | remove args]
#     
#  the xm config file should have something like:
#   dmmd:md;/dev/md0;md;/dev/md1;lvm;/dev/vg1/lv1
#  or
#   dmmd:lvm;/dev/vg1/lv1;lvm;/dev/vg1/lv2;md;/dev/md0
#  note the last device will be used for VM

# History:
#  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:
LANG=C
LC_MESSAGES=C
export LANG LC_MESSAGES

dir=$(dirname "$0")
. "$dir/block-common.sh"

#exec >> /tmp/block-dmmd-`date +%F_%T.%N`.log 2>&1
echo ""
date
set -x
echo shell-flags: $-
command=$1

# We check for errors ourselves:
set +e

function run_mdadm()
{
	local mdadm_cmd=$1
	local msg
	local rc

	msg="`/sbin/mdadm $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

	return 1
}

function activate_md()
{
	local par=$1
	local already_active=0 cfg dev rc t

	if [ ${par} = ${par%%(*} ]; then 
		# No configuration file specified:
		dev=$par
		cfd=
	else
		dev=${par%%(*}
		t=${par#*(}
		cfg="-c ${t%%)*}"
	fi
	if /sbin/mdadm -Q -D $dev; then
		already_active=1
	fi
	run_mdadm "-A $dev $cfg"
	rc=$?
	if [ $already_active -eq 1 ] && [ $rc -eq 2 ]; then
		return 0
	fi
	return $rc
}

function deactivate_md ()
{
	local par=$1	# Make it explicitly local

	## We need the device name only while deactivating
	/sbin/mdadm -S ${par%%(*}
	return $?
}

function activate_lvm ()
{
	# First scan for PVs and VGs; we may then have to activate the VG
	#  first, but can ignore errors:
	/sbin/pvscan || :
	/sbin/vgscan --mknodes || :
	/sbin/vgchange -ay ${1%/*} || :
	/sbin/lvchange -ay $1
	return $?
}

function deactivate_lvm ()
{
	/sbin/lvchange -an $1
	if [ $? -eq 0 ]; then
		# We may have to deactivate the VG now, but can ignore errors:
		/sbin/vgchange -an ${1%/*} || :
		# Maybe we need to cleanup the LVM cache:
		/sbin/vgscan --mknodes || :
		return 0
	fi
	return 1
}

BP=100
SP=$BP
VBD=

declare -a stack
function push ()
{
    if [ -z "$1" ]; then
        return
    fi
    let "SP -= 1"
    stack[$SP]="${1}"
    return
}
function pop ()
{
    VBD=

    if [ "$SP" -eq "$BP" ]; then
        return
    fi

    VBD=${stack[$SP]}
    let "SP += 1"
    return
}
function activate_dmmd ()
{
#   echo $1 $2
    case $1 in
        md)
            activate_md $2
            return
            ;;
        lvm)
            activate_lvm $2
            return
            ;;
    esac
}
function deactivate_dmmd()
{
    case "$1" in
        md)
            deactivate_md $2
            return
            ;;
        lvm)
            deactivate_lvm $2
            return
            ;;
    esac
}
function cleanup_stack ()
{
    while [ 1 ]; do
        pop
        if [ -z "$VBD" ]; then
            break
        fi
        deactivate_dmmd $VBD
    done
    return
}

function parse_par ()
{
    local ac par rc s t		# Make these explicitly local vars

    ac=$1
    par="$2"

    echo "parse_paring $1, $2"
    par="$par;"
    while [ 1 ]; do
        t=${par%%;*}
        if [ -z "$t" ]; then
            return 0
        fi
        par=${par#*;}

        s=${par%%;*}
        if [ -z "$s" ]; then
            return 1
        fi
        par=${par#*;}

        echo "type is $t, dev is $s"
        if [ "$ac" = "activate" ]; then
            activate_dmmd $t $s
            rc=$?
            if [ $rc -ne 0 ]; then
               return 1
            fi
        fi
        echo "push $t $s"
        push "$t $s"

    done
}

echo $command

case "$command" in
  add)
    p=`xenstore-read $XENBUS_PATH/params` || true
    claim_lock "dmmd"
    dmmd=$p
    echo "before parse_par $dmmd"
    parse_par activate "$dmmd"
    rc=$?
    echo "reach here with rc: $rc"
    if [ $rc -ne 0 ]; then
       cleanup_stack
       release_lock "dmmd"
       exit 1
    fi
    claim_lock "block"
    xenstore-write $XENBUS_PATH/node ${dmmd##*;}
    write_dev ${dmmd##*;}
    release_lock "block"
    release_lock "dmmd"
    exit 0
    ;;

  remove)
    p=`xenstore-read $XENBUS_PATH/params` || true
    claim_lock "dmmd"
    dmmd=$p
    parse_par noactivate "$dmmd"
    cleanup_stack
    release_lock "dmmd"
    exit 0
    ;;
esac
openSUSE Build Service is sponsored by