diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 06:53:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 06:53:20 +0000 |
commit | e5a812082ae033afb1eed82c0f2df3d0f6bdc93f (patch) | |
tree | a6716c9275b4b413f6c9194798b34b91affb3cc7 /agents/ocf/attribute.in | |
parent | Initial commit. (diff) | |
download | pacemaker-e5a812082ae033afb1eed82c0f2df3d0f6bdc93f.tar.xz pacemaker-e5a812082ae033afb1eed82c0f2df3d0f6bdc93f.zip |
Adding upstream version 2.1.6.upstream/2.1.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'agents/ocf/attribute.in')
-rwxr-xr-x | agents/ocf/attribute.in | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/agents/ocf/attribute.in b/agents/ocf/attribute.in new file mode 100755 index 0000000..ade3a1c --- /dev/null +++ b/agents/ocf/attribute.in @@ -0,0 +1,240 @@ +#!/bin/sh +# +# ocf:pacemaker:attribute resource agent +# +# Copyright 2016-2023 the Pacemaker project contributors +# +# The version control history for this file may have further details. +# +# This source code is licensed under the GNU General Public License version 2 +# or later (GPLv2+) WITHOUT ANY WARRANTY. +# + +USAGE="Usage: $0 {start|stop|monitor|migrate_to|migrate_from|validate-all|meta-data} + +Expects to have a fully populated OCF RA-compliant environment set." + +# Load OCF helper functions +: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} +. "${OCF_FUNCTIONS}" +: ${__OCF_ACTION:="$1"} + +# Ensure certain variables are set and not empty +: ${HA_VARRUN:="/var/run"} +: ${OCF_RESKEY_CRM_meta_globally_unique:="false"} +: ${OCF_RESOURCE_INSTANCE:="undef"} + +DEFAULT_STATE_FILE="${HA_VARRUN%%/}/opa-${OCF_RESOURCE_INSTANCE}.state" +if [ "${OCF_RESKEY_CRM_meta_globally_unique}" = "false" ]; then + # Strip off any trailing clone marker (note + is not portable in sed) + DEFAULT_STATE_FILE=$(echo "$DEFAULT_STATE_FILE" | sed s/:[0-9][0-9]*\.state/.state/) +fi + +DEFAULT_ATTR_NAME="opa-${OCF_RESOURCE_INSTANCE}" +DEFAULT_ACTIVE_VALUE="1" +DEFAULT_INACTIVE_VALUE="0" + +: ${OCF_RESKEY_state:="$DEFAULT_STATE_FILE"} +: ${OCF_RESKEY_name:="$DEFAULT_ATTR_NAME"} + +# If the user did not set a value, use the default. If the user explicitly set +# a value to the empty string, use that (-z "${V+x}" tests whether $V was set). +if [ -z "${OCF_RESKEY_active_value+x}" ]; then + OCF_RESKEY_active_value="$DEFAULT_ACTIVE_VALUE" +fi +if [ -z "${OCF_RESKEY_inactive_value+x}" ]; then + OCF_RESKEY_inactive_value="$DEFAULT_INACTIVE_VALUE" +fi + +usage() { + USAGE_RC=$1 + cat <<END +$USAGE +END + return $USAGE_RC +} + +meta_data() { + cat <<END +<?xml version="1.0"?> +<resource-agent name="attribute" version="@VERSION@"> + <version>1.1</version> + <longdesc lang="en"> +This resource agent controls a node attribute for the node it's running on. +It sets the attribute one way when started, and another way when stopped, +according to the configuration parameters. + </longdesc> + <shortdesc lang="en">Manages a node attribute</shortdesc> + <parameters> + + <parameter name="state" unique-group="state"> + <longdesc lang="en"> +Full path of a temporary file to store the resource state in + </longdesc> + <shortdesc lang="en">State file</shortdesc> + <content type="string" default="${DEFAULT_STATE_FILE}" /> + </parameter> + + <parameter name="name" unique-group="name"> + <longdesc lang="en"> +Name of node attribute to manage + </longdesc> + <shortdesc lang="en">Attribute name</shortdesc> + <content type="string" default="${DEFAULT_ATTR_NAME}" /> + </parameter> + + <parameter name="active_value"> + <longdesc lang="en"> +Value to use for node attribute when resource becomes active (empty string is +discouraged, because monitor cannot distinguish it from a query error) + </longdesc> + <shortdesc lang="en">Attribute value when active</shortdesc> + <content type="string" default="$DEFAULT_ACTIVE_VALUE" /> + </parameter> + + <parameter name="inactive_value"> + <longdesc lang="en"> +Value to use for node attribute when resource becomes inactive + </longdesc> + <shortdesc lang="en">Attribute value when inactive</shortdesc> + <content type="string" default="$DEFAULT_INACTIVE_VALUE" /> + </parameter> + + </parameters> + <actions> + <action name="start" timeout="20s" /> + <action name="stop" timeout="20s" /> + <action name="monitor" timeout="20s" interval="10s" depth="0"/> + <action name="reload" timeout="20s" /> + <action name="migrate_to" timeout="20s" /> + <action name="migrate_from" timeout="20s" /> + <action name="validate-all" timeout="20s" depth="0" /> + <action name="meta-data" timeout="5s" /> + </actions> +</resource-agent> +END + return $OCF_SUCCESS +} + +validate() { + # Host-specific checks + if [ "$OCF_CHECK_LEVEL" = "10" ]; then + VALIDATE_DIR=$(dirname "${OCF_RESKEY_state}") + + if [ ! -d "$VALIDATE_DIR" ]; then + ocf_exit_reason "state file '$OCF_RESKEY_state' does not have a valid directory" + return $OCF_ERR_PERM + fi + + if [ ! -w "$VALIDATE_DIR" ] || [ ! -x "$VALIDATE_DIR" ]; then + ocf_exit_reason "insufficient privileges on directory of state file '$OCF_RESKEY_state'" + return $OCF_ERR_PERM + fi + fi + + if [ "$OCF_RESKEY_active_value" = "$OCF_RESKEY_inactive_value" ]; then + ocf_exit_reason "active value '%s' must be different from inactive value '%s'" \ + "$OCF_RESKEY_active_value" "$OCF_RESKEY_inactive_value" + return $OCF_ERR_CONFIGURED + fi + + return $OCF_SUCCESS +} + +get_attribute() { + GET_LINE=$(attrd_updater -n "$OCF_RESKEY_name" -Q 2>/dev/null) + if [ $? -ne 0 ]; then + echo "" + else + echo "$GET_LINE" | sed -e "s/.* value=\"\(.*\)\"$/\1/" + fi +} + +set_attribute() { + attrd_updater -n "$OCF_RESKEY_name" -U "$1" 2>/dev/null + # TODO if above call is async, loop until get_attribute returns expected value +} + +check_attribute() { + CHECK_VALUE=$(get_attribute) + CHECK_REASON="" + if [ ! -f "$OCF_RESKEY_state" ]; then + if [ "$CHECK_VALUE" != "" ] && [ "$CHECK_VALUE" != "$OCF_RESKEY_inactive_value" ]; then + CHECK_REASON="Node attribute $OCF_RESKEY_name='$CHECK_VALUE' differs from expected value '$OCF_RESKEY_inactive_value'" + return $OCF_ERR_GENERIC + fi + return $OCF_NOT_RUNNING + fi + if [ "$CHECK_VALUE" != "$OCF_RESKEY_active_value" ]; then + CHECK_REASON="Node attribute $OCF_RESKEY_name='$CHECK_VALUE' differs from expected value '$OCF_RESKEY_active_value'" + return $OCF_ERR_GENERIC + fi + return $OCF_SUCCESS +} + +monitor() { + check_attribute + MONITOR_RC=$? + if [ $MONITOR_RC -eq $OCF_ERR_GENERIC ]; then + ocf_exit_reason "$CHECK_REASON" + fi + return $MONITOR_RC +} + +start() { + check_attribute + if [ $? -eq $OCF_SUCCESS ]; then + return $OCF_SUCCESS + fi + + touch "${OCF_RESKEY_state}" 2>/dev/null + if [ $? -ne 0 ]; then + ocf_exit_reason "Unable to manage state file $OCF_RESKEY_state" + return $OCF_ERR_GENERIC + fi + + set_attribute "${OCF_RESKEY_active_value}" + if [ $? -ne 0 ]; then + rm -f "${OCF_RESKEY_state}" + ocf_exit_reason "Unable to set node attribute $OCF_RESKEY_name='$OCF_RESKEY_active_value'" + return $OCF_ERR_GENERIC + fi + + return $OCF_SUCCESS +} + +stop() { + check_attribute + if [ $? -eq $OCF_NOT_RUNNING ]; then + return $OCF_SUCCESS + fi + + rm -f ${OCF_RESKEY_state} + + set_attribute "${OCF_RESKEY_inactive_value}" + if [ $? -ne 0 ]; then + ocf_exit_reason "Unable to set node attribute $OCF_RESKEY_name='$OCF_RESKEY_inactive_value'" + return $OCF_ERR_GENERIC + fi + + return $OCF_SUCCESS +} + +case $__OCF_ACTION in +meta-data) meta_data ;; +start) start ;; +stop) stop ;; +monitor) monitor ;; +# We don't do anything special for live migration, but we support it so that +# other resources that live migrate can depend on this one. +migrate_to) stop ;; +migrate_from) start ;; +reload) start ;; +validate-all) validate ;; +usage|help) usage $OCF_SUCCESS ;; +*) usage $OCF_ERR_UNIMPLEMENTED ;; +esac + +exit $? + +# vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: |