#!/bin/sh # # VolumeGroup # # Description: Manages an LVM2 volume group as an HA resource in # an OCF-compliant cluster # # # Authors: Alan Robertson, Lars Marowsky-Bree, Florian Haas, # and others from the Linux-HA project # License: GNU General Public License (GPL) # Copyright: (C) 2002 - 2005 International Business Machines, Inc. # (C) 2010 LINBIT HA-Solutions GmbH # # This code significantly inspired by the LVM resource # in FailSafe by Lars Marowsky-Bree # ####################################################################### # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat} . ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs ####################################################################### usage() { methods=`VolumeGroup_methods` methods=`echo $methods | tr ' ' '|'` cat <<EOF usage: $0 $methods $0 manages an LVM Volume Group (VG) as an HA resource The 'start' operation brings the given volume online The 'stop' operation takes the given volume offline The 'status' operation reports whether the volume is available The 'monitor' operation reports whether the volume seems present The 'validate-all' operation checks whether the OCF parameters are valid The 'methods' operation reports on the methods $0 supports EOF } meta_data() { cat <<EOF <?xml version="1.0"?> <!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> <resource-agent name="VolumeGroup"> <version>1.0</version> <longdesc lang="en"> Resource script for an LVM Volume Group. </longdesc> <shortdesc lang="en">Controls the availability of an LVM Volume Group</shortdesc> <parameters> <parameter name="volgrpname" unique="0" required="1"> <longdesc lang="en"> The name of volume group. </longdesc> <shortdesc lang="en">Volume group name</shortdesc> <content type="string" default="" /> </parameter> <parameter name="exclusive" unique="0" required="0"> <longdesc lang="en"> If set, the volume group will be activated exclusively. </longdesc> <shortdesc lang="en">Exclusive activation</shortdesc> <content type="boolean" default="false" /> </parameter> </parameters> <actions> <action name="start" timeout="30" /> <action name="stop" timeout="30" /> <action name="status" timeout="30" /> <action name="monitor" depth="0" timeout="30" interval="10" /> <action name="methods" timeout="5" /> <action name="meta-data" timeout="5" /> <action name="validate-all" timeout="5" /> </actions> </resource-agent> EOF } # # methods: What methods/operations do we support? # VolumeGroup_methods() { cat <<EOF start stop status monitor methods validate-all usage EOF } # # Report on LVM volume status. VG may be reported as active # ($OCF_SUCCESS) or inactive ($OCF_NOT_RUNNING) # VolumeGroup_status() { VGOUT=`vgdisplay -v $OCF_RESKEY_volgrpname 2>&1` || exit $OCF_ERR_GENERIC echo "$VGOUT" | grep -i 'Status[ \t]*available' >/dev/null rc=$? if [ $rc -eq 0 ]; then ocf_log debug "LVM Volume Group $OCF_RESKEY_volgrpname is available (started)" else ocf_log debug "LVM Volume Group $OCF_RESKEY_volgrpname is not available (stopped)" return $OCF_NOT_RUNNING fi if echo "$VGOUT" | grep -i 'Access.*read/write' >/dev/null; then ocf_log debug "Volume $OCF_RESKEY_volgrpname is available read/write (running)" else ocf_log debug "Volume $OCF_RESKEY_volgrpname is available read-only (running)" fi return $OCF_SUCCESS } # # Monitor the volume - does it really seem to be working? May report # $OCF_SUCCESS or $OCF_NOT_RUNNING like VolumeGroup_status, plus # $OCF_ERR_GENERIC in case vgck reports an error. # VolumeGroup_monitor() { if ! VolumeGroup_status $OCF_RESKEY_volgrpname; then ocf_log info "LVM Volume Group $OCF_RESKEY_volgrpname is offline" return $OCF_NOT_RUNNING fi ocf_run vgck $OCF_RESKEY_volgrpname || exit $OCF_ERR_GENERIC return $OCF_SUCCESS } # # Activate the volume group, either locally (if $OCF_RESKEY_exclusive # is false or unset), or exclusively (if $OCF_RESKEY_exclusive is # true). # Either returns successfully, or exits with $OCF_ERR_GENERIC. # VolumeGroup_start() { ocf_log info "Activating volume group $OCF_RESKEY_volgrpname" ocf_run vgscan local active_mode active_mode="ly" if ocf_is_true "$OCF_RESKEY_exclusive" ; then active_mode="ey" fi ocf_run vgchange -a $active_mode $OCF_RESKEY_volgrpname || exit $OCF_ERR_GENERIC if ! VolumeGroup_status $OCF_RESKEY_volgrpname; then ocf_log err "LVM: $OCF_RESKEY_volgrpname did not activate correctly" exit $OCF_ERR_GENERIC fi return $OCF_SUCCESS } # # Deactivate the volume group. # Either returns successfully, or exits with $OCF_ERR_GENERIC. # VolumeGroup_stop() { if ! VolumeGroup_status; then ocf_log debug "Volume Group $OCF_RESKEY_volgrpname already stopped" return $OCF_SUCCESS fi ocf_log info "Deactivating volume group $OCF_RESKEY_volgrpname" ocf_run vgchange -a ln $OCF_RESKEY_volgrpname || exit $OCF_ERR_GENERIC if VolumeGroup_status; then ocf_log err "LVM: $OCF_RESKEY_volgrpname did not stop correctly" exit $OCF_ERR_GENERIC fi return $OCF_SUCCESS } # # Check whether the OCF instance parameters are valid. # Either returns successfully, or exits with # $OCF_ERR_CONFIGURED if required parameters are missing; # $OCF_ERR_INSTALLED if required binaries are missing; # $OCF_ERR_GENERIC in case of any other error. # VolumeGroup_validate_all() { if [ -z $OCF_RESKEY_volgrpname ]; then ocf_log err 'Missing required parameter "volgrpname"!' exit $OCF_ERR_CONFIGURED fi check_binary vgchange check_binary vgck check_binary vgdisplay # Run the following tests only if we're not invoked by a probe # operation if ! ocf_is_probe; then # Off-the-shelf tests... vgck "$OCF_RESKEY_volgrpname" >/dev/null 2>&1 if [ $? -ne 0 ]; then ocf_log err "Volume group $OCF_RESKEY_volgrpname does not exist or contains error!" exit $OCF_ERR_GENERIC fi # Double-check vgdisplay -v "$OCF_RESKEY_volgrpname" >/dev/null 2>&1 if [ $? -ne 0 ]; then ocf_log err "Volume group $OCF_RESKEY_volgrpname does not exist or contains error!" exit $OCF_ERR_GENERIC fi fi return $OCF_SUCCESS } # # 'main' starts here... # if [ $# -ne 1 ]; then usage exit $OCF_ERR_ARGS fi case $1 in meta-data) meta_data exit $OCF_SUCCESS;; methods) VolumeGroup_methods exit $OCF_SUCCESS;; usage) usage exit $OCF_SUCCESS;; *) ;; esac # Everything except usage and meta-data must pass the validate test VolumeGroup_validate_all # What kind of method was invoked? case "$1" in start) VolumeGroup_start ;; stop) VolumeGroup_stop ;; status) VolumeGroup_status ;; monitor) VolumeGroup_monitor ;; validate-all) ;; notify|promote|demote|migrate_from|migrate_to) usage exit $OCF_ERR_UNIMPLEMENTED ;; *) usage exit $OCF_ERR_ARGS ;; esac exit $?