summaryrefslogtreecommitdiffstats
path: root/heartbeat/ZFS
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xheartbeat/ZFS212
1 files changed, 212 insertions, 0 deletions
diff --git a/heartbeat/ZFS b/heartbeat/ZFS
new file mode 100755
index 0000000..560c1b5
--- /dev/null
+++ b/heartbeat/ZFS
@@ -0,0 +1,212 @@
+#!/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
+
+# Defaults
+OCF_RESKEY_pool_default=""
+OCF_RESKEY_importargs_default=""
+OCF_RESKEY_importforce_default=true
+
+: ${OCF_RESKEY_pool=${OCF_RESKEY_pool_default}}
+: ${OCF_RESKEY_importargs=${OCF_RESKEY_importargs_default}}
+: ${OCF_RESKEY_importforce=${OCF_RESKEY_importforce_default}}
+
+USAGE="usage: $0 {start|stop|status|monitor|validate-all|meta-data}";
+
+#######################################################################
+
+meta_data() {
+ cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="ZFS" version="1.0">
+<version>1.0</version>
+<longdesc lang="en">
+This script manages ZFS pools
+It can import a ZFS pool or export it
+</longdesc>
+<shortdesc lang="en">Manages ZFS pools</shortdesc>
+
+<parameters>
+<parameter name="pool" unique="1" required="1">
+<longdesc lang="en">
+The name of the ZFS pool to manage, e.g. "tank".
+</longdesc>
+<shortdesc lang="en">ZFS pool name</shortdesc>
+<content type="string" default="${OCF_RESKEY_pool_default}" />
+</parameter>
+<parameter name="importargs" unique="0" required="0">
+<longdesc lang="en">
+Arguments to zpool import, e.g. "-d /dev/disk/by-id".
+</longdesc>
+<shortdesc lang="en">Import arguments</shortdesc>
+<content type="string" default="${OCF_RESKEY_importargs_default}" />
+</parameter>
+<parameter name="importforce" unique="0" required="0">
+<longdesc lang="en">
+zpool import is given the -f option.
+</longdesc>
+<shortdesc lang="en">Import is forced</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_importforce_default}" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="60s" />
+<action name="stop" timeout="60s" />
+<action name="monitor" depth="0" timeout="30s" interval="5s" />
+<action name="validate-all" timeout="30s" />
+<action name="meta-data" timeout="5s" />
+</actions>
+</resource-agent>
+END
+ exit $OCF_SUCCESS
+}
+
+zpool_is_imported () {
+ # Check if ZFS kstats exists
+ if [ -d /proc/spl/kstat/zfs/ ] ; then
+ # Check the existence of kstats for the pool. If the stats exists, the pool was imported.
+ [ -d /proc/spl/kstat/zfs/"${OCF_RESKEY_pool}" ]
+ rc=$?
+ else
+ # If ZFS kstats do not exists, fallback to the standard check
+ rc=$(zpool list -H "$OCF_RESKEY_pool" > /dev/null)
+ fi
+ return $rc
+}
+
+# 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.
+zpool_import () {
+ if ! zpool_is_imported; then
+ ocf_log debug "${OCF_RESKEY_pool}:starting import"
+
+ # 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 ocf_is_true "${OCF_RESKEY_importforce}"; then
+ FORCE=-f
+ else
+ FORCE=""
+ fi
+ if zpool import $FORCE $OCF_RESKEY_importargs -o cachefile=none "$OCF_RESKEY_pool" ; then
+ ocf_log debug "${OCF_RESKEY_pool}:import successful"
+ return $OCF_SUCCESS
+ else
+ ocf_log debug "${OCF_RESKEY_pool}: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.
+zpool_export () {
+ if zpool_is_imported; then
+ ocf_log debug "${OCF_RESKEY_pool}:starting export"
+
+ # -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
+ ocf_log debug "${OCF_RESKEY_pool}:export successful"
+ return $OCF_SUCCESS
+ else
+ ocf_log debug "${OCF_RESKEY_pool}: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
+ # Since version 0.7.10 status can be obtained without locks
+ # https://github.com/zfsonlinux/zfs/pull/7563
+ if [ -f /proc/spl/kstat/zfs/$OCF_RESKEY_pool/state ] ; then
+ HEALTH=$(cat /proc/spl/kstat/zfs/$OCF_RESKEY_pool/state)
+ else
+ HEALTH=$(zpool list -H -o health "$OCF_RESKEY_pool")
+ fi
+
+ 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 $?