-
Notifications
You must be signed in to change notification settings - Fork 339
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1159 from kgaillot/fixes
New resource agent for node attributes, with other minor updates
- Loading branch information
Showing
5 changed files
with
248 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
#!/bin/sh | ||
# | ||
# ocf:pacemaker:attribute resource agent | ||
# | ||
# Copyright (C) 2016 Andrew Beekhof <andrew@beekhof.net> | ||
# | ||
# This source code is licensed under 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"} | ||
|
||
# Values may be empty string | ||
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"?> | ||
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> | ||
<resource-agent name="attribute" version="1.0"> | ||
<version>1.0</version> | ||
<shortdesc lang="en">Manages a node attribute</shortdesc> | ||
<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> | ||
<parameters> | ||
<parameter name="state" unique="1"> | ||
<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="1"> | ||
<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" unique="0"> | ||
<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" unique="0"> | ||
<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="20" /> | ||
<action name="stop" timeout="20" /> | ||
<action name="monitor" timeout="20" interval="10" depth="0"/> | ||
<action name="reload" timeout="20" /> | ||
<action name="migrate_to" timeout="20" /> | ||
<action name="migrate_from" timeout="20" /> | ||
<action name="validate-all" timeout="20" /> | ||
<action name="meta-data" timeout="5" /> | ||
</actions> | ||
</resource-agent> | ||
END | ||
return $OCF_SUCCESS | ||
} | ||
|
||
validate() { | ||
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 | ||
|
||
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" -o ! -x "$VALIDATE_DIR" ]; then | ||
ocf_exit_reason "insufficient privileges on directory of state file '$OCF_RESKEY_state'" | ||
return $OCF_ERR_PERM | ||
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" != "" -a "$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: expandtab:tabstop=4:softtabstop=4:shiftwidth=4:textwidth=80 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters