From a444becc9744d04754a3d780df3884e71f18a84e Mon Sep 17 00:00:00 2001 From: David Teigland Date: Fri, 24 Aug 2012 12:21:31 -0500 Subject: sanlvm: add script --- lvm/sanlvm | 390 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100755 lvm/sanlvm diff --git a/lvm/sanlvm b/lvm/sanlvm new file mode 100755 index 0000000..2fff9b7 --- /dev/null +++ b/lvm/sanlvm @@ -0,0 +1,390 @@ +#!/bin/bash + +host_id=0 +cmd="" +vgname="" +lvname="" +lock_mode="" +active_mode="" +offset="" + +help() { + vg="\$vg" + host_id="\$host_id" + echo "" + echo "1. /etc/sanlvm.conf" + echo " must contain unique host_id definition from 1 to 2000, e.g." + echo " host_id 1" + echo "" + echo "2. sanlvm vgcreate [options] $vg " + echo " create vg, unprotected by sanlock," + echo " create and initialize storage in $vg for sanlock to use" + echo " vgcreate [options] $vg " + echo " lvcreate -n leases -L 1G $vg" + echo " sanlock direct init -s $vg:0:/dev/$vg/leases:0" + echo " sanlock direct init -r $vg:vglk:/dev/$vg/leases:1048576" + echo " vgchange --addtag @sanlvm $vg" + echo "" + echo "3. sanlvm start" + echo " start lockspaces for vgs @sanlvm, created above" + echo " sanlock add_lockspace -s $vg:$host_id:/dev/$vg/leases:0" + echo "" + echo "4. sanlvm ..." + echo " lvm commands within $vg are serialized by sanlock" + echo " sanlock command -r $vg:vglk:/dev/$vg/leases:1048576 -c /sbin/lvm ..." + echo "" + exit 0 +} + +if [[ $# == 0 ]]; then + help +fi + +arg1=$1 + +if [[ $arg1 == "help" ]]; then + help +fi + +if [[ $arg1 == "--ex" ]] || [[ $arg1 == "--sh" ]]; then + lock_mode=$arg1 + cmd=$2 +else + cmd=$1 +fi + +# vg name is the arg preceding the first pv path arg, +# or the last arg when no pv paths exist +# e.g. vgcreate, vgchange, vgextend, lvcreate + +get_vg_name() { + prev=$2 + + for i in $args + do + first=`expr substr $i 1 1` + if [ "$first" == "/" ]; then + vgname=$prev + return + fi + + prev=$i + done + + for i in $args + do + vgname=$i + done +} + +# lv name follows -n or --name arg +# FIXME: this doesn't work without a space, i.e. -nfoo + +get_lv_name() { + save_next=0 + + for i in $args + do + if [[ $save_next == 1 ]] + lvname=$i + return + fi + + if [[ "$i" == "-n" ]] || [[ "$i" == "--name" ]]; then + save_next=1 + continue + fi + done +} + +# vg name is part of an lv path, e.g. lvextend, lvremove +# first arg containing '/' + +get_vg_lv_name() { + for i in $args + do + ind=`expr index $i /` + if [ "$ind" -gt 0 ]; then + lvname=`basename $i` + dir=`dirname $i` + vgname=`basename $dir` + return + fi + done +} + +get_host_id() { + host_id=`awk '/^host_id/ { print $2 }' < /etc/sanlvm.conf` + + if [[ $? -ne 0 ]]; then + echo no host_id found in /etc/sanlvm.conf + exit 1 + fi +} + +# search lvchange args for -a, ---available +# if there's a "y" anywhere after the option, then active_mode="y" +# if there's a "n" anywhere after the option, then active_mode="n" + +get_active_mode() { + for i in $args + do + if [[ "$i" == "-ay" ]] || [[ "$i" == "-aly" ]] || [[ "$i" == "-aey" ]]; then + active_mode="y" + return + fi + + if [[ "$i" == "-an" ]] || [[ "$i" == "-aln" ]] || [[ "$i" == "-aen" ]]; then + active_mode="n" + return + fi + + if [[ "$i" == "-a" ]] || [[ "$i == "--available" ]]; then + check_next=1 + continue + fi + + if [[ $check_next == 1 ]]; then + ind=`expr index $i y` + if [ "$ind" -gt 0 ]; then + active_mode="y" + else + active_mode="n" + fi + return + fi + done +} + +# get the offset value from the @sanlvm_offset_xyz tag on the lv + +get_lease_offset() { + tags=`lvs --noheadings -o lv_name,lv_tags $vgname | grep $lvname | awk '{print $2}'` + + # FIXME: handle case where the lv has tags other than ours + + offset=`echo $tags | cut --delimiter=_ --fields=3` +} + +if [[ "$cmd" == "start" ]]; then + get_host_id + + for vgname in `vgs @sanlvm --noheadings -o vg_name`; do + lvm lvchange -a y /dev/$vgname/leases + echo adding lockspace $vgname, this may take minutes... + sanlock add_lockspace -s $vgname:$host_id:/dev/$vgname/leases:0 + done + + exit 0 +fi + +if [[ "$cmd" == "vgcreate" ]]; then + args=$* + + get_vg_name + + lvm "$@" + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + lvm lvcreate -n leases -L 1G $vgname + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + sanlock direct init -s $vgname:0:/dev/$vgname/leases:0 + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + sanlock direct init -r $vgname:vglk:/dev/$vgname/leases:1048576 + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + lvm vgchange --addtag @sanlvm $vgname + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + exit 0 + +elif [[ "$cmd" == "_lvcreate" ]]; then + # wrapped by vglk + + shift + + args=$* + + get_vg_name + get_lv_name + + # FIXME: get offset by searching leases lv for unused lease area + offset=2097152 + + # FIXME: add arg to disable activation + # lvcreate + lvm "$@" + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + # FIXME: can remove this once lvcreate doesn't activate + lvm lvchange -an $vgname/$lvname + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + lvm lvchange --addtag @sanlvm_offset_$offset $vgname/$lvname + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + sanlock direct init -r $vgname:$lvname:/dev/$vgname/leases:$offset + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + exit 0 + +elif [[ "$cmd" == "lvcreate" ]]; then + # we need the multiple steps in _lvcreate to all be wrapped in vglk + + args=$* + + get_vg_name + + sanlock command -r $vgname:vglk:/dev/$vgname/leases:1048576 -c ./sanlvm _lvcreate "$@" + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + exit 0 + +elif [[ "$cmd" == "_lvremove" ]]; then + # wrapped by vglk + + shift + + args=$* + + get_vg_lv_name + get_lease_offset + + # lvremove, this will fail if the lv is in use + lvm "$@" + + # FIXME: release lv lease is there is one + + # FIXME: clear the lease area that was used for the lv activation + # lease, if there was one (there was an offset tag) + + exit 0 + +elif [[ "$cmd" == "lvremove" ]]; then + # we need the multiple steps in _lvremove to all be wrapped in vglk + + args=$* + + get_vg_lv_name + + sanlock command -r $vgname:vglk:/dev/$vgname/leases:1048576 -c ./sanlvm _lvremove "$@" + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + exit 0 + + +elif [[ "$cmd" == "lvchange" ]]; then + # sanlvmd is a process that sanlock views as owning the lv + # activation leases. sanlvmd should restrict sigkill, and + # on sigterm from sanlock, it should try to forcibly deactivate + # the sanlvm lvs, or suspend the lv's or suspend lv's, replace + # with the error target and resume. + # (what about handling different vg lockspaces separately?) + + args=$* + + get_vg_lv_name + get_active_mode + get_lease_offset + + if [[ "$active_mode" == "y" ]]; then + # acquire lease, then activate + + if [[ "$lock_mode" == "--sh" ]]; then + suffix=":SH" + elif [[ "$lock_mode" == "--ex" ]]; then + suffix="" + else + echo "use sanlvm --ex|sh for lv activation" + exit 1 + fi + + sanlock client acquire -r $vgname:$lvname:/dev/$vgname/leases:$offset$suffix -p `pidof sanlvmd` + + # lvchange activate + lvm "$@" + + elif [[ "$active_mode" == "n" ]]; then + # deactivate, then release lease + + # lvchange deactivate + lvm "$@" + + sanlock client release -r $vgname:$lvname:/dev/$vgname/leases:$offset -p `pidof sanlvmd` + else + # non-activation related change to lv + # FIXME: do we also want to take ex lv lease? + sanlock command -r $vgname:vglk:/dev/$vgname/leases:1048576 -c /sbin/lvm "$@ + fi + + exit 0 + +elif [[ "$cmd" == "lvextend" ]] || [[ "$cmd" == "lvreduce" ]]; then + args=$* + + get_vg_lv_name + + # FIXME: do we also want to take ex lv lease? + + sanlock command -r $vgname:vglk:/dev/$vgname/leases:1048576 -c /sbin/lvm "$@" + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + exit 0 + +else + if [[ $# -lt 2 ]]; then + echo vg name required + exit 1 + fi + + args=$* + + get_vg_name + + sanlock command -r $vgname:vglk:/dev/$vgname/leases:1048576 -c /sbin/lvm "$@" + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + exit 0 +fi + -- cgit