#!/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