diff --git a/heartbeat/ZFS b/heartbeat/ZFS new file mode 100755 index 000000000..a629c69c0 --- /dev/null +++ b/heartbeat/ZFS @@ -0,0 +1,211 @@ +#!/bin/sh +# +# License: GNU General Public License (GPL) +# Support: zfs@lists.illumos.org +# Written by: Saso Kiselkov +# +# This script manages ZFS pools +# It can import a ZFS pool or export it +# +# usage: $0 {start|stop|status|monitor|validate-all|meta-data} +# +# The "start" arg imports a ZFS pool. +# The "stop" arg exports it. +# +# OCF parameters are as follows +# OCF_RESKEY_pool - the pool to import/export +# +####################################################################### +# Initialization: + +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} +. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs +: ${HELPERS_DIR=${OCF_ROOT}/lib/heartbeat/helpers} + +# Set the variable below to '1' to enable zpool import/export logging. +# This is useful to determine how long these operations take on your system. +# DEBUG=0 +DEBUGLOG="/var/log/ZFS_cluster_debug.log" + +USAGE="usage: $0 {start|stop|status|monitor|validate-all|meta-data}"; + +####################################################################### + +debug_log () { + if [ "$DEBUG" -eq 1 ]; then + echo "`date`:${OCF_RESKEY_pool}:" $@ >> "$DEBUGLOG" + fi +} + +meta_data() { + cat < + + +1.0 + +This script manages ZFS pools +It can import a ZFS pool or export it + +Manages ZFS pools + + + + +The name of the ZFS pool to manage, e.g. "tank". + +ZFS pool name + + + + +Arguments to zpool import, e.g. "-d /dev/disk/by-id". + +Import arguments + + + + + + + + + + + + +END + exit $OCF_SUCCESS +} + +zpool_is_imported () { + zpool list -H "$OCF_RESKEY_pool" > /dev/null +} + +# Forcibly imports a ZFS pool, mounting all of its auto-mounted filesystems +# (as configured in the `mountpoint' and `canmount' properties) +# If the pool is already imported, no operation is taken. +# You can use the zfs-helper script to assist pool setup before and/or +# after import. +zpool_import () { + if ! zpool_is_imported; then + debug_log "starting import" + if [ -x "${HELPERS_DIR}/zfs-helper" ]; then + debug_log "pre-import: start" + "${HELPERS_DIR}/zfs-helper" pre-import "$OCF_RESKEY_pool" + debug_log "pre-import: done" + fi + + # The meanings of the options to import are as follows: + # -f : import even if the pool is marked as imported to another + # system - the system may have failed and not exported it + # cleanly. + # -o cachefile=none : the import should be temporary, so do not + # cache it persistently (across machine reboots). We want + # the CRM to explicitly control imports of this pool. + if zpool import -f $OCF_RESKEY_importargs -o cachefile=none "$OCF_RESKEY_pool" ; then + debug_log "import successful" + if [ -x "${HELPERS_DIR}/zfs-helper" ]; then + debug_log "post-import: starting" + "${HELPERS_DIR}/zfs-helper" post-import "$OCF_RESKEY_pool" + debug_log "post-import: done" + fi + return $OCF_SUCCESS + else + debug_log "import failed" + return $OCF_ERR_GENERIC + fi + fi +} + +# Forcibly exports a ZFS pool, unmounting all of its filesystems in the process +# If the pool is not imported, no operation is taken. +# You can use the zfs-helper script to assist pool setup before and/or +# after export. +zpool_export () { + if zpool_is_imported; then + debug_log "starting export" + if [ -x "${HELPERS_DIR}/zfs-helper" ]; then + debug_log "pre-export: start" + "${HELPERS_DIR}/zfs-helper" pre-export "$OCF_RESKEY_pool" + debug_log "pre-export: done" + fi + + # -f : force the export, even if we have mounted filesystems + # Please note that this may fail with a "busy" error if there are + # other kernel subsystems accessing the pool (e.g. SCSI targets). + # Always make sure the pool export is last in your failover logic. + if zpool export -f "$OCF_RESKEY_pool" ; then + debug_log "export successful" + if [ -x "${HELPERS_DIR}/zfs-helper" ]; then + debug_log "post-export: starting" + "${HELPERS_DIR}/zfs-helper" post-export "$OCF_RESKEY_pool" + debug_log "post-export: done" + fi + return $OCF_SUCCESS + else + debug_log "export failed" + return $OCF_ERR_GENERIC + fi + fi +} + +# Monitors the health of a ZFS pool resource. Please note that this only +# checks whether the pool is imported and functional, not whether it has +# any degraded devices (use monitoring systems such as Zabbix for that). +zpool_monitor () { + # If the pool is not imported, then we can't monitor its health + if ! zpool_is_imported; then + return $OCF_NOT_RUNNING + fi + + # Check the pool status + HEALTH=`zpool list -H -o health "$OCF_RESKEY_pool"` + case "$HEALTH" in + ONLINE|DEGRADED) return $OCF_SUCCESS;; + FAULTED) return $OCF_NOT_RUNNING;; + *) return $OCF_ERR_GENERIC;; + esac +} + +# Validates whether we can import a given ZFS pool +zpool_validate () { + # Check that the `zpool' command is known + if ! which zpool > /dev/null; then + return $OCF_ERR_INSTALLED + fi + + # If the pool is imported, then it is obviously valid + if zpool_is_imported; then + return $OCF_SUCCESS + fi + + # Check that the pool can be imported + if zpool import $OCF_RESKEY_importargs | grep 'pool:' | grep "\\<$OCF_RESKEY_pool\\>" > /dev/null; + then + return $OCF_SUCCESS + else + return $OCF_ERR_CONFIGURED + fi +} + +usage () { + echo $USAGE >&2 + return $1 +} + +if [ $# -ne 1 ]; then + usage $OCF_ERR_ARGS +fi + +case $1 in + meta-data) meta_data;; + start) zpool_import;; + stop) zpool_export;; + status|monitor) zpool_monitor;; + validate-all) zpool_validate;; + usage) usage $OCF_SUCCESS;; + *) usage $OCF_ERR_UNIMPLEMENTED;; +esac + +exit $?