diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index eafb2d10b..e082bac20 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -1,170 +1,171 @@ # # doc: Linux-HA resource agents # # Copyright (C) 2009 Florian Haas # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = $(doc_DATA) $(REFENTRY_STYLESHEET) \ mkappendix.sh ralist.sh CLEANFILES = $(man_MANS) $(xmlfiles) metadata-*.xml STYLESHEET_PREFIX ?= http://docbook.sourceforge.net/release/xsl/current MANPAGES_STYLESHEET ?= $(STYLESHEET_PREFIX)/manpages/docbook.xsl HTML_STYLESHEET ?= $(STYLESHEET_PREFIX)/xhtml/docbook.xsl FO_STYLESHEET ?= $(STYLESHEET_PREFIX)/fo/docbook.xsl REFENTRY_STYLESHEET ?= ra2refentry.xsl XSLTPROC_OPTIONS ?= --xinclude XSLTPROC_MANPAGES_OPTIONS ?= $(XSLTPROC_OPTIONS) XSLTPROC_HTML_OPTIONS ?= $(XSLTPROC_OPTIONS) XSLTPROC_FO_OPTIONS ?= $(XSLTPROC_OPTIONS) radir = $(top_srcdir)/heartbeat # OCF_ROOT=. is necessary due to a sanity check in ocf-shellfuncs # (which tests whether $OCF_ROOT points to a directory metadata-%.xml: $(radir)/% OCF_ROOT=. OCF_FUNCTIONS_DIR=$(radir) $< meta-data > $@ metadata-IPv6addr.xml: ../../heartbeat/IPv6addr OCF_ROOT=. OCF_FUNCTIONS_DIR=$(radir) $< meta-data > $@ # Please note: we can't name the man pages # ocf:heartbeat:. Believe me, I've tried. It looks like it # works, but then it doesn't. While make can deal correctly with # colons in target names (when properly escaped), it royally messes up # when it is deals with _dependencies_ that contain colons. See Bug # 12126 on savannah.gnu.org. But, maybe it gets fixed soon, it was # first reported in 1995 and added to Savannah in in 2005... if BUILD_DOC man_MANS = ocf_heartbeat_AoEtarget.7 \ ocf_heartbeat_AudibleAlarm.7 \ ocf_heartbeat_ClusterMon.7 \ ocf_heartbeat_CTDB.7 \ ocf_heartbeat_Delay.7 \ ocf_heartbeat_Dummy.7 \ ocf_heartbeat_EvmsSCC.7 \ ocf_heartbeat_Evmsd.7 \ ocf_heartbeat_Filesystem.7 \ ocf_heartbeat_ICP.7 \ ocf_heartbeat_IPaddr.7 \ ocf_heartbeat_IPaddr2.7 \ ocf_heartbeat_IPsrcaddr.7 \ ocf_heartbeat_LVM.7 \ ocf_heartbeat_LinuxSCSI.7 \ ocf_heartbeat_MailTo.7 \ ocf_heartbeat_ManageRAID.7 \ ocf_heartbeat_ManageVE.7 \ ocf_heartbeat_Pure-FTPd.7 \ ocf_heartbeat_Raid1.7 \ ocf_heartbeat_Route.7 \ ocf_heartbeat_SAPDatabase.7 \ ocf_heartbeat_SAPInstance.7 \ ocf_heartbeat_SendArp.7 \ ocf_heartbeat_ServeRAID.7 \ ocf_heartbeat_SphinxSearchDaemon.7 \ ocf_heartbeat_Squid.7 \ ocf_heartbeat_Stateful.7 \ ocf_heartbeat_SysInfo.7 \ ocf_heartbeat_VIPArip.7 \ ocf_heartbeat_VirtualDomain.7 \ ocf_heartbeat_WAS.7 \ ocf_heartbeat_WAS6.7 \ ocf_heartbeat_WinPopup.7 \ ocf_heartbeat_Xen.7 \ ocf_heartbeat_Xinetd.7 \ ocf_heartbeat_anything.7 \ ocf_heartbeat_apache.7 \ ocf_heartbeat_asterisk.7 \ ocf_heartbeat_clvm.7 \ ocf_heartbeat_conntrackd.7 \ ocf_heartbeat_db2.7 \ ocf_heartbeat_dhcpd.7 \ ocf_heartbeat_docker.7 \ ocf_heartbeat_eDir88.7 \ ocf_heartbeat_ethmonitor.7 \ ocf_heartbeat_exportfs.7 \ ocf_heartbeat_fio.7 \ ocf_heartbeat_galera.7 \ ocf_heartbeat_iSCSILogicalUnit.7 \ ocf_heartbeat_iSCSITarget.7 \ ocf_heartbeat_iface-bridge.7 \ ocf_heartbeat_iface-vlan.7 \ ocf_heartbeat_ids.7 \ ocf_heartbeat_iscsi.7 \ ocf_heartbeat_jboss.7 \ ocf_heartbeat_kamailio.7 \ ocf_heartbeat_lxc.7 \ ocf_heartbeat_mysql.7 \ ocf_heartbeat_mysql-proxy.7 \ ocf_heartbeat_named.7 \ ocf_heartbeat_nfsnotify.7 \ ocf_heartbeat_nfsserver.7 \ ocf_heartbeat_nginx.7 \ ocf_heartbeat_oracle.7 \ ocf_heartbeat_oralsnr.7 \ ocf_heartbeat_pgsql.7 \ ocf_heartbeat_pingd.7 \ ocf_heartbeat_portblock.7 \ ocf_heartbeat_postfix.7 \ ocf_heartbeat_pound.7 \ ocf_heartbeat_proftpd.7 \ ocf_heartbeat_rsyncd.7 \ ocf_heartbeat_rsyslog.7 \ ocf_heartbeat_scsi2reservation.7 \ ocf_heartbeat_sfex.7 \ ocf_heartbeat_slapd.7 \ + ocf_heartbeat_sg_persist.7 \ ocf_heartbeat_symlink.7 \ ocf_heartbeat_syslog-ng.7 \ ocf_heartbeat_tomcat.7 \ ocf_heartbeat_varnish.7 \ ocf_heartbeat_vmware.7 \ ocf_heartbeat_zabbixserver.7 if USE_IPV6ADDR_AGENT man_MANS += ocf_heartbeat_IPv6addr.7 endif xmlfiles = $(man_MANS:.7=.xml) %.1 %.5 %.7 %.8: %.xml $(XSLTPROC) \ $(XSLTPROC_MANPAGES_OPTIONS) \ $(MANPAGES_STYLESHEET) $< ocf_heartbeat_%.xml: metadata-%.xml $(srcdir)/$(REFENTRY_STYLESHEET) $(XSLTPROC) --novalid \ --stringparam package $(PACKAGE_NAME) \ --stringparam version $(VERSION) \ --output $@ \ $(srcdir)/$(REFENTRY_STYLESHEET) $< ocf_resource_agents.xml: $(xmlfiles) mkappendix.sh ./mkappendix.sh $(xmlfiles) > $@ %.html: %.xml $(XSLTPROC) \ $(XSLTPROC_HTML_OPTIONS) \ --output $@ \ $(HTML_STYLESHEET) $< xml: ocf_resource_agents.xml endif diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am index 330b7f7ed..d9ce755aa 100644 --- a/heartbeat/Makefile.am +++ b/heartbeat/Makefile.am @@ -1,154 +1,155 @@ # Makefile.am for OCF RAs # # Author: Sun Jing Dong # Copyright (C) 2004 IBM # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = $(ocf_SCRIPTS) $(ocfcommon_DATA) \ $(common_DATA) $(hb_DATA) $(dtd_DATA) \ README AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/linux-ha halibdir = $(libexecdir)/heartbeat ocfdir = $(OCF_RA_DIR_PREFIX)/heartbeat dtddir = $(datadir)/$(PACKAGE_NAME) dtd_DATA = ra-api-1.dtd if USE_IPV6ADDR_AGENT ocf_PROGRAMS = IPv6addr else ocf_PROGRAMS = endif if IPV6ADDR_COMPATIBLE halib_PROGRAMS = send_ua else halib_PROGRAMS = endif IPv6addr_SOURCES = IPv6addr.c IPv6addr_utils.c send_ua_SOURCES = send_ua.c IPv6addr_utils.c IPv6addr_LDADD = -lplumb $(LIBNETLIBS) send_ua_LDADD = $(LIBNETLIBS) ocf_SCRIPTS = ClusterMon \ CTDB \ Dummy \ IPaddr \ IPaddr2 \ anything \ AoEtarget \ apache \ asterisk \ nginx \ AudibleAlarm \ clvm \ conntrackd \ db2 \ dhcpd \ Delay \ dnsupdate \ docker \ eDir88 \ EvmsSCC \ Evmsd \ ethmonitor \ exportfs \ Filesystem \ fio \ galera \ ids \ iscsi \ ICP \ IPsrcaddr \ iSCSITarget \ iSCSILogicalUnit \ iface-bridge \ iface-vlan \ jboss \ kamailio \ LinuxSCSI \ LVM \ lxc \ MailTo \ ManageRAID \ ManageVE \ mysql \ mysql-proxy \ named \ nfsnotify \ nfsserver \ oracle \ oralsnr \ pingd \ portblock \ postfix \ pound \ pgsql \ proftpd \ Pure-FTPd \ Raid1 \ Route \ rsyncd \ rsyslog \ SAPDatabase \ SAPInstance \ SendArp \ ServeRAID \ slapd \ SphinxSearchDaemon \ Squid \ Stateful \ SysInfo \ scsi2reservation \ sfex \ + sg_persist \ symlink \ syslog-ng \ tomcat \ VIPArip \ VirtualDomain \ varnish \ vmware \ WAS \ WAS6 \ WinPopup \ Xen \ Xinetd \ zabbixserver ocfcommondir = $(OCF_LIB_DIR_PREFIX)/heartbeat ocfcommon_DATA = ocf-shellfuncs \ ocf-binaries \ ocf-directories \ ocf-returncodes \ ocf-rarun \ apache-conf.sh \ http-mon.sh \ sapdb-nosha.sh \ sapdb.sh \ ora-common.sh \ mysql-common.sh \ findif.sh # Legacy locations hbdir = $(sysconfdir)/ha.d hb_DATA = shellfuncs diff --git a/heartbeat/sg_persist b/heartbeat/sg_persist new file mode 100644 index 000000000..c4af069dd --- /dev/null +++ b/heartbeat/sg_persist @@ -0,0 +1,673 @@ +#!/bin/bash +# +# +# OCF Resource Agent compliant PERSISTENT SCSI RESERVATION resource script. +# +# +# Copyright (c) 2011 Evgeny Nifontov and lwang@suse.com All Rights Reserved. +# +# "Heartbeat drbd OCF Resource Agent: 2007, Lars Marowsky-Bree" was used +# as example of multistate OCF Resource Agent. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Further, this software is distributed without any warranty that it is +# free of the rightful claim of any third person regarding infringement +# or the like. Any license provided herein, whether implied or +# otherwise, applies only to this software file. Patent licenses, if +# any, provided herein do not apply to combinations of this program with +# other software, or any other product whatsoever. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# +# OCF instance parameters +# OCF_RESKEY_sg_persist_binary +# OCF_RESKEY_devs +# OCF_RESKEY_required_devs_nof +# OCF_RESKEY_reservation_type +# OCF_RESKEY_master_score_base +# OCF_RESKEY_master_score_dev_factor +# OCF_RESKEY_master_score_delay +# +# TODO +# +# 1) PROBLEM: devices which were not accessible during 'start' action, will be never registered/reserved +# TODO: 'Master' and 'Salve' registers new devs in 'monitor' action +# TODO: 'Master' reserves new devs in 'monitor' action + +####################################################################### +# Initialization: + +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} +. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs + +# set default values + : ${sg_persist_binary="sg_persist"} # binary name for the resource + : ${devs=""} # device list + : ${required_devs_nof=1} # number of required devices + : ${reservation_type=1} # reservation type + : ${master_score_base=0} # master score base + : ${master_score_dev_factor=100} # device factor for master score + : ${master_score_delay=30} # delay for master score + +####################################################################### + + +meta_data() { + cat < + + +1.1 + + +This resource agent manages SCSI PERSISTENT RESERVATIONS. +"sg_persist" from sg3_utils is used, please see its documentation. +Should be used as multistate (Master/Slave) resource +Slave registers its node id ("crm_node -i") as reservation key ( --param-rk ) on each device in the "devs" list. +Master reservs all devices from "devs" list with reservation "--prout-type" value from "reservation_type" parameter. + +Manages SCSI PERSISTENT RESERVATIONS + + + + +The name of the binary that manages the resource + +the binay name of the resource + + + + + +Device list. Multiple devices can be listed with blank space as separator. +Shell wildcars are allowed. + +device list + + + + + +Minimum number of "working" devices from device list + 1) existing + 2) "sg_persist --read-keys \$device" works (Return code 0) +resource actions "start","monitor","promote" and "validate-all" return "\$OCF_ERR_INSTALLED" +if the actual number of "working" devices is less then "required_devs_nof". +resource actions "stop" and "demote" tries to remove reservations and registration keys from +all working devices, but always return "\$OCF_SUCCESS" + +minimum number of working devices + + + + + +reservation type + +reservation type + + + + + +master_score_base value +"master_score_base" value is used in "master_score" calculation: +master_score = \$master_score_base + \$master_score_dev_factor * \$working_devs +if set to bigger value in sg_persist resource configuration on some node, this node will be "preferred" for master role. + +base master_score value + + + + + +Working device factor in master_score calculation +each "working" device provides additional value to "master_score", +so the node that sees more devices will be preferred for the "Master"-role +Setting it to 0 will disable this behavior. + +working device factor in master_score calculation + + + + + +master/slave decreases/increases its master_score after delay of \$master_score_delay seconds +so if some device gets inaccessible, the slave decreases its master_score first and the resource will no be watched +and after this device reappears again the master increases its master_score first +this can work only if the master_score_delay is bigger then monitor interval on both master and slave +Setting it to 0 will disable this behavior. + +master_score decrease/increase delay time + + + + + + + + + + + + + + + + +END + + exit $OCF_SUCCESS +} + +sg_persist_init() { + + if ! ocf_is_root ; then + ocf_log err "You must be root to perform this operation." + exit $OCF_ERR_PERM + fi + + : ${SG_PERSIST:="$sg_persist_binary"} + check_binary $SG_PERSIST + + ROLE=$OCF_RESKEY_CRM_meta_role + NOW=$(date +%s) + + RESOURCE="${OCF_RESOURCE_INSTANCE}" + MASTER_SCORE_VAR_NAME="master-${OCF_RESOURCE_INSTANCE}" + PENDING_VAR_NAME="pending-$MASTER_SCORE_VAR_NAME" + + #only works with corocync + CRM_NODE="${HA_SBIN_DIR}/crm_node" + NODE_ID_DEC=$($CRM_NODE -i) + + NODE=$($CRM_NODE -l | $GREP $NODE_ID_DEC) + NODE=${NODE#$NODE_ID_DEC } + NODE=${NODE% *} + + MASTER_SCORE_ATTRIBUTE="${HA_SBIN_DIR}/crm_attribute --lifetime=reboot --name=$MASTER_SCORE_VAR_NAME --node=$NODE" + CRM_MASTER="${HA_SBIN_DIR}/crm_master --lifetime=reboot" + PENDING_ATTRIBUTE="${HA_SBIN_DIR}/crm_attribute --lifetime=reboot --name=$PENDING_VAR_NAME --node=$NODE" + + NODE_ID_HEX=$(printf '0x%x' $NODE_ID_DEC) + + if [ -z "$NODE_ID_HEX" ]; then + ocf_log err "Couldn't get node id with \"$CRM_NODE\"" + exit $OCF_ERR_INSTALLED + fi + + ocf_log debug "$RESOURCE: NODE:$NODE, ROLE:$ROLE, NODE_ID DEC:$NODE_ID_DEC HEX:$NODE_ID_HEX" + + DEVS=${OCF_RESKEY_devs:=$devs} + REQUIRED_DEVS_NOF=${OCF_RESKEY_required_devs_nof:=$required_devs_nof} + RESERVATION_TYPE=${OCF_RESKEY_reservation_type:=$reservation_type} + MASTER_SCORE_BASE=${OCF_RESKEY_master_score_base:=$master_score_base} + MASTER_SCORE_DEV_FACTOR=${OCF_RESKEY_master_score_dev_factor:=$master_score_dev_factor} + MASTER_SCORE_DELAY=${OCF_RESKEY_master_score_delay:=$master_score_delay} + + ocf_log debug "$RESOURCE: DEVS=$DEVS" + ocf_log debug "$RESOURCE: REQUIRED_DEVS_NOF=$REQUIRED_DEVS_NOF" + ocf_log debug "$RESOURCE: RESERVATION_TYPE=$RESERVATION_TYPE" + ocf_log debug "$RESOURCE: MASTER_SCORE_BASE=$MASTER_SCORE_BASE" + ocf_log debug "$RESOURCE: MASTER_SCORE_DEV_FACTOR=$MASTER_SCORE_DEV_FACTOR" + ocf_log debug "$RESOURCE: MASTER_SCORE_DELAY=$MASTER_SCORE_DELAY" + + #expand path wildcards + DEVS=$(echo $DEVS) + + if [ -z "$DEVS" ]; then + ocf_log err "\"devs\" not defined" + exit $OCF_ERR_INSTALLED + fi + + sg_persist_check_devs + sg_persist_get_status +} + +sg_persist_action_usage() { + cat <&1` + if [ $? -eq $OCF_SUCCESS ]; then + WORKING_DEVS+=($dev) + echo $READ_KEYS | $GREP $NODE_ID_HEX >/dev/null + if [ $? -eq 0 ]; then + REGISTERED_DEVS+=($dev) + + READ_RESERVATION=`ocf_run $SG_PERSIST --in --read-reservation $dev 2>&1` + if [ $? -eq $OCF_SUCCESS ]; then + echo $READ_RESERVATION | $GREP $NODE_ID_HEX >/dev/null + if [ $? -eq 0 ]; then + RESERVED_DEVS+=($dev) + fi + + reservation_key=`echo $READ_RESERVATION | $GREP -o 'Key=0x[0-9a-f]*' | $GREP -o '0x[0-9a-f]*'` + if [ -n "$reservation_key" ]; then + DEVS_WITH_RESERVATION+=($dev) + RESERVATION_KEYS+=($reservation_key) + fi + fi + fi + fi + done + + WORKING_DEVS_NOF=${#WORKING_DEVS[*]} + + ocf_log debug "$RESOURCE: working devices: `sg_persist_echo_array ${WORKING_DEVS[*]}`" + ocf_log debug "$RESOURCE: number of working devices: $WORKING_DEVS_NOF" + + ocf_log debug "$RESOURCE: registered devices: `sg_persist_echo_array ${REGISTERED_DEVS[*]}`" + ocf_log debug "$RESOURCE: reserved devices: `sg_persist_echo_array ${RESERVED_DEVS[*]}`" + ocf_log debug "$RESOURCE: devices with reservation: `sg_persist_echo_array ${DEVS_WITH_RESERVATION[*]}`" + ocf_log debug "$RESOURCE: reservation keys: `sg_persist_echo_array ${RESERVATION_KEYS[*]}`" + + MASTER_SCORE=$(($MASTER_SCORE_BASE + $MASTER_SCORE_DEV_FACTOR*$WORKING_DEVS_NOF)) + ocf_log debug "$RESOURCE: master_score: $MASTER_SCORE_BASE + $MASTER_SCORE_DEV_FACTOR*$WORKING_DEVS_NOF = $MASTER_SCORE" + +} + +sg_persist_check_devs() { + + for dev in $DEVS + do + if [ -e "$dev" ]; then + EXISTING_DEVS+=($dev) + fi + done + + EXISTING_DEVS_NOF=${#EXISTING_DEVS[*]} + if [ $EXISTING_DEVS_NOF -lt $REQUIRED_DEVS_NOF ]; then + ocf_log err "Number of existing devices=$EXISTING_DEVS_NOF less then required_devs_nof=$REQUIRED_DEVS_NOF" + exit $OCF_ERR_INSTALLED + fi + +} + +sg_persist_is_registered() { + for registered_dev in ${REGISTERED_DEVS[*]} + do + if [ "$registered_dev" == "$1" ]; then + return 0 + fi + done + return 1 +} + +sg_persist_get_reservation_key() { + for array_index in ${!DEVS_WITH_RESERVATION[*]} + do + if [ "${DEVS_WITH_RESERVATION[$array_index]}" == "$1" ]; then + echo ${RESERVATION_KEYS[$array_index]} + return 0 + fi + done + echo "" +} + +sg_persist_echo_array() { + str_count=0 + arr_str="" + + for str in "$@" + do + arr_str="$arr_str[$str_count]:$str " + str_count=$(($str_count+1)) + done + echo $arr_str +} + +sg_persist_parse_act_pending() { + + ACT_PENDING_TS=0 + ACT_PENDING_SCORE=0 + + if [ -n "$ACT_PENDING" ]; then + ACT_PENDING_TS=${ACT_PENDING%%_*} + ACT_PENDING_SCORE=${ACT_PENDING##*_} + fi +} + +sg_persist_clear_pending() { + if [ -n "$ACT_PENDING" ]; then + DO_PENDING_UPDATE="YES" + NEW_PENDING="" + fi +} + +sg_persist_new_master_score() { + DO_MASTER_SCORE_UPDATE="YES" + NEW_MASTER_SCORE=$1 +} + +sg_persist_new_pending() { + DO_PENDING_UPDATE="YES" + NEW_PENDING=$1 +} + + +# Functions invoked by resource manager actions + +sg_persist_action_start() { + + ocf_run $MASTER_SCORE_ATTRIBUTE --update=$MASTER_SCORE + ocf_run $PENDING_ATTRIBUTE --update="" + + if [ $WORKING_DEVS_NOF -lt $REQUIRED_DEVS_NOF ]; then + ocf_log err "$RESOURCE: Number of working devices=$WORKING_DEVS_NOF less then required_devs_nof=$REQUIRED_DEVS_NOF" + exit $OCF_ERR_GENERIC + fi + + for dev in ${WORKING_DEVS[*]} + do + if sg_persist_is_registered $dev ; then + : OK + else + ocf_run $SG_PERSIST --out --register --param-rk=0 --param-sark=$NODE_ID_HEX $dev + if [ $? -ne $OCF_SUCCESS ] + then + return $OCF_ERR_GENERIC + fi + fi + done + + return $OCF_SUCCESS +} + +sg_persist_action_stop() { + + if [ ${#REGISTERED_DEVS[*]} -eq 0 ]; then + ocf_log debug "$RESOURCE stop: already no registrations" + else + # Clear preference for becoming master + ocf_run $MASTER_SCORE_ATTRIBUTE --delete + ocf_run $PENDING_ATTRIBUTE --delete + + for dev in ${REGISTERED_DEVS[*]} + do + ocf_run $SG_PERSIST --out --register --param-rk=$NODE_ID_HEX --param-sark=0 $dev + done + fi + + return $OCF_SUCCESS +} + +sg_persist_action_monitor() { + + ACT_MASTER_SCORE=`ocf_run -q $MASTER_SCORE_ATTRIBUTE --query --quiet 2>&1` + ocf_log debug "$RESOURCE monitor: ACT_MASTER_SCORE=$ACT_MASTER_SCORE" + + ACT_PENDING=`ocf_run $PENDING_ATTRIBUTE --query --quiet 2>&1` + ocf_log debug "$RESOURCE monitor: ACT_PENDING=$ACT_PENDING" + + sg_persist_parse_act_pending + ocf_log debug "$RESOURCE monitor: ACT_PENDING_TS=$ACT_PENDING_TS" + ocf_log debug "$RESOURCE monitor: ACT_PENDING_VAL=$ACT_PENDING_SCORE" + + ocf_log debug "$MASTER_SCORE, $ACT_MASTER_SCORE, $ROLE" + + DO_MASTER_SCORE_UPDATE="NO" + DO_PENDING_UPDATE="NO" + if [ -n "$ACT_MASTER_SCORE" ] + then + if [ $ACT_MASTER_SCORE -eq $MASTER_SCORE ]; then + sg_persist_clear_pending + else + case $ROLE in + Master) + if [ $MASTER_SCORE -lt $ACT_MASTER_SCORE ]; then + if [ -n "$ACT_PENDING" ] + then + if [ $(($NOW-$ACT_PENDING_TS-$MASTER_SCORE_DELAY)) -ge 0 ]; then + sg_persist_new_master_score $MASTER_SCORE + sg_persist_clear_pending + fi + else + if [ $MASTER_SCORE_DELAY -eq 0 ]; then + sg_persist_new_master_score $MASTER_SCORE + sg_persist_clear_pending + else + sg_persist_new_pending "${NOW}_${MASTER_SCORE}" + fi + fi + else + sg_persist_new_master_score $MASTER_SCORE + sg_persist_clear_pending + fi + ;; + + Slave) + if [ $MASTER_SCORE -gt $ACT_MASTER_SCORE ]; then + if [ -n "$ACT_PENDING" ]; then + if [ $(($NOW-$ACT_PENDING_TS-$MASTER_SCORE_DELAY)) -ge 0 ]; then + sg_persist_new_master_score $MASTER_SCORE + sg_persist_clear_pending + fi + else + if [ $MASTER_SCORE_DELAY -eq 0 ]; then + sg_persist_new_master_score $MASTER_SCORE + sg_persist_clear_pending + else + sg_persist_new_pending "${NOW}_${MASTER_SCORE}" + fi + fi + else + sg_persist_new_master_score $MASTER_SCORE + sg_persist_clear_pending + fi + ;; + + *) + ;; + + esac + fi + fi + + if [ $DO_MASTER_SCORE_UPDATE == "YES" ]; then + ocf_run $MASTER_SCORE_ATTRIBUTE --update=$NEW_MASTER_SCORE + fi + + if [ $DO_PENDING_UPDATE == "YES" ]; then + ocf_run $PENDING_ATTRIBUTE --update=$NEW_PENDING + fi + + if [ ${#REGISTERED_DEVS[*]} -eq 0 ]; then + ocf_log debug "$RESOURCE monitor: no registrations" + return $OCF_NOT_RUNNING + fi + + if [ ${#RESERVED_DEVS[*]} -eq ${#WORKING_DEVS[*]} ]; then + return $OCF_RUNNING_MASTER + fi + + if [ ${#REGISTERED_DEVS[*]} -eq ${#WORKING_DEVS[*]} ]; then + if [ $RESERVATION_TYPE -eq 7 ] || [ $RESERVATION_TYPE -eq 8 ]; then + if [ ${#DEVS_WITH_RESERVATION[*]} -gt 0 ]; then + return $OCF_RUNNING_MASTER + else + return $OCF_SUCCESS + fi + else + return $OCF_SUCCESS + fi + fi + + ocf_log err "$RESOURCE monitor: unexpected state" + + return $OCF_ERR_GENERIC +} + +sg_persist_action_promote() { + + if [ ${#RESERVED_DEVS[*]} -gt 0 ]; then + ocf_log info "$RESOURCE promote: already master" + return $OCF_SUCCESS + fi + + for dev in ${WORKING_DEVS[*]} + do + reservation_key=`sg_persist_get_reservation_key $dev` + case $RESERVATION_TYPE in + 1|3|5|6) + if [ -z "$reservation_key" ]; then + ocf_run $SG_PERSIST --out --reserve --param-rk=$NODE_ID_HEX --prout-type=$RESERVATION_TYPE $dev + if [ $? -ne $OCF_SUCCESS ]; then + return $OCF_ERR_GENERIC + fi + else + ocf_run $SG_PERSIST --out --preempt --param-sark=$reservation_key --param-rk=$NODE_ID_HEX --prout-type=$RESERVATION_TYPE $dev + if [ $? -ne $OCF_SUCCESS ]; then + return $OCF_ERR_GENERIC + fi + fi + ;; + + 7|8) + if [ -z "$reservation_key" ]; then + ocf_run $SG_PERSIST --out --reserve --param-rk=$NODE_ID_HEX --prout-type=$RESERVATION_TYPE $dev + if [ $? -ne $OCF_SUCCESS ] + then + return $OCF_ERR_GENERIC + fi + else + ocf_log info "$RESOURCE promote: there already exist an reservation holder, all registrants become reservation holders" + return $OCF_SUCCESS + fi + ;; + + *) + return $OCF_ERR_ARGS + ;; + + esac + done + + return $OCF_SUCCESS +} + +sg_persist_action_demote() { + case $RESERVATION_TYPE in + 1|3|5|6) + if [ ${#RESERVED_DEVS[*]} -eq 0 ]; then + ocf_log info "$RESOURCE demote: already slave" + return $OCF_SUCCESS + fi + + for dev in ${RESERVED_DEVS[*]} + do + ocf_run $SG_PERSIST --out --release --param-rk=$NODE_ID_HEX --prout-type=$RESERVATION_TYPE $dev + if [ $? -ne $OCF_SUCCESS ]; then + return $OCF_ERR_GENERIC + fi + done + ;; + + 7|8) #in case of 7/8, --release won't release the reservation unless unregister the key. + if [ ${#REGISTERED_DEVS[*]} -eq 0 ]; then + ocf_log info "$RESOURCE demote: already slave" + return $OCF_SUCCESS + fi + + for dev in ${REGISTERED_DEVS[*]} + do + ocf_run $SG_PERSIST --out --register --param-rk=$NODE_ID_HEX --param-sark=0 $dev + if [ $? -ne $OCF_SUCCESS ]; then + return $OCF_ERR_GENERIC + fi + done + ;; + + *) + return $OCF_ERR_ARGS + ;; + esac + + return $OCF_SUCCESS +} + +sg_persist_action_notify() { + local n_type="$OCF_RESKEY_CRM_meta_notify_type" + local n_op="$OCF_RESKEY_CRM_meta_notify_operation" + set -- $OCF_RESKEY_CRM_meta_notify_active_resource + local n_active="$#" + set -- $OCF_RESKEY_CRM_meta_notify_stop_resource + local n_stop="$#" + set -- $OCF_RESKEY_CRM_meta_notify_start_resource + local n_start="$#" + + ocf_log debug "$RESOURCE notify: $n_type for $n_op - counts: active $n_active - starting $n_start - stopping $n_stop" + + return $OCF_SUCCESS +} + +sg_persist_action_validate_all () { + + if [ "$OCF_RESKEY_CRM_meta_master_max" != "1" ] && [ "$RESERVATION_TYPE" != "7" ] && [ "$RESERVATION_TYPE" != "8" ]; then + ocf_log err "Master options misconfigured." + exit $OCF_ERR_CONFIGURED + fi + + return $OCF_SUCCESS +} + +if [ $# -ne 1 ]; then + echo "Incorrect parameter count." + sg_persist_action_usage + exit $OCF_ERR_ARGS +fi + +ACTION=$1 +case $ACTION in + meta-data) + meta_data + ;; + + validate-all) + sg_persist_init + sg_persist_action_validate_all + ;; + + start|promote|monitor|stop|demote) + ocf_log debug "$RESOURCE: starting action \"$ACTION\"" + sg_persist_init + sg_persist_action_$ACTION + exit $? + ;; + + notify) + sg_persist_action_notify + exit $? + ;; + + usage|help) + sg_persist_action_usage + exit $OCF_SUCCESS + ;; + + *) + sg_persist_action_usage + exit $OCF_ERR_ARGS + ;; + + esac diff --git a/tools/ocft/Makefile.am b/tools/ocft/Makefile.am index 780654400..6218bc370 100644 --- a/tools/ocft/Makefile.am +++ b/tools/ocft/Makefile.am @@ -1,59 +1,60 @@ # Author: John Shi # jshi@suse.de # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = $(ocftcfgs_DATA) $(ocft_DATA) sbin_SCRIPTS = ocft ocftcfgsdir = $(datadir)/$(PACKAGE_NAME)/ocft/configs ocftcfgs_DATA = apache \ IPaddr2 \ IPaddr2v4 \ IPaddr2v6 \ IPv6addr \ Filesystem \ LVM \ Raid1 \ IPsrcaddr \ MailTo \ jboss \ mysql \ mysql-proxy \ pgsql \ db2 \ oracle \ drbd.linbit \ exportfs \ exportfs-multidir \ nfsserver \ portblock \ iscsi \ named \ postfix \ + sg_persist \ tomcat \ Xinetd \ Xen \ VirtualDomain \ SendArp ocftdir = $(datadir)/$(PACKAGE_NAME)/ocft ocft_DATA = README \ README.zh_CN \ caselib diff --git a/tools/ocft/sg_persist b/tools/ocft/sg_persist new file mode 100644 index 000000000..f11d36df9 --- /dev/null +++ b/tools/ocft/sg_persist @@ -0,0 +1,225 @@ +# sg_persist +# Before use sg_persist ocft test case you have to prepare to make pacemaker +# can be started successfully because sg_persist RA needs to use the result of +# `crm_node -i` as sg_persist register key. + +CONFIG + Agent sg_persist + AgentRoot /usr/lib/ocf/resource.d/heartbeat + InstallPackage sg3_utils + HangTimeout 20 + +VARIABLE + + # Please set the disk you want to test + #OCFT_DEVS="/dev/disk/by-id/scsi-14945540000000000844965720e6e555176b19461345d68d5" + OCFT_DEVS= + + # please set the IP addrees of the other server. + IP_2= + +SETUP-AGENT + # start pacemaker to get node_id through crm_node -i + systemctl start pacemaker + +CLEANUP-AGENT + +CASE-BLOCK required_args + Env HA_SBIN_DIR="" + Env OCF_RESKEY_devs="$OCFT_DEVS" + Env OCF_RESKEY_reservation_type=1 + Env OCF_RESKEY_CRM_meta_notify=true + Env OCF_RESKEY_CRM_meta_master_max=1 + +CASE-BLOCK required_args_error + Env HA_SBIN_DIR="" + Env OCF_RESKEY_devs="$OCFT_DEVS" + Env OCF_RESKEY_reservation_type=1 + Env OCF_RESKEY_CRM_meta_notify=true + Env OCF_RESKEY_CRM_meta_master_max=2 + +CASE-BLOCK required_args_type_5 + Env HA_SBIN_DIR="" + Env OCF_RESKEY_devs="$OCFT_DEVS" + Env OCF_RESKEY_reservation_type=5 + Env OCF_RESKEY_CRM_meta_notify=true + Env OCF_RESKEY_CRM_meta_master_max=1 + +CASE-BLOCK required_args_type_7 + Env HA_SBIN_DIR="" + Env OCF_RESKEY_devs="$OCFT_DEVS" + Env OCF_RESKEY_reservation_type=7 + Env OCF_RESKEY_CRM_meta_notify=true + Env OCF_RESKEY_CRM_meta_master_max=2 + +CASE-BLOCK default_status + AgentRun stop + +CASE-BLOCK prepare + Include required_args + Include default_status + +CASE-BLOCK prepare_type_5 + Include required_args_type_5 + Include default_status + +CASE-BLOCK prepare_type_7 + Include required_args_type_7 + Include default_status + +CASE "check base env" + Include prepare + AgentRun start OCF_SUCCESS + +CASE "check base env: unset 'OCF_RESKEY_sg_persist_devs'" + Include prepare + Unenv OCF_RESKEY_devs + AgentRun start OCF_ERR_INSTALLED + +CASE "validate all" + Include required_args + AgentRun validate-all OCF_SUCCESS + +CASE "validate all--type:5" + Include required_args_type_5 + AgentRun validate-all OCF_SUCCESS + +CASE "validate all--type:7" + Include required_args_type_7 + AgentRun validate-all OCF_SUCCESS + +CASE "validate all--error configured" + Include required_args_error + AgentRun validate-all OCF_ERR_CONFIGURED + +CASE "normal start" + Include prepare + AgentRun start OCF_SUCCESS + +CASE "normal stop" + Include prepare + AgentRun start + AgentRun stop OCF_SUCCESS + +CASE "double start" + Include prepare + AgentRun start + AgentRun start OCF_SUCCESS + +CASE "double stop" + Include prepare + AgentRun stop + AgentRun stop OCF_SUCCESS + +CASE "monitor when running" + Include prepare + AgentRun start + AgentRun monitor OCF_SUCCESS + +CASE "monitor when not running" + Include prepare + AgentRun stop + AgentRun monitor OCF_NOT_RUNNING + +CASE "Primary/Secondary monitor" + Include prepare + AgentRun start + AgentRun promote + AgentRun monitor OCF_RUNNING_MASTER + AgentRun demote + AgentRun monitor OCF_SUCCESS + AgentRun stop + +CASE "promote/demote test in single-primary mode" + Include prepare + Include@$IP_2 prepare + + # start + AgentRun start + AgentRun@$IP_2 start + + # promote local first + AgentRun promote OCF_SUCCESS + + # demote local prepare for remote promote + AgentRun demote + + # remote promote + AgentRun@$IP_2 promote OCF_SUCCESS + AgentRun@$IP_2 monitor OCF_RUNNING_MASTER + AgentRun monitor OCF_SUCCESS + + # promote local then promote(by preempt) remote, which will cause local OCF_NOT_RUNNING + AgentRun promote OCF_SUCCESS + AgentRun monitor OCF_RUNNING_MASTER + AgentRun@$IP_2 monitor OCF_NOT_RUNNING + + # remove all reservation registration + AgentRun demote + AgentRun stop + AgentRun@$IP_2 stop + + +CASE "normal start--type 5" + Include prepare_type_5 + Include@$IP_2 prepare_type_5 + AgentRun start OCF_SUCCESS + AgentRun@$IP_2 start OCF_SUCCESS + +CASE "promote/demote test in single-primary mode" + Include prepare_type_5 + Include@$IP_2 prepare_type_5 + + # start + AgentRun start + AgentRun@$IP_2 start + + # promote local first + AgentRun promote OCF_SUCCESS + AgentRun monitor OCF_RUNNING_MASTER + + # demote local prepare for remote promote + AgentRun demote + # remote promote + AgentRun@$IP_2 promote OCF_SUCCESS + AgentRun@$IP_2 monitor OCF_RUNNING_MASTER + AgentRun monitor OCF_SUCCESS + + # promote local then promote(by preempt) remote, which will cause local OCF_NOT_RUNNING + AgentRun promote OCF_SUCCESS + AgentRun monitor OCF_RUNNING_MASTER + AgentRun@$IP_2 monitor OCF_NOT_RUNNING + + # remove all reservation registration + AgentRun demote + AgentRun stop + AgentRun@$IP_2 stop + +CASE "normal start--type 7: 2 masters" + Include prepare_type_7 + Include@$IP_2 prepare_type_7 + AgentRun start OCF_SUCCESS + AgentRun@$IP_2 start OCF_SUCCESS + + +CASE "Primary/Primary monitor--type 7" + Include prepare_type_7 + Include@$IP_2 prepare_type_7 + + AgentRun start OCF_SUCCESS + AgentRun@$IP_2 start OCF_SUCCESS + + AgentRun promote OCF_SUCCESS + AgentRun monitor OCF_RUNNING_MASTER + + AgentRun@$IP_2 promote OCF_SUCCESS + AgentRun monitor OCF_RUNNING_MASTER + AgentRun@$IP_2 monitor OCF_RUNNING_MASTER + + AgentRun demote OCF_SUCCESS + AgentRun monitor OCF_NOT_RUNNING + AgentRun@$IP_2 demote OCF_SUCCESS + AgentRun@$IP_2 monitor OCF_NOT_RUNNING + + AgentRun stop + AgentRun@$IP_2 stop