resource-agent package update
Signed-off-by: basebuilder_pel7ppc64bebuilder0 <basebuilder@powerel.org>master
parent
df4eea222a
commit
1199308520
|
|
@ -0,0 +1,418 @@
|
|||
From bd60deaa906cc5fe1cd46549b1318d2b940395ef Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Thu, 11 Jun 2015 08:41:50 -0500
|
||||
Subject: [PATCH] NovaCompute agent
|
||||
|
||||
---
|
||||
doc/man/Makefile.am | 1 +
|
||||
heartbeat/Makefile.am | 4 +
|
||||
heartbeat/NovaCompute | 363 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 368 insertions(+)
|
||||
create mode 100644 heartbeat/NovaCompute
|
||||
|
||||
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
|
||||
index 653e818..69acf3a 100644
|
||||
--- a/doc/man/Makefile.am
|
||||
+++ b/doc/man/Makefile.am
|
||||
@@ -73,6 +73,7 @@ man_MANS = ocf_heartbeat_AoEtarget.7 \
|
||||
ocf_heartbeat_MailTo.7 \
|
||||
ocf_heartbeat_ManageRAID.7 \
|
||||
ocf_heartbeat_ManageVE.7 \
|
||||
+ ocf_heartbeat_NovaCompute.7 \
|
||||
ocf_heartbeat_Pure-FTPd.7 \
|
||||
ocf_heartbeat_Raid1.7 \
|
||||
ocf_heartbeat_Route.7 \
|
||||
diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am
|
||||
index e4ed4fd..b77c589 100644
|
||||
--- a/heartbeat/Makefile.am
|
||||
+++ b/heartbeat/Makefile.am
|
||||
@@ -29,6 +29,8 @@ halibdir = $(libexecdir)/heartbeat
|
||||
|
||||
ocfdir = $(OCF_RA_DIR_PREFIX)/heartbeat
|
||||
|
||||
+ospdir = $(OCF_RA_DIR_PREFIX)/openstack
|
||||
+
|
||||
dtddir = $(datadir)/$(PACKAGE_NAME)
|
||||
dtd_DATA = ra-api-1.dtd
|
||||
|
||||
@@ -50,6 +52,8 @@ send_ua_SOURCES = send_ua.c IPv6addr_utils.c
|
||||
IPv6addr_LDADD = -lplumb $(LIBNETLIBS)
|
||||
send_ua_LDADD = $(LIBNETLIBS)
|
||||
|
||||
+osp_SCRIPTS = NovaCompute
|
||||
+
|
||||
ocf_SCRIPTS = ClusterMon \
|
||||
CTDB \
|
||||
Dummy \
|
||||
diff --git a/heartbeat/NovaCompute b/heartbeat/NovaCompute
|
||||
new file mode 100644
|
||||
index 0000000..f71abeb
|
||||
--- /dev/null
|
||||
+++ b/heartbeat/NovaCompute
|
||||
@@ -0,0 +1,363 @@
|
||||
+#!/bin/sh
|
||||
+#
|
||||
+#
|
||||
+# NovaCompute agent manages compute daemons.
|
||||
+#
|
||||
+# Copyright (c) 2015
|
||||
+#
|
||||
+# 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.
|
||||
+#
|
||||
+
|
||||
+#######################################################################
|
||||
+# Initialization:
|
||||
+
|
||||
+###
|
||||
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
+###
|
||||
+
|
||||
+: ${__OCF_ACTION=$1}
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+meta_data() {
|
||||
+ cat <<END
|
||||
+<?xml version="1.0"?>
|
||||
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
+<resource-agent name="NovaCompute" version="1.0">
|
||||
+<version>1.0</version>
|
||||
+
|
||||
+<longdesc lang="en">
|
||||
+OpenStack Nova Compute Server.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">OpenStack Nova Compute Server</shortdesc>
|
||||
+
|
||||
+<parameters>
|
||||
+
|
||||
+<parameter name="auth_url" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Authorization URL for connecting to keystone in admin context
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Authorization URL</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="username" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Username for connecting to keystone in admin context
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Username</shortdesc>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="password" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Password for connecting to keystone in admin context
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Password</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="tenant_name" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Tenant name for connecting to keystone in admin context.
|
||||
+Note that with Keystone V3 tenant names are only unique within a domain.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Tenant name</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="domain" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+DNS domain in which hosts live, useful when the cluster uses short names and nova uses FQDN
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">DNS domain</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="endpoint_type" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Nova API location (internal, public or admin URL)
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Nova API location (internal, public or admin URL)</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="no_shared_storage" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Disable shared storage recovery for instances. Use at your own risk!
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Disable shared storage recovery for instances</shortdesc>
|
||||
+<content type="boolean" default="0" />
|
||||
+</parameter>
|
||||
+
|
||||
+</parameters>
|
||||
+
|
||||
+<actions>
|
||||
+<action name="start" timeout="120" />
|
||||
+<action name="stop" timeout="300" />
|
||||
+<action name="monitor" timeout="20" interval="10" depth="0"/>
|
||||
+<action name="validate-all" timeout="20" />
|
||||
+<action name="meta-data" timeout="5" />
|
||||
+<action name="notify" timeout="600" />
|
||||
+</actions>
|
||||
+</resource-agent>
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+# don't exit on TERM, to test that lrmd makes sure that we do exit
|
||||
+trap sigterm_handler TERM
|
||||
+sigterm_handler() {
|
||||
+ ocf_log info "They use TERM to bring us down. No such luck."
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+nova_usage() {
|
||||
+ cat <<END
|
||||
+usage: $0 {start|stop|monitor|notify|validate-all|meta-data}
|
||||
+
|
||||
+Expects to have a fully populated OCF RA-compliant environment set.
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+nova_pid() {
|
||||
+ ps axf | grep python.*nova-compute | grep -v grep | awk '{print $1}'
|
||||
+}
|
||||
+
|
||||
+nova_start() {
|
||||
+ nova_monitor
|
||||
+ if [ $? = $OCF_SUCCESS ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ export LIBGUESTFS_ATTACH_METHOD=appliance
|
||||
+ su nova -s /bin/sh -c /usr/bin/nova-compute &
|
||||
+
|
||||
+ rc=$OCF_NOT_RUNNING
|
||||
+ ocf_log info "Waiting for nova to start"
|
||||
+ while [ $rc != $OCF_SUCCESS ]; do
|
||||
+ nova_monitor
|
||||
+ rc=$?
|
||||
+ done
|
||||
+
|
||||
+## TEMPORARY disable call to "service enable" that seems to create
|
||||
+## issues and it is unnecessary since fence_compute doesn't disable
|
||||
+## the service
|
||||
+
|
||||
+# if [ "x${OCF_RESKEY_domain}" != x ]; then
|
||||
+# export service_host="${NOVA_HOST}.${OCF_RESKEY_domain}"
|
||||
+# else
|
||||
+# export service_host="${NOVA_HOST}"
|
||||
+# fi
|
||||
+
|
||||
+# python -c "import os; from novaclient import client as nova_client; nova = nova_client.Client('2', os.environ.get('OCF_RESKEY_username'), os.environ.get('OCF_RESKEY_password'), os.environ.get('OCF_RESKEY_tenant_name'), os.environ.get('OCF_RESKEY_auth_url')); nova.services.enable(os.environ.get('service_host'), 'nova-compute');"
|
||||
+
|
||||
+# rc=$?
|
||||
+# if [ $rc != 0 ]; then
|
||||
+# ocf_exit_reason "nova.services.enable failed $rc"
|
||||
+# exit $OCF_NOT_RUNNING
|
||||
+# fi
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+nova_stop() {
|
||||
+ pid=$(nova_pid)
|
||||
+ if [ "x$pid" != x ]; then
|
||||
+ su nova -c "kill -TERM $pid" -s /bin/bash
|
||||
+ fi
|
||||
+
|
||||
+ while [ "x$pid" != x ]; do
|
||||
+ sleep 1
|
||||
+ pid=$(nova_pid)
|
||||
+ done
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+nova_monitor() {
|
||||
+ pid=$(nova_pid)
|
||||
+ if [ "x$pid" != x ]; then
|
||||
+ ## TEMPORARY disable call to fence_compute to avoid noise on first
|
||||
+ ## first startup due to nova-compute not being fast enough to populate
|
||||
+ ## the db and fence_compute checking if node exists and it's enabled
|
||||
+ #state=$(fence_compute ${fence_options} -o status -n $NOVA_HOST | grep Status)
|
||||
+ #if [ "x$state" = "xStatus: ON" ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ #else
|
||||
+ # ocf_exit_reason "Nova status: $state"
|
||||
+ # return $OCF_ERR_GENERIC
|
||||
+ #fi
|
||||
+ fi
|
||||
+
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+}
|
||||
+
|
||||
+nova_notify() {
|
||||
+ if [ "x${OCF_RESKEY_CRM_meta_notify_operation}" != "xstop" ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ elif [ "x${OCF_RESKEY_CRM_meta_notify_type}" != "xpost" ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ # Only the first node not stopping performs evacuates for now
|
||||
+ # Can we allow all of them to do it? It would make this block much simpler.
|
||||
+ for host in ${OCF_RESKEY_CRM_meta_notify_active_uname}; do
|
||||
+ for stop in ${OCF_RESKEY_CRM_meta_notify_stop_uname}; do
|
||||
+ if [ "$stop" = "$host" ]; then
|
||||
+ : $host is one of the nodes that is stopping
|
||||
+
|
||||
+ elif [ "x$(echo ${host} | awk -F. '{print $1}')" != "x$(uname -n | awk -F. '{print $1}')" ]; then
|
||||
+ : We are not the first non-stopping node
|
||||
+ return $OCF_SUCCESS
|
||||
+
|
||||
+ else
|
||||
+ # Also repeat for any peer NOT in active_uname somehow?
|
||||
+ for node in $OCF_RESKEY_CRM_meta_notify_stop_uname; do
|
||||
+ ocf_log info "Performing evacuations for $node"
|
||||
+ fence_compute ${fence_options} -o reboot -n $node
|
||||
+ done
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+ done
|
||||
+ done
|
||||
+}
|
||||
+
|
||||
+nova_validate() {
|
||||
+ rc=$OCF_SUCCESS
|
||||
+ fence_options=""
|
||||
+
|
||||
+ check_binary openstack-config
|
||||
+ check_binary fence_compute
|
||||
+ check_binary nova-compute
|
||||
+
|
||||
+ if [ ! -f /etc/nova/nova.conf ]; then
|
||||
+ ocf_exit_reason "/etc/nova/nova.conf not found"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_auth_url}" ]; then
|
||||
+ ocf_exit_reason "auth_url not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -k ${OCF_RESKEY_auth_url}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_username}" ]; then
|
||||
+ ocf_exit_reason "username not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -l ${OCF_RESKEY_username}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_password}" ]; then
|
||||
+ ocf_exit_reason "password not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -p ${OCF_RESKEY_password}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_tenant_name}" ]; then
|
||||
+ ocf_exit_reason "tenant_name not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -t ${OCF_RESKEY_tenant_name}"
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_domain}" ]; then
|
||||
+ fence_options="${fence_options} -d ${OCF_RESKEY_domain}"
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_no_shared_storage}" ]; then
|
||||
+ if ocf_is_true "${OCF_RESKEY_no_shared_storage}"; then
|
||||
+ fence_options="${fence_options} --no-shared-storage"
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_endpoint_type}" ]; then
|
||||
+ case ${OCF_RESKEY_endpoint_type} in
|
||||
+ adminURL|publicURL|internalURL) ;;
|
||||
+ *)
|
||||
+ ocf_exit_reason "endpoint_type ${OCF_RESKEY_endpoint_type} not valid. Use adminURL or publicURL or internalURL"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ ;;
|
||||
+ esac
|
||||
+ fence_options="${fence_options} -e ${OCF_RESKEY_endpoint_type}"
|
||||
+ fi
|
||||
+
|
||||
+ # we take a chance here and hope that host is either not configured
|
||||
+ # or configured in nova.conf
|
||||
+
|
||||
+ NOVA_HOST=$(openstack-config --get /etc/nova/nova.conf DEFAULT host 2>/dev/null)
|
||||
+ if [ $? = 1 ]; then
|
||||
+ if [ "x${OCF_RESKEY_domain}" != x ]; then
|
||||
+ NOVA_HOST=$(uname -n | awk -F. '{print $1}')
|
||||
+ else
|
||||
+ NOVA_HOST=$(uname -n)
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ # We only need to check a configured value, calculated ones are fine
|
||||
+ openstack-config --get /etc/nova/nova.conf DEFAULT host 2>/dev/null
|
||||
+ if [ $? = 0 ]; then
|
||||
+ if [ "x${OCF_RESKEY_domain}" != x ]; then
|
||||
+ short_host=$(uname -n | awk -F. '{print $1}')
|
||||
+ if [ "x$NOVA_HOST" != "x${short_host}" ]; then
|
||||
+ ocf_exit_reason "Invalid Nova host name, must be ${short_host} in order for instance recovery to function"
|
||||
+ rc=$OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ elif [ "x$NOVA_HOST" != "x$(uname -n)" ]; then
|
||||
+ ocf_exit_reason "Invalid Nova host name, must be $(uname -n) in order for instance recovery to function"
|
||||
+ rc=$OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if [ $rc != $OCF_SUCCESS ]; then
|
||||
+ exit $rc
|
||||
+ fi
|
||||
+ return $rc
|
||||
+}
|
||||
+
|
||||
+case $__OCF_ACTION in
|
||||
+meta-data) meta_data
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+usage|help) nova_usage
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+esac
|
||||
+
|
||||
+nova_validate
|
||||
+
|
||||
+case $__OCF_ACTION in
|
||||
+start) nova_start;;
|
||||
+stop) nova_stop;;
|
||||
+monitor) nova_monitor;;
|
||||
+notify) nova_notify;;
|
||||
+validate-all) exit $OCF_SUCCESS;;
|
||||
+*) nova_usage
|
||||
+ exit $OCF_ERR_UNIMPLEMENTED
|
||||
+ ;;
|
||||
+esac
|
||||
+rc=$?
|
||||
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
|
||||
+exit $rc
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
diff --git a/heartbeat/apache b/heartbeat/apache
|
||||
index 726e8fb..1369804 100755
|
||||
--- a/heartbeat/apache
|
||||
+++ b/heartbeat/apache
|
||||
@@ -63,7 +63,8 @@ fi
|
||||
LOCALHOST="http://localhost"
|
||||
HTTPDOPTS="-DSTATUS"
|
||||
DEFAULT_IBMCONFIG=/opt/IBMHTTPServer/conf/httpd.conf
|
||||
-DEFAULT_NORMCONFIG="/etc/apache2/httpd.conf"
|
||||
+DEFAULT_SUSECONFIG="/etc/apache2/httpd.conf"
|
||||
+DEFAULT_RHELCONFIG="/etc/httpd/conf/httpd.conf"
|
||||
#
|
||||
# You can also set
|
||||
# HTTPD
|
||||
@@ -82,7 +83,8 @@ CMD=`basename $0`
|
||||
# assumed if no config file is specified. If this command is
|
||||
# invoked as *IBM*, then the default config file name is
|
||||
# $DEFAULT_IBMCONFIG, otherwise the default config file
|
||||
-# will be $DEFAULT_NORMCONFIG.
|
||||
+# will be either $DEFAULT_RHELCONFIG or $DEFAULT_SUSECONFIG depending
|
||||
+# on which is detected.
|
||||
usage() {
|
||||
cat <<-!
|
||||
usage: $0 action
|
||||
@@ -146,7 +148,7 @@ validate_default_config() {
|
||||
# the relevant config is generated and valid. We're also taking
|
||||
# this opportunity to enable mod_status if it's not present.
|
||||
validate_default_suse_config() {
|
||||
- if [ "$CONFIGFILE" = "$DEFAULT_NORMCONFIG" ] && \
|
||||
+ if [ "$CONFIGFILE" = "$DEFAULT_SUSECONFIG" ] && \
|
||||
grep -Eq '^Include[[:space:]]+/etc/apache2/sysconfig.d/include.conf' "$CONFIGFILE"
|
||||
then
|
||||
[ -x "/usr/sbin/a2enmod" ] && ocf_run -q /usr/sbin/a2enmod status
|
||||
@@ -336,6 +338,16 @@ apache_monitor() {
|
||||
esac
|
||||
}
|
||||
|
||||
+detect_default_config()
|
||||
+{
|
||||
+ if [ -f $DEFAULT_SUSECONFIG ]; then
|
||||
+ echo $DEFAULT_SUSECONFIG
|
||||
+ else
|
||||
+ echo $DEFAULT_RHELCONFIG
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+
|
||||
apache_meta_data(){
|
||||
cat <<END
|
||||
<?xml version="1.0"?>
|
||||
@@ -373,7 +385,7 @@ This file is parsed to provide defaults for various other
|
||||
resource agent parameters.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">configuration file path</shortdesc>
|
||||
-<content type="string" default="/etc/apache2/httpd.conf" />
|
||||
+<content type="string" default="$(detect_default_config)" />
|
||||
</parameter>
|
||||
|
||||
<parameter name="httpd">
|
||||
@@ -548,7 +560,7 @@ find_httpd_prog() {
|
||||
if [ "X$OCF_RESKEY_httpd" != X -a "X$HTTPD" != X ]; then
|
||||
ocf_log info "Using $HTTPD as HTTPD"
|
||||
fi
|
||||
- DefaultConfig=$DEFAULT_NORMCONFIG
|
||||
+ DefaultConfig=$(detect_default_config)
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
From a165410d95a7976e5249530b08d4dbeca7a7df27 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Wed, 2 Oct 2013 15:43:56 -0500
|
||||
Subject: [PATCH] Fix: VirtualDomain: Fixes comparison of uninitialized variable during force stop
|
||||
|
||||
---
|
||||
heartbeat/VirtualDomain | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
index b7ac912..04b4390 100755
|
||||
--- a/heartbeat/VirtualDomain
|
||||
+++ b/heartbeat/VirtualDomain
|
||||
@@ -295,7 +295,7 @@ VirtualDomain_Start() {
|
||||
force_stop()
|
||||
{
|
||||
local out ex
|
||||
- local status
|
||||
+ local status=0
|
||||
|
||||
ocf_log info "Issuing forced shutdown (destroy) request for domain ${DOMAIN_NAME}."
|
||||
out=$(virsh $VIRSH_OPTIONS destroy ${DOMAIN_NAME} 2>&1)
|
||||
--
|
||||
1.7.1
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
From f00dcaf19467e3d96d9790d386b860b53ca381f9 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Mon, 7 Oct 2013 19:37:43 -0500
|
||||
Subject: [PATCH] High: VirtualDomain: Ensure it is possible to manage a libvirt domain defined outside of VirtualDomain
|
||||
|
||||
---
|
||||
heartbeat/VirtualDomain | 17 +++++++++++++++++
|
||||
1 files changed, 17 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
index f7ed100..8d5e181 100755
|
||||
--- a/heartbeat/VirtualDomain
|
||||
+++ b/heartbeat/VirtualDomain
|
||||
@@ -257,6 +257,15 @@ VirtualDomain_Status() {
|
||||
return $rc
|
||||
}
|
||||
|
||||
+verify_undefined() {
|
||||
+ for dom in `virsh --connect=${OCF_RESKEY_hypervisor} list --all --name`; do
|
||||
+ if [ "$dom" = "$DOMAIN_NAME" ]; then
|
||||
+ virsh $VIRSH_OPTIONS undefine $DOMAIN_NAME > /dev/null 2>&1
|
||||
+ return
|
||||
+ fi
|
||||
+ done
|
||||
+}
|
||||
+
|
||||
VirtualDomain_Start() {
|
||||
local snapshotimage
|
||||
|
||||
@@ -276,6 +285,14 @@ VirtualDomain_Start() {
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
+ # Make sure domain is undefined before creating.
|
||||
+ # The 'create' command guarantees that the domain will be
|
||||
+ # undefined on shutdown, but requires the domain to be undefined.
|
||||
+ # if a user defines the domain
|
||||
+ # outside of this agent, we have to ensure that the domain
|
||||
+ # is restored to an 'undefined' state before creating.
|
||||
+ verify_undefined
|
||||
+
|
||||
virsh $VIRSH_OPTIONS create ${OCF_RESKEY_config}
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
--
|
||||
1.7.1
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
From bd3b09252eedbeeab2635f82259714975702257e Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Mon, 20 Jan 2014 10:29:23 -0600
|
||||
Subject: [PATCH] High: VirtualDomain: Fixes parsing domain name from xml file.
|
||||
|
||||
If the domain xml is not generated by virsh, it is possible
|
||||
VirtualDomain will not be able to detect the domain's name
|
||||
from the xml file. This is a result of the parsing command
|
||||
not taking into account trailing whitespace characters.
|
||||
---
|
||||
heartbeat/VirtualDomain | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
index 3ca4f6d..11c8df9 100755
|
||||
--- a/heartbeat/VirtualDomain
|
||||
+++ b/heartbeat/VirtualDomain
|
||||
@@ -565,7 +565,7 @@ if [ ! -r $OCF_RESKEY_config ]; then
|
||||
fi
|
||||
|
||||
# Retrieve the domain name from the xml file.
|
||||
-DOMAIN_NAME=`egrep '.*<name>.*</name>$' ${OCF_RESKEY_config} | sed -e 's/.*<name>\(.*\)<\/name>$/\1/' 2>/dev/null`
|
||||
+DOMAIN_NAME=`egrep '[[:space:]]*<name>.*</name>[[:space:]]*$' ${OCF_RESKEY_config} | sed -e 's/[[:space:]]*<name>\(.*\)<\/name>[[:space:]]*$/\1/' 2>/dev/null`
|
||||
if [ -z $DOMAIN_NAME ]; then
|
||||
ocf_log err "This is unexpected. Cannot determine domain name."
|
||||
exit $OCF_ERR_GENERIC
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
index 2f62df4..bc326e5 100755
|
||||
--- a/heartbeat/nfsserver
|
||||
+++ b/heartbeat/nfsserver
|
||||
@@ -307,6 +307,10 @@ prepare_directory ()
|
||||
[ -d "$fp/$STATD_DIR/sm.bak" ] || mkdir -p "$fp/$STATD_DIR/sm.bak"
|
||||
[ -n "`id -u rpcuser`" -a "`id -g rpcuser`" ] && chown -R rpcuser.rpcuser "$fp/$STATD_DIR"
|
||||
|
||||
+ [ -f "$fp/etab" ] || touch "$fp/etab"
|
||||
+ [ -f "$fp/xtab" ] || touch "$fp/xtab"
|
||||
+ [ -f "$fp/rmtab" ] || touch "$fp/rmtab"
|
||||
+
|
||||
[ $SELINUX_ENABLED -eq 0 ] && chcon -R "$SELINUX_LABEL" "$fp"
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,250 @@
|
|||
From 3afd24d578006d68746f9ce35321d0ed34df92e2 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Mon, 25 Aug 2014 15:01:13 -0500
|
||||
Subject: [PATCH 3/4] High: doc: Add pcs to man page example section
|
||||
|
||||
PCS and CRM SHELL now have their own example sections in the
|
||||
resource-agent man pages. Below is an example of the CRM SHELL
|
||||
and PCS examples for the IPaddr2 agent.
|
||||
|
||||
EXAMPLE CRM SHELL
|
||||
The following is an example configuration for a IPaddr2 resource using the crm(8) shell:
|
||||
|
||||
primitive p_IPaddr2 ocf:heartbeat:IPaddr2 \
|
||||
params \
|
||||
ip=string \
|
||||
op monitor depth="0" timeout="20s" interval="10s"
|
||||
|
||||
EXAMPLE PCS
|
||||
The following is an example configuration for a IPaddr2 resource using pcs(8)
|
||||
|
||||
pcs resource create p_IPaddr2 ocf:heartbeat:IPaddr2 \
|
||||
ip=string \
|
||||
op monitor depth="0" timeout="20s" interval="10s"
|
||||
---
|
||||
doc/man/ra2refentry.xsl | 141 +++++++++++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 123 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/doc/man/ra2refentry.xsl b/doc/man/ra2refentry.xsl
|
||||
index 41a60aa..ac148ef 100644
|
||||
--- a/doc/man/ra2refentry.xsl
|
||||
+++ b/doc/man/ra2refentry.xsl
|
||||
@@ -50,7 +50,8 @@
|
||||
<xsl:apply-templates select="$this" mode="description"/>
|
||||
<xsl:apply-templates select="$this" mode="parameters"/>
|
||||
<xsl:apply-templates select="$this" mode="actions"/>
|
||||
- <xsl:apply-templates select="$this" mode="example"/>
|
||||
+ <xsl:apply-templates select="$this" mode="examplecrmsh"/>
|
||||
+ <xsl:apply-templates select="$this" mode="examplepcs"/>
|
||||
<xsl:apply-templates select="$this" mode="seealso"/>
|
||||
</xsl:template>
|
||||
|
||||
@@ -403,10 +404,10 @@
|
||||
</xsl:template>
|
||||
|
||||
|
||||
- <!-- Mode Example -->
|
||||
- <xsl:template match="resource-agent" mode="example">
|
||||
+ <!-- Mode Example CRM Shell-->
|
||||
+ <xsl:template match="resource-agent" mode="examplecrmsh">
|
||||
<refsection>
|
||||
- <title>Example</title>
|
||||
+ <title>Example CRM Shell</title>
|
||||
<para>
|
||||
<xsl:text>The following is an example configuration for a </xsl:text>
|
||||
<xsl:value-of select="@name"/>
|
||||
@@ -428,7 +429,7 @@
|
||||
<xsl:text> \
|
||||
params \
|
||||
</xsl:text>
|
||||
- <xsl:apply-templates select="parameters" mode="example"/>
|
||||
+ <xsl:apply-templates select="parameters" mode="examplecrmsh"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="@name"/><xsl:text> \</xsl:text>
|
||||
@@ -440,7 +441,7 @@
|
||||
<xsl:text>
|
||||
meta allow-migrate="true" \</xsl:text>
|
||||
</xsl:if>
|
||||
- <xsl:apply-templates select="actions" mode="example"/>
|
||||
+ <xsl:apply-templates select="actions" mode="examplecrmsh"/>
|
||||
</programlisting>
|
||||
<!-- Insert a master/slave set definition if the resource
|
||||
agent supports promotion and demotion -->
|
||||
@@ -457,15 +458,15 @@
|
||||
</refsection>
|
||||
</xsl:template>
|
||||
|
||||
- <xsl:template match="parameters" mode="example">
|
||||
- <xsl:apply-templates select="parameter[@required = 1]" mode="example"/>
|
||||
+ <xsl:template match="parameters" mode="examplecrmsh">
|
||||
+ <xsl:apply-templates select="parameter[@required = 1]" mode="examplecrmsh"/>
|
||||
</xsl:template>
|
||||
|
||||
- <xsl:template match="parameter" mode="example">
|
||||
+ <xsl:template match="parameter" mode="examplecrmsh">
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:text>=</xsl:text>
|
||||
- <xsl:apply-templates select="content" mode="example"/>
|
||||
+ <xsl:apply-templates select="content" mode="examplecrmsh"/>
|
||||
<xsl:text> \</xsl:text>
|
||||
<xsl:if test="following-sibling::parameter/@required = 1">
|
||||
<xsl:text>
|
||||
@@ -473,7 +474,7 @@
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
- <xsl:template match="content" mode="example">
|
||||
+ <xsl:template match="content" mode="examplecrmsh">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@default != ''">
|
||||
<xsl:text>"</xsl:text>
|
||||
@@ -486,23 +487,23 @@
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
- <xsl:template match="actions" mode="example">
|
||||
+ <xsl:template match="actions" mode="examplecrmsh">
|
||||
<!-- In the CRM shell example, show only the monitor action -->
|
||||
- <xsl:apply-templates select="action[@name = 'monitor']" mode="example"/>
|
||||
+ <xsl:apply-templates select="action[@name = 'monitor']" mode="examplecrmsh"/>
|
||||
</xsl:template>
|
||||
|
||||
- <xsl:template match="action" mode="example">
|
||||
+ <xsl:template match="action" mode="examplecrmsh">
|
||||
<xsl:text>
|
||||
op </xsl:text>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:text> </xsl:text>
|
||||
- <xsl:apply-templates select="@*" mode="example"/>
|
||||
+ <xsl:apply-templates select="@*" mode="examplecrmsh"/>
|
||||
<xsl:if test="following-sibling::action/@name = 'monitor'">
|
||||
<xsl:text>\</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
- <xsl:template match="action/@*" mode="example">
|
||||
+ <xsl:template match="action/@*" mode="examplecrmsh">
|
||||
<xsl:choose>
|
||||
<xsl:when test="name() = 'name'"><!-- suppress --></xsl:when>
|
||||
<xsl:otherwise>
|
||||
@@ -517,9 +518,113 @@
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
- <xsl:template match="longdesc" mode="example"/>
|
||||
+ <xsl:template match="longdesc" mode="examplecrmsh"/>
|
||||
|
||||
- <xsl:template match="shortdesc" mode="example"/>
|
||||
+ <xsl:template match="shortdesc" mode="examplecrmsh"/>
|
||||
+
|
||||
+ <!-- Mode Example PCS-->
|
||||
+ <xsl:template match="resource-agent" mode="examplepcs">
|
||||
+ <refsection>
|
||||
+ <title>Example PCS</title>
|
||||
+ <para>
|
||||
+ <xsl:text>The following is an example configuration for a </xsl:text>
|
||||
+ <xsl:value-of select="@name"/>
|
||||
+ <xsl:text> resource using </xsl:text>
|
||||
+ <citerefentry><refentrytitle>pcs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
+ </para>
|
||||
+ <programlisting>
|
||||
+ <xsl:text>pcs resource create p_</xsl:text>
|
||||
+ <xsl:value-of select="@name"/>
|
||||
+ <xsl:text> </xsl:text>
|
||||
+ <xsl:value-of select="$class"/>
|
||||
+ <xsl:text>:</xsl:text>
|
||||
+ <xsl:value-of select="$provider"/>
|
||||
+ <xsl:text>:</xsl:text>
|
||||
+ <xsl:choose>
|
||||
+ <xsl:when test="parameters/parameter[@required = 1]">
|
||||
+ <xsl:value-of select="@name"/>
|
||||
+ <xsl:text> \
|
||||
+</xsl:text>
|
||||
+ <xsl:apply-templates select="parameters" mode="examplepcs"/>
|
||||
+ </xsl:when>
|
||||
+ <xsl:otherwise>
|
||||
+ <xsl:value-of select="@name"/><xsl:text> \</xsl:text>
|
||||
+ </xsl:otherwise>
|
||||
+ </xsl:choose>
|
||||
+ <xsl:apply-templates select="actions" mode="examplepcs"/>
|
||||
+
|
||||
+ <!-- Insert a master/slave set definition if the resource
|
||||
+ agent supports promotion and demotion -->
|
||||
+ <xsl:if test="actions/action/@name = 'promote' and actions/action/@name = 'demote'">
|
||||
+ <xsl:text>--master</xsl:text>
|
||||
+ </xsl:if>
|
||||
+ </programlisting>
|
||||
+
|
||||
+ </refsection>
|
||||
+ </xsl:template>
|
||||
+
|
||||
+ <xsl:template match="parameters" mode="examplepcs">
|
||||
+ <xsl:apply-templates select="parameter[@required = 1]" mode="examplepcs"/>
|
||||
+ </xsl:template>
|
||||
+
|
||||
+ <xsl:template match="parameter" mode="examplepcs">
|
||||
+ <xsl:text> </xsl:text>
|
||||
+ <xsl:value-of select="@name"/>
|
||||
+ <xsl:text>=</xsl:text>
|
||||
+ <xsl:apply-templates select="content" mode="examplepcs"/>
|
||||
+ <xsl:text> \</xsl:text>
|
||||
+ <xsl:if test="following-sibling::parameter/@required = 1">
|
||||
+ <xsl:text>
|
||||
+</xsl:text>
|
||||
+ </xsl:if>
|
||||
+ </xsl:template>
|
||||
+
|
||||
+ <xsl:template match="content" mode="examplepcs">
|
||||
+ <xsl:choose>
|
||||
+ <xsl:when test="@default != ''">
|
||||
+ <xsl:text>"</xsl:text>
|
||||
+ <xsl:value-of select="@default"/>
|
||||
+ <xsl:text>"</xsl:text>
|
||||
+ </xsl:when>
|
||||
+ <xsl:otherwise>
|
||||
+ <replaceable><xsl:value-of select="@type"/></replaceable>
|
||||
+ </xsl:otherwise>
|
||||
+ </xsl:choose>
|
||||
+ </xsl:template>
|
||||
+
|
||||
+ <xsl:template match="actions" mode="examplepcs">
|
||||
+ <!-- In the CRM shell example, show only the monitor action -->
|
||||
+ <xsl:apply-templates select="action[@name = 'monitor']" mode="examplepcs"/>
|
||||
+ </xsl:template>
|
||||
+
|
||||
+ <xsl:template match="action" mode="examplepcs">
|
||||
+ <xsl:text>
|
||||
+ op </xsl:text>
|
||||
+ <xsl:value-of select="@name"/>
|
||||
+ <xsl:text> </xsl:text>
|
||||
+ <xsl:apply-templates select="@*" mode="examplepcs"/>
|
||||
+ <xsl:if test="following-sibling::action/@name = 'monitor'">
|
||||
+ <xsl:text>\</xsl:text>
|
||||
+ </xsl:if>
|
||||
+ </xsl:template>
|
||||
+
|
||||
+ <xsl:template match="action/@*" mode="examplepcs">
|
||||
+ <xsl:choose>
|
||||
+ <xsl:when test="name() = 'name'"><!-- suppress --></xsl:when>
|
||||
+ <xsl:otherwise>
|
||||
+ <xsl:value-of select="name()"/>
|
||||
+ <xsl:text>="</xsl:text>
|
||||
+ <xsl:value-of select="current()"/>
|
||||
+ <xsl:text>" </xsl:text>
|
||||
+ </xsl:otherwise>
|
||||
+ </xsl:choose>
|
||||
+ <xsl:if test="following-sibling::*">
|
||||
+ <xsl:text> </xsl:text>
|
||||
+ </xsl:if>
|
||||
+ </xsl:template>
|
||||
+
|
||||
+ <xsl:template match="longdesc" mode="examplepcs"/>
|
||||
+ <xsl:template match="shortdesc" mode="examplepcs"/>
|
||||
|
||||
<xsl:template match="resource-agent" mode="seealso">
|
||||
<refsection>
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
From c954c6470fe61c73396b45ca75310d146997f81b Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Wed, 29 Apr 2015 11:16:18 -0500
|
||||
Subject: [PATCH 5/6] db2 support
|
||||
|
||||
---
|
||||
heartbeat/db2 | 60 +++++++++++++++++++++++++++++++++++++++++++++--------------
|
||||
1 file changed, 46 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/db2 b/heartbeat/db2
|
||||
index f9db2f8..fed2d86 100755
|
||||
--- a/heartbeat/db2
|
||||
+++ b/heartbeat/db2
|
||||
@@ -132,6 +132,9 @@ END
|
||||
db2_validate() {
|
||||
local db2home db2sql db2instance
|
||||
|
||||
+ # db2 uses korn shell
|
||||
+ check_binary "ksh"
|
||||
+
|
||||
# check required instance vars
|
||||
if [ -z "$OCF_RESKEY_instance" ]
|
||||
then
|
||||
@@ -208,6 +211,14 @@ db2_validate() {
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
+master_score()
|
||||
+{
|
||||
+ if ! have_binary "crm_master"; then
|
||||
+ return
|
||||
+ fi
|
||||
+
|
||||
+ crm_master $*
|
||||
+}
|
||||
|
||||
#
|
||||
# Run the given command as db2 instance user
|
||||
@@ -380,8 +391,17 @@ db2_check_config_compatibility() {
|
||||
#
|
||||
db2_start() {
|
||||
local output start_cmd db
|
||||
+ local start_opts="dbpartitionnum $db2node"
|
||||
+
|
||||
+ # If we detect that db partitions are not in use, and no
|
||||
+ # partition is explicitly specified, activate without
|
||||
+ # partition information. This allows db2 instances without
|
||||
+ # partition support to be managed.
|
||||
+ if [ -z "$OCF_RESKEY_dbpartitionnum" ] && ! [ -a "$db2sql/db2nodes.cfg" ]; then
|
||||
+ start_opts=""
|
||||
+ fi
|
||||
|
||||
- if output=$(runasdb2 db2start dbpartitionnum $db2node)
|
||||
+ if output=$(runasdb2 db2start $start_opts)
|
||||
then
|
||||
ocf_log info "DB2 instance $instance($db2node) started: $output"
|
||||
else
|
||||
@@ -473,10 +493,15 @@ db2_start() {
|
||||
#
|
||||
db2_stop_bg() {
|
||||
local rc output
|
||||
+ local stop_opts="dbpartitionnum $db2node"
|
||||
|
||||
rc=$OCF_SUCCESS
|
||||
|
||||
- if output=$(runasdb2 db2stop force dbpartitionnum $db2node)
|
||||
+ if [ -z "$OCF_RESKEY_dbpartitionnum" ] && ! [ -a "$db2sql/db2nodes.cfg" ]; then
|
||||
+ stop_opts=""
|
||||
+ fi
|
||||
+
|
||||
+ if output=$(runasdb2 db2stop force $stop_opts)
|
||||
then
|
||||
ocf_log info "DB2 instance $instance($db2node) stopped: $output"
|
||||
else
|
||||
@@ -502,13 +527,13 @@ db2_stop() {
|
||||
local stop_timeout grace_timeout stop_bg_pid i must_kill
|
||||
|
||||
# remove master score
|
||||
- crm_master -D -l reboot
|
||||
+ master_score -D -l reboot
|
||||
|
||||
# be very early here in order to avoid stale data
|
||||
rm -f $STATE_FILE
|
||||
|
||||
- if ! db2_instance_status
|
||||
- then
|
||||
+ db2_instance_status
|
||||
+ if [ $? -eq $OCF_NOT_RUNNING ]; then
|
||||
ocf_log info "DB2 instance $instance already stopped"
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
@@ -585,7 +610,12 @@ db2_instance_status() {
|
||||
local pscount
|
||||
|
||||
pscount=$(runasdb2 $db2bin/db2nps $db2node | cut -c9- | grep ' db2[^ ]' | wc -l)
|
||||
- test $pscount -ge 4
|
||||
+ if [ $pscount -ge 4 ]; then
|
||||
+ return $OCF_SUCCESS;
|
||||
+ elif [ $pscount -ge 1 ]; then
|
||||
+ return $OCF_GENERIC_ERR
|
||||
+ fi
|
||||
+ return $OCF_NOT_RUNNING
|
||||
}
|
||||
|
||||
#
|
||||
@@ -626,12 +656,14 @@ db2_hadr_status() {
|
||||
#
|
||||
db2_monitor() {
|
||||
local CMD output hadr db
|
||||
+ local rc
|
||||
|
||||
- if ! db2_instance_status
|
||||
- then
|
||||
+ db2_instance_status
|
||||
+ rc=$?
|
||||
+ if [ $rc -ne $OCF_SUCCESS ]; then
|
||||
# instance is dead remove master score
|
||||
- crm_master -D -l reboot
|
||||
- exit $OCF_NOT_RUNNING
|
||||
+ master_score -D -l reboot
|
||||
+ exit $rc
|
||||
fi
|
||||
|
||||
[ $db2node = 0 ] || return 0
|
||||
@@ -667,22 +699,22 @@ db2_monitor() {
|
||||
ocf_log err "DB2 message: $output"
|
||||
|
||||
# dead primary, remove master score
|
||||
- crm_master -D -l reboot
|
||||
+ master_score -D -l reboot
|
||||
return $OCF_ERR_GENERIC
|
||||
esac
|
||||
fi
|
||||
|
||||
ocf_log debug "DB2 database $instance($db2node)/$db appears to be working"
|
||||
- ocf_is_ms && crm_master -v 10000 -l reboot
|
||||
+ ocf_is_ms && master_score -v 10000 -l reboot
|
||||
;;
|
||||
|
||||
Standby/*Peer)
|
||||
- crm_master -v 8000 -l reboot
|
||||
+ master_score -v 8000 -l reboot
|
||||
;;
|
||||
|
||||
Standby/*)
|
||||
ocf_log warn "DB2 database $instance($db2node)/$db in status $hadr can never be promoted"
|
||||
- crm_master -D -l reboot
|
||||
+ master_score -D -l reboot
|
||||
;;
|
||||
|
||||
*)
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
index 6f80981..b159c2c 100755
|
||||
--- a/heartbeat/VirtualDomain
|
||||
+++ b/heartbeat/VirtualDomain
|
||||
@@ -65,10 +65,10 @@ for this virtual domain.
|
||||
<longdesc lang="en">
|
||||
Hypervisor URI to connect to. See the libvirt documentation for
|
||||
details on supported URI formats. The default is system dependent.
|
||||
-Determine your systems default uri by running 'virsh --quiet uri'
|
||||
+Determine the system's default uri by running 'virsh --quiet uri'.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">Hypervisor URI</shortdesc>
|
||||
-<content type="string" />
|
||||
+<content type="string"/>
|
||||
</parameter>
|
||||
|
||||
<parameter name="force_stop" unique="0" required="0">
|
||||
@@ -202,15 +202,44 @@ update_utilization() {
|
||||
fi
|
||||
}
|
||||
|
||||
+# attempt to check domain status outside of libvirt using the emulator process
|
||||
+pid_status()
|
||||
+{
|
||||
+ local rc=$OCF_ERR_GENERIC
|
||||
+ local emulator
|
||||
+
|
||||
+ emulator=$(basename $(egrep '[[:space:]]*<emulator>.*</emulator>[[:space:]]*$' ${OCF_RESKEY_config} | sed -e 's/[[:space:]]*<emulator>\(.*\)<\/emulator>[[:space:]]*$/\1/'))
|
||||
+
|
||||
+ case "$emulator" in
|
||||
+ qemu-kvm|qemu-system-*)
|
||||
+ ps awx | grep -E "[q]emu-(kvm|system).*-name $DOMAIN_NAME " > /dev/null 2>&1
|
||||
+ if [ $? -eq 0 ]; then
|
||||
+ # domain exists and is running
|
||||
+ ocf_log debug "Virtual domain $DOMAIN_NAME is currently running."
|
||||
+ rc=$OCF_SUCCESS
|
||||
+ else
|
||||
+ # domain pid does not exist on local machine
|
||||
+ ocf_log debug "Virtual domain $DOMAIN_NAME is currently not running."
|
||||
+ rc=$OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+ ;;
|
||||
+ # This can be expanded to check for additional emulators
|
||||
+ *)
|
||||
+ ;;
|
||||
+ esac
|
||||
+
|
||||
+ return $rc
|
||||
+}
|
||||
+
|
||||
VirtualDomain_Status() {
|
||||
local try=0
|
||||
rc=$OCF_ERR_GENERIC
|
||||
status="no state"
|
||||
while [ "$status" = "no state" ]; do
|
||||
try=$(($try + 1 ))
|
||||
- status="`virsh $VIRSH_OPTIONS domstate $DOMAIN_NAME 2>&1`"
|
||||
+ status=$(virsh $VIRSH_OPTIONS domstate $DOMAIN_NAME 2>&1|tr 'A-Z' 'a-z')
|
||||
case "$status" in
|
||||
- *"error:"*"Domain not found"*|"shut off")
|
||||
+ *"error:"*"domain not found"*|"shut off")
|
||||
# shut off: domain is defined, but not started, will not happen if
|
||||
# domain is created but not defined
|
||||
# Domain not found: domain is not defined and thus not started
|
||||
@@ -226,7 +255,7 @@ VirtualDomain_Status() {
|
||||
ocf_log debug "Virtual domain $DOMAIN_NAME is currently $status."
|
||||
rc=$OCF_SUCCESS
|
||||
;;
|
||||
- ""|*"Failed to reconnect to the hypervisor"*|"no state")
|
||||
+ ""|*"failed to "*"connect to the hypervisor"*|"no state")
|
||||
# Empty string may be returned when virsh does not
|
||||
# receive a reply from libvirtd.
|
||||
# "no state" may occur when the domain is currently
|
||||
@@ -240,6 +269,14 @@ VirtualDomain_Status() {
|
||||
# the domain if necessary.
|
||||
ocf_log error "Virtual domain $DOMAIN_NAME has no state during stop operation, bailing out."
|
||||
return $OCF_ERR_GENERIC;
|
||||
+ elif [ "$__OCF_ACTION" = "monitor" ]; then
|
||||
+ pid_status
|
||||
+ rc=$?
|
||||
+ if [ $rc -ne $OCF_ERR_GENERIC ]; then
|
||||
+ # we've successfully determined the domains status outside of libvirt
|
||||
+ return $rc
|
||||
+ fi
|
||||
+
|
||||
else
|
||||
# During all other actions, we just wait and try
|
||||
# again, relying on the CRM/LRM to time us out if
|
||||
@@ -312,11 +349,11 @@ force_stop()
|
||||
local status=0
|
||||
|
||||
ocf_log info "Issuing forced shutdown (destroy) request for domain ${DOMAIN_NAME}."
|
||||
- out=$(virsh $VIRSH_OPTIONS destroy ${DOMAIN_NAME} 2>&1)
|
||||
+ out=$(virsh $VIRSH_OPTIONS destroy ${DOMAIN_NAME} 2>&1|tr 'A-Z' 'a-z')
|
||||
ex=$?
|
||||
echo >&2 "$out"
|
||||
case $ex$out in
|
||||
- *"error:"*"domain is not running"*|*"error:"*"Domain not found"*)
|
||||
+ *"error:"*"domain is not running"*|*"error:"*"domain not found"*)
|
||||
: ;; # unexpected path to the intended outcome, all is well
|
||||
[!0]*)
|
||||
return $OCF_ERR_GENERIC ;;
|
||||
@@ -544,8 +581,8 @@ case $1 in
|
||||
;;
|
||||
esac
|
||||
|
||||
-OCF_RESKEY_hypervisor_default="$(virsh --quiet uri)"
|
||||
-: ${OCF_RESKEY_hypervisor=${OCF_RESKEY_hypervisor_default}}
|
||||
+# Grab the virsh uri default, but only if hypervisor isn't set
|
||||
+: ${OCF_RESKEY_hypervisor=$(virsh --quiet uri)}
|
||||
|
||||
# Set options to be passed to virsh:
|
||||
VIRSH_OPTIONS="--connect=${OCF_RESKEY_hypervisor} --quiet"
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
index b159c2c..3a6b6a9 100755
|
||||
--- a/heartbeat/VirtualDomain
|
||||
+++ b/heartbeat/VirtualDomain
|
||||
@@ -21,11 +21,13 @@ OCF_RESKEY_force_stop_default=0
|
||||
OCF_RESKEY_autoset_utilization_cpu_default="true"
|
||||
OCF_RESKEY_autoset_utilization_hv_memory_default="true"
|
||||
OCF_RESKEY_migrateport_default=$(( 49152 + $(ocf_maybe_random) % 64 ))
|
||||
+OCF_RESKEY_CRM_meta_timeout_default=90000
|
||||
|
||||
: ${OCF_RESKEY_force_stop=${OCF_RESKEY_force_stop_default}}
|
||||
: ${OCF_RESKEY_autoset_utilization_cpu=${OCF_RESKEY_autoset_utilization_cpu_default}}
|
||||
: ${OCF_RESKEY_autoset_utilization_hv_memory=${OCF_RESKEY_autoset_utilization_hv_memory_default}}
|
||||
: ${OCF_RESKEY_migrateport=${OCF_RESKEY_migrateport_default}}
|
||||
+: ${OCF_RESKEY_CRM_meta_timeout=${OCF_RESKEY_CRM_meta_timeout_default}}
|
||||
#######################################################################
|
||||
|
||||
## I'd very much suggest to make this RA use bash,
|
||||
@@ -165,8 +167,8 @@ Restore state on start/stop
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
-<action name="start" timeout="90" />
|
||||
-<action name="stop" timeout="90" />
|
||||
+<action name="start" timeout="$OCF_RESKEY_CRM_meta_timeout_default" />
|
||||
+<action name="stop" timeout="$OCF_RESKEY_CRM_meta_timeout_default" />
|
||||
<action name="status" depth="0" timeout="30" interval="10" />
|
||||
<action name="monitor" depth="0" timeout="30" interval="10" />
|
||||
<action name="migrate_from" timeout="60" />
|
||||
@@ -183,9 +185,17 @@ set_util_attr() {
|
||||
local cval outp
|
||||
|
||||
cval=$(crm_resource -Q -r $OCF_RESOURCE_INSTANCE -z -g $attr 2>/dev/null)
|
||||
+ if [ $? -ne 0 ] && [ -z "$cval" ]; then
|
||||
+ crm_resource -Q -r $OCF_RESOURCE_INSTANCE -z -g $attr 2>&1 | grep -e "not connected" > /dev/null 2>&1
|
||||
+ if [ $? -eq 0 ]; then
|
||||
+ ocf_log debug "Unable to set utilization attribute, cib is not available"
|
||||
+ return
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
if [ "$cval" != "$val" ]; then
|
||||
- outp=`crm_resource -r $OCF_RESOURCE_INSTANCE -z -p $attr -v $val 2>&1` ||
|
||||
- ocf_log warn "crm_resource failed to set utilization attribute $attr: $outp"
|
||||
+ outp=$(crm_resource -r $OCF_RESOURCE_INSTANCE -z -p $attr -v $val 2>&1) ||
|
||||
+ ocf_log warn "crm_resource failed to set utilization attribute $attr: $outp"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -193,22 +203,49 @@ update_utilization() {
|
||||
local dom_cpu dom_mem
|
||||
|
||||
if ocf_is_true "$OCF_RESKEY_autoset_utilization_cpu"; then
|
||||
- dom_cpu=$(LANG=C virsh $VIRSH_OPTIONS dominfo ${DOMAIN_NAME} | awk '/CPU\(s\)/{print $2}')
|
||||
+ dom_cpu=$(LANG=C virsh $VIRSH_OPTIONS dominfo ${DOMAIN_NAME} 2>/dev/null | awk '/CPU\(s\)/{print $2}')
|
||||
test -n "$dom_cpu" && set_util_attr cpu $dom_cpu
|
||||
fi
|
||||
if ocf_is_true "$OCF_RESKEY_autoset_utilization_hv_memory"; then
|
||||
- dom_mem=$(LANG=C virsh $VIRSH_OPTIONS dominfo ${DOMAIN_NAME} | awk '/Max memory/{printf("%d", $3/1024)}')
|
||||
+ dom_mem=$(LANG=C virsh $VIRSH_OPTIONS dominfo ${DOMAIN_NAME} 2>/dev/null | awk '/Max memory/{printf("%d", $3/1024)}')
|
||||
test -n "$dom_mem" && set_util_attr hv_memory "$dom_mem"
|
||||
fi
|
||||
}
|
||||
|
||||
+get_emulator()
|
||||
+{
|
||||
+ local emulator=""
|
||||
+
|
||||
+ emulator=$(virsh $VIRSH_OPTIONS dumpxml $DOMAIN_NAME 2>/dev/null | sed -n -e 's/[[:space:]]*<emulator>\(.*\)<\/emulator>[[:space:]]*$/\1/p')
|
||||
+ if [ -z "$emulator" ] && [ -a "$EMULATOR_STATE" ]; then
|
||||
+ emulator=$(cat $EMULATOR_STATE)
|
||||
+ fi
|
||||
+ if [ -z "$emulator" ]; then
|
||||
+ emulator=$(cat ${OCF_RESKEY_config} | sed -n -e 's/[[:space:]]*<emulator>\(.*\)<\/emulator>[[:space:]]*$/\1/p')
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "$emulator" ]; then
|
||||
+ basename $emulator
|
||||
+ else
|
||||
+ ocf_log error "Unable to determine emulator for $DOMAIN_NAME"
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+update_emulator_cache()
|
||||
+{
|
||||
+ local emulator
|
||||
+
|
||||
+ emulator=$(get_emulator)
|
||||
+ if [ -n "$emulator" ]; then
|
||||
+ echo $emulator > $EMULATOR_STATE
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
# attempt to check domain status outside of libvirt using the emulator process
|
||||
pid_status()
|
||||
{
|
||||
local rc=$OCF_ERR_GENERIC
|
||||
- local emulator
|
||||
-
|
||||
- emulator=$(basename $(egrep '[[:space:]]*<emulator>.*</emulator>[[:space:]]*$' ${OCF_RESKEY_config} | sed -e 's/[[:space:]]*<emulator>\(.*\)<\/emulator>[[:space:]]*$/\1/'))
|
||||
+ local emulator=$(get_emulator)
|
||||
|
||||
case "$emulator" in
|
||||
qemu-kvm|qemu-system-*)
|
||||
@@ -237,13 +274,13 @@ VirtualDomain_Status() {
|
||||
status="no state"
|
||||
while [ "$status" = "no state" ]; do
|
||||
try=$(($try + 1 ))
|
||||
- status=$(virsh $VIRSH_OPTIONS domstate $DOMAIN_NAME 2>&1|tr 'A-Z' 'a-z')
|
||||
+ status=$(virsh $VIRSH_OPTIONS domstate $DOMAIN_NAME 2>&1 | tr 'A-Z' 'a-z')
|
||||
case "$status" in
|
||||
*"error:"*"domain not found"*|"shut off")
|
||||
# shut off: domain is defined, but not started, will not happen if
|
||||
# domain is created but not defined
|
||||
# Domain not found: domain is not defined and thus not started
|
||||
- ocf_log debug "Virtual domain $DOMAIN_NAME is currently $status."
|
||||
+ ocf_log debug "Virtual domain $DOMAIN_NAME is not running: $(echo $status | sed s/error://g)"
|
||||
rc=$OCF_NOT_RUNNING
|
||||
;;
|
||||
running|paused|idle|blocked|"in shutdown")
|
||||
@@ -282,12 +319,13 @@ VirtualDomain_Status() {
|
||||
# again, relying on the CRM/LRM to time us out if
|
||||
# this takes too long.
|
||||
ocf_log info "Virtual domain $DOMAIN_NAME currently has no state, retrying."
|
||||
- sleep 1
|
||||
fi
|
||||
+ sleep 1
|
||||
;;
|
||||
*)
|
||||
# any other output is unexpected.
|
||||
ocf_log error "Virtual domain $DOMAIN_NAME has unknown status \"$status\"!"
|
||||
+ sleep 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@@ -295,7 +333,7 @@ VirtualDomain_Status() {
|
||||
}
|
||||
|
||||
verify_undefined() {
|
||||
- for dom in `virsh --connect=${OCF_RESKEY_hypervisor} list --all --name`; do
|
||||
+ for dom in `virsh --connect=${OCF_RESKEY_hypervisor} list --all --name 2>/dev/null`; do
|
||||
if [ "$dom" = "$DOMAIN_NAME" ]; then
|
||||
virsh $VIRSH_OPTIONS undefine $DOMAIN_NAME > /dev/null 2>&1
|
||||
return
|
||||
@@ -340,6 +378,7 @@ VirtualDomain_Start() {
|
||||
while ! VirtualDomain_Monitor; do
|
||||
sleep 1
|
||||
done
|
||||
+
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
@@ -530,6 +569,7 @@ VirtualDomain_Monitor() {
|
||||
done
|
||||
fi
|
||||
|
||||
+ update_emulator_cache
|
||||
update_utilization
|
||||
|
||||
return ${rc}
|
||||
@@ -582,7 +622,7 @@ case $1 in
|
||||
esac
|
||||
|
||||
# Grab the virsh uri default, but only if hypervisor isn't set
|
||||
-: ${OCF_RESKEY_hypervisor=$(virsh --quiet uri)}
|
||||
+: ${OCF_RESKEY_hypervisor=$(virsh --quiet uri 2>/dev/null)}
|
||||
|
||||
# Set options to be passed to virsh:
|
||||
VIRSH_OPTIONS="--connect=${OCF_RESKEY_hypervisor} --quiet"
|
||||
@@ -608,6 +648,8 @@ if [ -z $DOMAIN_NAME ]; then
|
||||
exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
+EMULATOR_STATE="${HA_RSCTMP}/VirtualDomain-${DOMAIN_NAME}-emu.state"
|
||||
+
|
||||
case $1 in
|
||||
start)
|
||||
VirtualDomain_Start
|
||||
|
|
@ -0,0 +1,441 @@
|
|||
From 61dd0f9ca20b0f252996b6f610b4473ba83ca97a Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Wed, 12 Feb 2014 12:36:21 -0500
|
||||
Subject: [PATCH] High: clvm: Introducing clvmd resource agent
|
||||
|
||||
---
|
||||
doc/man/Makefile.am | 1 +
|
||||
heartbeat/Makefile.am | 1 +
|
||||
heartbeat/clvm | 396 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 398 insertions(+)
|
||||
create mode 100755 heartbeat/clvm
|
||||
|
||||
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
|
||||
index 3bf569a..49b5c58 100644
|
||||
--- a/doc/man/Makefile.am
|
||||
+++ b/doc/man/Makefile.am
|
||||
@@ -94,6 +94,7 @@ man_MANS = ocf_heartbeat_AoEtarget.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 \
|
||||
diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am
|
||||
index bc95f89..2c3056d 100644
|
||||
--- a/heartbeat/Makefile.am
|
||||
+++ b/heartbeat/Makefile.am
|
||||
@@ -61,6 +61,7 @@ ocf_SCRIPTS = ClusterMon \
|
||||
asterisk \
|
||||
nginx \
|
||||
AudibleAlarm \
|
||||
+ clvm \
|
||||
conntrackd \
|
||||
db2 \
|
||||
dhcpd \
|
||||
diff --git a/heartbeat/clvm b/heartbeat/clvm
|
||||
new file mode 100755
|
||||
index 0000000..3e7701d
|
||||
--- /dev/null
|
||||
+++ b/heartbeat/clvm
|
||||
@@ -0,0 +1,396 @@
|
||||
+#!/bin/bash
|
||||
+#
|
||||
+# Copyright (c) 2014 David Vossel <dvossel@redhat.com>
|
||||
+# All Rights Reserved.
|
||||
+#
|
||||
+# 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.
|
||||
+#
|
||||
+
|
||||
+#######################################################################
|
||||
+# Initialization:
|
||||
+
|
||||
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
+. ${OCF_FUNCTIONS_DIR}/ocf-directories
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+meta_data() {
|
||||
+ cat <<END
|
||||
+<?xml version="1.0"?>
|
||||
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
+<resource-agent name="clvm" version="0.9">
|
||||
+<version>1.0</version>
|
||||
+
|
||||
+<longdesc lang="en">
|
||||
+This agent manages the clvmd daemon.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">clvmd</shortdesc>
|
||||
+
|
||||
+<parameters>
|
||||
+<parameter name="with_cmirrord" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Start with cmirrord (cluster mirror log daemon).
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">activate cmirrord</shortdesc>
|
||||
+<content type="boolean" default="false" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="daemon_options" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Options to clvmd. Refer to clvmd.8 for detailed descriptions.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Daemon Options</shortdesc>
|
||||
+<content type="string" default="-d0"/>
|
||||
+</parameter>
|
||||
+</parameters>
|
||||
+
|
||||
+<actions>
|
||||
+<action name="start" timeout="90" />
|
||||
+<action name="stop" timeout="90" />
|
||||
+<action name="monitor" timeout="90" interval="30" depth="0" />
|
||||
+<action name="reload" timeout="90" />
|
||||
+<action name="meta-data" timeout="10" />
|
||||
+<action name="validate-all" timeout="20" />
|
||||
+</actions>
|
||||
+</resource-agent>
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+: ${OCF_RESKEY_daemon_options:="-d0"}
|
||||
+
|
||||
+sbindir=$HA_SBIN_DIR
|
||||
+if [ -z $sbindir ]; then
|
||||
+ sbindir=/usr/sbin
|
||||
+fi
|
||||
+DAEMON="clvmd"
|
||||
+CMIRROR="cmirrord"
|
||||
+DAEMON_PATH="${sbindir}/clvmd"
|
||||
+CMIRROR_PATH="${sbindir}/cmirrord"
|
||||
+LOCK_FILE="/var/lock/subsys/$DAEMON"
|
||||
+LVM_VGCHANGE=${sbindir}/vgchange
|
||||
+LVM_VGDISPLAY=${sbindir}/vgdisplay
|
||||
+LVM_VGSCAN=${sbindir}/vgscan
|
||||
+
|
||||
+# Leaving this in for legacy. We do not want to advertize
|
||||
+# the abilty to set options in the systconfig exists, we want
|
||||
+# to expand the OCF style options as necessary instead.
|
||||
+[ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster
|
||||
+[ -f /etc/sysconfig/$DAEMON ] && . /etc/sysconfig/$DAEMON
|
||||
+
|
||||
+CLVMD_TIMEOUT="90"
|
||||
+if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
|
||||
+ CLVMD_TIMEOUT=$(($OCF_RESKEY_CRM_meta_timeout/1000))
|
||||
+fi
|
||||
+
|
||||
+clvmd_usage()
|
||||
+{
|
||||
+ cat <<END
|
||||
+usage: $0 {start|stop|monitor|validate-all|meta-data}
|
||||
+
|
||||
+Expects to have a fully populated OCF RA-compliant environment set.
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+clvmd_validate()
|
||||
+{
|
||||
+ # check_binary will exit with OCF_ERR_INSTALLED
|
||||
+ # when binary is missing
|
||||
+ check_binary "pgrep"
|
||||
+ check_binary $DAEMON_PATH
|
||||
+ if ocf_is_true $OCF_RESKEY_with_cmirrord; then
|
||||
+ check_binary $CMIRROR_PATH
|
||||
+ fi
|
||||
+
|
||||
+ if [ "$__OCF_ACTION" != "monitor" ]; then
|
||||
+ check_binary "killall"
|
||||
+ check_binary $LVM_VGCHANGE
|
||||
+ check_binary $LVM_VGDISPLAY
|
||||
+ check_binary $LVM_VGSCAN
|
||||
+ fi
|
||||
+
|
||||
+ # Future validation checks here.
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+check_process()
|
||||
+{
|
||||
+ local binary=$1
|
||||
+ local pidfile="${HA_RSCTMP}/${binary}-${OCF_RESOURCE_INSTANCE}.pid"
|
||||
+ local pid
|
||||
+
|
||||
+ ocf_log debug "Checking status for ${binary}."
|
||||
+ if [ -e "$pidfile" ]; then
|
||||
+ cat /proc/$(cat $pidfile)/cmdline 2>/dev/null | grep -a "${binary}" > /dev/null 2>&1
|
||||
+ if [ $? -eq 0 ];then
|
||||
+ # shortcut without requiring pgrep to search through all procs
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ pid=$(pgrep ${binary})
|
||||
+ case $? in
|
||||
+ 0)
|
||||
+ ocf_log info "PID file (pid:${pid} at $pidfile) created for ${binary}."
|
||||
+ echo "$pid" > $pidfile
|
||||
+ return $OCF_SUCCESS;;
|
||||
+ 1)
|
||||
+ rm -f "$pidfile" > /dev/null 2>&1
|
||||
+ ocf_log info "$binary is not running"
|
||||
+ return $OCF_NOT_RUNNING;;
|
||||
+ *)
|
||||
+ rm -f "$pidfile" > /dev/null 2>&1
|
||||
+ ocf_log err "Error encountered detecting pid status of $binary"
|
||||
+ return $OCF_ERR_GENERIC;;
|
||||
+ esac
|
||||
+}
|
||||
+
|
||||
+clvmd_status()
|
||||
+{
|
||||
+ local rc
|
||||
+ local mirror_rc
|
||||
+ clvmd_validate
|
||||
+ if [ $? -ne $OCF_SUCCESS ]; then
|
||||
+ ocf_log error "Unable to monitor, Environment validation failed."
|
||||
+ return $?
|
||||
+ fi
|
||||
+
|
||||
+ check_process $DAEMON
|
||||
+ rc=$?
|
||||
+ mirror_rc=$rc
|
||||
+
|
||||
+ if ocf_is_true $OCF_RESKEY_with_cmirrord; then
|
||||
+ check_process $CMIRROR
|
||||
+ mirror_rc=$?
|
||||
+ fi
|
||||
+
|
||||
+ # If these ever don't match, return error to force recovery
|
||||
+ if [ $mirror_rc -ne $rc ]; then
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ return $rc
|
||||
+}
|
||||
+
|
||||
+# NOTE: replace this with vgs, once display filter per attr is implemented.
|
||||
+clustered_vgs() {
|
||||
+ ${LVM_VGDISPLAY} 2>/dev/null | awk 'BEGIN {RS="VG Name"} {if (/Clustered/) print $1;}'
|
||||
+}
|
||||
+
|
||||
+wait_for_process()
|
||||
+{
|
||||
+ local binary=$1
|
||||
+ local timeout=$2
|
||||
+ local count=0
|
||||
+
|
||||
+ ocf_log info "Waiting for $binary to exit"
|
||||
+ usleep 500000
|
||||
+ while [ $count -le $timeout ]; do
|
||||
+ check_process $binary
|
||||
+ if [ $? -eq $OCF_NOT_RUNNING ]; then
|
||||
+ ocf_log info "$binary terminated"
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+ sleep 1
|
||||
+ count=$((count+1))
|
||||
+ done
|
||||
+
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+}
|
||||
+
|
||||
+time_left()
|
||||
+{
|
||||
+ local end=$1
|
||||
+ local default=$2
|
||||
+ local now=$SECONDS
|
||||
+ local result=0
|
||||
+
|
||||
+ result=$(( $end - $now ))
|
||||
+ if [ $result -lt $default ]; then
|
||||
+ return $default
|
||||
+ fi
|
||||
+ return $result
|
||||
+}
|
||||
+
|
||||
+clvmd_stop()
|
||||
+{
|
||||
+ local LVM_VGS
|
||||
+ local rc=$OCF_SUCCESS
|
||||
+ local end=$(( $SECONDS + $CLVMD_TIMEOUT ))
|
||||
+
|
||||
+ clvmd_status
|
||||
+ if [ $? -eq $OCF_NOT_RUNNING ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ check_process $DAEMON
|
||||
+ if [ $? -ne $OCF_NOT_RUNNING ]; then
|
||||
+ LVM_VGS="$(clustered_vgs)"
|
||||
+
|
||||
+ if [ -n "$LVM_VGS" ]; then
|
||||
+ ocf_log info "Deactivating clustered VG(s):"
|
||||
+ ocf_run ${LVM_VGCHANGE} -anl $LVM_VGS
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ ocf_log error "Failed to deactivate volume groups, cluster vglist = $LVM_VGS"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ ocf_log info "Signaling $DAEMON to exit"
|
||||
+ killall -TERM $DAEMON
|
||||
+ if [ $? != 0 ]; then
|
||||
+ ocf_log error "Failed to signal -TERM to $DAEMON"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ wait_for_process $DAEMON $CLVMD_TIMEOUT
|
||||
+ rc=$?
|
||||
+ if [ $rc -ne $OCF_SUCCESS ]; then
|
||||
+ ocf_log error "$DAEMON failed to exit"
|
||||
+ return $rc
|
||||
+ fi
|
||||
+
|
||||
+ rm -f $LOCK_FILE
|
||||
+ fi
|
||||
+
|
||||
+ check_process $CMIRROR
|
||||
+ if [ $? -ne $OCF_NOT_RUNNING ] && ocf_is_true $OCF_RESKEY_with_cmirrord; then
|
||||
+ local timeout
|
||||
+ ocf_log info "Signaling $CMIRROR to exit"
|
||||
+ killall -INT $CMIRROR
|
||||
+
|
||||
+ time_left $end 10; timeout=$?
|
||||
+ wait_for_process $CMIRROR $timeout
|
||||
+ rc=$?
|
||||
+ if [ $rc -ne $OCF_SUCCESS ]; then
|
||||
+ killall -KILL $CMIRROR
|
||||
+ time_left $end 10; timeout=$?
|
||||
+ wait_for_process $CMIRROR $(time_left $end 10)
|
||||
+ rc=$?
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ return $rc
|
||||
+}
|
||||
+
|
||||
+start_process()
|
||||
+{
|
||||
+ local binary_path=$1
|
||||
+ local opts=$2
|
||||
+
|
||||
+ check_process "$(basename $binary_path)"
|
||||
+ if [ $? -ne $OCF_SUCCESS ]; then
|
||||
+ ocf_log info "Starting $binary_path: "
|
||||
+ ocf_run $binary_path $opts
|
||||
+ rc=$?
|
||||
+ if [ $rc -ne 0 ]; then
|
||||
+ ocf_log error "Failed to launch $binary_path, exit code $rc"
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+clvmd_activate_all()
|
||||
+{
|
||||
+ # Activate all volume groups by leaving the
|
||||
+ # "volume group name" parameter empty
|
||||
+ ocf_run ${LVM_VGCHANGE} -aay
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ ocf_log info "Failed to activate VG(s):"
|
||||
+ clvmd_stop
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+clvmd_start()
|
||||
+{
|
||||
+ local rc=0
|
||||
+ local CLVMDOPTS="-T${CLVMD_TIMEOUT} $OCF_RESKEY_daemon_options"
|
||||
+
|
||||
+ clvmd_validate
|
||||
+ if [ $? -ne $OCF_SUCCESS ]; then
|
||||
+ ocf_log error "Unable to start, Environment validation failed."
|
||||
+ return $?
|
||||
+ fi
|
||||
+
|
||||
+ clvmd_status
|
||||
+ if [ $? -eq $OCF_SUCCESS ]; then
|
||||
+ ocf_log debug "$DAEMON already started"
|
||||
+ clvmd_activate_all
|
||||
+ return $?;
|
||||
+ fi
|
||||
+
|
||||
+ # if either of these fail, script will exit OCF_ERR_GENERIC
|
||||
+ if ocf_is_true $OCF_RESKEY_with_cmirrord; then
|
||||
+ start_process $CMIRROR_PATH
|
||||
+ fi
|
||||
+ start_process $DAEMON_PATH $CLVMDOPTS
|
||||
+
|
||||
+ # Refresh local cache.
|
||||
+ #
|
||||
+ # It's possible that new PVs were added to this, or other VGs
|
||||
+ # while this node was down. So we run vgscan here to avoid
|
||||
+ # any potential "Missing UUID" messages with subsequent
|
||||
+ # LVM commands.
|
||||
+
|
||||
+ # The following step would be better and more informative to the user:
|
||||
+ # 'action "Refreshing VG(s) local cache:" ${LVM_VGSCAN}'
|
||||
+ # but it could show warnings such as:
|
||||
+ # 'clvmd not running on node x-y-z Unable to obtain global lock.'
|
||||
+ # and the action would be shown as FAILED when in reality it didn't.
|
||||
+ # Ideally vgscan should have a startup mode that would not print
|
||||
+ # unnecessary warnings.
|
||||
+
|
||||
+ ${LVM_VGSCAN} > /dev/null 2>&1
|
||||
+ touch $LOCK_FILE
|
||||
+
|
||||
+ clvmd_activate_all
|
||||
+
|
||||
+ clvmd_status
|
||||
+ return $?
|
||||
+}
|
||||
+
|
||||
+case $__OCF_ACTION in
|
||||
+ meta-data) meta_data
|
||||
+ exit $OCF_SUCCESS;;
|
||||
+
|
||||
+ start) clvmd_start;;
|
||||
+
|
||||
+ stop) clvmd_stop;;
|
||||
+
|
||||
+ monitor) clvmd_status;;
|
||||
+
|
||||
+ validate-all) clvmd_validate;;
|
||||
+
|
||||
+ usage|help) clvmd_usage;;
|
||||
+
|
||||
+ *) clvmd_usage
|
||||
+ exit $OCF_ERR_UNIMPLEMENTED;;
|
||||
+esac
|
||||
+
|
||||
+rc=$?
|
||||
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
|
||||
+exit $rc
|
||||
+
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
diff --git a/heartbeat/CTDB b/heartbeat/CTDB
|
||||
index b23ffae..3e36dd0 100755
|
||||
--- a/heartbeat/CTDB
|
||||
+++ b/heartbeat/CTDB
|
||||
@@ -572,10 +572,22 @@ ctdb_start() {
|
||||
|
||||
# Use logfile by default, or syslog if asked for
|
||||
- local log_option="--logfile=$OCF_RESKEY_ctdb_logfile"
|
||||
- if [ "$OCF_RESKEY_ctdb_logfile" = "syslog" ]; then
|
||||
- log_option="--syslog"
|
||||
- elif [ ! -d "$(dirname $OCF_RESKEY_ctdb_logfile)" ]; then
|
||||
+ # --logging supported from v4.3.0 and --logfile / --syslog support
|
||||
+ # has been removed from newer versions
|
||||
+ version=$(ctdb version | awk '{print $NF}')
|
||||
+ ocf_version_cmp "$version" "4.2.14"
|
||||
+ if [ "$?" -eq "2" ]; then
|
||||
+ log_option="--logging=file:$OCF_RESKEY_ctdb_logfile"
|
||||
+ if [ "$OCF_RESKEY_ctdb_logfile" = "syslog" ]; then
|
||||
+ log_option="--logging=syslog"
|
||||
+ fi
|
||||
+ else
|
||||
+ log_option="--logfile=$OCF_RESKEY_ctdb_logfile"
|
||||
+ if [ "$OCF_RESKEY_ctdb_logfile" = "syslog" ]; then
|
||||
+ log_option="--syslog"
|
||||
+ fi
|
||||
+ fi
|
||||
+ if [ ! -d "$(dirname $OCF_RESKEY_ctdb_logfile)" ]; then
|
||||
# ensure the logfile's directory exists, otherwise ctdb will fail to start
|
||||
mkdir -p $(dirname $OCF_RESKEY_ctdb_logfile)
|
||||
fi
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
From f681e6798d3a5ead5a0e077d6e73343b266ef56f Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Wed, 29 Apr 2015 11:18:25 -0500
|
||||
Subject: [PATCH 6/6] CTDB fixes
|
||||
|
||||
---
|
||||
heartbeat/CTDB | 61 +++++++++++++++++++++++++++++++++++++++++++++-------------
|
||||
1 file changed, 48 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/CTDB b/heartbeat/CTDB
|
||||
index d1e8d03..1cf9d8c 100755
|
||||
--- a/heartbeat/CTDB
|
||||
+++ b/heartbeat/CTDB
|
||||
@@ -72,6 +72,19 @@
|
||||
#######################################################################
|
||||
# Default parameter values:
|
||||
|
||||
+# Some distro's ctdb package stores the persistent db in /var/lib/ctdb,
|
||||
+# others store in /var/ctdb. This attempts to detect the correct default
|
||||
+# directory.
|
||||
+var_prefix="/var/lib/ctdb"
|
||||
+if [ ! -d "$var_prefix" ] && [ -d "/var/ctdb" ]; then
|
||||
+ var_prefix="/var/ctdb"
|
||||
+fi
|
||||
+
|
||||
+run_prefix="/run"
|
||||
+if [ ! -d "$var_prefix" ] && [ -d "/var/run" ]; then
|
||||
+ var_prefix="/var/run"
|
||||
+fi
|
||||
+
|
||||
: ${OCF_RESKEY_ctdb_manages_samba:=no}
|
||||
: ${OCF_RESKEY_ctdb_manages_winbind:=no}
|
||||
: ${OCF_RESKEY_ctdb_service_smb:=""}
|
||||
@@ -84,9 +97,10 @@
|
||||
: ${OCF_RESKEY_ctdb_config_dir:=/etc/ctdb}
|
||||
: ${OCF_RESKEY_ctdb_binary:=/usr/bin/ctdb}
|
||||
: ${OCF_RESKEY_ctdbd_binary:=/usr/sbin/ctdbd}
|
||||
-: ${OCF_RESKEY_ctdb_socket:=/var/lib/ctdb/ctdb.socket}
|
||||
-: ${OCF_RESKEY_ctdb_dbdir:=/var/lib/ctdb}
|
||||
+: ${OCF_RESKEY_ctdb_dbdir:=${var_prefix}}
|
||||
: ${OCF_RESKEY_ctdb_logfile:=/var/log/ctdb/log.ctdb}
|
||||
+: ${OCF_RESKEY_ctdb_rundir:=${run_prefix}/ctdb}
|
||||
+: ${OCF_RESKEY_ctdb_socket:=${OCF_RESKEY_ctdb_rundir}/ctdbd.socket}
|
||||
: ${OCF_RESKEY_ctdb_debuglevel:=2}
|
||||
|
||||
: ${OCF_RESKEY_smb_conf:=/etc/samba/smb.conf}
|
||||
@@ -104,12 +118,13 @@ meta_data() {
|
||||
|
||||
<longdesc lang="en">
|
||||
This resource agent manages CTDB, allowing one to use Clustered Samba in a
|
||||
-Linux-HA/Pacemaker cluster. You need a shared filesystem (e.g. OCFS2) on
|
||||
+Linux-HA/Pacemaker cluster. You need a shared filesystem (e.g. OCFS2 or GFS2) on
|
||||
which the CTDB lock will be stored. Create /etc/ctdb/nodes containing a list
|
||||
of private IP addresses of each node in the cluster, then configure this RA
|
||||
-as a clone. To have CTDB manage Samba, set ctdb_manages_samba="yes".
|
||||
-Note that this option will be deprecated in future, in favour of configuring
|
||||
-a separate Samba resource.
|
||||
+as a clone. This agent expects the samba and windbind resources
|
||||
+to be managed outside of CTDB's control as a separate set of resources controlled
|
||||
+by the cluster manager. The optional support for enabling CTDB management of these
|
||||
+daemons will be depreciated.
|
||||
|
||||
For more information see http://linux-ha.org/wiki/CTDB_(resource_agent)
|
||||
</longdesc>
|
||||
@@ -235,7 +250,7 @@ Full path to the domain socket that ctdbd will create, used for
|
||||
local clients to attach and communicate with the ctdb daemon.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">CTDB socket location</shortdesc>
|
||||
-<content type="string" default="/var/lib/ctdb/ctdb.socket" />
|
||||
+<content type="string" default="${OCF_RESKEY_ctdb_socket}" />
|
||||
</parameter>
|
||||
|
||||
<parameter name="ctdb_dbdir" unique="1" required="0">
|
||||
@@ -244,7 +259,7 @@ The directory to put the local CTDB database files in.
|
||||
Persistent database files will be put in ctdb_dbdir/persistent.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">CTDB database directory</shortdesc>
|
||||
-<content type="string" default="/var/lib/ctdb" />
|
||||
+<content type="string" default="${OCF_RESKEY_ctdb_dbdir}" />
|
||||
</parameter>
|
||||
|
||||
<parameter name="ctdb_logfile" unique="0" required="0">
|
||||
@@ -256,6 +271,15 @@ value "syslog".
|
||||
<content type="string" default="/var/log/ctdb/log.ctdb" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="ctdb_rundir" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Full path to ctdb runtime directory, used for storage of socket
|
||||
+lock state.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">CTDB runtime directory location</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_ctdb_rundir}" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="ctdb_debuglevel" unique="0" required="0">
|
||||
<longdesc lang="en">
|
||||
What debug level to run at (0-10). Higher means more verbose.
|
||||
@@ -538,7 +562,16 @@ ctdb_start() {
|
||||
|
||||
# Use logfile by default, or syslog if asked for
|
||||
local log_option="--logfile=$OCF_RESKEY_ctdb_logfile"
|
||||
- [ "$OCF_RESKEY_ctdb_logfile" = "syslog" ] && log_option="--syslog"
|
||||
+ if [ "$OCF_RESKEY_ctdb_logfile" = "syslog" ]; then
|
||||
+ log_option="--syslog"
|
||||
+ elif [ ! -d "$(dirname $OCF_RESKEY_ctdb_logfile)" ]; then
|
||||
+ # ensure the logfile's directory exists, otherwise ctdb will fail to start
|
||||
+ mkdir -p $(dirname $OCF_RESKEY_ctdb_logfile)
|
||||
+ fi
|
||||
+
|
||||
+ # ensure ctdb's rundir exists, otherwise it will fail to start
|
||||
+ mkdir -p $OCF_RESKEY_ctdb_rundir 2>/dev/null
|
||||
+
|
||||
# public addresses file (should not be present, but need to set for correctness if it is)
|
||||
local pub_addr_option=""
|
||||
[ -f "${OCF_RESKEY_ctdb_config_dir}/public_addresses" ] && \
|
||||
@@ -562,7 +595,7 @@ ctdb_start() {
|
||||
if [ $? -ne 0 ]; then
|
||||
# cleanup smb.conf
|
||||
cleanup_smb_conf
|
||||
-
|
||||
+
|
||||
ocf_exit_reason "Failed to execute $OCF_RESKEY_ctdbd_binary."
|
||||
return $OCF_ERR_GENERIC
|
||||
else
|
||||
@@ -589,10 +622,10 @@ ctdb_start() {
|
||||
fi
|
||||
done
|
||||
fi
|
||||
-
|
||||
+
|
||||
# ctdbd will (or can) actually still be running at this point, so kill it
|
||||
ctdb_stop
|
||||
-
|
||||
+
|
||||
ocf_exit_reason "Timeout waiting for CTDB to stabilize"
|
||||
return $OCF_ERR_GENERIC
|
||||
}
|
||||
@@ -601,7 +634,7 @@ ctdb_start() {
|
||||
ctdb_stop() {
|
||||
# Do nothing if already stopped
|
||||
pkill -0 -f $OCF_RESKEY_ctdbd_binary || return $OCF_SUCCESS
|
||||
-
|
||||
+
|
||||
# Tell it to die nicely
|
||||
invoke_ctdb shutdown >/dev/null 2>&1
|
||||
rv=$?
|
||||
@@ -645,6 +678,8 @@ ctdb_monitor() {
|
||||
if [ $? -ne 0 ]; then
|
||||
if echo $status | grep -qs 'Connection refused'; then
|
||||
return $OCF_NOT_RUNNING
|
||||
+ elif echo $status | grep -qs 'No such file or directory'; then
|
||||
+ return $OCF_NOT_RUNNING
|
||||
else
|
||||
ocf_exit_reason "CTDB status call failed: $status"
|
||||
return $OCF_ERR_GENERIC
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
From 4e2576c0b339537790e253c11d9dfcf99b7b114d Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Tue, 1 Apr 2014 17:28:39 -0400
|
||||
Subject: [PATCH] Low: VirtualDomain: Allow monitoring of lxc domains without
|
||||
libvirtd
|
||||
|
||||
---
|
||||
heartbeat/VirtualDomain | 20 ++++++++++++++------
|
||||
1 file changed, 14 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
index b0cdd5f..692a2ef 100755
|
||||
--- a/heartbeat/VirtualDomain
|
||||
+++ b/heartbeat/VirtualDomain
|
||||
@@ -249,15 +249,17 @@ pid_status()
|
||||
|
||||
case "$emulator" in
|
||||
qemu-kvm|qemu-system-*)
|
||||
+ rc=$OCF_NOT_RUNNING
|
||||
ps awx | grep -E "[q]emu-(kvm|system).*-name $DOMAIN_NAME " > /dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
- # domain exists and is running
|
||||
- ocf_log debug "Virtual domain $DOMAIN_NAME is currently running."
|
||||
rc=$OCF_SUCCESS
|
||||
- else
|
||||
- # domain pid does not exist on local machine
|
||||
- ocf_log debug "Virtual domain $DOMAIN_NAME is currently not running."
|
||||
- rc=$OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+ ;;
|
||||
+ libvirt_lxc)
|
||||
+ rc=$OCF_NOT_RUNNING
|
||||
+ ps awx | grep -E "[l]ibvirt_lxc.*-name $DOMAIN_NAME " > /dev/null 2>&1
|
||||
+ if [ $? -eq 0 ]; then
|
||||
+ rc=$OCF_SUCCESS
|
||||
fi
|
||||
;;
|
||||
# This can be expanded to check for additional emulators
|
||||
@@ -265,6 +267,12 @@ pid_status()
|
||||
;;
|
||||
esac
|
||||
|
||||
+ if [ $rc -eq $OCF_SUCCESS ]; then
|
||||
+ ocf_log debug "Virtual domain $DOMAIN_NAME is currently running."
|
||||
+ elif [ $rc -eq $OCF_NOT_RUNNING ]; then
|
||||
+ ocf_log debug "Virtual domain $DOMAIN_NAME is currently not running."
|
||||
+ fi
|
||||
+
|
||||
return $rc
|
||||
}
|
||||
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
From d0ecd287511e49891245c68cd323e8f232aa033b Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Wed, 6 Aug 2014 14:05:18 -0400
|
||||
Subject: [PATCH] High: Filesystem: when loading kernel modules wait for
|
||||
filesystem to initialize
|
||||
|
||||
When the Filesystem agent is managing a filesystem type that
|
||||
is not present in /proc/filesystems, the agent attempts to
|
||||
load the kernel module for that filesystem.
|
||||
|
||||
This patch improves on that logic by
|
||||
1. verifying that modprobe worked
|
||||
2. give the module a brief period of time to initialize.
|
||||
|
||||
Item 2 is important because there is a brief period
|
||||
of time between when modprobe returns loading the gfs2
|
||||
module, and when gfs2 will show up in the /proc/filesystems
|
||||
list. Without retrying the search of the /proc/filesystems
|
||||
file, a gfs2 filesystem may fail to start correctly because
|
||||
it will look like the filesystem isn't supported.
|
||||
---
|
||||
heartbeat/Filesystem | 71 +++++++++++++++++++++++++++++++++++++++-------------
|
||||
1 file changed, 53 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index 9209818..9892b39 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -450,6 +450,58 @@ is_fsck_needed() {
|
||||
esac
|
||||
}
|
||||
|
||||
+fstype_supported()
|
||||
+{
|
||||
+ local support="$FSTYPE"
|
||||
+ local rc
|
||||
+
|
||||
+ if [ "X${HOSTOS}" != "XOpenBSD" ];then
|
||||
+ # skip checking /proc/filesystems for obsd
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ if [ -z "$FSTYPE" -o "$FSTYPE" = none ]; then
|
||||
+ : No FSTYPE specified, rely on the system has the right file-system support already
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ # support fuse-filesystems (e.g. GlusterFS)
|
||||
+ case $FSTYPE in
|
||||
+ glusterfs) support="fuse";;
|
||||
+ esac
|
||||
+
|
||||
+ grep -w "$support"'$' /proc/filesystems >/dev/null
|
||||
+ if [ $? -eq 0 ]; then
|
||||
+ # found the fs type
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ # if here, we should attempt to load the module and then
|
||||
+ # check the if the filesystem support exists again.
|
||||
+ $MODPROBE $support >/dev/null
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ ocf_log err "Couldn't find filesystem $FSTYPE in /proc/filesystems and failed to load kernal module"
|
||||
+ return $OCF_ERR_INSTALLED
|
||||
+ fi
|
||||
+
|
||||
+ # It is possible for the module to load and not be complete initialized
|
||||
+ # before we check /proc/filesystems again. Give this a few trys before
|
||||
+ # giving up entirely.
|
||||
+ for try in $(seq 5); do
|
||||
+ grep -w "$support"'$' /proc/filesystems >/dev/null
|
||||
+ if [ $? -eq 0 ] ; then
|
||||
+ # yes. found the filesystem after doing the modprobe
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+ ocf_log debug "Unable to find support for $FSTYPE in /proc/filesystems after modprobe, trying again"
|
||||
+ sleep 1
|
||||
+ done
|
||||
+
|
||||
+ ocf_log err "Couldn't find filesystem $FSTYPE in /proc/filesystems"
|
||||
+ return $OCF_ERR_INSTALLED
|
||||
+}
|
||||
+
|
||||
+
|
||||
#
|
||||
# START: Start up the filesystem
|
||||
#
|
||||
@@ -472,24 +524,7 @@ Filesystem_start()
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
- if [ "X${HOSTOS}" != "XOpenBSD" ];then
|
||||
- if [ -z "$FSTYPE" -o "$FSTYPE" = none ]; then
|
||||
- : No FSTYPE specified, rely on the system has the right file-system support already
|
||||
- else
|
||||
- local support="$FSTYPE"
|
||||
- # support fuse-filesystems (e.g. GlusterFS)
|
||||
- case $FSTYPE in
|
||||
- glusterfs) support="fuse";;
|
||||
- esac
|
||||
- grep -w "$support"'$' /proc/filesystems >/dev/null ||
|
||||
- $MODPROBE $support >/dev/null
|
||||
- grep -w "$support"'$' /proc/filesystems >/dev/null
|
||||
- if [ $? -ne 0 ] ; then
|
||||
- ocf_log err "Couldn't find filesystem $FSTYPE in /proc/filesystems"
|
||||
- return $OCF_ERR_INSTALLED
|
||||
- fi
|
||||
- fi
|
||||
- fi
|
||||
+ fstype_supported || exit $OCF_ERR_INSTALLED
|
||||
|
||||
# Check the filesystem & auto repair.
|
||||
# NOTE: Some filesystem types don't need this step... Please modify
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
From 5475e17858d143747e69b1bf9e8d230e74642561 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Fri, 11 Jul 2014 11:22:20 -0400
|
||||
Subject: [PATCH] Low: nfsnotify: fixes error message output
|
||||
|
||||
---
|
||||
heartbeat/nfsnotify | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/nfsnotify b/heartbeat/nfsnotify
|
||||
index 2e242de..2d0bbfc 100755
|
||||
--- a/heartbeat/nfsnotify
|
||||
+++ b/heartbeat/nfsnotify
|
||||
@@ -269,7 +269,7 @@ v3notify_start()
|
||||
ocf_log info "sending notifications with source address $ip"
|
||||
$SM_NOTIFY_BINARY -f $OCF_RESKEY_notify_args -v $ip -P "$cur_statd"
|
||||
if [ $? -ne 0 ]; then
|
||||
- ocf_log err "sm-notify with source host set to, $source_host, failed. view syslog for more information"
|
||||
+ ocf_log err "sm-notify with source host set to, $ip, failed. view syslog for more information"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
done
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
From 8042f21aaefd0616df4b0ef1df2f8e3f301786c4 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Wed, 16 Jul 2014 11:18:56 -0400
|
||||
Subject: [PATCH] Low: nfsserver: only set rquotad options when port is set
|
||||
|
||||
---
|
||||
heartbeat/nfsserver | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
index e44da1c..ac921f3 100755
|
||||
--- a/heartbeat/nfsserver
|
||||
+++ b/heartbeat/nfsserver
|
||||
@@ -428,7 +428,9 @@ set_env_args()
|
||||
set_arg "LOCKD_TCPPORT" "$OCF_RESKEY_lockd_tcp_port" "$tmpconfig" "true"
|
||||
|
||||
# rquotad_port
|
||||
- set_arg "RPCRQUOTADOPTS" "-p $OCF_RESKEY_rquotad_port" "$tmpconfig" "true"
|
||||
+ if [ -n "$OCF_RESKEY_rquotad_port" ]; then
|
||||
+ set_arg "RPCRQUOTADOPTS" "-p $OCF_RESKEY_rquotad_port" "$tmpconfig" "true"
|
||||
+ fi
|
||||
|
||||
# override local nfs config. preserve previous local config though.
|
||||
if [ -s $tmpconfig ]; then
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,87 @@
|
|||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index 9209818..6a852df 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -196,6 +196,26 @@ Only set this to "true" if you know what you are doing!
|
||||
<content type="boolean" default="$OCF_RESKEY_force_clones_default" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="force_unmount">
|
||||
+<longdesc lang="en">
|
||||
+This option allows specifying how to handle processes that are
|
||||
+currently accessing the mount directory.
|
||||
+
|
||||
+"true" : Default value, kill processes accessing mount point
|
||||
+"safe" : Kill processes accessing mount point using methods that
|
||||
+ avoid functions that could potentially block during process
|
||||
+ detection
|
||||
+"false" : Do not kill any processes.
|
||||
+
|
||||
+The 'safe' option uses shell logic to walk the /procs/ directory
|
||||
+for pids using the mount point while the default option uses the
|
||||
+fuser cli tool. fuser is known to perform operations that can potentially
|
||||
+block if unresponsive nfs mounts are in use on the system.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Kill processes before unmount</shortdesc>
|
||||
+<content type="boolean" default="true" />
|
||||
+</parameter>
|
||||
+
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -701,6 +721,25 @@ Filesystem_notify() {
|
||||
done
|
||||
}
|
||||
|
||||
+get_pids()
|
||||
+{
|
||||
+ local dir=$1
|
||||
+ local procs
|
||||
+ local mmap_procs
|
||||
+
|
||||
+ if ocf_is_true "$FORCE_UNMOUNT"; then
|
||||
+ if [ "X${HOSTOS}" = "XOpenBSD" ];then
|
||||
+ fstat | grep $dir | awk '{print $3}'
|
||||
+ else
|
||||
+ $FUSER -m $dir 2>/dev/null
|
||||
+ fi
|
||||
+ elif [ "$FORCE_UNMOUNT" = "safe" ]; then
|
||||
+ procs=$(find /proc/[0-9]*/ -type l -lname "${dir}/*" -or -lname "${dir}" 2>/dev/null | awk -F/ '{print $3}')
|
||||
+ mmap_procs=$(grep " ${dir}" /proc/[0-9]*/maps | awk -F/ '{print $3}')
|
||||
+ echo -e "${procs}\n${mmap_procs}" | sort | uniq
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
signal_processes() {
|
||||
local dir=$1
|
||||
local sig=$2
|
||||
@@ -708,15 +747,9 @@ signal_processes() {
|
||||
# fuser returns a non-zero return code if none of the
|
||||
# specified files is accessed or in case of a fatal
|
||||
# error.
|
||||
- pids=$(
|
||||
- if [ "X${HOSTOS}" = "XOpenBSD" ];then
|
||||
- fstat | grep $dir | awk '{print $3}'
|
||||
- else
|
||||
- $FUSER -m $dir 2>/dev/null
|
||||
- fi
|
||||
- )
|
||||
+ pids=$(get_pids "$dir")
|
||||
if [ -z "$pids" ]; then
|
||||
- ocf_log info "No processes on $dir were signalled"
|
||||
+ ocf_log info "No processes on $dir were signalled. force_unmount is set to '$FORCE_UNMOUNT'"
|
||||
return
|
||||
fi
|
||||
for pid in $pids; do
|
||||
@@ -1002,6 +1035,11 @@ if [ $# -ne 1 ]; then
|
||||
fi
|
||||
|
||||
# Check the OCF_RESKEY_ environment variables...
|
||||
+FORCE_UNMOUNT="yes"
|
||||
+if [ -n "${OCF_RESKEY_force_unmount}" ]; then
|
||||
+ FORCE_UNMOUNT=$OCF_RESKEY_force_unmount
|
||||
+fi
|
||||
+
|
||||
DEVICE=$OCF_RESKEY_device
|
||||
FSTYPE=$OCF_RESKEY_fstype
|
||||
if [ ! -z "$OCF_RESKEY_options" ]; then
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
From 4f6ebfc537b2d3671112a54873081685d47066db Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Fri, 18 Jul 2014 12:31:55 -0400
|
||||
Subject: [PATCH] Low: LVM: Warn users about the danger of lvmetad
|
||||
|
||||
---
|
||||
heartbeat/LVM | 19 +++++++++++++++++++
|
||||
1 file changed, 19 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/LVM b/heartbeat/LVM
|
||||
index 4378cd3..27cdfbd 100755
|
||||
--- a/heartbeat/LVM
|
||||
+++ b/heartbeat/LVM
|
||||
@@ -545,6 +545,25 @@ LVM_validate_all() {
|
||||
check_binary $AWK
|
||||
|
||||
##
|
||||
+ # lvmetad is a daemon that caches lvm metadata to improve the
|
||||
+ # performance of LVM commands. This daemon should never be used when
|
||||
+ # volume groups exist that are being managed by the cluster. The lvmetad
|
||||
+ # daemon introduces a response lag, where certain LVM commands look like
|
||||
+ # they have completed (like vg activation) when in fact the command
|
||||
+ # is still in progress by the lvmetad. This can cause reliability issues
|
||||
+ # when managing volume groups in the cluster. For Example, if you have a
|
||||
+ # volume group that is a dependency for another application, it is possible
|
||||
+ # the cluster will think the volume group is activated and attempt to start
|
||||
+ # the application before volume group is really accesible... lvmetad is bad.
|
||||
+ ##
|
||||
+ lvm dumpconfig global/use_lvmetad | grep 'use_lvmetad.*=.*1' > /dev/null 2>&1
|
||||
+ if [ $? -eq 0 ]; then
|
||||
+ # for now warn users that lvmetad is enabled and that they should disable it. In the
|
||||
+ # future we may want to consider refusing to start, or killing the lvmetad daemon.
|
||||
+ ocf_log warn "Disable lvmetad in lvm.conf. lvmetad should never be enabled in a clustered environment. Set use_lvmetad=0 and kill the lvmetad process"
|
||||
+ fi
|
||||
+
|
||||
+ ##
|
||||
# Off-the-shelf tests...
|
||||
##
|
||||
VGOUT=`vgck ${VOLUME} 2>&1`
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From 458c003e7f6f0caa2e1c7f4386e458a039500427 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Thu, 19 Jun 2014 14:52:36 -0500
|
||||
Subject: [PATCH] High: VirtualDomain: restore advertised start and stop
|
||||
timeout values to a sane value.
|
||||
|
||||
The meta_timeout default value is 90000 milliseconds. That value
|
||||
was used in the xml output to represent the default start and stop
|
||||
timeout which is reflected in seconds... not milliseconds. A
|
||||
90000 second timeout doesn't make sense as a default.
|
||||
---
|
||||
heartbeat/VirtualDomain | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
index c44c090..b0cdd5f 100755
|
||||
--- a/heartbeat/VirtualDomain
|
||||
+++ b/heartbeat/VirtualDomain
|
||||
@@ -167,8 +167,8 @@ Restore state on start/stop
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
-<action name="start" timeout="$OCF_RESKEY_CRM_meta_timeout_default" />
|
||||
-<action name="stop" timeout="$OCF_RESKEY_CRM_meta_timeout_default" />
|
||||
+<action name="start" timeout="90" />
|
||||
+<action name="stop" timeout="90" />
|
||||
<action name="status" depth="0" timeout="30" interval="10" />
|
||||
<action name="monitor" depth="0" timeout="30" interval="10" />
|
||||
<action name="migrate_from" timeout="60" />
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
From 54c26715a8eb5688081ea6e26cabe54d9de762d7 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Wed, 30 Jul 2014 13:03:14 -0500
|
||||
Subject: [PATCH 6/6] Low: galera: be very generous in the promotion timeout to
|
||||
allow SST to complete on large databases
|
||||
|
||||
---
|
||||
heartbeat/galera | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/galera b/heartbeat/galera
|
||||
index a361d7b..994aad0 100755
|
||||
--- a/heartbeat/galera
|
||||
+++ b/heartbeat/galera
|
||||
@@ -235,7 +235,7 @@ Cluster check user password
|
||||
<action name="monitor" depth="0" timeout="30" interval="20" />
|
||||
<action name="monitor" role="Master" depth="0" timeout="30" interval="10" />
|
||||
<action name="monitor" role="Slave" depth="0" timeout="30" interval="30" />
|
||||
-<action name="promote" timeout="120" />
|
||||
+<action name="promote" timeout="300" />
|
||||
<action name="demote" timeout="120" />
|
||||
<action name="validate-all" timeout="5" />
|
||||
<action name="meta-data" timeout="5" />
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
From bc1e7bdcedc1bb1bf473787f373261452e37e337 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Wed, 30 Jul 2014 12:59:46 -0500
|
||||
Subject: [PATCH 5/6] Low: galera: do not advertise notify in the usage
|
||||
|
||||
---
|
||||
heartbeat/galera | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/galera b/heartbeat/galera
|
||||
index 386daaf..a361d7b 100755
|
||||
--- a/heartbeat/galera
|
||||
+++ b/heartbeat/galera
|
||||
@@ -79,7 +79,7 @@ fi
|
||||
|
||||
usage() {
|
||||
cat <<UEND
|
||||
-usage: $0 (start|stop|validate-all|meta-data|monitor|promote|demote|notify)
|
||||
+usage: $0 (start|stop|validate-all|meta-data|monitor|promote|demote)
|
||||
|
||||
$0 manages a galera Database as an HA resource.
|
||||
|
||||
@@ -237,7 +237,6 @@ Cluster check user password
|
||||
<action name="monitor" role="Slave" depth="0" timeout="30" interval="30" />
|
||||
<action name="promote" timeout="120" />
|
||||
<action name="demote" timeout="120" />
|
||||
-<action name="notify" timeout="90" />
|
||||
<action name="validate-all" timeout="5" />
|
||||
<action name="meta-data" timeout="5" />
|
||||
</actions>
|
||||
@@ -683,7 +682,6 @@ case "$1" in
|
||||
monitor) galera_monitor;;
|
||||
promote) galera_promote;;
|
||||
demote) galera_demote;;
|
||||
- notify) galera_notify;;
|
||||
validate-all) exit $OCF_SUCCESS;;
|
||||
|
||||
*) usage
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,25 @@
|
|||
From e5c5c087ecf152bd69f5795024bfc655394c3c18 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Kurz <andreas.kurz@gmail.com>
|
||||
Date: Thu, 18 Sep 2014 23:06:36 +0200
|
||||
Subject: [PATCH 1/6] High: galera: do not ignore specified check_password
|
||||
|
||||
---
|
||||
heartbeat/galera | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/galera b/heartbeat/galera
|
||||
index 54654f8..386daaf 100755
|
||||
--- a/heartbeat/galera
|
||||
+++ b/heartbeat/galera
|
||||
@@ -672,7 +672,7 @@ fi
|
||||
|
||||
MYSQL_OPTIONS_CHECK="-nNE --user=${OCF_RESKEY_check_user}"
|
||||
if [ -n "${OCF_RESKEY_check_passwd}" ]; then
|
||||
- MYSQL_OPTIONS_CHECK="$MYSQL_OPTIONS_CHECK --password=${MYSQL_PASSWORD}"
|
||||
+ MYSQL_OPTIONS_CHECK="$MYSQL_OPTIONS_CHECK --password=${OCF_RESKEY_check_passwd}"
|
||||
fi
|
||||
|
||||
# What kind of method was invoked?
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,13 @@
|
|||
diff --git a/heartbeat/iSCSILogicalUnit b/heartbeat/iSCSILogicalUnit
|
||||
index b9c1139..ffd66ff 100755
|
||||
--- a/heartbeat/iSCSILogicalUnit
|
||||
+++ b/heartbeat/iSCSILogicalUnit
|
||||
@@ -362,7 +362,7 @@ iSCSILogicalUnit_start() {
|
||||
lio-t)
|
||||
# For lio, we first have to create a target device, then
|
||||
# add it to the Target Portal Group as an LU.
|
||||
- ocf_run targetcli /backstores/block create name=${OCF_RESOURCE_INSTANCE} dev=${OCF_RESKEY_path} write_back=False || exit $OCF_ERR_GENERIC
|
||||
+ ocf_run targetcli /backstores/block create name=${OCF_RESOURCE_INSTANCE} dev=${OCF_RESKEY_path} || exit $OCF_ERR_GENERIC
|
||||
if [ -n "${OCF_RESKEY_scsi_sn}" ]; then
|
||||
echo ${OCF_RESKEY_scsi_sn} > /sys/kernel/config/target/core/iblock_${OCF_RESKEY_lio_iblock}/${OCF_RESOURCE_INSTANCE}/wwn/vpd_unit_serial
|
||||
fi
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
From 3a9d34b37c3959c75b60a3598ed0786e5c48a7b3 Mon Sep 17 00:00:00 2001
|
||||
From: jprades <jprades@presenzia.net>
|
||||
Date: Wed, 17 Sep 2014 17:54:10 -0400
|
||||
Subject: [PATCH] High: iSCSILogicalUnit: fixes syntax errors
|
||||
|
||||
---
|
||||
heartbeat/iSCSILogicalUnit | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/iSCSILogicalUnit b/heartbeat/iSCSILogicalUnit
|
||||
index c4cee0d..b9c1139 100755
|
||||
--- a/heartbeat/iSCSILogicalUnit
|
||||
+++ b/heartbeat/iSCSILogicalUnit
|
||||
@@ -419,11 +419,11 @@ iSCSILogicalUnit_stop() {
|
||||
${initiator} ${OCF_RESKEY_lun} || exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
done
|
||||
- lun_configfs_path="/sys/kernel/config/target/iscsi/${OCF_RESKEY_target_iqn}/tpgt_1/lun/lun_#{${OCF_RESKEY_lun}/"
|
||||
+ lun_configfs_path="/sys/kernel/config/target/iscsi/${OCF_RESKEY_target_iqn}/tpgt_1/lun/lun_${OCF_RESKEY_lun}/"
|
||||
if [ -e "${lun_configfs_path}" ]; then
|
||||
ocf_run lio_node --dellun=${OCF_RESKEY_target_iqn} 1 ${OCF_RESKEY_lun} || exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
- block_configfs_path="/sys/kernel/config/target/core/iblock_${OCF_RESKEY_lio_iblock}/${OCF_RESKEY_INSTANCE}/udev_path"
|
||||
+ block_configfs_path="/sys/kernel/config/target/core/iblock_${OCF_RESKEY_lio_iblock}/${OCF_RESOURCE_INSTANCE}/udev_path"
|
||||
if [ -e "${block_configfs_path}" ]; then
|
||||
ocf_run tcm_node --freedev=iblock_${OCF_RESKEY_lio_iblock}/${OCF_RESOURCE_INSTANCE} || exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
@@ -478,7 +478,7 @@ iSCSILogicalUnit_monitor() {
|
||||
[ -e ${configfs_path} ] && [ `cat ${configfs_path}` = "${OCF_RESKEY_path}" ] && return $OCF_SUCCESS
|
||||
|
||||
# if we aren't activated, is a block device still left over?
|
||||
- block_configfs_path="/sys/kernel/config/target/core/iblock_${OCF_RESKEY_lio_iblock}/${OCF_RESKEY_INSTANCE}/udev_path"
|
||||
+ block_configfs_path="/sys/kernel/config/target/core/iblock_${OCF_RESKEY_lio_iblock}/${OCF_RESOURCE_INSTANCE}/udev_path"
|
||||
[ -e ${block_configfs_path} ] && ocf_log warn "existing block without an active lun: ${block_configfs_path}"
|
||||
[ -e ${block_configfs_path} ] && return $OCF_ERR_GENERIC
|
||||
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,466 @@
|
|||
From feffc766c48a1010c1bf4f8b1db74795d06dbd50 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Mon, 25 Aug 2014 14:57:09 -0500
|
||||
Subject: [PATCH 2/4] ethmonitor updates
|
||||
|
||||
---
|
||||
heartbeat/ethmonitor | 290 +++++++++++++++++++++++++++++++++------------------
|
||||
1 file changed, 187 insertions(+), 103 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/ethmonitor b/heartbeat/ethmonitor
|
||||
index b85d7fc..a447391 100755
|
||||
--- a/heartbeat/ethmonitor
|
||||
+++ b/heartbeat/ethmonitor
|
||||
@@ -1,14 +1,14 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
-# OCF Resource Agent compliant script.
|
||||
-# Monitor the vitality of a local network interface.
|
||||
+# OCF Resource Agent compliant script.
|
||||
+# Monitor the vitality of a local network interface.
|
||||
#
|
||||
# Based on the work by Robert Euhus and Lars Marowsky-Brée.
|
||||
#
|
||||
# Transfered from Ipaddr2 into ethmonitor by Alexander Krauth
|
||||
#
|
||||
# Copyright (c) 2011 Robert Euhus, Alexander Krauth, Lars Marowsky-Brée
|
||||
-# All Rights Reserved.
|
||||
+# All Rights Reserved.
|
||||
#
|
||||
# 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
|
||||
@@ -29,12 +29,12 @@
|
||||
# along with this program; if not, write the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
#
|
||||
-# OCF parameters are as below
|
||||
+# OCF parameters are as below
|
||||
#
|
||||
# OCF_RESKEY_interface
|
||||
# OCF_RESKEY_multiplicator
|
||||
# OCF_RESKEY_name
|
||||
-# OCF_RESKEY_repeat_count
|
||||
+# OCF_RESKEY_repeat_count
|
||||
# OCF_RESKEY_repeat_interval
|
||||
# OCF_RESKEY_pktcnt_timeout
|
||||
# OCF_RESKEY_arping_count
|
||||
@@ -70,10 +70,13 @@ The resource configuration requires a monitor operation, because the monitor doe
|
||||
In addition to the resource configuration, you need to configure some location constraints, based on a CIB attribute value.
|
||||
The name of the attribute value is configured in the 'name' option of this RA.
|
||||
|
||||
-Example constraint configuration:
|
||||
+Example constraint configuration using crmsh
|
||||
location loc_connected_node my_resource_grp \
|
||||
rule $id="rule_loc_connected_node" -INF: ethmonitor eq 0
|
||||
|
||||
+Example constraint configuration using pcs. Only allow 'my_resource' to run on nodes where eth0 ethernet device is available.
|
||||
+pcs constraint location my_resource rule score=-INFINITY ethmonitor-eth0 ne 1
|
||||
+
|
||||
The ethmonitor works in 3 different modes to test the interface vitality.
|
||||
1. call ip to see if the link status is up (if link is down -> error)
|
||||
2. call ip and watch the RX counter (if packages come around in a certain time -> success)
|
||||
@@ -157,14 +160,30 @@ Maximum number of IPs from ARP cache list to check for ARP REQUEST (arping) answ
|
||||
<content type="integer" default="5"/>
|
||||
</parameter>
|
||||
|
||||
+<parameter name="infiniband_device">
|
||||
+<longdesc lang="en">
|
||||
+For interfaces that are infiniband devices.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">infiniband device</shortdesc>
|
||||
+<content type="string" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="infiniband_port">
|
||||
+<longdesc lang="en">
|
||||
+For infiniband devices, this is the port to monitor.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">infiniband port</shortdesc>
|
||||
+<content type="integer" />
|
||||
+</parameter>
|
||||
+
|
||||
</parameters>
|
||||
<actions>
|
||||
-<action name="start" timeout="20s" />
|
||||
-<action name="stop" timeout="20s" />
|
||||
-<action name="status" depth="0" timeout="20s" interval="10s" />
|
||||
-<action name="monitor" depth="0" timeout="20s" interval="10s" />
|
||||
-<action name="meta-data" timeout="5s" />
|
||||
-<action name="validate-all" timeout="20s" />
|
||||
+<action name="start" timeout="60s" />
|
||||
+<action name="stop" timeout="20s" />
|
||||
+<action name="status" depth="0" timeout="60s" interval="10s" />
|
||||
+<action name="monitor" depth="0" timeout="60s" interval="10s" />
|
||||
+<action name="meta-data" timeout="5s" />
|
||||
+<action name="validate-all" timeout="20s" />
|
||||
</actions>
|
||||
</resource-agent>
|
||||
END
|
||||
@@ -173,7 +192,7 @@ END
|
||||
}
|
||||
|
||||
#
|
||||
-# Return true, if the interface exists
|
||||
+# Return true, if the interface exists
|
||||
#
|
||||
is_interface() {
|
||||
#
|
||||
@@ -181,14 +200,25 @@ is_interface() {
|
||||
#
|
||||
local iface=`$IP2UTIL -o -f inet addr show | grep " $1 " \
|
||||
| cut -d ' ' -f2 | sort -u | grep -v '^ipsec[0-9][0-9]*$'`
|
||||
- [ "$iface" != "" ]
|
||||
+ [ "$iface" != "" ]
|
||||
+}
|
||||
+
|
||||
+infiniband_status()
|
||||
+{
|
||||
+ local device="$OCF_RESKEY_infiniband_device"
|
||||
+
|
||||
+ if [ -n "$OCF_RESKEY_infiniband_port" ]; then
|
||||
+ device="${OCF_RESKEY_infiniband_device}:${OCF_RESKEY_infiniband_port}"
|
||||
+ fi
|
||||
+
|
||||
+ ibstatus ${device} | grep -q ACTIVE
|
||||
}
|
||||
|
||||
if_init() {
|
||||
local rc
|
||||
|
||||
if [ X"$OCF_RESKEY_interface" = "X" ]; then
|
||||
- ocf_log err "Interface name (the interface parameter) is mandatory"
|
||||
+ ocf_exit_reason "Interface name (the interface parameter) is mandatory"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
@@ -196,60 +226,67 @@ if_init() {
|
||||
|
||||
if is_interface $NIC
|
||||
then
|
||||
- case "$NIC" in
|
||||
- *:*) ocf_log err "Do not specify a virtual interface : $OCF_RESKEY_interface"
|
||||
- exit $OCF_ERR_CONFIGURED;;
|
||||
- *) ;;
|
||||
- esac
|
||||
+ case "$NIC" in
|
||||
+ *:*) ocf_exit_reason "Do not specify a virtual interface : $OCF_RESKEY_interface"
|
||||
+ exit $OCF_ERR_CONFIGURED;;
|
||||
+ *) ;;
|
||||
+ esac
|
||||
else
|
||||
- case $__OCF_ACTION in
|
||||
- validate-all) ocf_log err "Interface $NIC does not exist"
|
||||
- exit $OCF_ERR_CONFIGURED;;
|
||||
- *) ocf_log warn "Interface $NIC does not exist"
|
||||
- ## It might be a bond interface which is temporarily not available, therefore we want to continue here
|
||||
- ;;
|
||||
- esac
|
||||
+ case $__OCF_ACTION in
|
||||
+ validate-all)
|
||||
+ ocf_exit_reason "Interface $NIC does not exist"
|
||||
+ exit $OCF_ERR_CONFIGURED;;
|
||||
+ *)
|
||||
+ ## It might be a bond interface which is temporarily not available, therefore we want to continue here
|
||||
+ ocf_log warn "Interface $NIC does not exist"
|
||||
+ ;;
|
||||
+ esac
|
||||
fi
|
||||
|
||||
: ${OCF_RESKEY_multiplier:="1"}
|
||||
if ! ocf_is_decimal "$OCF_RESKEY_multiplier"; then
|
||||
- ocf_log err "Invalid OCF_RESKEY_multiplier [$OCF_RESKEY_multiplier]"
|
||||
+ ocf_exit_reason "Invalid OCF_RESKEY_multiplier [$OCF_RESKEY_multiplier]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
ATTRNAME=${OCF_RESKEY_name:-"ethmonitor-$NIC"}
|
||||
|
||||
- REP_COUNT=${OCF_RESKEY_repeat_count:-5}
|
||||
+ REP_COUNT=${OCF_RESKEY_repeat_count:-5}
|
||||
if ! ocf_is_decimal "$REP_COUNT" -o [ $REP_COUNT -lt 1 ]; then
|
||||
- ocf_log err "Invalid OCF_RESKEY_repeat_count [$REP_COUNT]"
|
||||
+ ocf_exit_reason "Invalid OCF_RESKEY_repeat_count [$REP_COUNT]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
+ fi
|
||||
REP_INTERVAL_S=${OCF_RESKEY_repeat_interval:-10}
|
||||
if ! ocf_is_decimal "$REP_INTERVAL_S"; then
|
||||
- ocf_log err "Invalid OCF_RESKEY_repeat_interval [$REP_INTERVAL_S]"
|
||||
+ ocf_exit_reason "Invalid OCF_RESKEY_repeat_interval [$REP_INTERVAL_S]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
: ${OCF_RESKEY_pktcnt_timeout:="5"}
|
||||
if ! ocf_is_decimal "$OCF_RESKEY_pktcnt_timeout"; then
|
||||
- ocf_log err "Invalid OCF_RESKEY_pktcnt_timeout [$OCF_RESKEY_pktcnt_timeout]"
|
||||
+ ocf_exit_reason "Invalid OCF_RESKEY_pktcnt_timeout [$OCF_RESKEY_pktcnt_timeout]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
: ${OCF_RESKEY_arping_count:="1"}
|
||||
if ! ocf_is_decimal "$OCF_RESKEY_arping_count"; then
|
||||
- ocf_log err "Invalid OCF_RESKEY_arping_count [$OCF_RESKEY_arping_count]"
|
||||
+ ocf_exit_reason "Invalid OCF_RESKEY_arping_count [$OCF_RESKEY_arping_count]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
: ${OCF_RESKEY_arping_timeout:="1"}
|
||||
if ! ocf_is_decimal "$OCF_RESKEY_arping_timeout"; then
|
||||
- ocf_log err "Invalid OCF_RESKEY_arping_timeout [$OCF_RESKEY_arping_count]"
|
||||
+ ocf_exit_reason "Invalid OCF_RESKEY_arping_timeout [$OCF_RESKEY_arping_count]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
: ${OCF_RESKEY_arping_cache_entries:="5"}
|
||||
if ! ocf_is_decimal "$OCF_RESKEY_arping_cache_entries"; then
|
||||
- ocf_log err "Invalid OCF_RESKEY_arping_cache_entries [$OCF_RESKEY_arping_cache_entries]"
|
||||
+ ocf_exit_reason "Invalid OCF_RESKEY_arping_cache_entries [$OCF_RESKEY_arping_cache_entries]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
- return $OCF_SUCCESS
|
||||
+
|
||||
+ if [ -n "$OCF_RESKEY_infiniband_device" ]; then
|
||||
+ #ibstatus is required if an infiniband_device is provided
|
||||
+ check_binary ibstatus
|
||||
+ fi
|
||||
+ return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
# get the link status on $NIC
|
||||
@@ -277,7 +314,7 @@ watch_pkt_counter () {
|
||||
for n in `seq $(( $OCF_RESKEY_pktcnt_timeout * 10 ))`; do
|
||||
sleep 0.1
|
||||
RX_PACKETS_NEW="`get_rx_packets`"
|
||||
- ocf_log debug "RX_PACKETS_OLD: $RX_PACKETS_OLD RX_PACKETS_NEW: $RX_PACKETS_NEW"
|
||||
+ ocf_log debug "RX_PACKETS_OLD: $RX_PACKETS_OLD RX_PACKETS_NEW: $RX_PACKETS_NEW"
|
||||
if [ "$RX_PACKETS_OLD" -ne "$RX_PACKETS_NEW" ]; then
|
||||
ocf_log debug "we received some packets."
|
||||
return 0
|
||||
@@ -308,7 +345,7 @@ do_arping () {
|
||||
}
|
||||
|
||||
#
|
||||
-# Check the interface depending on the level given as parameter: $OCF_RESKEY_check_level
|
||||
+# Check the interface depending on the level given as parameter: $OCF_RESKEY_check_level
|
||||
#
|
||||
# 09: check for nonempty ARP cache
|
||||
# 10: watch for packet counter changes
|
||||
@@ -322,21 +359,47 @@ do_arping () {
|
||||
# the tests for higher check levels are run.
|
||||
#
|
||||
if_check () {
|
||||
+ local arp_list
|
||||
# always check link status first
|
||||
link_status="`get_link_status`"
|
||||
ocf_log debug "link_status: $link_status (1=up, 0=down)"
|
||||
- [ $link_status -eq 0 ] && return $OCF_NOT_RUNNING
|
||||
+
|
||||
+ if [ $link_status -eq 0 ]; then
|
||||
+ ocf_log notice "link_status: DOWN"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+
|
||||
+ # if this is an infiniband device, try ibstatus script
|
||||
+ if [ -n "$OCF_RESKEY_infiniband_device" ]; then
|
||||
+ if infiniband_status; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+ ocf_log info "Infiniband device $OCF_RESKEY_infiniband_device is not available, check ibstatus for more information"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
|
||||
# watch for packet counter changes
|
||||
- ocf_log debug "watch for packet counter changes"
|
||||
- watch_pkt_counter && return $OCF_SUCCESS
|
||||
+ ocf_log debug "watch for packet counter changes"
|
||||
+ watch_pkt_counter
|
||||
+ if [ $? -eq 0 ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ else
|
||||
+ ocf_log debug "No packets received during packet watch timeout"
|
||||
+ fi
|
||||
|
||||
# check arping ARP cache entries
|
||||
- ocf_log debug "check arping ARP cache entries"
|
||||
- for ip in `get_arp_list`; do
|
||||
+ ocf_log debug "check arping ARP cache entries"
|
||||
+ arp_list=`get_arp_list`
|
||||
+ for ip in `echo $arp_list`; do
|
||||
do_arping $ip && return $OCF_SUCCESS
|
||||
done
|
||||
|
||||
+ # if we get here, the ethernet device is considered not running.
|
||||
+ # provide some logging information
|
||||
+ if [ -z "$arp_list" ]; then
|
||||
+ ocf_log info "No ARP cache entries found to arping"
|
||||
+ fi
|
||||
+
|
||||
# watch for packet counter changes in promiscios mode
|
||||
# ocf_log debug "watch for packet counter changes in promiscios mode"
|
||||
# be sure switch off promiscios mode in any case
|
||||
@@ -362,67 +425,89 @@ END
|
||||
}
|
||||
|
||||
set_cib_value() {
|
||||
- local score=`expr $1 \* $OCF_RESKEY_multiplier`
|
||||
- attrd_updater -n $ATTRNAME -v $score -q
|
||||
- local rc=$?
|
||||
- case $rc in
|
||||
- 0) ocf_log debug "attrd_updater: Updated $ATTRNAME = $score" ;;
|
||||
- *) ocf_log warn "attrd_updater: Could not update $ATTRNAME = $score: rc=$rc";;
|
||||
- esac
|
||||
- return $rc
|
||||
+ local score=`expr $1 \* $OCF_RESKEY_multiplier`
|
||||
+ attrd_updater -n $ATTRNAME -v $score -q
|
||||
+ local rc=$?
|
||||
+ case $rc in
|
||||
+ 0) ocf_log debug "attrd_updater: Updated $ATTRNAME = $score" ;;
|
||||
+ *) ocf_log warn "attrd_updater: Could not update $ATTRNAME = $score: rc=$rc";;
|
||||
+ esac
|
||||
+ return $rc
|
||||
}
|
||||
|
||||
if_monitor() {
|
||||
- ha_pseudo_resource $OCF_RESOURCE_INSTANCE monitor
|
||||
- local pseudo_status=$?
|
||||
- if [ $pseudo_status -ne $OCF_SUCCESS ]; then
|
||||
- exit $pseudo_status
|
||||
- fi
|
||||
-
|
||||
- local mon_rc=$OCF_NOT_RUNNING
|
||||
- local attr_rc=$OCF_NOT_RUNNING
|
||||
- local runs=0
|
||||
- local start_time
|
||||
- local end_time
|
||||
- local sleep_time
|
||||
- while [ $mon_rc -ne $OCF_SUCCESS -a $REP_COUNT -gt 0 ]
|
||||
- do
|
||||
- start_time=`date +%s%N`
|
||||
- if_check
|
||||
- mon_rc=$?
|
||||
- REP_COUNT=$(( $REP_COUNT - 1 ))
|
||||
- if [ $mon_rc -ne $OCF_SUCCESS -a $REP_COUNT -gt 0 ]; then
|
||||
- ocf_log warn "Monitoring of $OCF_RESOURCE_INSTANCE failed, $REP_COUNT retries left."
|
||||
- end_time=`date +%s%N`
|
||||
- sleep_time=`echo "scale=9; ( $start_time + ( $REP_INTERVAL_S * 1000000000 ) - $end_time ) / 1000000000" | bc -q 2> /dev/null`
|
||||
- sleep $sleep_time 2> /dev/null
|
||||
- runs=$(($runs + 1))
|
||||
- fi
|
||||
-
|
||||
- if [ $mon_rc -eq $OCF_SUCCESS -a $runs -ne 0 ]; then
|
||||
- ocf_log info "Monitoring of $OCF_RESOURCE_INSTANCE recovered from error"
|
||||
- fi
|
||||
- done
|
||||
-
|
||||
- ocf_log debug "Monitoring return code: $mon_rc"
|
||||
- if [ $mon_rc -eq $OCF_SUCCESS ]; then
|
||||
- set_cib_value 1
|
||||
- attr_rc=$?
|
||||
- else
|
||||
- ocf_log err "Monitoring of $OCF_RESOURCE_INSTANCE failed."
|
||||
- set_cib_value 0
|
||||
- attr_rc=$?
|
||||
- fi
|
||||
-
|
||||
- ## The resource should not fail, if the interface is down. It should fail, if the update of the CIB variable has errors.
|
||||
- ## To react on the interface failure you must use constraints based on the CIB variable value, not on the resource itself.
|
||||
- exit $attr_rc
|
||||
+ ha_pseudo_resource $OCF_RESOURCE_INSTANCE monitor
|
||||
+ local pseudo_status=$?
|
||||
+ if [ $pseudo_status -ne $OCF_SUCCESS ]; then
|
||||
+ exit $pseudo_status
|
||||
+ fi
|
||||
+
|
||||
+ local mon_rc=$OCF_NOT_RUNNING
|
||||
+ local attr_rc=$OCF_NOT_RUNNING
|
||||
+ local runs=0
|
||||
+ local start_time
|
||||
+ local end_time
|
||||
+ local sleep_time
|
||||
+ while [ $mon_rc -ne $OCF_SUCCESS -a $REP_COUNT -gt 0 ]
|
||||
+ do
|
||||
+ start_time=`date +%s%N`
|
||||
+ if_check
|
||||
+ mon_rc=$?
|
||||
+ REP_COUNT=$(( $REP_COUNT - 1 ))
|
||||
+ if [ $mon_rc -ne $OCF_SUCCESS -a $REP_COUNT -gt 0 ]; then
|
||||
+ ocf_log warn "Monitoring of $OCF_RESOURCE_INSTANCE failed, $REP_COUNT retries left."
|
||||
+ end_time=`date +%s%N`
|
||||
+ sleep_time=`echo "scale=9; ( $start_time + ( $REP_INTERVAL_S * 1000000000 ) - $end_time ) / 1000000000" | bc -q 2> /dev/null`
|
||||
+ sleep $sleep_time 2> /dev/null
|
||||
+ runs=$(($runs + 1))
|
||||
+ fi
|
||||
+
|
||||
+ if [ $mon_rc -eq $OCF_SUCCESS -a $runs -ne 0 ]; then
|
||||
+ ocf_log info "Monitoring of $OCF_RESOURCE_INSTANCE recovered from error"
|
||||
+ fi
|
||||
+ done
|
||||
+
|
||||
+ ocf_log debug "Monitoring return code: $mon_rc"
|
||||
+ if [ $mon_rc -eq $OCF_SUCCESS ]; then
|
||||
+ set_cib_value 1
|
||||
+ attr_rc=$?
|
||||
+ else
|
||||
+ ocf_log err "Monitoring of $OCF_RESOURCE_INSTANCE failed."
|
||||
+ set_cib_value 0
|
||||
+ attr_rc=$?
|
||||
+ fi
|
||||
+
|
||||
+ ## The resource should not fail, if the interface is down. It should fail, if the update of the CIB variable has errors.
|
||||
+ ## To react on the interface failure you must use constraints based on the CIB variable value, not on the resource itself.
|
||||
+ exit $attr_rc
|
||||
+}
|
||||
+
|
||||
+if_stop()
|
||||
+{
|
||||
+ attrd_updater -D -n $ATTRNAME
|
||||
+ ha_pseudo_resource $OCF_RESOURCE_INSTANCE stop
|
||||
}
|
||||
|
||||
+if_start()
|
||||
+{
|
||||
+ local rc
|
||||
+ ha_pseudo_resource $OCF_RESOURCE_INSTANCE start
|
||||
+ rc=$?
|
||||
+ if [ $rc -ne $OCF_SUCCESS ]; then
|
||||
+ ocf_exit_reason "Failure to create ethmonitor state file"
|
||||
+ return $rc
|
||||
+ fi
|
||||
+
|
||||
+ # perform the first monitor during the start operation
|
||||
+ if_monitor
|
||||
+ return $?
|
||||
+}
|
||||
+
|
||||
+
|
||||
if_validate() {
|
||||
- check_binary $IP2UTIL
|
||||
- check_binary arping
|
||||
- if_init
|
||||
+ check_binary $IP2UTIL
|
||||
+ check_binary arping
|
||||
+ if_init
|
||||
}
|
||||
|
||||
case $__OCF_ACTION in
|
||||
@@ -436,18 +521,17 @@ esac
|
||||
if_validate
|
||||
|
||||
case $__OCF_ACTION in
|
||||
-start) ha_pseudo_resource $OCF_RESOURCE_INSTANCE start
|
||||
+start) if_start
|
||||
exit $?
|
||||
;;
|
||||
-stop) attrd_updater -D -n $ATTRNAME
|
||||
- ha_pseudo_resource $OCF_RESOURCE_INSTANCE stop
|
||||
+stop) if_stop
|
||||
exit $?
|
||||
;;
|
||||
monitor|status) if_monitor
|
||||
exit $?
|
||||
;;
|
||||
validate-all) exit $?
|
||||
- ;;
|
||||
+ ;;
|
||||
*) if_usage
|
||||
exit $OCF_ERR_UNIMPLEMENTED
|
||||
;;
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,474 @@
|
|||
diff -uNr a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
--- a/heartbeat/nfsserver 2016-02-05 09:04:19.350003826 +0100
|
||||
+++ b/heartbeat/nfsserver 2016-02-05 09:04:58.463395839 +0100
|
||||
@@ -208,9 +208,9 @@
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
-<action name="start" timeout="90" />
|
||||
-<action name="stop" timeout="60s" />
|
||||
-<action name="monitor" depth="0" timeout="30s" interval="10" />
|
||||
+<action name="start" timeout="40" />
|
||||
+<action name="stop" timeout="20s" />
|
||||
+<action name="monitor" depth="0" timeout="20s" interval="10" />
|
||||
<action name="meta-data" timeout="5" />
|
||||
<action name="validate-all" timeout="30" />
|
||||
</actions>
|
||||
@@ -327,11 +327,12 @@
|
||||
nfs_exec()
|
||||
{
|
||||
local cmd=$1
|
||||
+ local svc=$2
|
||||
set_exec_mode
|
||||
|
||||
case $EXEC_MODE in
|
||||
1) ${OCF_RESKEY_nfs_init_script} $cmd;;
|
||||
- 2) systemctl $cmd nfs-server.service ;;
|
||||
+ 2) systemctl $cmd ${svc}.service ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -353,21 +354,117 @@
|
||||
|
||||
nfsserver_monitor ()
|
||||
{
|
||||
+ # Skip trying to start processes once before failing
|
||||
+ # when run from nfsserver_start ()
|
||||
+ if [ "$1" == "fromstart" ]; then
|
||||
+ ocf_log info "fromstart"
|
||||
+ fromstart=1
|
||||
+ else
|
||||
+ tries=1
|
||||
+ fi
|
||||
+
|
||||
+ # systemd
|
||||
+ if [ "$EXEC_MODE" -eq "2" ]; then
|
||||
+ ocf_log info "Status: rpcbind"
|
||||
+ rpcinfo &> /dev/null
|
||||
+ rc=$?
|
||||
+ if [ "$rc" -ne "0" ]; then
|
||||
+ if [ ! "$fromstart" ] && [ "$tries" -gt "0" ]; then
|
||||
+ nfsserver_start frommonitor
|
||||
+ rc=$?
|
||||
+ let tries=$tries-1
|
||||
+ fi
|
||||
+ if [ "$rc" -ne "0" ]; then
|
||||
+ ocf_exit_reason "rpcbind is not running"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ ocf_log info "Status: nfs-mountd"
|
||||
+ rpcinfo -t localhost 100005 &> /dev/null
|
||||
+ rc=$?
|
||||
+ if [ "$rc" -ne "0" ]; then
|
||||
+ if [ ! "$fromstart" ] && [ "$tries" -gt "0" ]; then
|
||||
+ nfsserver_start frommonitor
|
||||
+ rc=$?
|
||||
+ let tries=$tries-1
|
||||
+ fi
|
||||
+ if [ "$rc" -ne "0" ]; then
|
||||
+ ocf_exit_reason "nfs-mountd is not running"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ ocf_log info "Status: nfs-idmapd"
|
||||
+ fn=`mktemp`
|
||||
+ nfs_exec status nfs-idmapd > $fn 2>&1
|
||||
+ rc=$?
|
||||
+ ocf_log debug "$(cat $fn)"
|
||||
+ rm -f $fn
|
||||
+ if [ "$rc" -ne "0" ]; then
|
||||
+ if [ ! "$fromstart" ] && [ "$tries" -gt "0" ]; then
|
||||
+ nfsserver_start frommonitor
|
||||
+ rc=$?
|
||||
+ ocf_log info "Tried to start services: rc: $rc"
|
||||
+ let tries=$tries-1
|
||||
+ fi
|
||||
+ if [ "$rc" -ne "0" ]; then
|
||||
+ ocf_exit_reason "nfs-idmapd is not running"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ ocf_log info "Status: rpc-statd"
|
||||
+ rpcinfo -t localhost 100024 &> /dev/null
|
||||
+ rc=$?
|
||||
+ if [ "$rc" -ne "0" ]; then
|
||||
+ if [ ! "$fromstart" ] && [ "$tries" -gt "0" ]; then
|
||||
+ nfsserver_start frommonitor
|
||||
+ rc=$?
|
||||
+ let tries=$tries-1
|
||||
+ fi
|
||||
+ if [ "$rc" -ne "0" ]; then
|
||||
+ ocf_exit_reason "rpc-statd is not running"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
fn=`mktemp`
|
||||
- nfs_exec status > $fn 2>&1
|
||||
+ nfs_exec status nfs-server > $fn 2>&1
|
||||
rc=$?
|
||||
ocf_log debug "$(cat $fn)"
|
||||
rm -f $fn
|
||||
|
||||
- #Adapte LSB status code to OCF return code
|
||||
+ tfn="/proc/fs/nfsd/threads"
|
||||
+ if [ ! -f "$tfn" ] || [ "$(cat $tfn)" -le "0" ]; then
|
||||
+ if [ ! "$fromstart" ] && [ "$tries" -gt "0" ]; then
|
||||
+ nfsserver_start frommonitor
|
||||
+ rc=$?
|
||||
+ let tries=$tries-1
|
||||
+ fi
|
||||
+ if [ "$rc" -ne "0" ]; then
|
||||
+ ocf_exit_reason "NFS server not running: /proc/fs/nfsd/threads"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ #Adapt LSB status code to OCF return code
|
||||
if [ $rc -eq 0 ]; then
|
||||
# don't report success if nfs servers are up
|
||||
# without locking daemons.
|
||||
v3locking_exec "status"
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
- ocf_exit_reason "NFS server is up, but the locking daemons are down"
|
||||
- rc=$OCF_ERR_GENERIC
|
||||
+ if [ ! "$fromstart" ] && [ $tries -gt "0" ]; then
|
||||
+ nfsserver_start frommonitor
|
||||
+ rc=$?
|
||||
+ let tries=$tries-1
|
||||
+ fi
|
||||
+ if [ "$rc" -ne "0" ]; then
|
||||
+ ocf_exit_reason "NFS server is up, but the locking daemons are down"
|
||||
+ rc=$OCF_ERR_GENERIC
|
||||
+ fi
|
||||
fi
|
||||
return $rc
|
||||
elif [ $rc -eq 3 ]; then
|
||||
@@ -391,12 +488,7 @@
|
||||
# only write to the tmp /etc/sysconfig/nfs if sysconfig exists.
|
||||
# otherwise this distro does not support setting these options.
|
||||
if [ -d "/etc/sysconfig" ]; then
|
||||
- # replace if the value exists, append otherwise
|
||||
- if grep "^\s*${key}=" $file ; then
|
||||
- sed -i "s/\s*${key}=.*$/${key}=\"${value}\"/" $file
|
||||
- else
|
||||
- echo "${key}=\"${value}\"" >> $file
|
||||
- fi
|
||||
+ echo "${key}=\"${value}\"" >> $file
|
||||
elif [ "$requires_sysconfig" = "true" ]; then
|
||||
ocf_log warn "/etc/sysconfig/nfs not found, unable to set port and nfsd args."
|
||||
fi
|
||||
@@ -409,11 +501,6 @@
|
||||
local tmpconfig=$(mktemp ${HA_RSCTMP}/nfsserver-tmp-XXXXX)
|
||||
local statd_args
|
||||
|
||||
- if [ -f "$NFS_SYSCONFIG" ]; then
|
||||
- ## Take the $NFS_SYSCONFIG file as our skeleton
|
||||
- cp $NFS_SYSCONFIG $tmpconfig
|
||||
- fi
|
||||
-
|
||||
# nfsd args
|
||||
set_arg "RPCNFSDARGS" "$OCF_RESKEY_nfsd_args" "$tmpconfig" "true"
|
||||
|
||||
@@ -444,20 +531,14 @@
|
||||
|
||||
# override local nfs config. preserve previous local config though.
|
||||
if [ -s $tmpconfig ]; then
|
||||
- cat $NFS_SYSCONFIG | grep -q -e "$NFS_SYSCONFIG_AUTOGEN_TAG" > /dev/null 2>&1
|
||||
+ cat $NFS_SYSCONFIG | grep -e "$NFS_SYSCONFIG_AUTOGEN_TAG"
|
||||
if [ $? -ne 0 ]; then
|
||||
# backup local nfs config if it doesn't have our HA autogen tag in it.
|
||||
mv -f $NFS_SYSCONFIG $NFS_SYSCONFIG_LOCAL_BACKUP
|
||||
fi
|
||||
-
|
||||
- cat $tmpconfig | grep -q -e "$NFS_SYSCONFIG_AUTOGEN_TAG" > /dev/null 2>&1
|
||||
- if [ $? -ne 0 ]; then
|
||||
- echo "# $NFS_SYSCONFIG_AUTOGEN_TAG" > $NFS_SYSCONFIG
|
||||
- echo "# local config backup stored here, '$NFS_SYSCONFIG_LOCAL_BACKUP'" >> $NFS_SYSCONFIG
|
||||
- cat $tmpconfig >> $NFS_SYSCONFIG
|
||||
- else
|
||||
- cat $tmpconfig > $NFS_SYSCONFIG
|
||||
- fi
|
||||
+ echo "# $NFS_SYSCONFIG_AUTOGEN_TAG" > $NFS_SYSCONFIG
|
||||
+ echo "# local config backup stored here, '$NFS_SYSCONFIG_LOCAL_BACKUP'" >> $NFS_SYSCONFIG
|
||||
+ cat $tmpconfig >> $NFS_SYSCONFIG
|
||||
fi
|
||||
rm -f $tmpconfig
|
||||
}
|
||||
@@ -476,14 +557,13 @@
|
||||
[ -d "$fp/$STATD_DIR/sm" ] || mkdir -p "$fp/$STATD_DIR/sm"
|
||||
[ -d "$fp/$STATD_DIR/sm.ha" ] || mkdir -p "$fp/$STATD_DIR/sm.ha"
|
||||
[ -d "$fp/$STATD_DIR/sm.bak" ] || mkdir -p "$fp/$STATD_DIR/sm.bak"
|
||||
- [ -n "`id -u rpcuser 2>/dev/null`" -a "`id -g rpcuser 2>/dev/null`" ] &&
|
||||
- chown -R rpcuser.rpcuser "$fp/$STATD_DIR"
|
||||
+ [ -n "`id -u rpcuser`" -a "`id -g rpcuser`" ] && chown -R rpcuser.rpcuser "$fp/$STATD_DIR"
|
||||
|
||||
[ -f "$fp/etab" ] || touch "$fp/etab"
|
||||
[ -f "$fp/xtab" ] || touch "$fp/xtab"
|
||||
[ -f "$fp/rmtab" ] || touch "$fp/rmtab"
|
||||
|
||||
- dd if=/dev/urandom of=$fp/$STATD_DIR/state bs=1 count=4 >/dev/null 2>&1
|
||||
+ dd if=/dev/urandom of=$fp/$STATD_DIR/state bs=1 count=4 &> /dev/null
|
||||
[ -n "`id -u rpcuser`" -a "`id -g rpcuser`" ] && chown rpcuser.rpcuser "$fp/$STATD_DIR/state"
|
||||
[ $SELINUX_ENABLED -eq 0 ] && chcon -R "$SELINUX_LABEL" "$fp"
|
||||
}
|
||||
@@ -563,15 +643,15 @@
|
||||
|
||||
terminate()
|
||||
{
|
||||
- local pids
|
||||
- local i=0
|
||||
+ declare pids
|
||||
+ declare i=0
|
||||
|
||||
while : ; do
|
||||
pids=$(binary_status $1)
|
||||
[ -z "$pids" ] && return 0
|
||||
kill $pids
|
||||
sleep 1
|
||||
- i=$((i + 1))
|
||||
+ ((i++))
|
||||
[ $i -gt 3 ] && return 1
|
||||
done
|
||||
}
|
||||
@@ -579,22 +659,22 @@
|
||||
|
||||
killkill()
|
||||
{
|
||||
- local pids
|
||||
- local i=0
|
||||
+ declare pids
|
||||
+ declare i=0
|
||||
|
||||
while : ; do
|
||||
pids=$(binary_status $1)
|
||||
[ -z "$pids" ] && return 0
|
||||
kill -9 $pids
|
||||
sleep 1
|
||||
- i=$((i + 1))
|
||||
+ ((i++))
|
||||
[ $i -gt 3 ] && return 1
|
||||
done
|
||||
}
|
||||
|
||||
stop_process()
|
||||
{
|
||||
- local process=$1
|
||||
+ declare process=$1
|
||||
|
||||
ocf_log info "Stopping $process"
|
||||
if terminate $process; then
|
||||
@@ -665,9 +745,14 @@
|
||||
|
||||
nfsserver_start ()
|
||||
{
|
||||
+ # Skip monitor check when run from nfsserver_monitor ()
|
||||
+ if [ "$1" == "frommonitor" ]; then
|
||||
+ frommonitor=1
|
||||
+ fi
|
||||
+
|
||||
local rc;
|
||||
|
||||
- if nfsserver_monitor; then
|
||||
+ if [ ! "$frommonitor" ] && nfsserver_monitor fromstart; then
|
||||
ocf_log debug "NFS server is already started"
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
@@ -693,11 +778,32 @@
|
||||
modprobe nfsd
|
||||
fi
|
||||
|
||||
+ # systemd
|
||||
+ if [ "$EXEC_MODE" -eq "2" ]; then
|
||||
+ nfs_exec start rpcbind
|
||||
+ local i=10
|
||||
+ while [ "$i" -gt 0 ]; do
|
||||
+ ocf_log info "Start: rpcbind i: $i"
|
||||
+ rpcinfo &> /dev/null
|
||||
+ rc=$?
|
||||
+ if [ "$rc" -eq "0" ]; then
|
||||
+ break;
|
||||
+ fi
|
||||
+ sleep 1
|
||||
+ let i=$i-1
|
||||
+ done
|
||||
+ if [ "$i" -eq 0 ]; then
|
||||
+ ocf_exit_reason "Failed to start rpcbind"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
# check to see if we need to start rpc.statd
|
||||
v3locking_exec "status"
|
||||
if [ $? -ne $OCF_SUCCESS ]; then
|
||||
v3locking_exec "start"
|
||||
rc=$?
|
||||
+ ocf_log info "Start: v3locking: $rc"
|
||||
if [ $rc -ne 0 ]; then
|
||||
ocf_exit_reason "Failed to start NFS server locking daemons"
|
||||
return $rc
|
||||
@@ -706,8 +812,65 @@
|
||||
ocf_log info "rpc.statd already up"
|
||||
fi
|
||||
|
||||
+ # systemd
|
||||
+ if [ "$EXEC_MODE" -eq "2" ]; then
|
||||
+ nfs_exec start nfs-mountd
|
||||
+ local i=10
|
||||
+ while [ "$i" -gt 0 ]; do
|
||||
+ ocf_log info "Start: nfs-mountd i: $i"
|
||||
+ rpcinfo -t localhost 100005 &> /dev/null
|
||||
+ rc=$?
|
||||
+ if [ "$rc" -eq "0" ]; then
|
||||
+ break;
|
||||
+ fi
|
||||
+ sleep 1
|
||||
+ let i=$i-1
|
||||
+ done
|
||||
+ if [ "$i" -eq 0 ]; then
|
||||
+ ocf_exit_reason "Failed to start nfs-mountd"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ nfs_exec start nfs-idmapd
|
||||
+ local i=10
|
||||
+ while [ "$i" -gt 0 ]; do
|
||||
+ ocf_log info "Start: nfs-idmapd i: $i"
|
||||
+ fn=`mktemp`
|
||||
+ nfs_exec status nfs-idmapd > $fn 2>&1
|
||||
+ rc=$?
|
||||
+ ocf_log debug "$(cat $fn)"
|
||||
+ rm -f $fn
|
||||
+ if [ "$rc" -eq "0" ]; then
|
||||
+ break;
|
||||
+ fi
|
||||
+ sleep 1
|
||||
+ let i=$i-1
|
||||
+ done
|
||||
+ if [ "$i" -eq 0 ]; then
|
||||
+ ocf_exit_reason "Failed to start nfs-idmapd"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ nfs_exec start rpc-statd
|
||||
+ local i=10
|
||||
+ while [ "$i" -gt 0 ]; do
|
||||
+ ocf_log info "Start: rpc-statd i: $i"
|
||||
+ rpcinfo -t localhost 100024 &> /dev/null
|
||||
+ rc=$?
|
||||
+ if [ "$rc" -eq "0" ]; then
|
||||
+ break;
|
||||
+ fi
|
||||
+ sleep 1
|
||||
+ let i=$i-1
|
||||
+ done
|
||||
+ if [ "$i" -eq 0 ]; then
|
||||
+ ocf_exit_reason "Failed to start rpc-statd"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
fn=`mktemp`
|
||||
- nfs_exec start > $fn 2>&1
|
||||
+ nfs_exec start nfs-server > $fn 2>&1
|
||||
rc=$?
|
||||
ocf_log debug "$(cat $fn)"
|
||||
rm -f $fn
|
||||
@@ -717,6 +880,12 @@
|
||||
return $rc
|
||||
fi
|
||||
|
||||
+ tfn="/proc/fs/nfsd/threads"
|
||||
+ if [ ! -f "$tfn" ] || [ "$(cat $tfn)" -le "0" ]; then
|
||||
+ ocf_exit_reason "Failed to start NFS server: /proc/fs/nfsd/threads"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
notify_locks
|
||||
|
||||
ocf_log info "NFS server started"
|
||||
@@ -733,24 +902,71 @@
|
||||
cp -rpf $STATD_PATH/sm $STATD_PATH/sm.bak /var/lib/nfs/state $STATD_PATH/sm.ha > /dev/null 2>&1
|
||||
|
||||
fn=`mktemp`
|
||||
- nfs_exec stop > $fn 2>&1
|
||||
+ nfs_exec stop nfs-server > $fn 2>&1
|
||||
rc=$?
|
||||
ocf_log debug "$(cat $fn)"
|
||||
rm -f $fn
|
||||
|
||||
+ if [ $rc -ne 0 ]; then
|
||||
+ ocf_exit_reason "Failed to stop NFS server"
|
||||
+ return $rc
|
||||
+ fi
|
||||
+
|
||||
+ # systemd
|
||||
+ if [ "$EXEC_MODE" -eq "2" ]; then
|
||||
+ ocf_log info "Stop: threads"
|
||||
+ tfn="/proc/fs/nfsd/threads"
|
||||
+ if [ -f "$tfn" ] && [ "$(cat $tfn)" -gt "0" ]; then
|
||||
+ ocf_exit_reason "NFS server failed to stop: /proc/fs/nfsd/threads"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ nfs_exec stop rpc-statd &> /dev/null
|
||||
+ ocf_log info "Stop: rpc-statd"
|
||||
+ rpcinfo -t localhost 100024 &> /dev/null
|
||||
+ rc=$?
|
||||
+ if [ "$rc" -eq "0" ]; then
|
||||
+ ocf_exit_reason "Failed to stop rpc-statd"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ nfs_exec stop nfs-idmapd &> /dev/null
|
||||
+ ocf_log info "Stop: nfs-idmapd"
|
||||
+ fn=`mktemp`
|
||||
+ nfs_exec status nfs-idmapd > $fn 2>&1
|
||||
+ rc=$?
|
||||
+ ocf_log debug "$(cat $fn)"
|
||||
+ rm -f $fn
|
||||
+ if [ "$rc" -eq "0" ]; then
|
||||
+ ocf_exit_reason "Failed to stop nfs-idmapd"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ nfs_exec stop nfs-mountd &> /dev/null
|
||||
+ ocf_log info "Stop: nfs-mountd"
|
||||
+ rpcinfo -t localhost 100005 &> /dev/null
|
||||
+ rc=$?
|
||||
+ if [ "$rc" -eq "0" ]; then
|
||||
+ ocf_exit_reason "Failed to stop nfs-mountd"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
v3locking_exec "stop"
|
||||
if [ $? -ne 0 ]; then
|
||||
ocf_exit_reason "Failed to stop NFS locking daemons"
|
||||
rc=$OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
- if [ $rc -eq 0 ]; then
|
||||
- unbind_tree
|
||||
- ocf_log info "NFS server stopped"
|
||||
- else
|
||||
- ocf_exit_reason "Failed to stop NFS server"
|
||||
+ # systemd
|
||||
+ if [ "$EXEC_MODE" -eq "2" ]; then
|
||||
+ nfs_exec stop rpcbind &> /dev/null
|
||||
+ ocf_log info "Stop: rpcbind"
|
||||
fi
|
||||
- return $rc
|
||||
+
|
||||
+ unbind_tree
|
||||
+ ocf_log info "NFS server stopped"
|
||||
+ return 0
|
||||
}
|
||||
|
||||
nfsserver_validate ()
|
||||
|
|
@ -0,0 +1,337 @@
|
|||
diff -uNr a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
--- a/heartbeat/nfsserver 2016-07-21 12:40:55.417326145 +0200
|
||||
+++ b/heartbeat/nfsserver 2016-07-21 12:04:49.000000000 +0200
|
||||
@@ -352,45 +352,22 @@
|
||||
|
||||
nfsserver_monitor ()
|
||||
{
|
||||
- # Skip trying to start processes once before failing
|
||||
- # when run from nfsserver_start ()
|
||||
- if [ "$1" == "fromstart" ]; then
|
||||
- ocf_log info "fromstart"
|
||||
- fromstart=1
|
||||
- else
|
||||
- tries=1
|
||||
- fi
|
||||
-
|
||||
# systemd
|
||||
if [ "$EXEC_MODE" -eq "2" ]; then
|
||||
ocf_log info "Status: rpcbind"
|
||||
- rpcinfo &> /dev/null
|
||||
+ rpcinfo > /dev/null 2>&1
|
||||
rc=$?
|
||||
if [ "$rc" -ne "0" ]; then
|
||||
- if [ ! "$fromstart" ] && [ "$tries" -gt "0" ]; then
|
||||
- nfsserver_start frommonitor
|
||||
- rc=$?
|
||||
- let tries=$tries-1
|
||||
- fi
|
||||
- if [ "$rc" -ne "0" ]; then
|
||||
- ocf_exit_reason "rpcbind is not running"
|
||||
- return $OCF_NOT_RUNNING
|
||||
- fi
|
||||
+ ocf_exit_reason "rpcbind is not running"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
fi
|
||||
|
||||
ocf_log info "Status: nfs-mountd"
|
||||
- rpcinfo -t localhost 100005 &> /dev/null
|
||||
+ rpcinfo -t localhost 100005 > /dev/null 2>&1
|
||||
rc=$?
|
||||
if [ "$rc" -ne "0" ]; then
|
||||
- if [ ! "$fromstart" ] && [ "$tries" -gt "0" ]; then
|
||||
- nfsserver_start frommonitor
|
||||
- rc=$?
|
||||
- let tries=$tries-1
|
||||
- fi
|
||||
- if [ "$rc" -ne "0" ]; then
|
||||
- ocf_exit_reason "nfs-mountd is not running"
|
||||
- return $OCF_NOT_RUNNING
|
||||
- fi
|
||||
+ ocf_exit_reason "nfs-mountd is not running"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
fi
|
||||
|
||||
ocf_log info "Status: nfs-idmapd"
|
||||
@@ -400,31 +377,16 @@
|
||||
ocf_log debug "$(cat $fn)"
|
||||
rm -f $fn
|
||||
if [ "$rc" -ne "0" ]; then
|
||||
- if [ ! "$fromstart" ] && [ "$tries" -gt "0" ]; then
|
||||
- nfsserver_start frommonitor
|
||||
- rc=$?
|
||||
- ocf_log info "Tried to start services: rc: $rc"
|
||||
- let tries=$tries-1
|
||||
- fi
|
||||
- if [ "$rc" -ne "0" ]; then
|
||||
- ocf_exit_reason "nfs-idmapd is not running"
|
||||
- return $OCF_NOT_RUNNING
|
||||
- fi
|
||||
+ ocf_exit_reason "nfs-idmapd is not running"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
fi
|
||||
|
||||
ocf_log info "Status: rpc-statd"
|
||||
- rpcinfo -t localhost 100024 &> /dev/null
|
||||
+ rpcinfo -t localhost 100024 > /dev/null 2>&1
|
||||
rc=$?
|
||||
if [ "$rc" -ne "0" ]; then
|
||||
- if [ ! "$fromstart" ] && [ "$tries" -gt "0" ]; then
|
||||
- nfsserver_start frommonitor
|
||||
- rc=$?
|
||||
- let tries=$tries-1
|
||||
- fi
|
||||
- if [ "$rc" -ne "0" ]; then
|
||||
- ocf_exit_reason "rpc-statd is not running"
|
||||
- return $OCF_NOT_RUNNING
|
||||
- fi
|
||||
+ ocf_exit_reason "rpc-statd is not running"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -436,15 +398,8 @@
|
||||
|
||||
tfn="/proc/fs/nfsd/threads"
|
||||
if [ ! -f "$tfn" ] || [ "$(cat $tfn)" -le "0" ]; then
|
||||
- if [ ! "$fromstart" ] && [ "$tries" -gt "0" ]; then
|
||||
- nfsserver_start frommonitor
|
||||
- rc=$?
|
||||
- let tries=$tries-1
|
||||
- fi
|
||||
- if [ "$rc" -ne "0" ]; then
|
||||
- ocf_exit_reason "NFS server not running: /proc/fs/nfsd/threads"
|
||||
- return $OCF_NOT_RUNNING
|
||||
- fi
|
||||
+ ocf_exit_reason "NFS server not running: /proc/fs/nfsd/threads"
|
||||
+ return $OCF_NOT_RUNNING
|
||||
fi
|
||||
|
||||
#Adapt LSB status code to OCF return code
|
||||
@@ -454,15 +409,8 @@
|
||||
v3locking_exec "status"
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
- if [ ! "$fromstart" ] && [ $tries -gt "0" ]; then
|
||||
- nfsserver_start frommonitor
|
||||
- rc=$?
|
||||
- let tries=$tries-1
|
||||
- fi
|
||||
- if [ "$rc" -ne "0" ]; then
|
||||
- ocf_exit_reason "NFS server is up, but the locking daemons are down"
|
||||
- rc=$OCF_ERR_GENERIC
|
||||
- fi
|
||||
+ ocf_exit_reason "NFS server is up, but the locking daemons are down"
|
||||
+ rc=$OCF_ERR_GENERIC
|
||||
fi
|
||||
return $rc
|
||||
elif [ $rc -eq 3 ]; then
|
||||
@@ -561,7 +509,7 @@
|
||||
[ -f "$fp/xtab" ] || touch "$fp/xtab"
|
||||
[ -f "$fp/rmtab" ] || touch "$fp/rmtab"
|
||||
|
||||
- dd if=/dev/urandom of=$fp/$STATD_DIR/state bs=1 count=4 &> /dev/null
|
||||
+ dd if=/dev/urandom of=$fp/$STATD_DIR/state bs=1 count=4 > /dev/null 2>&1
|
||||
[ -n "`id -u rpcuser`" -a "`id -g rpcuser`" ] && chown rpcuser.rpcuser "$fp/$STATD_DIR/state"
|
||||
[ $SELINUX_ENABLED -eq 0 ] && chcon -R "$SELINUX_LABEL" "$fp"
|
||||
}
|
||||
@@ -656,15 +604,15 @@
|
||||
|
||||
terminate()
|
||||
{
|
||||
- declare pids
|
||||
- declare i=0
|
||||
+ local pids
|
||||
+ local i=0
|
||||
|
||||
while : ; do
|
||||
pids=$(binary_status $1)
|
||||
[ -z "$pids" ] && return 0
|
||||
kill $pids
|
||||
sleep 1
|
||||
- ((i++))
|
||||
+ i=$((i + 1))
|
||||
[ $i -gt 3 ] && return 1
|
||||
done
|
||||
}
|
||||
@@ -672,22 +620,22 @@
|
||||
|
||||
killkill()
|
||||
{
|
||||
- declare pids
|
||||
- declare i=0
|
||||
+ local pids
|
||||
+ local i=0
|
||||
|
||||
while : ; do
|
||||
pids=$(binary_status $1)
|
||||
[ -z "$pids" ] && return 0
|
||||
kill -9 $pids
|
||||
sleep 1
|
||||
- ((i++))
|
||||
+ i=$((i + 1))
|
||||
[ $i -gt 3 ] && return 1
|
||||
done
|
||||
}
|
||||
|
||||
stop_process()
|
||||
{
|
||||
- declare process=$1
|
||||
+ local process=$1
|
||||
|
||||
ocf_log info "Stopping $process"
|
||||
if terminate $process; then
|
||||
@@ -758,14 +706,9 @@
|
||||
|
||||
nfsserver_start ()
|
||||
{
|
||||
- # Skip monitor check when run from nfsserver_monitor ()
|
||||
- if [ "$1" == "frommonitor" ]; then
|
||||
- frommonitor=1
|
||||
- fi
|
||||
-
|
||||
local rc;
|
||||
|
||||
- if [ ! "$frommonitor" ] && nfsserver_monitor fromstart; then
|
||||
+ if nfsserver_monitor; then
|
||||
ocf_log debug "NFS server is already started"
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
@@ -796,21 +739,17 @@
|
||||
# systemd
|
||||
if [ "$EXEC_MODE" -eq "2" ]; then
|
||||
nfs_exec start rpcbind
|
||||
- local i=10
|
||||
- while [ "$i" -gt 0 ]; do
|
||||
+ local i=1
|
||||
+ while : ; do
|
||||
ocf_log info "Start: rpcbind i: $i"
|
||||
- rpcinfo &> /dev/null
|
||||
+ rpcinfo > /dev/null 2>&1
|
||||
rc=$?
|
||||
if [ "$rc" -eq "0" ]; then
|
||||
break;
|
||||
fi
|
||||
sleep 1
|
||||
- let i=$i-1
|
||||
+ i=$((i + 1))
|
||||
done
|
||||
- if [ "$i" -eq 0 ]; then
|
||||
- ocf_exit_reason "Failed to start rpcbind"
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
fi
|
||||
|
||||
# check to see if we need to start rpc.statd
|
||||
@@ -830,25 +769,21 @@
|
||||
# systemd
|
||||
if [ "$EXEC_MODE" -eq "2" ]; then
|
||||
nfs_exec start nfs-mountd
|
||||
- local i=10
|
||||
- while [ "$i" -gt 0 ]; do
|
||||
+ local i=1
|
||||
+ while : ; do
|
||||
ocf_log info "Start: nfs-mountd i: $i"
|
||||
- rpcinfo -t localhost 100005 &> /dev/null
|
||||
+ rpcinfo -t localhost 100005 > /dev/null 2>&1
|
||||
rc=$?
|
||||
if [ "$rc" -eq "0" ]; then
|
||||
break;
|
||||
fi
|
||||
sleep 1
|
||||
- let i=$i-1
|
||||
+ i=$((i + 1))
|
||||
done
|
||||
- if [ "$i" -eq 0 ]; then
|
||||
- ocf_exit_reason "Failed to start nfs-mountd"
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
|
||||
nfs_exec start nfs-idmapd
|
||||
- local i=10
|
||||
- while [ "$i" -gt 0 ]; do
|
||||
+ local i=1
|
||||
+ while : ; do
|
||||
ocf_log info "Start: nfs-idmapd i: $i"
|
||||
fn=`mktemp`
|
||||
nfs_exec status nfs-idmapd > $fn 2>&1
|
||||
@@ -859,29 +794,21 @@
|
||||
break;
|
||||
fi
|
||||
sleep 1
|
||||
- let i=$i-1
|
||||
+ i=$((i + 1))
|
||||
done
|
||||
- if [ "$i" -eq 0 ]; then
|
||||
- ocf_exit_reason "Failed to start nfs-idmapd"
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
|
||||
nfs_exec start rpc-statd
|
||||
- local i=10
|
||||
- while [ "$i" -gt 0 ]; do
|
||||
+ local i=1
|
||||
+ while : ; do
|
||||
ocf_log info "Start: rpc-statd i: $i"
|
||||
- rpcinfo -t localhost 100024 &> /dev/null
|
||||
+ rpcinfo -t localhost 100024 > /dev/null 2>&1
|
||||
rc=$?
|
||||
if [ "$rc" -eq "0" ]; then
|
||||
break;
|
||||
fi
|
||||
sleep 1
|
||||
- let i=$i-1
|
||||
+ i=$((i + 1))
|
||||
done
|
||||
- if [ "$i" -eq 0 ]; then
|
||||
- ocf_exit_reason "Failed to start rpc-statd"
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
fi
|
||||
|
||||
fn=`mktemp`
|
||||
@@ -936,16 +863,16 @@
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
- nfs_exec stop rpc-statd &> /dev/null
|
||||
+ nfs_exec stop rpc-statd > /dev/null 2>&1
|
||||
ocf_log info "Stop: rpc-statd"
|
||||
- rpcinfo -t localhost 100024 &> /dev/null
|
||||
+ rpcinfo -t localhost 100024 > /dev/null 2>&1
|
||||
rc=$?
|
||||
if [ "$rc" -eq "0" ]; then
|
||||
ocf_exit_reason "Failed to stop rpc-statd"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
- nfs_exec stop nfs-idmapd &> /dev/null
|
||||
+ nfs_exec stop nfs-idmapd > /dev/null 2>&1
|
||||
ocf_log info "Stop: nfs-idmapd"
|
||||
fn=`mktemp`
|
||||
nfs_exec status nfs-idmapd > $fn 2>&1
|
||||
@@ -957,9 +884,9 @@
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
- nfs_exec stop nfs-mountd &> /dev/null
|
||||
+ nfs_exec stop nfs-mountd > /dev/null 2>&1
|
||||
ocf_log info "Stop: nfs-mountd"
|
||||
- rpcinfo -t localhost 100005 &> /dev/null
|
||||
+ rpcinfo -t localhost 100005 > /dev/null 2>&1
|
||||
rc=$?
|
||||
if [ "$rc" -eq "0" ]; then
|
||||
ocf_exit_reason "Failed to stop nfs-mountd"
|
||||
@@ -975,8 +902,11 @@
|
||||
|
||||
# systemd
|
||||
if [ "$EXEC_MODE" -eq "2" ]; then
|
||||
- nfs_exec stop rpcbind &> /dev/null
|
||||
+ nfs_exec stop rpcbind > /dev/null 2>&1
|
||||
ocf_log info "Stop: rpcbind"
|
||||
+
|
||||
+ nfs_exec stop rpc-gssd > /dev/null 2>&1
|
||||
+ ocf_log info "Stop: rpc-gssd"
|
||||
fi
|
||||
|
||||
unbind_tree
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
From 2364eff6a6837ae4418f1876f7f29459fdeec3bb Mon Sep 17 00:00:00 2001
|
||||
From: Lars Ellenberg <lars.ellenberg@linbit.com>
|
||||
Date: Mon, 22 Sep 2014 15:26:59 +0200
|
||||
Subject: [PATCH 4/6] Fix: ha_log: drop global __ha_log_ignore_stderr_once hack
|
||||
|
||||
Use a helper function instead,
|
||||
which understands --ignore-stderr as first parameter.
|
||||
---
|
||||
heartbeat/ocf-shellfuncs.in | 23 +++++++++--------------
|
||||
1 file changed, 9 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
|
||||
index c370fca..fd916e7 100644
|
||||
--- a/heartbeat/ocf-shellfuncs.in
|
||||
+++ b/heartbeat/ocf-shellfuncs.in
|
||||
@@ -43,14 +43,6 @@ unset LANGUAGE; export LANGUAGE
|
||||
|
||||
__SCRIPT_NAME=`basename $0`
|
||||
|
||||
-# This is internal to shellfuncs.
|
||||
-# When set, ha_log can be used in a way that guarantees
|
||||
-# that stderr will not be printed to. This allows us to
|
||||
-# use ocf_exit_reason to print a string to stderr and use
|
||||
-# ha_log to print the same string to the other log facilities
|
||||
-# without having duplicate messages sent to stderr.
|
||||
-__ha_log_ignore_stderr_once=""
|
||||
-
|
||||
if [ -z "$OCF_ROOT" ]; then
|
||||
: ${OCF_ROOT=@OCF_ROOT_DIR@}
|
||||
fi
|
||||
@@ -189,12 +181,11 @@ set_logtag() {
|
||||
fi
|
||||
}
|
||||
|
||||
-ha_log() {
|
||||
- local ignore_stderr="$__ha_log_ignore_stderr_once"
|
||||
+__ha_log() {
|
||||
+ local ignore_stderr=false
|
||||
local loglevel
|
||||
|
||||
- # always reset this variable
|
||||
- __ha_log_ignore_stderr_once=""
|
||||
+ [ "x$1" = "x--ignore-stderr" ] && ignore_stderr=true && shift
|
||||
|
||||
[ none = "$HA_LOGFACILITY" ] && HA_LOGFACILITY=""
|
||||
# if we're connected to a tty, then output to stderr
|
||||
@@ -257,6 +248,11 @@ ha_log() {
|
||||
fi
|
||||
}
|
||||
|
||||
+ha_log()
|
||||
+{
|
||||
+ __ha_log "$@"
|
||||
+}
|
||||
+
|
||||
ha_debug() {
|
||||
|
||||
if [ "x${HA_debug}" = "x0" ] ; then
|
||||
@@ -383,8 +379,7 @@ ocf_exit_reason()
|
||||
|
||||
msg=$(printf "${fmt}" "$@")
|
||||
printf >&2 "%s%s\n" "$cookie" "$msg"
|
||||
- __ha_log_ignore_stderr_once="true"
|
||||
- ha_log "ERROR: $msg"
|
||||
+ __ha_log --ignore-stderr "ERROR: $msg"
|
||||
}
|
||||
|
||||
#
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
From de3c26d6333a00210de8d112cdb90dc8c2e19367 Mon Sep 17 00:00:00 2001
|
||||
From: Lars Ellenberg <lars.ellenberg@linbit.com>
|
||||
Date: Mon, 22 Sep 2014 14:58:58 +0200
|
||||
Subject: [PATCH 3/6] Fix: ocf_exit_reason: implicit format string "%s" for
|
||||
single argument version
|
||||
|
||||
Also, don't use the $msg as format string, but via "%s%s" "$cookie" "$msg".
|
||||
Or, depending on presence of % sequences in $msg,
|
||||
you'd get different output on stderr and via ha_log.
|
||||
|
||||
Without the patch:
|
||||
|
||||
( OCF_ROOT=$PWD dash -c '. heartbeat/ocf-shellfuncs.in ; ocf_exit_reason "0.x% Bugs less"' )
|
||||
dash: 372: printf: % B: invalid directive
|
||||
ocf-exit-reason:0.x
|
||||
( OCF_ROOT=$PWD dash -c '. heartbeat/ocf-shellfuncs.in ; ocf_exit_reason "0.x% bugs less"' )
|
||||
ocf-exit-reason:0.xugs less
|
||||
|
||||
With this patch:
|
||||
|
||||
( OCF_ROOT=$PWD dash -c '. heartbeat/ocf-shellfuncs.in ; ocf_exit_reason "0.x% Bugs less"' )
|
||||
ocf-exit-reason:0.x% Bugs less
|
||||
( OCF_ROOT=$PWD dash -c '. heartbeat/ocf-shellfuncs.in ; ocf_exit_reason "0.x% bugs less"' )
|
||||
ocf-exit-reason:0.x% bugs less
|
||||
---
|
||||
heartbeat/ocf-shellfuncs.in | 27 +++++++++++++++++++--------
|
||||
1 file changed, 19 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
|
||||
index 9ba8e26..c370fca 100644
|
||||
--- a/heartbeat/ocf-shellfuncs.in
|
||||
+++ b/heartbeat/ocf-shellfuncs.in
|
||||
@@ -356,22 +356,33 @@ ocf_log() {
|
||||
ocf_exit_reason()
|
||||
{
|
||||
local cookie="$OCF_EXIT_REASON_PREFIX"
|
||||
- local fmt="$1"
|
||||
+ local fmt
|
||||
local msg
|
||||
|
||||
- if [ $# -lt 1 ]; then
|
||||
- ocf_log err "Not enough arguments [$#] to ocf_log_exit_msg."
|
||||
- fi
|
||||
+ # No argument is likely not intentional.
|
||||
+ # Just one argument implies a printf format string of just "%s".
|
||||
+ # "Least surprise" in case some interpolated string from variable
|
||||
+ # expansion or other contains a percent sign.
|
||||
+ # More than one argument: first argument is going to be the format string.
|
||||
+ case $# in
|
||||
+ 0) ocf_log err "Not enough arguments to ocf_log_exit_msg." ;;
|
||||
+ 1) fmt="%s" ;;
|
||||
+
|
||||
+ *) fmt=$1
|
||||
+ shift
|
||||
+ case $fmt in
|
||||
+ *%*) : ;; # ok, does look like a format string
|
||||
+ *) ocf_log warn "Does not look like format string: [$fmt]" ;;
|
||||
+ esac ;;
|
||||
+ esac
|
||||
+
|
||||
if [ -z "$cookie" ]; then
|
||||
# use a default prefix
|
||||
cookie="ocf-exit-reason:"
|
||||
fi
|
||||
|
||||
- shift
|
||||
-
|
||||
msg=$(printf "${fmt}" "$@")
|
||||
-
|
||||
- printf >&2 "%s${msg}\n" "$cookie"
|
||||
+ printf >&2 "%s%s\n" "$cookie" "$msg"
|
||||
__ha_log_ignore_stderr_once="true"
|
||||
ha_log "ERROR: $msg"
|
||||
}
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
From da05792dae917d67b529a27b0605166774bb21b9 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Sun, 21 Sep 2014 11:19:07 -0400
|
||||
Subject: [PATCH 2/6] Fix: shellfuncs: fix syntax error caused by exit_reason
|
||||
support for dash shell.
|
||||
|
||||
---
|
||||
heartbeat/ocf-shellfuncs.in | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
|
||||
index ff7c32d..9ba8e26 100644
|
||||
--- a/heartbeat/ocf-shellfuncs.in
|
||||
+++ b/heartbeat/ocf-shellfuncs.in
|
||||
@@ -356,7 +356,7 @@ ocf_log() {
|
||||
ocf_exit_reason()
|
||||
{
|
||||
local cookie="$OCF_EXIT_REASON_PREFIX"
|
||||
- local fmt=$1
|
||||
+ local fmt="$1"
|
||||
local msg
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
From a8adbaa0716f0fa39e41293fe81530686f64e2c8 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Fri, 1 Aug 2014 15:31:38 -0400
|
||||
Subject: [PATCH] High: IPaddr2: support ocf_exit_reason
|
||||
|
||||
---
|
||||
heartbeat/IPaddr2 | 40 +++++++++++++++++++++-------------------
|
||||
1 file changed, 21 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/IPaddr2 b/heartbeat/IPaddr2
|
||||
index b645288..2791ea0 100755
|
||||
--- a/heartbeat/IPaddr2
|
||||
+++ b/heartbeat/IPaddr2
|
||||
@@ -342,12 +342,12 @@ ip_init() {
|
||||
local rc
|
||||
|
||||
if [ X`uname -s` != "XLinux" ]; then
|
||||
- ocf_log err "IPaddr2 only supported Linux."
|
||||
+ ocf_exit_reason "IPaddr2 only supported Linux."
|
||||
exit $OCF_ERR_INSTALLED
|
||||
fi
|
||||
|
||||
if [ X"$OCF_RESKEY_ip" = "X" ]; then
|
||||
- ocf_log err "IP address (the ip parameter) is mandatory"
|
||||
+ ocf_exit_reason "IP address (the ip parameter) is mandatory"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
@@ -359,7 +359,7 @@ ip_init() {
|
||||
then
|
||||
: YAY!
|
||||
else
|
||||
- ocf_log err "You must be root for $__OCF_ACTION operation."
|
||||
+ ocf_exit_reason "You must be root for $__OCF_ACTION operation."
|
||||
exit $OCF_ERR_PERM
|
||||
fi
|
||||
|
||||
@@ -382,14 +382,14 @@ ip_init() {
|
||||
IP_INC_NO=`expr ${OCF_RESKEY_CRM_meta_clone:-0} + 1`
|
||||
|
||||
if ocf_is_true ${OCF_RESKEY_lvs_support} && [ $IP_INC_GLOBAL -gt 1 ]; then
|
||||
- ocf_log err "LVS and load sharing do not go together well"
|
||||
+ ocf_exit_reason "LVS and load sharing do not go together well"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
if ocf_is_decimal "$IP_INC_GLOBAL" && [ $IP_INC_GLOBAL -gt 0 ]; then
|
||||
:
|
||||
else
|
||||
- ocf_log err "Invalid OCF_RESKEY_incarnations_max_global [$IP_INC_GLOBAL], should be positive integer"
|
||||
+ ocf_exit_reason "Invalid meta-attribute clone_max [$IP_INC_GLOBAL], should be positive integer"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
@@ -397,20 +397,20 @@ ip_init() {
|
||||
if [ $? -ne 0 ];then
|
||||
FAMILY=inet
|
||||
if ocf_is_true $OCF_RESKEY_lvs_ipv6_addrlabel ;then
|
||||
- ocf_log err "IPv4 does not support lvs_ipv6_addrlabel"
|
||||
+ ocf_exit_reason "IPv4 does not support lvs_ipv6_addrlabel"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
else
|
||||
FAMILY=inet6
|
||||
if ocf_is_true $OCF_RESKEY_lvs_support ;then
|
||||
- ocf_log err "The IPv6 does not support lvs_support"
|
||||
+ ocf_exit_reason "The IPv6 does not support lvs_support"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
if ocf_is_true $OCF_RESKEY_lvs_ipv6_addrlabel ;then
|
||||
if ocf_is_decimal "$OCF_RESKEY_lvs_ipv6_addrlabel_value" && [ $OCF_RESKEY_lvs_ipv6_addrlabel_value -ge 0 ]; then
|
||||
:
|
||||
else
|
||||
- ocf_log err "Invalid lvs_ipv6_addrlabel_value [$OCF_RESKEY_lvs_ipv6_addrlabel_value], should be positive integer"
|
||||
+ ocf_exit_reason "Invalid lvs_ipv6_addrlabel_value [$OCF_RESKEY_lvs_ipv6_addrlabel_value], should be positive integer"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
fi
|
||||
@@ -446,7 +446,7 @@ ip_init() {
|
||||
ocf_log warn "[$FINDIF] failed"
|
||||
exit $OCF_SUCCESS
|
||||
else
|
||||
- ocf_log err "[$FINDIF] failed"
|
||||
+ ocf_exit_reason "[$FINDIF] failed"
|
||||
exit $rc
|
||||
fi
|
||||
fi
|
||||
@@ -769,7 +769,8 @@ END
|
||||
}
|
||||
|
||||
ip_start() {
|
||||
- if [ -z "$NIC" ]; then # no nic found or specified
|
||||
+ if [ -z "$NIC" ]; then
|
||||
+ ocf_exit_reason "No nic found or specified"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
@@ -799,7 +800,7 @@ ip_start() {
|
||||
--local-node $IP_INC_NO \
|
||||
--hashmode $IP_CIP_HASH
|
||||
if [ $? -ne 0 ]; then
|
||||
- ocf_log err "iptables failed"
|
||||
+ ocf_exit_reason "iptables failed"
|
||||
exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
fi
|
||||
@@ -822,7 +823,7 @@ ip_start() {
|
||||
add_interface $OCF_RESKEY_ip $NETMASK ${BRDCAST:-none} $NIC $IFLABEL
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
- ocf_log err "$CMD failed."
|
||||
+ ocf_exit_reason "$CMD failed."
|
||||
exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
fi
|
||||
@@ -897,6 +898,7 @@ ip_stop() {
|
||||
if [ "$ip_del_if" = "yes" ]; then
|
||||
delete_interface $OCF_RESKEY_ip $NIC $NETMASK
|
||||
if [ $? -ne 0 ]; then
|
||||
+ ocf_exit_reason "Unable to remove IP [${OCF_RESKEY_ip} from interface [ $NIC ]"
|
||||
exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
@@ -940,7 +942,7 @@ set_send_arp_program() {
|
||||
ARP_SEND_FUN=run_send_ib_arp
|
||||
;;
|
||||
*)
|
||||
- ocf_log err "unrecognized arp_sender value: $OCF_RESKEY_arp_sender"
|
||||
+ ocf_exit_reason "unrecognized arp_sender value: $OCF_RESKEY_arp_sender"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
;;
|
||||
esac
|
||||
@@ -975,21 +977,21 @@ ip_validate() {
|
||||
|
||||
if ocf_is_true "$OCF_RESKEY_unique_clone_address" &&
|
||||
! ocf_is_true "$OCF_RESKEY_CRM_meta_globally_unique"; then
|
||||
- ocf_log err "unique_clone_address makes sense only with meta globally_unique set"
|
||||
+ ocf_exit_reason "unique_clone_address makes sense only with meta globally_unique set"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
if ocf_is_decimal "$OCF_RESKEY_arp_interval" && [ $OCF_RESKEY_arp_interval -gt 0 ]; then
|
||||
:
|
||||
else
|
||||
- ocf_log err "Invalid OCF_RESKEY_arp_interval [$OCF_RESKEY_arp_interval]"
|
||||
+ ocf_exit_reason "Invalid OCF_RESKEY_arp_interval [$OCF_RESKEY_arp_interval]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
if ocf_is_decimal "$OCF_RESKEY_arp_count" && [ $OCF_RESKEY_arp_count -gt 0 ]; then
|
||||
:
|
||||
else
|
||||
- ocf_log err "Invalid OCF_RESKEY_arp_count [$OCF_RESKEY_arp_count]"
|
||||
+ ocf_exit_reason "Invalid OCF_RESKEY_arp_count [$OCF_RESKEY_arp_count]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
@@ -1001,13 +1003,13 @@ ip_validate() {
|
||||
sourceip|sourceip-sourceport|sourceip-sourceport-destport)
|
||||
;;
|
||||
*)
|
||||
- ocf_log err "Invalid OCF_RESKEY_clusterip_hash [$IP_CIP_HASH]"
|
||||
+ ocf_exit_reason "Invalid OCF_RESKEY_clusterip_hash [$IP_CIP_HASH]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
;;
|
||||
esac
|
||||
|
||||
if ocf_is_true ${OCF_RESKEY_lvs_support}; then
|
||||
- ecf_log err "LVS and load sharing not advised to try"
|
||||
+ ocf_exit_reason "LVS and load sharing not advised to try"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
@@ -1020,7 +1022,7 @@ ip_validate() {
|
||||
esac
|
||||
|
||||
if [ $valid -eq 0 ]; then
|
||||
- ocf_log err "Invalid IF_MAC [$IF_MAC]"
|
||||
+ ocf_exit_reason "Invalid IF_MAC [$IF_MAC]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
From 0501ed8086e054d9b076719c5bd131edbc95db5b Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Fri, 1 Aug 2014 16:06:22 -0400
|
||||
Subject: [PATCH] High: VirtualDomain: exit reason support
|
||||
|
||||
---
|
||||
heartbeat/VirtualDomain | 19 ++++++++++---------
|
||||
1 file changed, 10 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
index 3a6b6a9..c44c090 100755
|
||||
--- a/heartbeat/VirtualDomain
|
||||
+++ b/heartbeat/VirtualDomain
|
||||
@@ -356,7 +356,7 @@ VirtualDomain_Start() {
|
||||
rm -f $snapshotimage
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
- ocf_log error "Failed to restore ${DOMAIN_NAME} from state file in ${OCF_RESKEY_snapshot} directory."
|
||||
+ ocf_exit_reason "Failed to restore ${DOMAIN_NAME} from state file in ${OCF_RESKEY_snapshot} directory."
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
@@ -371,7 +371,7 @@ VirtualDomain_Start() {
|
||||
virsh $VIRSH_OPTIONS create ${OCF_RESKEY_config}
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
- ocf_log error "Failed to start virtual domain ${DOMAIN_NAME}."
|
||||
+ ocf_exit_reason "Failed to start virtual domain ${DOMAIN_NAME}."
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
@@ -395,6 +395,7 @@ force_stop()
|
||||
*"error:"*"domain is not running"*|*"error:"*"domain not found"*)
|
||||
: ;; # unexpected path to the intended outcome, all is well
|
||||
[!0]*)
|
||||
+ ocf_exit_reason "forced stop failed"
|
||||
return $OCF_ERR_GENERIC ;;
|
||||
0*)
|
||||
while [ $status != $OCF_NOT_RUNNING ]; do
|
||||
@@ -525,14 +526,14 @@ VirtualDomain_Migrate_To() {
|
||||
virsh ${VIRSH_OPTIONS} migrate --live $DOMAIN_NAME ${remoteuri} ${migrateuri}
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
- ocf_log err "$DOMAIN_NAME: live migration to ${remoteuri} ${migrateuri} failed: $rc"
|
||||
+ ocf_exit_reason "$DOMAIN_NAME: live migration to ${remoteuri} ${migrateuri} failed: $rc"
|
||||
return $OCF_ERR_GENERIC
|
||||
else
|
||||
ocf_log info "$DOMAIN_NAME: live migration to ${target_node} succeeded."
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
else
|
||||
- ocf_log err "$DOMAIN_NAME: migrate_to: Not active locally!"
|
||||
+ ocf_exit_reason "$DOMAIN_NAME: migrate_to: Not active locally!"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
}
|
||||
@@ -560,7 +561,7 @@ VirtualDomain_Monitor() {
|
||||
# A monitor script returned a non-success exit
|
||||
# code. Stop iterating over the list of scripts, log a
|
||||
# warning message, and propagate $OCF_ERR_GENERIC.
|
||||
- ocf_log warn "Monitor command \"${script}\" for domain ${DOMAIN_NAME} returned ${script_rc} with output: ${script_output}"
|
||||
+ ocf_exit_reason "Monitor command \"${script}\" for domain ${DOMAIN_NAME} returned ${script_rc} with output: ${script_output}"
|
||||
rc=$OCF_ERR_GENERIC
|
||||
break
|
||||
else
|
||||
@@ -582,13 +583,13 @@ VirtualDomain_Validate_All() {
|
||||
done
|
||||
|
||||
if [ -z $OCF_RESKEY_config ]; then
|
||||
- ocf_log error "Missing configuration parameter \"config\"."
|
||||
+ ocf_exit_reason "Missing configuration parameter \"config\"."
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
if ocf_is_true $OCF_RESKEY_force_stop; then
|
||||
if [ -n "$OCF_RESKEY_snapshot" ]; then
|
||||
- ocf_log error "The 'force_stop' and 'snapshot' options can not be used together."
|
||||
+ ocf_exit_reason "The 'force_stop' and 'snapshot' options can not be used together."
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
fi
|
||||
@@ -601,7 +602,7 @@ VirtualDomain_Validate_All() {
|
||||
elif [ "$__OCF_ACTION" = "stop" ]; then
|
||||
ocf_log info "Configuration file $OCF_RESKEY_config not readable, resource considered stopped."
|
||||
else
|
||||
- ocf_log error "Configuration file $OCF_RESKEY_config does not exist or is not readable."
|
||||
+ ocf_exit_reason "Configuration file $OCF_RESKEY_config does not exist or is not readable."
|
||||
return $OCF_ERR_INSTALLED
|
||||
fi
|
||||
fi
|
||||
@@ -644,7 +645,7 @@ fi
|
||||
# Retrieve the domain name from the xml file.
|
||||
DOMAIN_NAME=`egrep '[[:space:]]*<name>.*</name>[[:space:]]*$' ${OCF_RESKEY_config} | sed -e 's/[[:space:]]*<name>\(.*\)<\/name>[[:space:]]*$/\1/' 2>/dev/null`
|
||||
if [ -z $DOMAIN_NAME ]; then
|
||||
- ocf_log err "This is unexpected. Cannot determine domain name."
|
||||
+ ocf_exit_reason "Unable to determine domain name."
|
||||
exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
From 6029211e47a83cec4a6c4e44a967e967cb0b92fb Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Fri, 1 Aug 2014 13:13:05 -0400
|
||||
Subject: [PATCH] High: ocf-binaries: have 'check_binary' set exit reason
|
||||
|
||||
---
|
||||
heartbeat/ocf-binaries.in | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/ocf-binaries.in b/heartbeat/ocf-binaries.in
|
||||
index a78a348..cbf70db 100644
|
||||
--- a/heartbeat/ocf-binaries.in
|
||||
+++ b/heartbeat/ocf-binaries.in
|
||||
@@ -56,7 +56,7 @@ check_binary () {
|
||||
if ! have_binary "$1"; then
|
||||
if [ "$OCF_NOT_RUNNING" = 7 ]; then
|
||||
# Chances are we have a fully setup OCF environment
|
||||
- ocf_log err "Setup problem: couldn't find command: $1"
|
||||
+ ocf_exit_reason "Setup problem: couldn't find command: $1"
|
||||
else
|
||||
echo "Setup problem: couldn't find command: $1"
|
||||
fi
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,43 @@
|
|||
From e334f036ab02ec6cdf4cf463e26d4f32e592f15c Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Fri, 15 Aug 2014 11:03:36 -0500
|
||||
Subject: [PATCH] High: exportfs: support exit reason string
|
||||
|
||||
---
|
||||
heartbeat/exportfs | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/exportfs b/heartbeat/exportfs
|
||||
index 471da24..3f91037 100755
|
||||
--- a/heartbeat/exportfs
|
||||
+++ b/heartbeat/exportfs
|
||||
@@ -239,7 +239,7 @@ exportfs_monitor ()
|
||||
ocf_log info "Directory ${OCF_RESKEY_directory} is not exported to ${OCF_RESKEY_clientspec} (stopped)."
|
||||
return $OCF_NOT_RUNNING;;
|
||||
*)
|
||||
- ocf_log err "Unable to determine export status for ${OCF_RESKEY_directory}."
|
||||
+ ocf_exit_reason "Unable to determine export status for ${OCF_RESKEY_directory}."
|
||||
return $OCF_ERR_GENERIC;;
|
||||
esac
|
||||
}
|
||||
@@ -340,7 +340,7 @@ exportfs_stop ()
|
||||
ocf_log info "Un-exported file system"
|
||||
return $OCF_SUCCESS
|
||||
else
|
||||
- ocf_log err "Failed to un-export file system"
|
||||
+ ocf_exit_reason "Failed to un-export file system"
|
||||
exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
}
|
||||
@@ -348,7 +348,7 @@ exportfs_stop ()
|
||||
exportfs_validate_all ()
|
||||
{
|
||||
if [ ! -d $OCF_RESKEY_directory ]; then
|
||||
- ocf_log err "$OCF_RESKEY_directory does not exist or is not a directory"
|
||||
+ ocf_exit_reason "$OCF_RESKEY_directory does not exist or is not a directory"
|
||||
return $OCF_ERR_INSTALLED
|
||||
fi
|
||||
}
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
From 0dfe07cbd9e74e0f7f3c85a42085972bf24e1d24 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Fri, 15 Aug 2014 10:50:06 -0500
|
||||
Subject: [PATCH] Introducing exit reason string support
|
||||
|
||||
---
|
||||
heartbeat/ocf-shellfuncs.in | 48 ++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 47 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
|
||||
index 254da57..ff7c32d 100644
|
||||
--- a/heartbeat/ocf-shellfuncs.in
|
||||
+++ b/heartbeat/ocf-shellfuncs.in
|
||||
@@ -43,6 +43,14 @@ unset LANGUAGE; export LANGUAGE
|
||||
|
||||
__SCRIPT_NAME=`basename $0`
|
||||
|
||||
+# This is internal to shellfuncs.
|
||||
+# When set, ha_log can be used in a way that guarantees
|
||||
+# that stderr will not be printed to. This allows us to
|
||||
+# use ocf_exit_reason to print a string to stderr and use
|
||||
+# ha_log to print the same string to the other log facilities
|
||||
+# without having duplicate messages sent to stderr.
|
||||
+__ha_log_ignore_stderr_once=""
|
||||
+
|
||||
if [ -z "$OCF_ROOT" ]; then
|
||||
: ${OCF_ROOT=@OCF_ROOT_DIR@}
|
||||
fi
|
||||
@@ -182,12 +190,20 @@ set_logtag() {
|
||||
}
|
||||
|
||||
ha_log() {
|
||||
+ local ignore_stderr="$__ha_log_ignore_stderr_once"
|
||||
local loglevel
|
||||
+
|
||||
+ # always reset this variable
|
||||
+ __ha_log_ignore_stderr_once=""
|
||||
+
|
||||
[ none = "$HA_LOGFACILITY" ] && HA_LOGFACILITY=""
|
||||
# if we're connected to a tty, then output to stderr
|
||||
if tty >/dev/null; then
|
||||
if [ "x$HA_debug" = "x0" -a "x$loglevel" = xdebug ] ; then
|
||||
return 0
|
||||
+ elif [ "$ignore_stderr" = "true" ]; then
|
||||
+ # something already printed this error to stderr, so ignore
|
||||
+ return 0
|
||||
fi
|
||||
if [ "$HA_LOGTAG" ]; then
|
||||
echo "$HA_LOGTAG: $*"
|
||||
@@ -226,7 +242,7 @@ ha_log() {
|
||||
echo "$HA_LOGTAG: "`hadate`"${*}" >> $HA_LOGFILE
|
||||
fi
|
||||
if
|
||||
- [ -z "$HA_LOGFACILITY" -a -z "$HA_LOGFILE" ]
|
||||
+ [ -z "$HA_LOGFACILITY" -a -z "$HA_LOGFILE" ] && ! [ "$ignore_stderr" = "true" ]
|
||||
then
|
||||
: appending to stderr
|
||||
echo `hadate`"${*}" >&2
|
||||
@@ -331,6 +347,36 @@ ocf_log() {
|
||||
}
|
||||
|
||||
#
|
||||
+# ocf_exit_reason: print exit error string to stderr
|
||||
+# Usage: Allows the OCF script to provide a string
|
||||
+# describing why the exit code was returned.
|
||||
+# Arguments: reason - required, The string that represents why the error
|
||||
+# occured.
|
||||
+#
|
||||
+ocf_exit_reason()
|
||||
+{
|
||||
+ local cookie="$OCF_EXIT_REASON_PREFIX"
|
||||
+ local fmt=$1
|
||||
+ local msg
|
||||
+
|
||||
+ if [ $# -lt 1 ]; then
|
||||
+ ocf_log err "Not enough arguments [$#] to ocf_log_exit_msg."
|
||||
+ fi
|
||||
+ if [ -z "$cookie" ]; then
|
||||
+ # use a default prefix
|
||||
+ cookie="ocf-exit-reason:"
|
||||
+ fi
|
||||
+
|
||||
+ shift
|
||||
+
|
||||
+ msg=$(printf "${fmt}" "$@")
|
||||
+
|
||||
+ printf >&2 "%s${msg}\n" "$cookie"
|
||||
+ __ha_log_ignore_stderr_once="true"
|
||||
+ ha_log "ERROR: $msg"
|
||||
+}
|
||||
+
|
||||
+#
|
||||
# ocf_deprecated: Log a deprecation warning
|
||||
# Usage: ocf_deprecated [param-name]
|
||||
# Arguments: param-name optional, name of a boolean resource
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
From 566544cb98bc4e373ac75fa8c6281ef031a673ca Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Fri, 1 Aug 2014 13:13:39 -0400
|
||||
Subject: [PATCH] High: nfsnotify: set exit reason strings in nfsnotify agent
|
||||
|
||||
---
|
||||
heartbeat/nfsnotify | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/nfsnotify b/heartbeat/nfsnotify
|
||||
index 2d0bbfc..5f72d58 100755
|
||||
--- a/heartbeat/nfsnotify
|
||||
+++ b/heartbeat/nfsnotify
|
||||
@@ -152,7 +152,7 @@ check_statd_pidfile()
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
- ocf_log err "$(cat $pidfile) for $binary is no longer running, sm-notify needs to re-notify clients"
|
||||
+ ocf_exit_reason "$(cat $pidfile) for $binary is no longer running, sm-notify needs to re-notify clients"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
@@ -179,7 +179,7 @@ write_statd_pid()
|
||||
return $OCF_NOT_RUNNING;;
|
||||
*)
|
||||
rm -f "$pidfile" > /dev/null 2>&1
|
||||
- ocf_log err "Error encountered detecting pid status of $binary"
|
||||
+ ocf_exit_reason "Error encountered detecting pid status of $binary"
|
||||
return $OCF_ERR_GENERIC;;
|
||||
esac
|
||||
}
|
||||
@@ -243,7 +243,7 @@ v3notify_start()
|
||||
ocf_log info "sending notifications on default source address."
|
||||
$SM_NOTIFY_BINARY -f $OCF_RESKEY_notify_args -P $cur_statd
|
||||
if [ $? -ne 0 ]; then
|
||||
- ocf_log err "sm-notify failed, view syslog for more information."
|
||||
+ ocf_exit_reason "sm-notify execution failed, view syslog for more information"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
@@ -269,7 +269,7 @@ v3notify_start()
|
||||
ocf_log info "sending notifications with source address $ip"
|
||||
$SM_NOTIFY_BINARY -f $OCF_RESKEY_notify_args -v $ip -P "$cur_statd"
|
||||
if [ $? -ne 0 ]; then
|
||||
- ocf_log err "sm-notify with source host set to, $ip, failed. view syslog for more information"
|
||||
+ ocf_exit_reason "sm-notify with source host set to [ $ip ] failed. view syslog for more information"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
done
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
From dab933121dfff2b4e9c141c141a196ddc40e9d56 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Fri, 1 Aug 2014 13:21:11 -0400
|
||||
Subject: [PATCH] High: nfsserver: support exit string in nfsserver agent
|
||||
|
||||
---
|
||||
heartbeat/nfsserver | 20 ++++++++++----------
|
||||
1 file changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
index ac921f3..de1a802 100755
|
||||
--- a/heartbeat/nfsserver
|
||||
+++ b/heartbeat/nfsserver
|
||||
@@ -317,7 +317,7 @@ set_exec_mode()
|
||||
fi
|
||||
fi
|
||||
|
||||
- ocf_log err "No init script or systemd unit file detected for nfs server"
|
||||
+ ocf_exit_reason "No init script or systemd unit file detected for nfs server"
|
||||
exit $OCF_ERR_INSTALLED
|
||||
}
|
||||
|
||||
@@ -366,7 +366,7 @@ nfsserver_monitor ()
|
||||
v3locking_exec "status"
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
- ocf_log error "NFS server is up, but the locking daemons are down"
|
||||
+ ocf_exit_reason "NFS server is up, but the locking daemons are down"
|
||||
rc=$OCF_ERR_GENERIC
|
||||
fi
|
||||
return $rc
|
||||
@@ -682,7 +682,7 @@ nfsserver_start ()
|
||||
v3locking_exec "start"
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
- ocf_log error "Failed to start NFS server locking daemons"
|
||||
+ ocf_exit_reason "Failed to start NFS server locking daemons"
|
||||
return $rc
|
||||
fi
|
||||
else
|
||||
@@ -696,7 +696,7 @@ nfsserver_start ()
|
||||
rm -f $fn
|
||||
|
||||
if [ $rc -ne 0 ]; then
|
||||
- ocf_log err "Failed to start NFS server"
|
||||
+ ocf_exit_reason "Failed to start NFS server"
|
||||
return $rc
|
||||
fi
|
||||
|
||||
@@ -723,16 +723,16 @@ nfsserver_stop ()
|
||||
|
||||
v3locking_exec "stop"
|
||||
if [ $? -ne 0 ]; then
|
||||
- ocf_log err "Failed to stop NFS locking daemons"
|
||||
+ ocf_exit_reason "Failed to stop NFS locking daemons"
|
||||
rc=$OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
if [ $rc -eq 0 ]; then
|
||||
unbind_tree
|
||||
ocf_log info "NFS server stopped"
|
||||
- return $OCF_SUCCESS
|
||||
+ else
|
||||
+ ocf_exit_reason "Failed to stop NFS server"
|
||||
fi
|
||||
- ocf_log err "Failed to stop NFS server"
|
||||
return $rc
|
||||
}
|
||||
|
||||
@@ -746,13 +746,13 @@ nfsserver_validate ()
|
||||
|
||||
|
||||
if [ -n "$OCF_RESKEY_CRM_meta_clone" ] && [ -n "$OCF_RESKEY_nfs_shared_infodir" ]; then
|
||||
- ocf_log err "This RA does not support clone mode when a shared info directory is in use."
|
||||
+ ocf_exit_reason "This RA does not support clone mode when a shared info directory is in use."
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
if [ -n "$OCF_RESKEY_nfs_smnotify_retry_time" ]; then
|
||||
if ! ocf_is_decimal "$OCF_RESKEY_nfs_smnotify_retry_time"; then
|
||||
- ocf_log err "Invalid nfs_smnotify_retry_time [$OCF_RESKEY_nfs_smnotify_retry_time]"
|
||||
+ ocf_exit_reason "Invalid nfs_smnotify_retry_time [$OCF_RESKEY_nfs_smnotify_retry_time]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
fi
|
||||
@@ -760,7 +760,7 @@ nfsserver_validate ()
|
||||
case ${OCF_RESKEY_nfs_notify_cmd##*/} in
|
||||
sm-notify|rpc.statd) ;;
|
||||
*)
|
||||
- ocf_log err "Invalid nfs_notify_cmd [$OCF_RESKEY_nfs_notify_cmd]"
|
||||
+ ocf_exit_reason "Invalid nfs_notify_cmd [$OCF_RESKEY_nfs_notify_cmd]"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
;;
|
||||
esac
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
From c25542d8808640fae7fad39e27e95e83ffde2e31 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Mon, 27 Oct 2014 18:22:27 -0400
|
||||
Subject: [PATCH] Low: docker: indicate when monitor_cmd is not available after
|
||||
startup
|
||||
|
||||
---
|
||||
heartbeat/docker | 29 ++++++++++++++++++++++-------
|
||||
1 file changed, 22 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/docker b/heartbeat/docker
|
||||
index 929b26b..a0dcee4 100755
|
||||
--- a/heartbeat/docker
|
||||
+++ b/heartbeat/docker
|
||||
@@ -168,15 +168,28 @@ END
|
||||
monitor_cmd_exec()
|
||||
{
|
||||
local rc=$OCF_SUCCESS
|
||||
- if [ -n "$OCF_RESKEY_monitor_cmd" ]; then
|
||||
- out=$(echo "$OCF_RESKEY_monitor_cmd" | nsenter --target $(docker inspect --format {{.State.Pid}} ${CONTAINER}) --mount --uts --ipc --net --pid 2>&1)
|
||||
- rc=$?
|
||||
- if [ $rc -ne 0 ]; then
|
||||
- ocf_log info "monitor cmd failed with exit code $rc"
|
||||
- ocf_log info "stdout/stderr: $out"
|
||||
- rc=$OCF_ERR_GENERIC
|
||||
+ local out
|
||||
+
|
||||
+ if [ -z "$OCF_RESKEY_monitor_cmd" ]; then
|
||||
+ return $rc
|
||||
+ fi
|
||||
+
|
||||
+ out=$(echo "$OCF_RESKEY_monitor_cmd" | nsenter --target $(docker inspect --format {{.State.Pid}} ${CONTAINER}) --mount --uts --ipc --net --pid 2>&1)
|
||||
+ rc=$?
|
||||
+ if [ $rc -ne 0 ]; then
|
||||
+ ocf_log info "monitor cmd exit code = $rc"
|
||||
+ ocf_log info "stdout/stderr: $out"
|
||||
+
|
||||
+ if [ $rc -eq 127 ]; then
|
||||
+ ocf_exit_reason "monitor_cmd, ${OCF_RESKEY_monitor_cmd} , not found within container."
|
||||
+ # there is no recovering from this, exit immediately
|
||||
+ exit $OCF_ERR_ARGS
|
||||
fi
|
||||
+ rc=$OCF_ERR_GENERIC
|
||||
+ else
|
||||
+ ocf_log info "monitor cmd passed: exit code = $rc"
|
||||
fi
|
||||
+
|
||||
return $rc
|
||||
}
|
||||
|
||||
@@ -288,6 +301,7 @@ docker_start()
|
||||
|
||||
monitor_cmd_exec
|
||||
if [ $? -eq $OCF_SUCCESS ]; then
|
||||
+ ocf_log notice "Container $CONTAINER started successfully"
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
@@ -365,6 +379,7 @@ docker_validate()
|
||||
fi
|
||||
|
||||
if [ -n "$OCF_RESKEY_monitor_cmd" ]; then
|
||||
+ ocf_log info "checking for nsenter, which is required when 'monitor_cmd' is specified"
|
||||
check_binary nsenter
|
||||
fi
|
||||
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
From 804b68824372f98e23b858f6284160c1f2b0e19f Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Sat, 25 Oct 2014 20:54:14 -0400
|
||||
Subject: [PATCH 2/2] High: docker: monitor_cmd option for executing status
|
||||
script within container
|
||||
|
||||
---
|
||||
heartbeat/docker | 76 +++++++++++++++++++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 67 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/docker b/heartbeat/docker
|
||||
index cdf4e82..929b26b 100755
|
||||
--- a/heartbeat/docker
|
||||
+++ b/heartbeat/docker
|
||||
@@ -106,6 +106,20 @@ it has initialized.
|
||||
<content type="string"/>
|
||||
</parameter>
|
||||
|
||||
+<parameter name="monitor_cmd" required="0" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Specifiy the full path of a command to launch within the container to check
|
||||
+the health of the container. This command must return 0 to indicate that
|
||||
+the container is healthy. A non-zero return code will indicate that the
|
||||
+container has failed and should be recovered.
|
||||
+
|
||||
+The command is executed using nsenter. In the future 'docker exec' will
|
||||
+be used once it is more widely supported.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">monitor command</shortdesc>
|
||||
+<content type="string"/>
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="force_kill" required="0" unique="0">
|
||||
<longdesc lang="en">
|
||||
Kill a container immediately rather than waiting for it to gracefully
|
||||
@@ -150,6 +164,22 @@ Expects to have a fully populated OCF RA-compliant environment set.
|
||||
END
|
||||
}
|
||||
|
||||
+
|
||||
+monitor_cmd_exec()
|
||||
+{
|
||||
+ local rc=$OCF_SUCCESS
|
||||
+ if [ -n "$OCF_RESKEY_monitor_cmd" ]; then
|
||||
+ out=$(echo "$OCF_RESKEY_monitor_cmd" | nsenter --target $(docker inspect --format {{.State.Pid}} ${CONTAINER}) --mount --uts --ipc --net --pid 2>&1)
|
||||
+ rc=$?
|
||||
+ if [ $rc -ne 0 ]; then
|
||||
+ ocf_log info "monitor cmd failed with exit code $rc"
|
||||
+ ocf_log info "stdout/stderr: $out"
|
||||
+ rc=$OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ fi
|
||||
+ return $rc
|
||||
+}
|
||||
+
|
||||
container_exists()
|
||||
{
|
||||
docker inspect $CONTAINER > /dev/null 2>&1
|
||||
@@ -171,7 +201,7 @@ remove_container()
|
||||
ocf_run docker rm $CONTAINER
|
||||
}
|
||||
|
||||
-docker_monitor()
|
||||
+docker_simple_status()
|
||||
{
|
||||
local val
|
||||
|
||||
@@ -195,11 +225,25 @@ docker_monitor()
|
||||
return $OCF_NOT_RUNNING
|
||||
}
|
||||
|
||||
+docker_monitor()
|
||||
+{
|
||||
+ local rc=0
|
||||
+
|
||||
+ docker_simple_status
|
||||
+ rc=$?
|
||||
+
|
||||
+ if [ $rc -ne 0 ]; then
|
||||
+ return $rc
|
||||
+ fi
|
||||
+
|
||||
+ monitor_cmd_exec
|
||||
+}
|
||||
+
|
||||
docker_start()
|
||||
{
|
||||
local run_opts="-d --name=${CONTAINER}"
|
||||
# check to see if the container has already started
|
||||
- docker_monitor
|
||||
+ docker_simple_status
|
||||
if [ $? -eq $OCF_SUCCESS ]; then
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
@@ -233,19 +277,29 @@ docker_start()
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
- docker_monitor
|
||||
- if [ $? -ne $OCF_SUCCESS ]; then
|
||||
- ocf_exit_reason "Newly created docker container exited after start"
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
|
||||
- return $OCF_SUCCESS
|
||||
+ # wait for monitor to pass before declaring that the container is started
|
||||
+ while true; do
|
||||
+ docker_simple_status
|
||||
+ if [ $? -ne $OCF_SUCCESS ]; then
|
||||
+ ocf_exit_reason "Newly created docker container exited after start"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ monitor_cmd_exec
|
||||
+ if [ $? -eq $OCF_SUCCESS ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ ocf_exit_reason "waiting on monitor_cmd to pass after start"
|
||||
+ sleep 1
|
||||
+ done
|
||||
}
|
||||
|
||||
docker_stop()
|
||||
{
|
||||
local timeout=60
|
||||
- docker_monitor
|
||||
+ docker_simple_status
|
||||
if [ $? -eq $OCF_NOT_RUNNING ]; then
|
||||
remove_container
|
||||
return $OCF_SUCCESS
|
||||
@@ -310,6 +364,10 @@ docker_validate()
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
+ if [ -n "$OCF_RESKEY_monitor_cmd" ]; then
|
||||
+ check_binary nsenter
|
||||
+ fi
|
||||
+
|
||||
image_exists
|
||||
if [ $? -ne 0 ]; then
|
||||
ocf_exit_reason "base image, ${OCF_RESKEY_image}, could not be found."
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
From 0f1b107a50dd2ba51277f6962dd0c28dfb8976fc Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Sat, 25 Oct 2014 20:23:55 -0400
|
||||
Subject: [PATCH 1/2] High: docker: replace 'container' argument with 'name'
|
||||
|
||||
I realized that the 'container' argument means something special in
|
||||
pacemaker. In order to avoid confusion, the 'container' argument for
|
||||
this agent has been changed to 'name'. Anyone using 'container' as
|
||||
an argument right now will not be affected. The option still works, it
|
||||
is depreciated now though.
|
||||
---
|
||||
heartbeat/docker | 19 ++++++++++++++++---
|
||||
1 file changed, 16 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/docker b/heartbeat/docker
|
||||
index 37a449b..cdf4e82 100755
|
||||
--- a/heartbeat/docker
|
||||
+++ b/heartbeat/docker
|
||||
@@ -59,7 +59,7 @@ The docker image to base this container off of.
|
||||
<content type="string"/>
|
||||
</parameter>
|
||||
|
||||
-<parameter name="container" required="0" unique="0">
|
||||
+<parameter name="name" required="0" unique="0">
|
||||
<longdesc lang="en">
|
||||
The name to give the created container. By default this will
|
||||
be that resource's instance name.
|
||||
@@ -87,6 +87,11 @@ users to do things such as setting a custom entry point and injecting
|
||||
environment variables into the newly created container. Note the '-d'
|
||||
option is supplied regardless of this value to force containers to run
|
||||
in the background.
|
||||
+
|
||||
+NOTE: Do not explicitly specify the --name argument in the run_opts. This
|
||||
+agent will set --name using either the resource's instance or the name
|
||||
+provided in the 'name' argument of this agent.
|
||||
+
|
||||
</longdesc>
|
||||
<shortdesc lang="en">run options</shortdesc>
|
||||
<content type="string"/>
|
||||
@@ -314,8 +319,16 @@ docker_validate()
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
-: ${OCF_RESKEY_container=${OCF_RESOURCE_INSTANCE}}
|
||||
-CONTAINER=$OCF_RESKEY_container
|
||||
+: ${OCF_RESKEY_name=${OCF_RESOURCE_INSTANCE}}
|
||||
+
|
||||
+if [ -n "$OCF_RESKEY_container" ]; then
|
||||
+ # we'll keep the container attribute around for a bit in order not to break
|
||||
+ # any existing deployments. The 'name' attribute is prefered now though.
|
||||
+ CONTAINER=$OCF_RESKEY_container
|
||||
+ ocf_log warn "The 'container' attribute is depreciated"
|
||||
+else
|
||||
+ CONTAINER=$OCF_RESKEY_name
|
||||
+fi
|
||||
|
||||
case $__OCF_ACTION in
|
||||
meta-data) meta_data
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
From 05fb27218f3b8a78bff0b0e668c8d38feeb93dca Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Thu, 23 Oct 2014 14:20:14 -0400
|
||||
Subject: [PATCH] High: docker: properly remove stale container during stop
|
||||
when 'reuse' is not enabled
|
||||
|
||||
---
|
||||
heartbeat/docker | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/docker b/heartbeat/docker
|
||||
index 546c423..37a449b 100755
|
||||
--- a/heartbeat/docker
|
||||
+++ b/heartbeat/docker
|
||||
@@ -157,6 +157,11 @@ remove_container()
|
||||
return 0
|
||||
fi
|
||||
|
||||
+ container_exists
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ # don't attempt to remove a container that doesn't exist
|
||||
+ return 0
|
||||
+ fi
|
||||
ocf_log notice "Cleaning up inactive container, ${CONTAINER}."
|
||||
ocf_run docker rm $CONTAINER
|
||||
}
|
||||
@@ -210,7 +215,10 @@ docker_start()
|
||||
if ocf_is_true "$OCF_RESKEY_reuse" && container_exists; then
|
||||
ocf_log info "starting existing container $CONTAINER."
|
||||
ocf_run docker start $CONTAINER
|
||||
- else
|
||||
+ else
|
||||
+ # make sure any previous container matching our container name is cleaned up first.
|
||||
+ # we already know at this point it wouldn't be running
|
||||
+ remove_container
|
||||
ocf_log info "running container $CONTAINER for the first time"
|
||||
ocf_run docker run $run_opts $OCF_RESKEY_image $OCF_RESKEY_run_cmd
|
||||
fi
|
||||
@@ -234,6 +242,7 @@ docker_stop()
|
||||
local timeout=60
|
||||
docker_monitor
|
||||
if [ $? -eq $OCF_NOT_RUNNING ]; then
|
||||
+ remove_container
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,375 @@
|
|||
From 6d4180b5ed46cda544e008b242f024b2ab143a83 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Thu, 23 Oct 2014 09:37:18 -0500
|
||||
Subject: [PATCH] introducing docker agent
|
||||
|
||||
---
|
||||
doc/man/Makefile.am | 1 +
|
||||
heartbeat/Makefile.am | 1 +
|
||||
heartbeat/docker | 330 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 332 insertions(+)
|
||||
create mode 100755 heartbeat/docker
|
||||
|
||||
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
|
||||
index e97c7e9..ee29756 100644
|
||||
--- a/doc/man/Makefile.am
|
||||
+++ b/doc/man/Makefile.am
|
||||
@@ -98,6 +98,7 @@ man_MANS = ocf_heartbeat_AoEtarget.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 \
|
||||
diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am
|
||||
index aab521f..f763533 100644
|
||||
--- a/heartbeat/Makefile.am
|
||||
+++ b/heartbeat/Makefile.am
|
||||
@@ -65,6 +65,7 @@ ocf_SCRIPTS = ClusterMon \
|
||||
conntrackd \
|
||||
db2 \
|
||||
dhcpd \
|
||||
+ docker \
|
||||
Delay \
|
||||
eDir88 \
|
||||
EvmsSCC \
|
||||
diff --git a/heartbeat/docker b/heartbeat/docker
|
||||
new file mode 100755
|
||||
index 0000000..546c423
|
||||
--- /dev/null
|
||||
+++ b/heartbeat/docker
|
||||
@@ -0,0 +1,330 @@
|
||||
+#!/bin/sh
|
||||
+#
|
||||
+# The docker HA resource agent creates and launches a docker container
|
||||
+# based off a supplied docker image. Containers managed by this agent
|
||||
+# are both created and removed upon the agent's start and stop actions.
|
||||
+#
|
||||
+# Copyright (c) 2014 David Vossel <dvossel@redhat.com>
|
||||
+# All Rights Reserved.
|
||||
+#
|
||||
+# 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.
|
||||
+#
|
||||
+
|
||||
+#######################################################################
|
||||
+# Initialization:
|
||||
+
|
||||
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+meta_data()
|
||||
+{
|
||||
+ cat <<END
|
||||
+<?xml version="1.0"?>
|
||||
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
+<resource-agent name="docker" version="0.9">
|
||||
+<version>1.0</version>
|
||||
+
|
||||
+<longdesc lang="en">
|
||||
+The docker HA resource agent creates and launches a docker container
|
||||
+based off a supplied docker image. Containers managed by this agent
|
||||
+are both created and removed upon the agent's start and stop actions.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Docker container resource agent.</shortdesc>
|
||||
+
|
||||
+<parameters>
|
||||
+<parameter name="image" required="1" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+The docker image to base this container off of.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">docker image</shortdesc>
|
||||
+<content type="string"/>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="container" required="0" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+The name to give the created container. By default this will
|
||||
+be that resource's instance name.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">docker container name</shortdesc>
|
||||
+<content type="string"/>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="allow_pull" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Allow the image to be pulled from the configured docker registry when
|
||||
+the image does not exist locally. NOTE, this can drastically increase
|
||||
+the time required to start the container if the image repository is
|
||||
+pulled over the network.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Allow pulling non-local images</shortdesc>
|
||||
+<content type="boolean"/>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="run_opts" required="0" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Add options to be appended to the 'docker run' command which is used
|
||||
+when creating the container during the start action. This option allows
|
||||
+users to do things such as setting a custom entry point and injecting
|
||||
+environment variables into the newly created container. Note the '-d'
|
||||
+option is supplied regardless of this value to force containers to run
|
||||
+in the background.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">run options</shortdesc>
|
||||
+<content type="string"/>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="run_cmd" required="0" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Specifiy a command to launch within the container once
|
||||
+it has initialized.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">run command</shortdesc>
|
||||
+<content type="string"/>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="force_kill" required="0" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Kill a container immediately rather than waiting for it to gracefully
|
||||
+shutdown
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">force kill</shortdesc>
|
||||
+<content type="boolean"/>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="reuse" required="0" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Allow the container to be reused after stopping the container. By default
|
||||
+containers are removed after stop. With the reuse option containers
|
||||
+will persist after the container stops.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">reuse container</shortdesc>
|
||||
+<content type="boolean"/>
|
||||
+</parameter>
|
||||
+
|
||||
+</parameters>
|
||||
+
|
||||
+<actions>
|
||||
+<action name="start" timeout="90" />
|
||||
+<action name="stop" timeout="90" />
|
||||
+<action name="monitor" timeout="30" interval="30" depth="0" />
|
||||
+<action name="meta-data" timeout="5" />
|
||||
+<action name="validate-all" timeout="30" />
|
||||
+</actions>
|
||||
+</resource-agent>
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+#######################################################################
|
||||
+REQUIRE_IMAGE_PULL=0
|
||||
+
|
||||
+docker_usage()
|
||||
+{
|
||||
+ cat <<END
|
||||
+usage: $0 {start|stop|monitor|validate-all|meta-data}
|
||||
+
|
||||
+Expects to have a fully populated OCF RA-compliant environment set.
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+container_exists()
|
||||
+{
|
||||
+ docker inspect $CONTAINER > /dev/null 2>&1
|
||||
+}
|
||||
+
|
||||
+remove_container()
|
||||
+{
|
||||
+ if ocf_is_true "$OCF_RESKEY_reuse"; then
|
||||
+ # never remove the container if we have reuse enabled.
|
||||
+ return 0
|
||||
+ fi
|
||||
+
|
||||
+ ocf_log notice "Cleaning up inactive container, ${CONTAINER}."
|
||||
+ ocf_run docker rm $CONTAINER
|
||||
+}
|
||||
+
|
||||
+docker_monitor()
|
||||
+{
|
||||
+ local val
|
||||
+
|
||||
+ container_exists
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+
|
||||
+ # retrieve the 'Running' attribute for the container
|
||||
+ val=$(docker inspect --format {{.State.Running}} $CONTAINER 2>/dev/null)
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ #not running as a result of container not being found
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+
|
||||
+ if ocf_is_true "$val"; then
|
||||
+ # container exists and is running
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+}
|
||||
+
|
||||
+docker_start()
|
||||
+{
|
||||
+ local run_opts="-d --name=${CONTAINER}"
|
||||
+ # check to see if the container has already started
|
||||
+ docker_monitor
|
||||
+ if [ $? -eq $OCF_SUCCESS ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "$OCF_RESKEY_run_opts" ]; then
|
||||
+ run_opts="$run_opts $OCF_RESKEY_run_opts"
|
||||
+ fi
|
||||
+
|
||||
+ if [ $REQUIRE_IMAGE_PULL -eq 1 ]; then
|
||||
+ ocf_log notice "Beginning pull of image, ${OCF_RESKEY_image}"
|
||||
+ docker pull "${OCF_RESKEY_image}"
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ ocf_exit_reason "failed to pull image ${OCF_RESKEY_image}"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if ocf_is_true "$OCF_RESKEY_reuse" && container_exists; then
|
||||
+ ocf_log info "starting existing container $CONTAINER."
|
||||
+ ocf_run docker start $CONTAINER
|
||||
+ else
|
||||
+ ocf_log info "running container $CONTAINER for the first time"
|
||||
+ ocf_run docker run $run_opts $OCF_RESKEY_image $OCF_RESKEY_run_cmd
|
||||
+ fi
|
||||
+
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ ocf_exit_reason "docker failed to launch container"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ docker_monitor
|
||||
+ if [ $? -ne $OCF_SUCCESS ]; then
|
||||
+ ocf_exit_reason "Newly created docker container exited after start"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+docker_stop()
|
||||
+{
|
||||
+ local timeout=60
|
||||
+ docker_monitor
|
||||
+ if [ $? -eq $OCF_NOT_RUNNING ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
|
||||
+ timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000) -10 ))
|
||||
+ if [ $timeout -lt 10 ]; then
|
||||
+ timeout=10
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if ocf_is_true "$OCF_RESKEY_force_kill"; then
|
||||
+ ocf_run docker kill $CONTAINER
|
||||
+ else
|
||||
+ ocf_log debug "waiting $timeout second[s] before killing container"
|
||||
+ ocf_run docker stop -t=$timeout $CONTAINER
|
||||
+ fi
|
||||
+
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ ocf_exit_reason "Failed to stop container, ${CONTAINER}, based on image, ${OCF_RESKEY_image}."
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ remove_container
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ ocf_exit_reason "Failed to remove stopped container, ${CONTAINER}, based on image, ${OCF_RESKEY_image}."
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+image_exists()
|
||||
+{
|
||||
+ local res=1
|
||||
+
|
||||
+
|
||||
+ echo "${OCF_RESKEY_image}" | grep -q ":"
|
||||
+ if [ $? -eq 0 ]; then
|
||||
+ docker images | awk '{print $1 ":" $2}' | grep "^${OCF_RESKEY_image}\$" > /dev/null 2>&1
|
||||
+ else
|
||||
+ docker images | awk '{print $1}' | grep "^${OCF_RESKEY_image}\$" > /dev/null 2>&1
|
||||
+ fi
|
||||
+ if [ $? -eq 0 ]; then
|
||||
+ return 0
|
||||
+ fi
|
||||
+ if ocf_is_true "$OCF_RESKEY_allow_pull"; then
|
||||
+ REQUIRE_IMAGE_PULL=1
|
||||
+ ocf_log notice "Image (${OCF_RESKEY_image}) does not exist locally but will be pulled during start"
|
||||
+ return 0
|
||||
+ fi
|
||||
+ # image not found.
|
||||
+ return 1
|
||||
+}
|
||||
+
|
||||
+docker_validate()
|
||||
+{
|
||||
+ check_binary docker
|
||||
+ if [ -z "$OCF_RESKEY_image" ]; then
|
||||
+ ocf_exit_reason "'image' option is required"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ image_exists
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ ocf_exit_reason "base image, ${OCF_RESKEY_image}, could not be found."
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+: ${OCF_RESKEY_container=${OCF_RESOURCE_INSTANCE}}
|
||||
+CONTAINER=$OCF_RESKEY_container
|
||||
+
|
||||
+case $__OCF_ACTION in
|
||||
+meta-data) meta_data
|
||||
+ exit $OCF_SUCCESS;;
|
||||
+start)
|
||||
+ docker_validate
|
||||
+ docker_start;;
|
||||
+stop) docker_stop;;
|
||||
+monitor) docker_monitor;;
|
||||
+validate-all) docker_validate;;
|
||||
+usage|help) docker_usage
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+*) docker_usage
|
||||
+ exit $OCF_ERR_UNIMPLEMENTED
|
||||
+ ;;
|
||||
+esac
|
||||
+rc=$?
|
||||
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
|
||||
+exit $rc
|
||||
+
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
From 328b228321e71260f9c0ea4b926b43f208aef158 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Tue, 7 Oct 2014 16:11:28 -0400
|
||||
Subject: [PATCH 2/2] High: mysql-common: avoid use of check_binary in common
|
||||
validation function.
|
||||
|
||||
Since the environment validation exit code needs to be interpreted
|
||||
differently now for monitor operations, we need to avoid functions like
|
||||
'check_binary' that exit the process immediately upon failure. Instead
|
||||
we should use 'have_binary' in this situation.
|
||||
|
||||
This allows the mysql agent to work properly in a scenario where the entire
|
||||
mysql install resides on shared storage.
|
||||
---
|
||||
heartbeat/mysql-common.sh | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/mysql-common.sh b/heartbeat/mysql-common.sh
|
||||
index a02f8cd..310f487 100755
|
||||
--- a/heartbeat/mysql-common.sh
|
||||
+++ b/heartbeat/mysql-common.sh
|
||||
@@ -94,8 +94,16 @@ CRM_ATTR_REPL_INFO="${HA_SBIN_DIR}/crm_attribute --type crm_config --name ${INST
|
||||
|
||||
mysql_common_validate()
|
||||
{
|
||||
- check_binary $OCF_RESKEY_binary
|
||||
- check_binary $OCF_RESKEY_client_binary
|
||||
+
|
||||
+ if ! have_binary "$OCF_RESKEY_binary"; then
|
||||
+ ocf_exit_reason "Setup problem: couldn't find command: $OCF_RESKEY_binary"
|
||||
+ return $OCF_ERR_INSTALLED;
|
||||
+ fi
|
||||
+
|
||||
+ if ! have_binary "$OCF_RESKEY_client_binary"; then
|
||||
+ ocf_exit_reason "Setup problem: couldn't find command: $OCF_RESKEY_client_binary"
|
||||
+ return $OCF_ERR_INSTALLED;
|
||||
+ fi
|
||||
|
||||
if [ ! -f $OCF_RESKEY_config ]; then
|
||||
ocf_exit_reason "Config $OCF_RESKEY_config doesn't exist";
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
From 6ac8332d16837a3481341316e61962e6f78694dd Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Tue, 7 Oct 2014 16:11:19 -0400
|
||||
Subject: [PATCH 1/2] High: mysql: report error when validation fails during
|
||||
monitor yet pid is still active
|
||||
|
||||
---
|
||||
heartbeat/mysql | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/mysql b/heartbeat/mysql
|
||||
index 6cfe0a0..d895369 100755
|
||||
--- a/heartbeat/mysql
|
||||
+++ b/heartbeat/mysql
|
||||
@@ -1007,7 +1007,16 @@ LSB_STATUS_STOPPED=3
|
||||
if [ $rc -ne 0 ]; then
|
||||
case "$1" in
|
||||
stop) ;;
|
||||
- monitor) exit $OCF_NOT_RUNNING;;
|
||||
+ monitor)
|
||||
+ mysql_common_status "info"
|
||||
+ if [ $? -eq $OCF_SUCCESS ]; then
|
||||
+ # if validatation fails and pid is active, always treat this as an error
|
||||
+ ocf_exit_reason "environment validation failed, active pid is in unknown state."
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ # validation failed and pid is not active, it's safe to say this instance is inactive.
|
||||
+ exit $OCF_NOT_RUNNING;;
|
||||
+
|
||||
status) exit $LSB_STATUS_STOPPED;;
|
||||
*) exit $rc;;
|
||||
esac
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
From 42a016eb56d79f287190f3abe68c2a7e1b3ca50b Mon Sep 17 00:00:00 2001
|
||||
From: John Ruemker <jruemker@redhat.com>
|
||||
Date: Wed, 17 Sep 2014 18:02:03 -0400
|
||||
Subject: [PATCH] High: mysql: do not report success on 'stop' if validation
|
||||
fails
|
||||
|
||||
---
|
||||
heartbeat/mysql | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/mysql b/heartbeat/mysql
|
||||
index dc862f5..6cfe0a0 100755
|
||||
--- a/heartbeat/mysql
|
||||
+++ b/heartbeat/mysql
|
||||
@@ -1006,7 +1006,7 @@ rc=$?
|
||||
LSB_STATUS_STOPPED=3
|
||||
if [ $rc -ne 0 ]; then
|
||||
case "$1" in
|
||||
- stop) exit $OCF_SUCCESS;;
|
||||
+ stop) ;;
|
||||
monitor) exit $OCF_NOT_RUNNING;;
|
||||
status) exit $LSB_STATUS_STOPPED;;
|
||||
*) exit $rc;;
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
From 8d25da64ab9dee8545a0c52f7db08213a03ea106 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 28 Feb 2017 15:46:40 +0100
|
||||
Subject: [PATCH] LVM: add check_writethrough parameter
|
||||
|
||||
---
|
||||
heartbeat/LVM | 19 +++++++++++++++++++
|
||||
1 file changed, 19 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/LVM b/heartbeat/LVM
|
||||
index 90a900b..5b265f5 100755
|
||||
--- a/heartbeat/LVM
|
||||
+++ b/heartbeat/LVM
|
||||
@@ -29,6 +29,8 @@
|
||||
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
|
||||
+OCF_RESKEY_check_writethrough_default="false"
|
||||
+
|
||||
#######################################################################
|
||||
|
||||
|
||||
@@ -106,6 +108,14 @@ logical volumes.
|
||||
<content type="string" default="false" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="check_writethrough" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+If set to true, check if cache_mode is set to writethrough.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Check if cache_mode is set to writethrough</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_check_writethrough_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -583,6 +593,13 @@ LVM_validate_all() {
|
||||
exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
+ if ocf_is_true "$OCF_RESKEY_check_writethrough"; then
|
||||
+ if ! lvs --noheadings -o cache_mode "$OCF_RESKEY_volgrpname" | grep -q "writethrough"; then
|
||||
+ ocf_exit_reason "LVM cache is not in writethrough mode."
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
##
|
||||
# If exclusive activation is not enabled, then
|
||||
# further checking of proper setup is not necessary
|
||||
@@ -690,6 +707,8 @@ if [ -n "$OCF_RESKEY_tag" ]; then
|
||||
OUR_TAG=$OCF_RESKEY_tag
|
||||
fi
|
||||
|
||||
+: ${OCF_RESKEY_check_writethrough=${OCF_RESKEY_check_writethrough_default}}
|
||||
+
|
||||
# What kind of method was invoked?
|
||||
case "$1" in
|
||||
|
||||
|
|
@ -0,0 +1,520 @@
|
|||
From 0305c97abc49d0f7a93b3602a745805f7e8776d3 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Thu, 25 Jun 2015 16:23:45 -0500
|
||||
Subject: [PATCH 1/3] bz1160365-iface-vlan.patch
|
||||
|
||||
---
|
||||
doc/man/Makefile.am | 1 +
|
||||
heartbeat/Makefile.am | 1 +
|
||||
heartbeat/iface-vlan | 475 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 477 insertions(+)
|
||||
create mode 100755 heartbeat/iface-vlan
|
||||
|
||||
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
|
||||
index 653e818..091ec24 100644
|
||||
--- a/doc/man/Makefile.am
|
||||
+++ b/doc/man/Makefile.am
|
||||
@@ -107,6 +107,7 @@ man_MANS = ocf_heartbeat_AoEtarget.7 \
|
||||
ocf_heartbeat_iSCSILogicalUnit.7 \
|
||||
ocf_heartbeat_iSCSITarget.7 \
|
||||
ocf_heartbeat_ids.7 \
|
||||
+ ocf_heartbeat_iface-vlan.7 \
|
||||
ocf_heartbeat_iscsi.7 \
|
||||
ocf_heartbeat_jboss.7 \
|
||||
ocf_heartbeat_lxc.7 \
|
||||
diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am
|
||||
index e4ed4fd..6df4080 100644
|
||||
--- a/heartbeat/Makefile.am
|
||||
+++ b/heartbeat/Makefile.am
|
||||
@@ -76,6 +76,7 @@ ocf_SCRIPTS = ClusterMon \
|
||||
fio \
|
||||
galera \
|
||||
ids \
|
||||
+ iface-vlan \
|
||||
iscsi \
|
||||
ICP \
|
||||
IPsrcaddr \
|
||||
diff --git a/heartbeat/iface-vlan b/heartbeat/iface-vlan
|
||||
new file mode 100755
|
||||
index 0000000..bc8583c
|
||||
--- /dev/null
|
||||
+++ b/heartbeat/iface-vlan
|
||||
@@ -0,0 +1,475 @@
|
||||
+#!/bin/sh
|
||||
+#
|
||||
+# OCF Resource Agent compliant iface-vlan script.
|
||||
+#
|
||||
+# Implements network VLAN interface management
|
||||
+#
|
||||
+# Copyright (C) 2013 Red Hat, Inc. All rights reserved.
|
||||
+# Author: Fabio M. Di Nitto <fdinitto@redhat.com>
|
||||
+#
|
||||
+# 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.
|
||||
+#
|
||||
+#
|
||||
+
|
||||
+# TODO:
|
||||
+#
|
||||
+# OCF parameters are as below
|
||||
+# OCF_RESKEY_vlan_interface
|
||||
+# OCF_RESKEY_vlan_id
|
||||
+# OCF_RESKEY_vlan_name
|
||||
+# OCF_RESKEY_vlan_reorder_hdr
|
||||
+# OCF_RESKEY_vlan_gvrp
|
||||
+# OCF_RESKEY_vlan_mvrp
|
||||
+# OCF_RESKEY_vlan_loose_binding
|
||||
+#
|
||||
+
|
||||
+#######################################################################
|
||||
+# Initialization:
|
||||
+
|
||||
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
+
|
||||
+# Defaults
|
||||
+OCF_RESKEY_vlan_reorder_hdr_default=1
|
||||
+OCF_RESKEY_vlan_gvrp_default=0
|
||||
+OCF_RESKEY_vlan_mvrp_default=0
|
||||
+OCF_RESKEY_vlan_loose_binding_default=0
|
||||
+OCF_RESKEY_vlan_name_default=${OCF_RESKEY_vlan_interface}.${OCF_RESKEY_vlan_id}
|
||||
+
|
||||
+: ${OCF_RESKEY_vlan_name=${OCF_RESKEY_vlan_name_default}}
|
||||
+: ${OCF_RESKEY_vlan_reorder_hdr=${OCF_RESKEY_vlan_reorder_hdr_default}}
|
||||
+: ${OCF_RESKEY_vlan_gvrp=${OCF_RESKEY_vlan_gvrp_default}}
|
||||
+
|
||||
+# don't set defaults for mvrp or loose binding since both
|
||||
+# are rather new kernel features and they might not be supported
|
||||
+#: ${OCF_RESKEY_vlan_mvrp=${OCF_RESKEY_vlan_mvrp_default}}
|
||||
+#: ${OCF_RESKEY_vlan_loose_binding=${OCF_RESKEY_vlan_loose_binding_default}}
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+vlan_usage() {
|
||||
+ cat <<END
|
||||
+usage: $0 {start|stop|status|monitor|validate-all|meta-data}
|
||||
+
|
||||
+Expects to have a fully populated OCF RA-compliant environment set.
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+vlan_meta_data() {
|
||||
+ cat <<END
|
||||
+<?xml version="1.0"?>
|
||||
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
+<resource-agent name="iface-vlan">
|
||||
+ <version>1.0</version>
|
||||
+
|
||||
+ <longdesc lang="en">
|
||||
+ This resource manages VLAN network interfaces.
|
||||
+ It can add, remove, configure VLANs.
|
||||
+ </longdesc>
|
||||
+
|
||||
+ <shortdesc lang="en">
|
||||
+ Manages VLAN network interfaces.
|
||||
+ </shortdesc>
|
||||
+
|
||||
+ <parameters>
|
||||
+ <parameter name="vlan_interface" unique="1" required="1">
|
||||
+ <longdesc lang="en">
|
||||
+ Define the interface where VLAN should be attached.
|
||||
+ </longdesc>
|
||||
+ <shortdesc lang="en">
|
||||
+ Network interface.
|
||||
+ </shortdesc>
|
||||
+ <content type="string"/>
|
||||
+ </parameter>
|
||||
+
|
||||
+ <parameter name="vlan_id" unique="1" required="1">
|
||||
+ <longdesc lang="en">
|
||||
+ Define the VLAN ID. It has to be a value between 0 and 4094.
|
||||
+ </longdesc>
|
||||
+ <shortdesc lang="en">
|
||||
+ Define the VLAN ID.
|
||||
+ </shortdesc>
|
||||
+ <content type="integer"/>
|
||||
+ </parameter>
|
||||
+
|
||||
+ <parameter name="vlan_name" unique="1">
|
||||
+ <longdesc lang="en">
|
||||
+ Define the name of the VLAN interface (max 15 charaters).
|
||||
+ </longdesc>
|
||||
+ <shortdesc lang="en">
|
||||
+ Name of the VLAN.
|
||||
+ </shortdesc>
|
||||
+ <content type="string" default="vlan_interface.vlan.id" />
|
||||
+ </parameter>
|
||||
+
|
||||
+ <parameter name="vlan_reorder_hdr" unique="0">
|
||||
+ <longdesc lang="en">
|
||||
+ Enable or disable header reordering.
|
||||
+ </longdesc>
|
||||
+ <shortdesc lang="en">
|
||||
+ Enable or disable header reordering.
|
||||
+ </shortdesc>
|
||||
+ <content type="boolean" default="${OCF_RESKEY_vlan_reorder_hdr_default}"/>
|
||||
+ </parameter>
|
||||
+
|
||||
+ <parameter name="vlan_gvrp" unique="0">
|
||||
+ <longdesc lang="en">
|
||||
+ Enable or disable GARP VLAN registration protocol.
|
||||
+ </longdesc>
|
||||
+ <shortdesc lang="en">
|
||||
+ Enable or disable gvrp.
|
||||
+ </shortdesc>
|
||||
+ <content type="boolean" default="${OCF_RESKEY_vlan_gvrp_default}"/>
|
||||
+ </parameter>
|
||||
+
|
||||
+ <parameter name="vlan_mvrp" unique="0">
|
||||
+ <longdesc lang="en">
|
||||
+ Enable or disable Multiple VLAN Registration Protocol.
|
||||
+ Please note that most distributions do not ship a version of iproute2
|
||||
+ that supports mvrp yet, even if the kernel has support for it.
|
||||
+ Check output of $IPADDR2 link add type vlan --help in the FLAG
|
||||
+ section to verify if mvrp support is available.
|
||||
+ </longdesc>
|
||||
+ <shortdesc lang="en">
|
||||
+ Enable or disable mvrp.
|
||||
+ </shortdesc>
|
||||
+ <content type="boolean" default="${OCF_RESKEY_vlan_mvrp_default}"/>
|
||||
+ </parameter>
|
||||
+
|
||||
+ <parameter name="vlan_loose_binding" unique="0">
|
||||
+ <longdesc lang="en">
|
||||
+ Enable or disable VLAN loose bind. By default the VLAN interface
|
||||
+ admin status (UP/DOWN) follows the underneath inteface status.
|
||||
+ Enabling loose bind allows the VLAN to disconnect from the
|
||||
+ interface status. Be very careful that enabling loose binding
|
||||
+ could invalidate this agent monitor operations.
|
||||
+ Please note that most distributions do not ship a version of iproute2
|
||||
+ that supports loose_binding yet, even if the kernel has support for it.
|
||||
+ Check output of $IPADDR2 link add type vlan --help in the FLAG
|
||||
+ section to verify if loose_binding support is available.
|
||||
+ </longdesc>
|
||||
+ <shortdesc lang="en">
|
||||
+ Enable or disable loose binding.
|
||||
+ </shortdesc>
|
||||
+ <content type="boolean" default="${OCF_RESKEY_vlan_loose_binding_default}"/>
|
||||
+ </parameter>
|
||||
+ </parameters>
|
||||
+
|
||||
+ <actions>
|
||||
+ <action name="start" timeout="30s" />
|
||||
+ <action name="stop" timeout="20s" />
|
||||
+ <action name="status" timeout="20s" depth="0" interval="10s" />
|
||||
+ <action name="monitor" timeout="20s" depth="0" interval="10s" />
|
||||
+ <action name="meta-data" timeout="5s" />
|
||||
+ <action name="validate-all" timeout="20s" />
|
||||
+ </actions>
|
||||
+</resource-agent>
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+# check if the interface is admin up/down
|
||||
+
|
||||
+iface_is_up() {
|
||||
+ if ! $IP2UTIL -o link show $1 | \
|
||||
+ sed -e 's#.*<##g' -e 's#>.*##' -e 's#LOWER_UP##g' | \
|
||||
+ grep -q UP; then
|
||||
+ return 1
|
||||
+ fi
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+# check if the slaves have link layer up/down
|
||||
+# see kernel network documentation on meaning of LOWER_UP flag
|
||||
+# for more in depth explanation on how it works
|
||||
+# NOTE: this check is not reliable in virt environment
|
||||
+# since interfaces are always LOWER_UP. There is no way
|
||||
+# from the guest to know if the host has disconnected somehow
|
||||
+
|
||||
+iface_lower_is_up() {
|
||||
+ if ! $IP2UTIL -o link show $1 | \
|
||||
+ grep -q LOWER_UP; then
|
||||
+ return 1
|
||||
+ fi
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+vlan_validate() {
|
||||
+ check_binary $IP2UTIL
|
||||
+
|
||||
+ if [ -z "$OCF_RESKEY_vlan_interface" ]; then
|
||||
+ ocf_log err "Invalid OCF_RESKEY_vlan_interface: value cannot be empty"
|
||||
+ return 1
|
||||
+ fi
|
||||
+
|
||||
+ # the echo .. is the equivalent of strlen in bash
|
||||
+ #
|
||||
+ # /usr/include/linux/if.h:#define IFNAMSIZ 16
|
||||
+ # needs to include 0 byte end string
|
||||
+
|
||||
+ if [ "${#OCF_RESKEY_vlan_interface}" -gt 15 ]; then
|
||||
+ ocf_log err "Invalid OCF_RESKEY_vlan_interface: name is too long"
|
||||
+ return 1
|
||||
+ fi
|
||||
+
|
||||
+ if [ ! -d "/sys/class/net" ]; then
|
||||
+ ocf_log err "Unable to find sysfs network class in /sys"
|
||||
+ return 1
|
||||
+ fi
|
||||
+
|
||||
+ if [ ! -e "/sys/class/net/$OCF_RESKEY_vlan_interface" ]; then
|
||||
+ ocf_log err "Invalid OCF_RESKEY_vlan_interface: $OCF_RESKEY_vlan_interface does not exists"
|
||||
+ return 1
|
||||
+ fi
|
||||
+
|
||||
+ if [ -z "$OCF_RESKEY_vlan_id" ]; then
|
||||
+ ocf_log err "Invalid OCF_RESKEY_vlan_id: value cannot be empty"
|
||||
+ return 1
|
||||
+ fi
|
||||
+ if ! ocf_is_decimal "$OCF_RESKEY_vlan_id" || \
|
||||
+ [ "$OCF_RESKEY_vlan_id" -gt "4094" ]; then
|
||||
+ ocf_log err "Invalid OCF_RESKEY_vlan_id: must be a decimal value (0 to 4094 included)"
|
||||
+ return 1
|
||||
+ fi
|
||||
+
|
||||
+ if [ "${#OCF_RESKEY_vlan_name}" -gt 15 ]; then
|
||||
+ ocf_log err "Invalid OCF_RESKEY_vlan_name: name is too long"
|
||||
+ return 1
|
||||
+ fi
|
||||
+
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+vlan_check() {
|
||||
+ if [ -e "/sys/class/net/$OCF_RESKEY_vlan_name" ]; then
|
||||
+ if [ ! -e "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" ]; then
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ else
|
||||
+ if [ -e "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" ]; then
|
||||
+ error="$(rm -f "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" 2>&1)"
|
||||
+ if [ "$?" != "0" ]; then
|
||||
+ ocf_log err "Unable to remove stale lock file for vlan $OCF_RESKEY_vlan_name: $error"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ fi
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+
|
||||
+ if ! iface_is_up $OCF_RESKEY_vlan_interface; then
|
||||
+ if ocf_is_true "$OCF_RESKEY_vlan_loose_binding"; then
|
||||
+ ocf_log warn "Interface $OCF_RESKEY_vlan_interface is administratively down"
|
||||
+ else
|
||||
+ ocf_log err "Interface $OCF_RESKEY_vlan_interface is administratively down"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if ! iface_is_up $OCF_RESKEY_vlan_name; then
|
||||
+ ocf_log err "VLAN $OCF_RESKEY_vlan_name is administratively down"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ if ! iface_lower_is_up $OCF_RESKEY_vlan_name; then
|
||||
+ ocf_log err "VLAN $OCF_RESKEY_vlan_name has no active link-layer"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+# we need a simpler stop version to clean after us if start fails
|
||||
+# without involving any error checking
|
||||
+# rolling back in case of failure is otherwise complex
|
||||
+
|
||||
+vlan_force_stop() {
|
||||
+ $IP2UTIL link delete "$OCF_RESKEY_vlan_name" >/dev/null 2>&1
|
||||
+ rm -f "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" 2>&1
|
||||
+}
|
||||
+
|
||||
+vlan_start() {
|
||||
+ # check if the vlan already exists
|
||||
+ vlan_check
|
||||
+ ret=$?
|
||||
+ if [ "$ret" != "$OCF_NOT_RUNNING" ]; then
|
||||
+ return $ret
|
||||
+ fi
|
||||
+
|
||||
+ # make sure kernel module is loaded
|
||||
+ if [ ! -e /proc/net/vlan ]; then
|
||||
+ error="$(modprobe 8021q 2>&1)"
|
||||
+ if [ "$?" != "0" ]; then
|
||||
+ ocf_log err "Unable to load kernel 8021q driver: $error"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ # generate options
|
||||
+ VLANOPTS=""
|
||||
+
|
||||
+ if [ -n "$OCF_RESKEY_vlan_reorder_hdr" ]; then
|
||||
+ if ocf_is_true "$OCF_RESKEY_vlan_reorder_hdr"; then
|
||||
+ VLANOPTS="reorder_hdr on"
|
||||
+ else
|
||||
+ VLANOPTS="reorder_hdr off"
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "$OCF_RESKEY_vlan_gvrp" ]; then
|
||||
+ if ocf_is_true "$OCF_RESKEY_vlan_gvrp"; then
|
||||
+ VLANOPTS="$VLANOPTS gvrp on"
|
||||
+ else
|
||||
+ VLANOPTS="$VLANOPTS gvrp off"
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "$OCF_RESKEY_vlan_mvrp" ]; then
|
||||
+ if ocf_is_true "$OCF_RESKEY_vlan_mvrp"; then
|
||||
+ VLANOPTS="$VLANOPTS mvrp on"
|
||||
+ else
|
||||
+ VLANOPTS="$VLANOPTS mvrp off"
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "$OCF_RESKEY_vlan_loose_binding" ]; then
|
||||
+ if ocf_is_true "$OCF_RESKEY_vlan_loose_binding"; then
|
||||
+ VLANOPTS="$VLANOPTS loose_binding on"
|
||||
+ else
|
||||
+ VLANOPTS="$VLANOPTS loose_binding off"
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ # create the VLAN
|
||||
+ error="$($IP2UTIL link add link "$OCF_RESKEY_vlan_interface" name "$OCF_RESKEY_vlan_name" type vlan id "$OCF_RESKEY_vlan_id" $VLANOPTS 2>&1)"
|
||||
+ if [ "$?" != "0" ]; then
|
||||
+ ocf_log err "Unable to create VLAN $OCF_RESKEY_vlan_name: $error"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ # set the interface up
|
||||
+ error="$($IP2UTIL link set dev "$OCF_RESKEY_vlan_interface" up 2>&1)"
|
||||
+ if [ "$?" != "0" ]; then
|
||||
+ ocf_log err "Unable to set VLAN $OCF_RESKEY_vlan_interface up: $error"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ # set the vlan up
|
||||
+ error="$($IP2UTIL link set dev "$OCF_RESKEY_vlan_name" up 2>&1)"
|
||||
+ if [ "$?" != "0" ]; then
|
||||
+ ocf_log err "Unable to set VLAN $OCF_RESKEY_vlan_name up: $error"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ error="$(touch "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" 2>&1)"
|
||||
+ if [ "$?" != "0" ]; then
|
||||
+ ocf_log err "Unable to create lock file for VLAN $OCF_RESKEY_vlan_name: $error"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+vlan_stop() {
|
||||
+ vlan_check
|
||||
+ ret=$?
|
||||
+ if [ "$ret" = "$OCF_NOT_RUNNING" ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+ if [ "$ret" != "$OCF_SUCCESS" ]; then
|
||||
+ return $ret
|
||||
+ fi
|
||||
+
|
||||
+ # set vlan down
|
||||
+ error="$($IP2UTIL link set dev "$OCF_RESKEY_vlan_name" down 2>&1)"
|
||||
+ if [ "$?" != "0" ]; then
|
||||
+ ocf_log err "Unable to set VLAN $OCF_RESKEY_vlan_name down: $error"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ # delete vlan
|
||||
+ error="$($IP2UTIL link delete "$OCF_RESKEY_vlan_name" 2>&1)"
|
||||
+ if [ "$?" != "0" ]; then
|
||||
+ ocf_log err "Unable to delete VLAN $OCF_RESKEY_vlan_name: $error"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ error="$(rm -f "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" 2>&1)"
|
||||
+ if [ "$?" != "0" ]; then
|
||||
+ ocf_log err "Unable to remove lock file for VLAN $OCF_RESKEY_vlan_name: $error"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+case $__OCF_ACTION in
|
||||
+ meta-data)
|
||||
+ vlan_meta_data
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+ usage|help)
|
||||
+ vlan_usage
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+esac
|
||||
+
|
||||
+if [ ! -d "$HA_RSCTMP" ]; then
|
||||
+ ocf_log debug "$HA_RSCTMP not found, we are probably being executed manually"
|
||||
+ mkdir -p "$HA_RSCTMP"
|
||||
+fi
|
||||
+
|
||||
+if [ -n "$__OCF_ACTION" ] && ! vlan_validate; then
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+fi
|
||||
+
|
||||
+case $__OCF_ACTION in
|
||||
+ start|stop)
|
||||
+ if ! ocf_is_root; then
|
||||
+ ocf_log err "You must be root for $__OCF_ACTION operation."
|
||||
+ exit $OCF_ERR_PERM
|
||||
+ fi
|
||||
+ ;;
|
||||
+esac
|
||||
+
|
||||
+case $__OCF_ACTION in
|
||||
+ start)
|
||||
+ vlan_start
|
||||
+ ret=$?
|
||||
+ if [ "$ret" != "$OCF_SUCCESS" ]; then
|
||||
+ vlan_force_stop
|
||||
+ fi
|
||||
+ exit $ret
|
||||
+ ;;
|
||||
+ stop)
|
||||
+ vlan_stop
|
||||
+ exit $?
|
||||
+ ;;
|
||||
+ status|monitor)
|
||||
+ vlan_check
|
||||
+ exit $?
|
||||
+ ;;
|
||||
+ validate-all)
|
||||
+ # vlan_validate above does the trick
|
||||
+ ;;
|
||||
+ *)
|
||||
+ vlan_usage
|
||||
+ exit $OCF_ERR_UNIMPLEMENTED
|
||||
+ ;;
|
||||
+esac
|
||||
+# vi:sw=4:ts=8:
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
diff --git a/heartbeat/SAPHana b/heartbeat/SAPHana
|
||||
index f4db17a..412152b 100644
|
||||
--- a/heartbeat/SAPHana
|
||||
+++ b/heartbeat/SAPHana
|
||||
@@ -137,7 +137,7 @@ function saphana_meta_data() {
|
||||
<shortdesc lang="en">Manages two SAP HANA instances in system replication (SR).</shortdesc>
|
||||
<longdesc lang="en">
|
||||
The SAPHanaSR resource agent manages two SAP Hana instances (databases) which are configured
|
||||
-in system replication. This first version is limitted to the scale-up scenario. Scale-Up is
|
||||
+in system replication. This first version is limitted to the scale-up scenario. Scale-Out is
|
||||
not supported in this version.
|
||||
|
||||
Managing the two SAP HANA instances means that the resource agent controls the start/stop of the
|
||||
@@ -231,7 +231,9 @@ The resource agent uses the following four interfaces provided by SAP:
|
||||
<parameter name="SAPHanaFilter" unique="0" required="0">
|
||||
<shortdesc lang="en">Define SAPHana resource agent messages to be printed</shortdesc>
|
||||
<longdesc lang="en">Define SAPHana resource agent messages to be printed.
|
||||
- This parameter should only be set of been requested by SUSE support. The default is sufficient for normal operation.
|
||||
+ This parameter should only be set if requested by support. The default is sufficient for normal operation.
|
||||
+ Values: ra-act-lpa-dec-flow
|
||||
+ You could specify any combination of the above values like "ra-act-flow"
|
||||
</longdesc>
|
||||
<content type="string" default="" />
|
||||
</parameter>
|
||||
@@ -480,7 +482,7 @@ function get_crm_master()
|
||||
# globals: sr_name(w), remoteHost(w), otherNodes(w)
|
||||
# globals: ATTR_NAME_HANA_SYNC_STATUS(w), ATTR_NAME_HANA_CLONE_STATE(w)
|
||||
# globals: DIR_EXECUTABLE(w), SAPSTARTSRV(w), SAPCONTROL(w), DIR_PROFILE(w), SAPSTARTPROFILE(w), LD_LIBRARY_PATH(w), PATH(w)
|
||||
-# globals: LPA_DIRECTORY(w), SIDInstanceName(w), remoteNode(w)
|
||||
+# globals: LPA_DIRECTORY(w), SIDInstanceName(w), remoteNode(w), hdbSrQueryTimeout(w)
|
||||
# saphana_init : Define global variables with default values, if optional parameters are not set
|
||||
#
|
||||
function saphana_init() {
|
||||
@@ -497,6 +499,8 @@ function saphana_init() {
|
||||
super_ocf_log debug "DBG: Used new method to get SID ($SID) and InstanceNr ($InstanceNr)"
|
||||
sid=$(echo "$SID" | tr [:upper:] [:lower:])
|
||||
sidadm="${sid}adm"
|
||||
+ # TODO PRIO3: Do we need a parameter for the RA to be able to adjust hdbSrQueryTimeout?
|
||||
+ hdbSrQueryTimeout=180
|
||||
# DONE: PRIO4: SAPVIRHOST might be different to NODENAME
|
||||
# DONE: PRIO1: ASK: Is the output format of ListInstances fix? Could we take that as an API? Answer: Yes
|
||||
# try to catch: Inst Info : LNX - 42 - lv9041 - 740, patch 36, changelist 1444691
|
||||
@@ -827,7 +831,7 @@ function analyze_hana_sync_status()
|
||||
super_ocf_log err "ACT: Secure store users are missing (see best practice manual how to setup the users)"
|
||||
rc=$OCF_ERR_CONFIGURED
|
||||
fi
|
||||
- hana_sync_status=$(timeout 60 $DIR_EXECUTABLE/hdbsql -a -x -U $secUser $query_state); sqlrc=$?
|
||||
+ hana_sync_status=$(timeout $hdbSrQueryTimeout $DIR_EXECUTABLE/hdbsql -a -x -U $secUser $query_state); sqlrc=$?
|
||||
hana_sync_status=$(echo $hana_sync_status | dequote)
|
||||
super_ocf_log debug "DBG: hdbsql rc=$sqlrc hana_sync_status=\"$hana_sync_status\""
|
||||
if [ "$sqlrc" -eq 0 -a "$hana_sync_status" != "" ]; then
|
||||
@@ -846,10 +850,10 @@ function analyze_hana_sync_status()
|
||||
# TODO: PRIO9: for first we assume there is only ONE secondary site (like ROT)
|
||||
# TODO: PRIO3: should we loop over all cluster nodes fetching their roles-attribute? To minimize sql-queries?
|
||||
#
|
||||
- all_secondary_hosts=$(timeout 60 hdbsql -a -x -U $secUser $query_secondaries ); sqlrc=$?
|
||||
+ all_secondary_hosts=$(timeout $hdbSrQueryTimeout hdbsql -a -x -U $secUser $query_secondaries ); sqlrc=$?
|
||||
all_secondary_hosts=$(echo $all_secondary_hosts | dequote);
|
||||
if [ "$sqlrc" -eq 0 ]; then
|
||||
- all_broken_secondary_hosts=$(timeout 60 hdbsql -a -x -U $secUser $query_failed_secondaries); sqlrc=$?
|
||||
+ all_broken_secondary_hosts=$(timeout $hdbSrQueryTimeout hdbsql -a -x -U $secUser $query_failed_secondaries); sqlrc=$?
|
||||
all_broken_secondary_hosts=$(echo $all_broken_secondary_hosts | dequote);
|
||||
if [ "$sqlrc" -eq 0 ]; then
|
||||
if [ -n "$all_broken_secondary_hosts" ]; then
|
||||
@@ -869,9 +873,9 @@ function analyze_hana_sync_status()
|
||||
fi
|
||||
fi
|
||||
else
|
||||
- # return codes 19: license error -> set SFAIL!
|
||||
case "$sqlrc" in
|
||||
19 )
|
||||
+ # return codes 19: license error -> set SFAIL!
|
||||
# DONE: PRIO1: We should NOT set SFAIL, if HDB is exactly broken now
|
||||
# When HDB breaks during monitor this could prevent a prositive remote failover
|
||||
super_ocf_log warn "ACT: Was not able to fetch HANA SYNC STATUS - set sync status to SFAIL for ALL OTHER cluster hosts"
|
||||
diff --git a/heartbeat/SAPHanaTopology b/heartbeat/SAPHanaTopology
|
||||
index 19fbbb4..082ad29 100644
|
||||
--- a/heartbeat/SAPHanaTopology
|
||||
+++ b/heartbeat/SAPHanaTopology
|
||||
@@ -123,7 +123,7 @@ function sht_meta_data() {
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
<resource-agent name="SAPHanaTopology">
|
||||
- <version>0.149.3</version>
|
||||
+ <version>0.149.4</version>
|
||||
<shortdesc lang="en">Analyzes SAP HANA System Replication Topology.</shortdesc>
|
||||
<longdesc lang="en">This RA analyzes the SAP HANA topology and "sends" all findings via the node status attributes to
|
||||
all nodes in the cluster. These attributes are taken by the SAPHana RA to control the SAP Hana Databases.
|
||||
@@ -172,7 +172,7 @@ SAPHanaTopology scans the output table of landscapeHostConfiguration.py to ident
|
||||
<shortdesc lang="en">Define type of SAPHanaTopology RA messages to be printed</shortdesc>
|
||||
<longdesc lang="en">Define type of SAPHanaTopology RA messages to be printed.
|
||||
Define SAPHana resource agent messages to be printed.
|
||||
- This parameter should only be set of been requested by SUSE support. The default is sufficient for normal operation.
|
||||
+ This parameter should only be set if requested by support. The default is sufficient for normal operation.
|
||||
Values: ra-act-lpa-dec-flow
|
||||
You could specify any combination of the above values like "ra-act-flow"
|
||||
</longdesc>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
diff --git a/heartbeat/SAPHana b/heartbeat/SAPHana
|
||||
index 412152b..1ff6a7d 100644
|
||||
--- a/heartbeat/SAPHana
|
||||
+++ b/heartbeat/SAPHana
|
||||
@@ -356,7 +356,8 @@ function get_hana_attribute()
|
||||
local attr_node=$1
|
||||
local attr_name=$2
|
||||
local attr_store=${3:-reboot} # DONE: PRIO5 get this (optional) from parameter
|
||||
- crm_attribute -N ${attr_node} -G -n "$attr_name" -l $attr_store -q; rc=$?
|
||||
+ local attr_default=${4:-}
|
||||
+ crm_attribute -N ${attr_node} -G -n "$attr_name" -l $attr_store -q -d "$attr_default"; rc=$?
|
||||
super_ocf_log info "FLOW $FUNCNAME rc=$rc"
|
||||
return $rc
|
||||
}
|
||||
@@ -373,9 +374,10 @@ function set_hana_attribute()
|
||||
local attr_value=$2
|
||||
local attr_name=$3
|
||||
local attr_store=${4:-reboot} # DONE: PRIO5 get this (optional) from parameter
|
||||
+ local attr_default=${5:-}
|
||||
local rc=1
|
||||
local attr_old=""
|
||||
- attr_old=$(get_hana_attribute $attr_node $attr_name $attr_store); get_rc=$?
|
||||
+ attr_old=$(get_hana_attribute $attr_node $attr_name $attr_store $attr_default); get_rc=$?
|
||||
if [ "$attr_old" != "$attr_value" ]; then
|
||||
super_ocf_log debug "DBG: SET attribute $attr_name for node ${attr_node} to ${attr_value} former ($attr_old) get_rc=$get_rc "
|
||||
crm_attribute -N $attr_node -v $attr_value -n "$attr_name" -l $attr_store; rc=$?
|
||||
@@ -578,8 +580,8 @@ function saphana_init() {
|
||||
remoteHost=$(get_hana_attribute ${NODENAME} ${ATTR_NAME_HANA_REMOTEHOST[@]});
|
||||
if [ -z "$remoteHost" ]; then
|
||||
if [ ${#otherNodes[@]} -eq 1 ]; then # we are a 2 node cluster, lets assume the other is the remote-host
|
||||
- remoteHost=${otherNodes[0]}
|
||||
- remoteNode=$remoteHost
|
||||
+ remoteNode=${otherNodes[0]}
|
||||
+ remoteHost=$(get_hana_attribute $remoteNode ${ATTR_NAME_HANA_VHOST[@]} "$remoteNode");
|
||||
super_ocf_log debug "DBG: auto-guess remoteHost=$remoteHost"
|
||||
else
|
||||
super_ocf_log debug "DBG: Could not auto-guess remoteHost out of list (${otherNodes[@]})"
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
--- a/heartbeat/SAPHana 2015-05-07 07:47:41.654914103 -0500
|
||||
+++ b/heartbeat/SAPHana 2015-05-07 07:47:06.164755744 -0500
|
||||
@@ -1733,8 +1733,8 @@
|
||||
analyze_hana_sync_status
|
||||
;;
|
||||
esac
|
||||
- rem_role=$(get_hana_attribute ${remoteHost} ${ATTR_NAME_HANA_ROLES[@]})
|
||||
- rem_clone_status=$(get_hana_attribute ${remoteHost} ${ATTR_NAME_HANA_CLONE_STATE[@]})
|
||||
+ rem_role=$(get_hana_attribute ${remoteNode} ${ATTR_NAME_HANA_ROLES[@]})
|
||||
+ rem_clone_status=$(get_hana_attribute ${remoteNode} ${ATTR_NAME_HANA_CLONE_STATE[@]})
|
||||
if [ "$promote_attr" = "DEMOTED" -a "$rem_clone_status" = "PROMOTED" ]; then
|
||||
case "$rem_role" in
|
||||
[234]:P:* ) # dual primary, but other instance marked as PROMOTED by the cluster
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,441 @@
|
|||
diff --git a/heartbeat/SAPHana b/heartbeat/SAPHana
|
||||
index 1913dc3..ed0443b 100644
|
||||
--- a/heartbeat/SAPHana
|
||||
+++ b/heartbeat/SAPHana
|
||||
@@ -48,6 +48,8 @@ HANA_STATE_SECONDARY=1
|
||||
HANA_STATE_STANDALONE=2
|
||||
HANA_STATE_DEFECT=3
|
||||
|
||||
+debug_attributes=0
|
||||
+
|
||||
SH=/bin/sh
|
||||
|
||||
#
|
||||
@@ -132,19 +134,19 @@ function saphana_meta_data() {
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
<resource-agent name="SAPHana">
|
||||
-<version>0.149.4</version>
|
||||
+<version>0.149.7</version>
|
||||
|
||||
<shortdesc lang="en">Manages two SAP HANA instances in system replication (SR).</shortdesc>
|
||||
<longdesc lang="en">
|
||||
The SAPHanaSR resource agent manages two SAP Hana instances (databases) which are configured
|
||||
-in system replication. This first version is limitted to the scale-up scenario. Scale-Out is
|
||||
+in system replication. This first version is limited to the scale-up scenario. Scale-Out is
|
||||
not supported in this version.
|
||||
|
||||
Managing the two SAP HANA instances means that the resource agent controls the start/stop of the
|
||||
instances. In addition the resource agent is able to monitor the SAP HANA databases to check their
|
||||
availability on landscape host configuration level. For this monitoring the resource agent relies on interfaces
|
||||
provided by SAP. A third task of the resource agent is to also check the synchronisation status
|
||||
-of the two SAP HANA databases. If the synchronisation is not "SOK", than the cluster avoids to
|
||||
+of the two SAP HANA databases. If the synchronisation is not "SOK", then the cluster avoids to
|
||||
failover to the secondary side, if the primary fails. This is to improve the data consistency.
|
||||
|
||||
The resource agent uses the following four interfaces provided by SAP:
|
||||
@@ -162,7 +164,7 @@ The resource agent uses the following four interfaces provided by SAP:
|
||||
|
||||
3. hdbnsutil
|
||||
The interface hdbnsutil is used to check the "topology" of the system replication as well as the current configuration
|
||||
- (primary/secondary) of a SAP HANA database instance. A second task of the interface is the posibility to run a
|
||||
+ (primary/secondary) of a SAP HANA database instance. A second task of the interface is the possibility to run a
|
||||
system replication takeover (sr_takeover) or to register a former primary to a newer one (sr_register).
|
||||
|
||||
4. hdbsql / systemReplicationStatus
|
||||
@@ -198,7 +200,7 @@ The resource agent uses the following four interfaces provided by SAP:
|
||||
</parameter>
|
||||
<parameter name="AUTOMATED_REGISTER" unique="0" required="0">
|
||||
<shortdesc lang="en">Define, if a former primary should automatically be registered.</shortdesc>
|
||||
- <longdesc lang="en">The parameter AUTOMATED_REGISTER defines, wether a former primary instance should
|
||||
+ <longdesc lang="en">The parameter AUTOMATED_REGISTER defines, whether a former primary instance should
|
||||
be registered automatically by the resource agent during cluster/resource start, if the DUPLICATE_PRIMARY_TIMEOUT is expired... TDB
|
||||
</longdesc>
|
||||
<content type="boolean" default="false" />
|
||||
@@ -207,7 +209,7 @@ The resource agent uses the following four interfaces provided by SAP:
|
||||
<shortdesc lang="en">Time difference needed between to primary time stamps, if a dual-primary situation occurs</shortdesc>
|
||||
<longdesc lang="en">Time difference needed between to primary time stamps,
|
||||
if a dual-primary situation occurs. If the time difference is
|
||||
- less than the time gap, than the cluster hold one or both instances in a "WAITING" status. This is to give a admin
|
||||
+ less than the time gap, then the cluster hold one or both instances in a "WAITING" status. This is to give an admin
|
||||
a chance to react on a failover. A failed former primary will be registered after the time difference is passed. After
|
||||
this registration to the new primary all data will be overwritten by the system replication.
|
||||
</longdesc>
|
||||
@@ -316,7 +318,7 @@ function remoteHost2remoteNode()
|
||||
# descript: is_clone : find out if we are configured to run in a Master/Slave configuration
|
||||
# rc: 0: it is a clone, 1: it is not a clone
|
||||
#
|
||||
-# DONE: PRIO2: For the first shippment (scale-out) we need to limit the clones to 2
|
||||
+# DONE: PRIO2: For the first shipment (scale-out) we need to limit the clones to 2
|
||||
#
|
||||
function is_clone() {
|
||||
super_ocf_log info "FLOW $FUNCNAME ($*)"
|
||||
@@ -356,8 +358,14 @@ function get_hana_attribute()
|
||||
local attr_node=$1
|
||||
local attr_name=$2
|
||||
local attr_store=${3:-reboot} # DONE: PRIO5 get this (optional) from parameter
|
||||
- local attr_default=${4:-}
|
||||
- crm_attribute -N ${attr_node} -G -n "$attr_name" -l $attr_store -q -d "$attr_default"; rc=$?
|
||||
+ local attr_default=${5:-}
|
||||
+ local attr_val=""
|
||||
+ attr_val=$(crm_attribute -N ${attr_node} -G -n "$attr_name" -l $attr_store -q -d "$attr_default"); rc=$?
|
||||
+ if [ $debug_attributes -eq 1 ]; then
|
||||
+ dstr=$(date)
|
||||
+ echo "$dstr: SAPHana: crm_attribute -N ${attr_node} -G -n \"$attr_name\" -l $attr_store -q --> $attr_val" >> /var/log/fhATTRIBUTE
|
||||
+ fi
|
||||
+ echo "$attr_val"
|
||||
super_ocf_log info "FLOW $FUNCNAME rc=$rc"
|
||||
return $rc
|
||||
}
|
||||
@@ -381,6 +389,10 @@ function set_hana_attribute()
|
||||
if [ "$attr_old" != "$attr_value" ]; then
|
||||
super_ocf_log debug "DBG: SET attribute $attr_name for node ${attr_node} to ${attr_value} former ($attr_old) get_rc=$get_rc "
|
||||
crm_attribute -N $attr_node -v $attr_value -n "$attr_name" -l $attr_store; rc=$?
|
||||
+ if [ $debug_attributes -eq 1 ]; then
|
||||
+ dstr=$(date)
|
||||
+ echo "$dstr: SAPHana: crm_attribute -N $attr_node -v $attr_value -n \"$attr_name\" -l $attr_store" >> /var/log/fhATTRIBUTE
|
||||
+ fi
|
||||
else
|
||||
super_ocf_log debug "DBG: LET attribute $attr_name for node ${attr_node} still be ${attr_value}"
|
||||
rc=0
|
||||
@@ -448,7 +460,7 @@ scoring_crm_master()
|
||||
local roles="$1"
|
||||
local sync="$2"
|
||||
local skip=0
|
||||
- local myScore=-1
|
||||
+ local myScore=""
|
||||
for scan in "${SCORING_TABLE_PREFERRED_SITE_TAKEOVER[@]}"; do
|
||||
if [ $skip -eq 0 ]; then
|
||||
read rolePatt syncPatt score <<< $scan
|
||||
@@ -461,7 +473,10 @@ scoring_crm_master()
|
||||
fi
|
||||
done
|
||||
super_ocf_log debug "DBG: scoring_crm_master adjust score $myScore"
|
||||
- set_crm_master $myScore
|
||||
+ # TODO: PRIO1: DO Not Score, If we did not found our role/sync at this moment - bsc#919925
|
||||
+ if [ -n "$myScore" ]; then
|
||||
+ set_crm_master $myScore
|
||||
+ fi
|
||||
}
|
||||
|
||||
#
|
||||
@@ -1068,6 +1083,27 @@ function saphana_start_primary()
|
||||
case "$lpa_dec" in
|
||||
0 ) # LPA says start-up
|
||||
lpa_advice="start"
|
||||
+ # TODO: PRIO1: We need to do a special handling for remote being a 234-Secondary in SR Status SOK
|
||||
+ # if ( remote_role like [234]:S ) && ( remote_sync_status is SOK|PRIM ) && ( PreferSiteTakeover )
|
||||
+ # then lpa_advice="wait"
|
||||
+ remoteRole=$(get_hana_attribute $remoteNode ${ATTR_NAME_HANA_ROLES[@]})
|
||||
+ remoteSync=$(get_hana_attribute $remoteNode ${ATTR_NAME_HANA_SYNC_STATUS[@]})
|
||||
+ super_ocf_log info "DEC: saphana_primary - checking remoteStatus"
|
||||
+ if ocf_is_true "${PreferSiteTakeover}"; then
|
||||
+ remoteStatus="$remoteRole:$remoteSync"
|
||||
+ case "$remoteStatus" in
|
||||
+ [234]:S:*:SOK | [234]:S:*:PRIM )
|
||||
+ lpa_advice="wait"
|
||||
+ # TODO: PRIO3: Split WAIT into WAIT4TAKEOVER
|
||||
+ super_ocf_log info "DEC: saphana_primary - waiting for secondary to takeover (SOK, PreferSiteTakover)"
|
||||
+ ;;
|
||||
+ * )
|
||||
+ super_ocf_log info "DEC: saphana_primary - remoteStatus is: $remoteStatus"
|
||||
+ ;;
|
||||
+ esac
|
||||
+ else
|
||||
+ super_ocf_log info "DEC: saphana_primary - PreferSiteTakeover set to false"
|
||||
+ fi
|
||||
;;
|
||||
1) # LPA says register!
|
||||
lpa_advice="register"
|
||||
@@ -1075,7 +1111,7 @@ function saphana_start_primary()
|
||||
2) # LPA says wait for second LPT
|
||||
lpa_advice="wait"
|
||||
;;
|
||||
- 3 | 4 ) # LPA says something is completely wrong - FAIL resource
|
||||
+ 3 | 4 ) # LPA says something is completely wrong - FAIL resource # TODO: PRIO1: RC3 for waiting remote side to report lss
|
||||
lpa_advice="fail"
|
||||
;;
|
||||
* ) # LPA failed with an unkonown status - FAIL resource
|
||||
@@ -1098,7 +1134,7 @@ function saphana_start_primary()
|
||||
super_ocf_log info "LPA: landcape: UP, LPA: start ==> keep running"
|
||||
LPTloc=$(date '+%s')
|
||||
lpa_set_lpt $LPTloc
|
||||
- rc=$OCF_SUCCSESS
|
||||
+ rc=$OCF_SUCCESS
|
||||
;;
|
||||
1 ) # landcape says we are down, lets start and adjust scores and return code
|
||||
super_ocf_log info "LPA: landcape: DOWN, LPA: start ==> start instance"
|
||||
@@ -1149,7 +1185,7 @@ function saphana_start_primary()
|
||||
case "$lss" in
|
||||
2 | 3 | 4 ) # as we ARE up we just keep it up
|
||||
# TODO: PRIO3: I now change from "just keep it up to take that down"
|
||||
- # TODO: PRIO3: OCF_SUCCSESS, OCF_NOT_RUNNING or OCF_ERR_xxxx ?
|
||||
+ # TODO: PRIO3: OCF_SUCCESS, OCF_NOT_RUNNING or OCF_ERR_xxxx ?
|
||||
set_crm_master -9000
|
||||
#scoring_crm_master "$my_role" "$my_sync"
|
||||
rc=$OCF_ERR_GENERIC
|
||||
@@ -1159,7 +1195,7 @@ function saphana_start_primary()
|
||||
# TODO: PRIO3: Check, if WAITING is correct here
|
||||
set_hana_attribute ${NODENAME} "WAITING" ${ATTR_NAME_HANA_CLONE_STATE[@]}
|
||||
set_crm_master -9000
|
||||
- rc=$OCF_SUCCSESS
|
||||
+ rc=$OCF_SUCCESS
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
@@ -1277,7 +1313,7 @@ function saphana_start_secondary()
|
||||
super_ocf_log info "ACT: PRIMARY seams to be down now ==> WAITING"
|
||||
set_hana_attribute ${NODENAME} "WAITING" ${ATTR_NAME_HANA_CLONE_STATE[@]}
|
||||
set_crm_master -INFINITY
|
||||
- rc=$OCF_SUCCSESS
|
||||
+ rc=$OCF_SUCCESS
|
||||
fi
|
||||
else
|
||||
lpa_set_lpt 30
|
||||
@@ -1286,7 +1322,7 @@ function saphana_start_secondary()
|
||||
super_ocf_log info "ACT: wait_for_primary_master ==> WAITING"
|
||||
set_hana_attribute ${NODENAME} "WAITING" ${ATTR_NAME_HANA_CLONE_STATE[@]}
|
||||
set_crm_master -INFINITY
|
||||
- rc=$OCF_SUCCSESS
|
||||
+ rc=$OCF_SUCCESS
|
||||
fi
|
||||
super_ocf_log info "FLOW $FUNCNAME rc=$rc"
|
||||
return $rc
|
||||
@@ -1453,7 +1489,8 @@ function lpa_init_lpt() {
|
||||
# LPTlocal > LPTremore ===> rc=0 (start)
|
||||
# LPTRemote > LPTlocal ===> rc=1 (register)
|
||||
# Stalemate in all other cases ==> STALEMATE-HANDLING ===> rc=2 (wait)
|
||||
-# LPTRemote is not initialized (0)
|
||||
+# LPTRemote is not initialized or node not kown in cluster (crm_mon -l) (0)
|
||||
+# TODO: PRIO1: Need to introduce a return-code 3 for remote sides lpa not ready
|
||||
# THEN:
|
||||
# WAIT ==> like STALEMATE-HANDLING ===> rc=2 (wait)
|
||||
#
|
||||
@@ -1625,7 +1662,6 @@ function saphana_monitor_primary()
|
||||
else
|
||||
super_ocf_log info "LPA: Dual primary detected and AUTOMATED_REGISTER='false' ==> WAITING"
|
||||
fi
|
||||
-
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
promoted=0;
|
||||
@@ -1853,11 +1889,11 @@ function saphana_monitor_secondary()
|
||||
scoring_crm_master "$my_role" "$my_sync"
|
||||
;;
|
||||
"SFAIL" ) # This is currently NOT a possible node to promote
|
||||
- super_ocf_log info "DEC: secondary with sync status FAILED ==> EXCLUDE as posible takeover node"
|
||||
+ super_ocf_log info "DEC: secondary with sync status FAILED ==> EXCLUDE as possible takeover node"
|
||||
set_crm_master -INFINITY
|
||||
;;
|
||||
"*" ) # Unknown sync status
|
||||
- super_ocf_log info "DEC: secondary with sync status UKNOWN/UNDEFINED ==> EXCLUDE as posible takeover node"
|
||||
+ super_ocf_log info "DEC: secondary with sync status UKNOWN/UNDEFINED ==> EXCLUDE as possible takeover node"
|
||||
set_crm_master -INFINITY
|
||||
;;
|
||||
esac
|
||||
@@ -1889,10 +1925,12 @@ function saphana_monitor_clone() {
|
||||
local rc=$OCF_ERR_GENERIC
|
||||
local promoted=0
|
||||
local init_attribute=0
|
||||
+ local lpaRc=0
|
||||
+ local mRc=0
|
||||
+ local myMaster=-1
|
||||
|
||||
my_role=$(get_hana_attribute ${NODENAME} ${ATTR_NAME_HANA_ROLES[@]})
|
||||
my_sync=$(get_hana_attribute ${NODENAME} ${ATTR_NAME_HANA_SYNC_STATUS[@]})
|
||||
- lpa_check_lpt_status # TODO: PRIO3 : remove that line later - its only to call lpa_check_lpt_status much more often for checking
|
||||
|
||||
if ocf_is_probe; then
|
||||
super_ocf_log debug "DBG: PROBE ONLY"
|
||||
@@ -1904,6 +1942,16 @@ function saphana_monitor_clone() {
|
||||
#
|
||||
check_for_primary; primary_status=$?
|
||||
if [ $primary_status -eq $HANA_STATE_PRIMARY ]; then
|
||||
+ # FIX: bsc#919925 Leaving Node Maintenance stops HANA Resource Agent
|
||||
+ # TODO: PRIO1: Maybe we need a lpa-check here to
|
||||
+ if ocf_is_probe; then
|
||||
+ myMaster=$(get_crm_master); mRc=$?
|
||||
+ if [ $mRc -ne 0 ]; then
|
||||
+ set_crm_master 5
|
||||
+ elif [ $myMaster -eq -1 ]; then
|
||||
+ set_crm_master 5
|
||||
+ fi
|
||||
+ fi
|
||||
saphana_monitor_primary; rc=$?
|
||||
else
|
||||
if [ $primary_status -eq $HANA_STATE_SECONDARY ]; then
|
||||
diff --git a/heartbeat/SAPHanaTopology b/heartbeat/SAPHanaTopology
|
||||
index 082ad29..1d4887f 100644
|
||||
--- a/heartbeat/SAPHanaTopology
|
||||
+++ b/heartbeat/SAPHanaTopology
|
||||
@@ -14,6 +14,7 @@
|
||||
# Support: linux@sap.com
|
||||
# License: GNU General Public License (GPL)
|
||||
# Copyright: (c) 2014 SUSE Linux Products GmbH
|
||||
+# (c) 2015 SUSE Linux GmbH
|
||||
#
|
||||
# An example usage:
|
||||
# See usage() function below for more details...
|
||||
@@ -39,6 +40,8 @@ HANA_STATE_SECONDARY=1
|
||||
HANA_STATE_STANDALONE=2
|
||||
HANA_STATE_DEFECT=3
|
||||
|
||||
+debug_attributes=0
|
||||
+
|
||||
SH=/bin/sh
|
||||
|
||||
#
|
||||
@@ -123,7 +126,7 @@ function sht_meta_data() {
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
<resource-agent name="SAPHanaTopology">
|
||||
- <version>0.149.4</version>
|
||||
+ <version>0.149.6</version>
|
||||
<shortdesc lang="en">Analyzes SAP HANA System Replication Topology.</shortdesc>
|
||||
<longdesc lang="en">This RA analyzes the SAP HANA topology and "sends" all findings via the node status attributes to
|
||||
all nodes in the cluster. These attributes are taken by the SAPHana RA to control the SAP Hana Databases.
|
||||
@@ -205,7 +208,13 @@ function get_hana_attribute()
|
||||
local attr_node=$1
|
||||
local attr_name=$2
|
||||
local attr_store=${3:-reboot} # DONE: PRIO5 get this (optional) from parameter
|
||||
- crm_attribute -N ${attr_node} -G -n "$attr_name" -l $attr_store -q; rc=$?
|
||||
+ local attr_val=""
|
||||
+ attr_val=$(crm_attribute -N ${attr_node} -G -n "$attr_name" -l $attr_store -q); rc=$?
|
||||
+ if [ $debug_attributes -eq 1 ]; then
|
||||
+ dstr=$(date)
|
||||
+ echo "$dstr: SAPHanaTopology: crm_attribute -N ${attr_node} -G -n \"$attr_name\" -l $attr_store -q --> $attr_val" >> /var/log/fhATTRIBUTE
|
||||
+ fi
|
||||
+ echo "$attr_val"
|
||||
if [ $rc -ne 0 ]; then
|
||||
super_ocf_log debug "DBG: ATTRIBUTE-FAILURE: crm_attribute -N $attr_node -G -n "$attr_name" -l $attr_store -q"
|
||||
fi
|
||||
@@ -230,6 +239,10 @@ function set_hana_attribute()
|
||||
attr_old=$(get_hana_attribute $attr_node $attr_name $attr_store); get_rc=$?
|
||||
if [ "$attr_old" != "$attr_value" ]; then
|
||||
super_ocf_log debug "DBG: SET attribute $attr_name for node ${attr_node} to ${attr_value} former ($attr_old) get_rc=$get_rc "
|
||||
+ if [ $debug_attributes -eq 1 ]; then
|
||||
+ dstr=$(date)
|
||||
+ echo "$dstr: SAPHanaTopology: crm_attribute -N $attr_node -v $attr_value -n \"$attr_name\" -l $attr_store" >> /var/log/fhATTRIBUTE
|
||||
+ fi
|
||||
crm_attribute -N $attr_node -v "$attr_value" -n "$attr_name" -l $attr_store; rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
super_ocf_log debug "DBG: ATTRIBUTE-FAILURE: crm_attribute -N $attr_node -v $attr_value -n "$attr_name" -l $attr_store"
|
||||
@@ -377,18 +390,32 @@ function sht_init() {
|
||||
*openais* ) nodelist=$(crm_node -l | awk '/member/ {print $2}');;
|
||||
*cman* ) nodelist=$(crm_node -l);;
|
||||
esac
|
||||
+ #### SAP-CALL
|
||||
hdbANSWER=$(su - ${sidadm} -c "hdbnsutil -sr_state --sapcontrol=1" 2>/dev/null)
|
||||
super_ocf_log debug "DBG2: hdbANSWER=\$\(su - ${sidadm} -c \"hdbnsutil -sr_state --sapcontrol=1\"\)"
|
||||
site=$(echo "$hdbANSWER" | awk -F= '/site name/ {print $2}')
|
||||
srmode=$(echo "$hdbANSWER" | awk -F= '/mode/ {print $2}')
|
||||
- MAPPING=$(echo "$hdbANSWER" | awk -F[=/] '$1 ~ "mapping" && $3 !~ site { print $4 }' site=$site)
|
||||
+ if [ $debug_attributes -eq 1 ]; then
|
||||
+ dstr=$(date)
|
||||
+ echo "$dstr: SAPHanaTopology: srmode=$srmode" >> /var/log/fhATTRIBUTE
|
||||
+ fi
|
||||
+ MAPPING=$(echo "$hdbANSWER" | awk -F[=/] '$1 == "mapping" && $3 != site { print $4 }' site=$site)
|
||||
super_ocf_log debug "DBG: site=$site, mode=$srmode, MAPPING=$MAPPING"
|
||||
#
|
||||
# filter all non-cluster mappings
|
||||
#
|
||||
- hanaRemoteHost=$(for n1 in $nodelist; do for n2 in $MAPPING; do if [ "$n1" == "$n2" ]; then echo $n1; fi; done; done )
|
||||
- super_ocf_log info "DEC: site=$site, mode=$srmode, MAPPING=$MAPPING, hanaRemoteHost=$hanaRemoteHost"
|
||||
- super_ocf_log debug "DBG: site=$site, mode=$srmode, MAPPING=$MAPPING, hanaRemoteHost=$hanaRemoteHost"
|
||||
+ # DONE: PRIO2: Need mapping between HANA HOSTS not cluster NODES
|
||||
+ local hanaVHost
|
||||
+ hanaRemoteHost=$(for n1 in $nodelist; do
|
||||
+ hanaVHost=$(get_hana_attribute ${n1} ${ATTR_NAME_HANA_VHOST[@]})
|
||||
+ for n2 in $MAPPING; do
|
||||
+ if [ "$hanaVHost" == "$n2" ]; then
|
||||
+ echo $hanaVHost;
|
||||
+ fi;
|
||||
+ done;
|
||||
+ done )
|
||||
+ super_ocf_log info "DEC: site=$site, mode=$srmode, MAPPING=$MAPPING, hanaRemoteHost=$hanaRemoteHost"
|
||||
+ super_ocf_log debug "DBG: site=$site, mode=$srmode, MAPPING=$MAPPING, hanaRemoteHost=$hanaRemoteHost"
|
||||
super_ocf_log info "FLOW $FUNCNAME rc=$OCF_SUCCESS"
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
@@ -422,6 +449,7 @@ function check_for_primary() {
|
||||
super_ocf_log err "ACT: check_for_primary: we didn't expect node_status to be: <$node_status>"
|
||||
dump=$( echo $node_status | hexdump -C );
|
||||
super_ocf_log err "ACT: check_for_primary: we didn't expect node_status to be: DUMP <$dump>"
|
||||
+ #### SAP-CALL
|
||||
node_full_status=$(su - ${sidadm} -c "hdbnsutil -sr_state" 2>/dev/null )
|
||||
node_status=$(echo "$node_full_status" | awk '$1=="mode:" {print $2}')
|
||||
super_ocf_log info "DEC: check_for_primary: loop=$i: node_status=$node_status"
|
||||
@@ -440,6 +468,7 @@ function check_for_primary() {
|
||||
#
|
||||
function start_saphostagent()
|
||||
{
|
||||
+ ### SAP-CALL
|
||||
if [ -x "${HOSTEXEC_PATH}" ]; then
|
||||
${HOSTEXEC_PATH} pf=${HOSTEXEC_PROFILE_PATH}
|
||||
fi
|
||||
@@ -453,9 +482,10 @@ function start_saphostagent()
|
||||
#
|
||||
function stop_saphostagent()
|
||||
{
|
||||
- if [ -x "${HOSTEXEC_PATH}" ]; then
|
||||
- ${HOSTEXEC_PATH} -stop
|
||||
- fi
|
||||
+ ### SAP-CALL
|
||||
+ if [ -x "${HOSTEXEC_PATH}" ]; then
|
||||
+ ${HOSTEXEC_PATH} -stop
|
||||
+ fi
|
||||
}
|
||||
|
||||
#
|
||||
@@ -586,7 +616,7 @@ function sht_validate() {
|
||||
#
|
||||
function sht_start_clone() {
|
||||
super_ocf_log info "FLOW $FUNCNAME ($*)"
|
||||
- local rc=$OCF_NOT_RUNNING
|
||||
+ local rc=$OCF_NOT_RUNNING
|
||||
sht_start; rc=$?
|
||||
return $rc
|
||||
}
|
||||
@@ -666,27 +696,30 @@ function sht_monitor_clone() {
|
||||
# DONE: PRIO1: ASK: Is the output format of ListInstances fix? Could we take that as an API?
|
||||
# try to catch: Inst Info : LNX - 42 - lv9041 - 740, patch 36, changelist 1444691
|
||||
# We rely on the following format: SID is word#4, NR is work#6, vHost is word#8
|
||||
+ #### SAP-CALL
|
||||
vName=$(/usr/sap/hostctrl/exe/saphostctrl -function ListInstances \
|
||||
| awk '$4 == SID && $6=NR { print $8 }' SID=$SID NR=$InstanceNr 2>/dev/null )
|
||||
- super_ocf_log debug "DBG: ListInstances: $(/usr/sap/hostctrl/exe/saphostctrl -function ListInstances)"
|
||||
+ # super_ocf_log debug "DBG: ListInstances: $(/usr/sap/hostctrl/exe/saphostctrl -function ListInstances)"
|
||||
if [ -n "$vName" ]; then
|
||||
set_hana_attribute ${NODENAME} "$vName" ${ATTR_NAME_HANA_VHOST[@]}
|
||||
else
|
||||
vName=$(get_hana_attribute ${NODENAME} ${ATTR_NAME_HANA_VHOST[@]})
|
||||
fi
|
||||
#site=$(get_site_name)
|
||||
+ #### SAP-CALL
|
||||
hanaANSWER=$(su - $sidadm -c "python exe/python_support/landscapeHostConfiguration.py" 2>/dev/null); hanalrc="$?"
|
||||
hanarole=$(echo "$hanaANSWER" | tr -d ' ' | awk -F'|' '$2 == host { printf "%s:%s:%s:%s\n",$10,$11,$12,$13 } ' host=${vName})
|
||||
#if [ -z "$MAPPING" ]; then
|
||||
# super_ocf_log info "ACT: Did not find remote Host at this moment"
|
||||
#fi
|
||||
- # FH TODO PRIO1: TRY TO GET RID OF "ATTR_NAME_HANA_REMOTEHOST"
|
||||
+ # FH TODO PRIO3: TRY TO GET RID OF "ATTR_NAME_HANA_REMOTEHOST"
|
||||
if [ -n "$hanaRemoteHost" ]; then
|
||||
set_hana_attribute ${NODENAME} "$hanaRemoteHost" ${ATTR_NAME_HANA_REMOTEHOST[@]}
|
||||
fi
|
||||
set_hana_attribute ${NODENAME} "$hanalrc:$hanaPrim:$hanarole" ${ATTR_NAME_HANA_ROLES[@]}
|
||||
- set_hana_attribute ${NODENAME} "$site" ${ATTR_NAME_HANA_SITE[@]}
|
||||
- set_hana_attribute ${NODENAME} "$vName" ${ATTR_NAME_HANA_VHOST[@]}
|
||||
+ if [ -n "$site" ]; then
|
||||
+ set_hana_attribute ${NODENAME} "$site" ${ATTR_NAME_HANA_SITE[@]}
|
||||
+ fi
|
||||
case "$hanaPrim" in
|
||||
P ) ;;
|
||||
S ) # only secondary may propargate its sync status
|
||||
@@ -701,7 +734,6 @@ function sht_monitor_clone() {
|
||||
done
|
||||
;;
|
||||
esac
|
||||
- #ATTR_NAME_HANA_STATUS # TODO: PRIO5: For SCALE-OUT: Fill that attribute later
|
||||
super_ocf_log info "FLOW $FUNCNAME rc=$rc"
|
||||
return $rc
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
diff --git a/heartbeat/galera b/heartbeat/galera
|
||||
index 994aad0..d74a70d 100755
|
||||
--- a/heartbeat/galera
|
||||
+++ b/heartbeat/galera
|
||||
@@ -342,6 +342,14 @@ is_readonly()
|
||||
|
||||
master_exists()
|
||||
{
|
||||
+ if [ "$__OCF_ACTION" = "demote" ]; then
|
||||
+ # We don't want to detect master instances during demote.
|
||||
+ # 1. we could be detecting ourselves as being master, which is no longer the case.
|
||||
+ # 2. we could be detecting other master instances that are in the process of shutting down.
|
||||
+ # by not detecting other master instances in "demote" we are deferring this check
|
||||
+ # to the next recurring monitor operation which will be much more accurate
|
||||
+ return 1
|
||||
+ fi
|
||||
# determine if a master instance is already up and is healthy
|
||||
crm_mon --as-xml | grep "resource.*id=\"${OCF_RESOURCE_INSTANCE}\".*role=\"Master\".*active=\"true\".*orphaned=\"false\".*failed=\"false\"" > /dev/null 2>&1
|
||||
return $?
|
||||
@@ -441,20 +449,24 @@ galera_promote()
|
||||
extra_opts="--wsrep-cluster-address=gcomm://"
|
||||
else
|
||||
ocf_exit_reason "Failure, Attempted to promote Master instance of $OCF_RESOURCE_INSTANCE before bootstrap node has been detected."
|
||||
+ clear_last_commit
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
-
|
||||
fi
|
||||
|
||||
- # make sure the read only instance is stopped
|
||||
- mysql_common_stop
|
||||
- rc=$?
|
||||
- if [ $rc -ne $OCF_SUCCESS ] && [ $rc -ne $OCF_NOT_RUNNING ]; then
|
||||
- ocf_exit_reason "Failed to stop read-only galera instance during promotion to Master"
|
||||
- return $rc
|
||||
+ galera_monitor
|
||||
+ if [ $? -eq $OCF_RUNNING_MASTER ]; then
|
||||
+ if ocf_is_true $bootstrap; then
|
||||
+ promote_everyone
|
||||
+ clear_bootstrap_node
|
||||
+ ocf_log info "boostrap node already up, promoting the rest of the galera instances."
|
||||
+ fi
|
||||
+ clear_last_commit
|
||||
+ return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
- sleep 4
|
||||
+ # last commit is no longer relevant once promoted
|
||||
+ clear_last_commit
|
||||
|
||||
mysql_common_prepare_dirs
|
||||
mysql_common_start "$extra_opts"
|
||||
@@ -492,9 +504,6 @@ galera_promote()
|
||||
wait_for_sync
|
||||
fi
|
||||
|
||||
- # last commit is no longer relevant once promoted
|
||||
- clear_last_commit
|
||||
-
|
||||
ocf_log info "Galera started"
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
@@ -510,14 +519,14 @@ galera_demote()
|
||||
|
||||
# if this node was previously a bootstrap node, that is no longer the case.
|
||||
clear_bootstrap_node
|
||||
+ clear_last_commit
|
||||
|
||||
- # start again in slave mode so the new last commit is recorded
|
||||
+ # record last commit by "starting" galera. start is just detection of the last sequence number
|
||||
galera_start
|
||||
}
|
||||
|
||||
galera_start()
|
||||
{
|
||||
- local extra_opts='--read-only=true'
|
||||
local last_commit
|
||||
|
||||
echo $OCF_RESKEY_wsrep_cluster_address | grep -q $NODENAME
|
||||
@@ -526,22 +535,39 @@ galera_start()
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
- mysql_common_prepare_dirs
|
||||
- mysql_common_start "$extra_opts"
|
||||
-
|
||||
- is_readonly
|
||||
- if [ $? -ne 0 ]; then
|
||||
- ocf_exit_reason "Slave instance did not start correctly in read-only mode, Make sure local galera.cnf does not have wsrep_cluster_address set."
|
||||
+ galera_monitor
|
||||
+ if [ $? -eq $OCF_RUNNING_MASTER ]; then
|
||||
+ ocf_exit_reason "master galera instance started outside of the cluster's control"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
- ocf_log info "attempting to detect last commit version"
|
||||
- while [ -z "$last_commit" ]; do
|
||||
- last_commit=$(get_status_variable "wsrep_last_committed")
|
||||
- if [ -z "$last_commit" ]; then
|
||||
- sleep 1
|
||||
+ mysql_common_prepare_dirs
|
||||
+
|
||||
+ ocf_log info "attempting to detect last commit version by reading ${OCF_RESKEY_datadir}/grastate.dat"
|
||||
+ last_commit="$(cat ${OCF_RESKEY_datadir}/grastate.dat | sed -n 's/^seqno.\s*\(.*\)\s*$/\1/p')"
|
||||
+ if [ -z "$last_commit" ] || [ "$last_commit" = "-1" ]; then
|
||||
+ ocf_log info "now attempting to detect last commit version using 'mysqld_safe --wsrep-recover'"
|
||||
+ local tmp=$(mktemp)
|
||||
+ ${OCF_RESKEY_binary} --defaults-file=$OCF_RESKEY_config \
|
||||
+ --pid-file=$OCF_RESKEY_pid \
|
||||
+ --socket=$OCF_RESKEY_socket \
|
||||
+ --datadir=$OCF_RESKEY_datadir \
|
||||
+ --user=$OCF_RESKEY_user \
|
||||
+ --wsrep-recover > $tmp 2>&1
|
||||
+
|
||||
+ last_commit="$(cat $tmp | sed -n 's/.*WSREP\:\s*[R|r]ecovered\s*position.*\:\(.*\)\s*$/\1/p')"
|
||||
+ rm -f $tmp
|
||||
+
|
||||
+ if [ "$last_commit" = "-1" ]; then
|
||||
+ last_commit="0"
|
||||
fi
|
||||
- done
|
||||
+ fi
|
||||
+
|
||||
+ if [ -z "$last_commit" ]; then
|
||||
+ ocf_exit_reason "Unable to detect last known write sequence number"
|
||||
+ clear_last_commit
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
ocf_log info "Last commit version found: $last_commit"
|
||||
|
||||
set_last_commit $last_commit
|
||||
@@ -567,28 +593,40 @@ galera_monitor()
|
||||
if ocf_is_probe; then
|
||||
status_loglevel="info"
|
||||
fi
|
||||
-
|
||||
+
|
||||
mysql_common_status $status_loglevel
|
||||
rc=$?
|
||||
|
||||
- # If status returned an error, return that immediately
|
||||
- if [ $rc -ne $OCF_SUCCESS ]; then
|
||||
+ if [ $rc -eq $OCF_NOT_RUNNING ]; then
|
||||
+ last_commit=$(get_last_commit $node)
|
||||
+ if [ -n "$last_commit" ]; then
|
||||
+ # if last commit is set, this instance is considered started in slave mode
|
||||
+ rc=$OCF_SUCCESS
|
||||
+ master_exists
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ detect_first_master
|
||||
+ else
|
||||
+ # a master instance exists and is healthy, promote this
|
||||
+ # local read only instance
|
||||
+ # so it can join the master galera cluster.
|
||||
+ set_master_score
|
||||
+ fi
|
||||
+ fi
|
||||
+ return $rc
|
||||
+ elif [ $rc -ne $OCF_SUCCESS ]; then
|
||||
return $rc
|
||||
fi
|
||||
|
||||
+ # if we make it here, mysql is running. Check cluster status now.
|
||||
+
|
||||
echo $OCF_RESKEY_wsrep_cluster_address | grep -q $NODENAME
|
||||
if [ $? -ne 0 ]; then
|
||||
ocf_exit_reason "local node <${NODENAME}> is started, but is not a member of the wsrep_cluster_address <${OCF_RESKEY_wsrep_cluster_address}>"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
- is_readonly
|
||||
- if [ $? -ne 0 ]; then
|
||||
- is_primary
|
||||
- if [ $? -ne 0 ]; then
|
||||
- ocf_exit_reason "local node <${NODENAME}> is neither in primary mode nor in read_only mode. Unknown state."
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
+ is_primary
|
||||
+ if [ $? -eq 0 ]; then
|
||||
|
||||
if ocf_is_probe; then
|
||||
# restore master score during probe
|
||||
@@ -596,18 +634,10 @@ galera_monitor()
|
||||
set_master_score
|
||||
fi
|
||||
rc=$OCF_RUNNING_MASTER
|
||||
- else
|
||||
- master_exists
|
||||
- if [ $? -ne 0 ]; then
|
||||
- detect_first_master
|
||||
- else
|
||||
- # a master instance exists and is healthy, promote this
|
||||
- # local read only instance
|
||||
- # so it can join the master galera cluster.
|
||||
- set_master_score
|
||||
- fi
|
||||
+ else
|
||||
+ ocf_exit_reason "local node <${NODENAME}> is started, but not in primary mode. Unknown state."
|
||||
+ rc=$OCF_ERR_GENERIC
|
||||
fi
|
||||
- # TODO look at what is done in the wait script
|
||||
|
||||
return $rc
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
From e0f3e2190cfef76b9d7383a0009b678ed2ef4b17 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Wed, 29 Apr 2015 11:08:55 -0500
|
||||
Subject: [PATCH 1/6] bz1171162-clvmd-opt-fix
|
||||
|
||||
---
|
||||
heartbeat/clvm | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/clvm b/heartbeat/clvm
|
||||
index dcefcca..a1e2bc4 100755
|
||||
--- a/heartbeat/clvm
|
||||
+++ b/heartbeat/clvm
|
||||
@@ -370,7 +370,7 @@ clvmd_start()
|
||||
if ocf_is_true $OCF_RESKEY_with_cmirrord; then
|
||||
start_process $CMIRROR_PATH
|
||||
fi
|
||||
- start_process $DAEMON_PATH $CLVMDOPTS
|
||||
+ start_process $DAEMON_PATH "$CLVMDOPTS"
|
||||
|
||||
# Refresh local cache.
|
||||
#
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
From d828c825c58f2da4b4edd6548c5fd254842a0add Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Wed, 29 Apr 2015 11:15:18 -0500
|
||||
Subject: [PATCH 4/6] nginx agent support
|
||||
|
||||
---
|
||||
heartbeat/nginx | 27 ++++++++++++---------------
|
||||
1 file changed, 12 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/nginx b/heartbeat/nginx
|
||||
index 65fd8f2..fadc545 100755
|
||||
--- a/heartbeat/nginx
|
||||
+++ b/heartbeat/nginx
|
||||
@@ -31,7 +31,7 @@
|
||||
# OCF_RESKEY_status10regex
|
||||
# OCF_RESKEY_status10url
|
||||
# OCF_RESKEY_client
|
||||
-# OCF_RESKEY_testurl
|
||||
+# OCF_RESKEY_test20url
|
||||
# OCF_RESKEY_test20regex
|
||||
# OCF_RESKEY_test20conffile
|
||||
# OCF_RESKEY_test20name
|
||||
@@ -416,7 +416,7 @@ start_nginx() {
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
if
|
||||
- ocf_run $NGINXD -t -c $CONFIGFILE
|
||||
+ ocf_run $NGINXD $OPTIONS -t -c $CONFIGFILE
|
||||
then
|
||||
: Configuration file $CONFIGFILE looks OK
|
||||
else
|
||||
@@ -442,7 +442,7 @@ start_nginx() {
|
||||
[ $ec -eq $OCF_NOT_RUNNING ]
|
||||
then
|
||||
tries=`expr $tries + 1`
|
||||
- ocf_log info "Waiting for $NGINXD -c $CONFIGFILE to come up (try $tries)"
|
||||
+ ocf_log info "Waiting for $NGINXD $OPTIONS -c $CONFIGFILE to come up (try $tries)"
|
||||
true
|
||||
else
|
||||
false
|
||||
@@ -727,25 +727,25 @@ For example, you can set this paramter to "wget" if you prefer that to curl.
|
||||
<content type="string" />
|
||||
</parameter>
|
||||
|
||||
-<parameter name="testurl">
|
||||
+<parameter name="test20url">
|
||||
<longdesc lang="en">
|
||||
URL to test. If it does not start with "http", then it's
|
||||
considered to be relative to the document root address.
|
||||
</longdesc>
|
||||
-<shortdesc lang="en">Level 10 monitor url</shortdesc>
|
||||
+<shortdesc lang="en">Level 20 monitor url</shortdesc>
|
||||
<content type="string" />
|
||||
</parameter>
|
||||
|
||||
<parameter name="test20regex">
|
||||
<longdesc lang="en">
|
||||
-Regular expression to match in the output of testurl.
|
||||
+Regular expression to match in the output of test20url.
|
||||
Case insensitive.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">Level 20 monitor regular expression</shortdesc>
|
||||
<content type="string" />
|
||||
</parameter>
|
||||
|
||||
-<parameter name="testconffile">
|
||||
+<parameter name="test20conffile">
|
||||
<longdesc lang="en">
|
||||
A file which contains a more complex test configuration. Could be useful if
|
||||
you have to check more than one web application or in case sensitive
|
||||
@@ -785,14 +785,11 @@ Extra options to apply when starting nginx.
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
-<action name="start" timeout="40s" />
|
||||
+<action name="start" timeout="60s" />
|
||||
<action name="stop" timeout="60s" />
|
||||
<action name="reload" timeout="40s" />
|
||||
<action name="status" timeout="30s" />
|
||||
-<action name="monitor" timeout="30s" depth="0" interval="10s" />
|
||||
-<action name="monitor" timeout="30s" depth="10" interval="30s" />
|
||||
-<action name="monitor" timeout="45s" depth="20" />
|
||||
-<action name="monitor" timeout="60s" depth="30" />
|
||||
+<action name="monitor" timeout="30s" depth="0" interval="20s" />
|
||||
<action name="meta-data" timeout="5" />
|
||||
<action name="validate-all" timeout="5" />
|
||||
</actions>
|
||||
@@ -838,11 +835,11 @@ validate_all_nginx() {
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
if
|
||||
- ocf_run $NGINXD -t -c $CONFIGFILE
|
||||
+ ocf_run $NGINXD $OPTIONS -t -c $CONFIGFILE
|
||||
then
|
||||
: Cool $NGINXD likes $CONFIGFILE
|
||||
else
|
||||
- ocf_log err "$NGINXD -t -c $CONFIGFILE reported a configuration error."
|
||||
+ ocf_log err "$NGINXD $OPTIONS -t -c $CONFIGFILE reported a configuration error."
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
return $OCF_SUCCESS
|
||||
@@ -859,7 +856,7 @@ then
|
||||
OPTIONS="$OCF_RESKEY_options"
|
||||
CLIENT=${OCF_RESKEY_client}
|
||||
TESTREGEX=${OCF_RESKEY_status10regex:-'Reading: [0-9]+ Writing: [0-9]+ Waiting: [0-9]+'}
|
||||
- TESTURL="$OCF_RESKEY_status10url"
|
||||
+ TESTURL="$OCF_RESKEY_test20url"
|
||||
TESTREGEX20=${OCF_RESKEY_test20regex}
|
||||
TESTCONFFILE="$OCF_RESKEY_test20conffile"
|
||||
TESTNAME="$OCF_RESKEY_test20name"
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,564 @@
|
|||
From d83b9a9394ef69ca2801c84dee46094a224ca654 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Thu, 5 Mar 2015 13:47:58 -0600
|
||||
Subject: [PATCH] redis agent support
|
||||
|
||||
---
|
||||
doc/man/Makefile.am | 1 +
|
||||
heartbeat/Makefile.am | 1 +
|
||||
heartbeat/redis | 519 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 521 insertions(+)
|
||||
create mode 100644 heartbeat/redis
|
||||
|
||||
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
|
||||
index 43d60d9..653e818 100644
|
||||
--- a/doc/man/Makefile.am
|
||||
+++ b/doc/man/Makefile.am
|
||||
@@ -125,6 +125,7 @@ man_MANS = ocf_heartbeat_AoEtarget.7 \
|
||||
ocf_heartbeat_pound.7 \
|
||||
ocf_heartbeat_proftpd.7 \
|
||||
ocf_heartbeat_rabbitmq-cluster.7 \
|
||||
+ ocf_heartbeat_redis.7 \
|
||||
ocf_heartbeat_rsyncd.7 \
|
||||
ocf_heartbeat_rsyslog.7 \
|
||||
ocf_heartbeat_scsi2reservation.7 \
|
||||
diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am
|
||||
index 3bcf2d9..e4ed4fd 100644
|
||||
--- a/heartbeat/Makefile.am
|
||||
+++ b/heartbeat/Makefile.am
|
||||
@@ -105,6 +105,7 @@ ocf_SCRIPTS = ClusterMon \
|
||||
rabbitmq-cluster \
|
||||
Raid1 \
|
||||
Route \
|
||||
+ redis \
|
||||
rsyncd \
|
||||
rsyslog \
|
||||
SAPDatabase \
|
||||
diff --git a/heartbeat/redis b/heartbeat/redis
|
||||
new file mode 100644
|
||||
index 0000000..6b479b2
|
||||
--- /dev/null
|
||||
+++ b/heartbeat/redis
|
||||
@@ -0,0 +1,519 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+. ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs
|
||||
+
|
||||
+: ${OCF_RESKEY_bin:=/usr/bin/redis-server}
|
||||
+: ${OCF_RESKEY_client_bin:=/usr/bin/redis-cli}
|
||||
+: ${OCF_RESKEY_user:=redis}
|
||||
+: ${OCF_RESKEY_rundir:=/var/run/redis}
|
||||
+: ${OCF_RESKEY_pidfile_name:=redis-server.pid}
|
||||
+: ${OCF_RESKEY_socket_name:=redis.sock}
|
||||
+: ${OCF_RESKEY_port:=6379}
|
||||
+
|
||||
+if [ -z "$OCF_RESKEY_config" ]; then
|
||||
+ if [ -f "/etc/redis.conf" ]; then
|
||||
+ OCF_RESKEY_config="/etc/redis.conf"
|
||||
+ else
|
||||
+ OCF_RESKEY_config="/etc/redis/redis.conf"
|
||||
+ fi
|
||||
+fi
|
||||
+
|
||||
+CHECK_SLAVE_STATE=0
|
||||
+
|
||||
+REDIS_SERVER="$OCF_RESKEY_bin"
|
||||
+REDIS_CLIENT="$OCF_RESKEY_client_bin"
|
||||
+REDIS_CONFIG="$OCF_RESKEY_config"
|
||||
+REDIS_USER="$OCF_RESKEY_user"
|
||||
+REDIS_RUNDIR="$OCF_RESKEY_rundir"
|
||||
+REDIS_PIDFILE="$OCF_RESKEY_rundir/$OCF_RESKEY_pidfile_name"
|
||||
+REDIS_SOCKET="$OCF_RESKEY_rundir/$OCF_RESKEY_socket_name"
|
||||
+REDIS_REPLICATION_PORT="$OCF_RESKEY_port"
|
||||
+
|
||||
+function meta_data() {
|
||||
+ cat <<EOI
|
||||
+<?xml version="1.0"?>
|
||||
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
+<resource-agent name="redis">
|
||||
+<version>1.0</version>
|
||||
+
|
||||
+<longdesc lang="en">
|
||||
+Resource agent script for redis server.
|
||||
+
|
||||
+This resource fully supports master/slave replication. The master preference of a node is determined by the 'slave_priority' parameter of the redis config.
|
||||
+When taking the resource from 'unmanaged' to 'managed', the currently active master will be given a priority of 1000 (plus 1 for each active connection). The default 'slave_priority' is 100, so the master will stay master. For a slave to become master after converting the resource to managed, set a slave_priority greater than 1000.
|
||||
+</longdesc>
|
||||
+
|
||||
+<shortdesc lang="en">Redis server</shortdesc>
|
||||
+
|
||||
+<parameters>
|
||||
+<parameter name="bin" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Path to \`redis-server\`
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Path to \`redis-server\`</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_bin}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="client_bin" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Path to \`redis-cli\`
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Path to \`redis-cli\`</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_client_bin}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="config" unique="1" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Path to 'redis.conf'
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Path to 'redis.conf'</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_config}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="user" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+User to run redis as
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Redis user</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_user}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="rundir" unique="1" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Directory to store socket and pid file in
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Redis var/run dir</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_rundir}"/>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="pidfile_name" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+The filename to use for the pidfile. Will be created in the rundir.
|
||||
+Should only be a basename, not a full path.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Redis pidfile name</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_pidfile_name}"/>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="socket_name" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+The filename to use for the socket. Will be crated in the rundir.
|
||||
+Should only be a basename, not a full path.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Redis socket name</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_socket_name}"/>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="port" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Port for replication client to connect to on remote server
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Replication port</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_port}"/>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="wait_last_known_master" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+During redis cluster bootstrap, wait for the last known master to be
|
||||
+promoted before allowing any other instances in the cluster to be
|
||||
+promoted. This lessens the risk of data loss when persistent data
|
||||
+is in use.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Wait for last known master</shortdesc>
|
||||
+<content type="boolean" default="false"/>
|
||||
+</parameter>
|
||||
+</parameters>
|
||||
+
|
||||
+<actions>
|
||||
+<action name="start" timeout="120" />
|
||||
+<action name="stop" timeout="120" />
|
||||
+<action name="status" timeout="60" />
|
||||
+<action name="monitor" depth="0" timeout="60" interval="45" />
|
||||
+<action name="monitor" role="Master" depth="0" timeout="60" interval="20" />
|
||||
+<action name="monitor" role="Slave" depth="0" timeout="60" interval="60" />
|
||||
+<action name="promote" timeout="120" />
|
||||
+<action name="demote" timeout="120" />
|
||||
+<action name="notify" timeout="90" />
|
||||
+<action name="validate-all" timeout="5" />
|
||||
+<action name="meta-data" timeout="5" />
|
||||
+</actions>
|
||||
+</resource-agent>
|
||||
+EOI
|
||||
+}
|
||||
+
|
||||
+INSTANCE_ATTR_NAME=`echo ${OCF_RESOURCE_INSTANCE}| awk -F : '{print $1}'`
|
||||
+CRM_ATTR_REPL_INFO="${HA_SBIN_DIR}/crm_attribute --type crm_config --name ${INSTANCE_ATTR_NAME}_REPL_INFO -s redis_replication"
|
||||
+MASTER_HOST=""
|
||||
+MASTER_ACTIVE_CACHED=""
|
||||
+MASTER_ACTIVE=""
|
||||
+
|
||||
+master_is_active()
|
||||
+{
|
||||
+ if [ -z "$MASTER_ACTIVE_CACHED" ]; then
|
||||
+ # determine if a master instance is already up and is healthy
|
||||
+ crm_mon --as-xml | grep "resource.*id=\"${OCF_RESOURCE_INSTANCE}\".*role=\"Master\".*active=\"true\".*orphaned=\"false\".*failed=\"false\"" > /dev/null 2>&1
|
||||
+ MASTER_ACTIVE=$?
|
||||
+ MASTER_ACTIVE_CACHED="true"
|
||||
+ fi
|
||||
+ return $MASTER_ACTIVE
|
||||
+}
|
||||
+
|
||||
+function set_master()
|
||||
+{
|
||||
+ MASTER_HOST="$1"
|
||||
+ ${CRM_ATTR_REPL_INFO} -v "$1" -q
|
||||
+}
|
||||
+
|
||||
+function last_known_master()
|
||||
+{
|
||||
+ if [ -z "$MASTER_HOST" ]; then
|
||||
+ MASTER_HOST="$(${CRM_ATTR_REPL_INFO} --query -q 2>/dev/null)"
|
||||
+ fi
|
||||
+ echo "$MASTER_HOST"
|
||||
+}
|
||||
+
|
||||
+function crm_master_reboot() {
|
||||
+ "${HA_SBIN_DIR}/crm_master" -l reboot "$@"
|
||||
+}
|
||||
+
|
||||
+function calculate_score()
|
||||
+{
|
||||
+ perf_score="$1"
|
||||
+ connected_clients="$2"
|
||||
+
|
||||
+ if ocf_is_true "$OCF_RESKEY_wait_last_known_master"; then
|
||||
+ # only set perferred score by slave_priority if
|
||||
+ # we are not waiting for the last known master. Otherwise
|
||||
+ # we want the agent to have complete control over the scoring.
|
||||
+ perf_score=""
|
||||
+ connected_clients="0"
|
||||
+ fi
|
||||
+
|
||||
+ if [[ -z "$perf_score" ]]; then
|
||||
+ if [[ "$(last_known_master)" == "$NODENAME" ]]; then
|
||||
+ perf_score=1000
|
||||
+ else
|
||||
+ perf_score=1
|
||||
+ fi
|
||||
+ fi
|
||||
+ perf_score=$(( perf_score + connected_clients ))
|
||||
+ echo "$perf_score"
|
||||
+}
|
||||
+
|
||||
+function set_score()
|
||||
+{
|
||||
+ local score="$1"
|
||||
+
|
||||
+ if ocf_is_true "$OCF_RESKEY_wait_last_known_master" && ! master_is_active; then
|
||||
+ local last_master="$(last_known_master)"
|
||||
+ if [ -n "$last_master" ] && [[ "$last_master" != "$NODENAME" ]]; then
|
||||
+ ocf_log info "Postponing setting master score for ${NODENAME} until last known master instance [${last_master}] is promoted"
|
||||
+ return
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ ocf_log debug "monitor: Setting master score to '$score'"
|
||||
+ crm_master_reboot -v "$score"
|
||||
+}
|
||||
+
|
||||
+function redis_client() {
|
||||
+ ocf_log debug "redis_client: '$REDIS_CLIENT' -s '$REDIS_SOCKET' $@"
|
||||
+ "$REDIS_CLIENT" -s "$REDIS_SOCKET" "$@" | sed 's/\r//'
|
||||
+}
|
||||
+
|
||||
+function simple_status() {
|
||||
+ local pid
|
||||
+
|
||||
+ if ! [ -f "$REDIS_PIDFILE" ]; then
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+
|
||||
+ pid="$(<"$REDIS_PIDFILE")"
|
||||
+ pidof "$REDIS_SERVER" | grep -q "\<$pid\>" || return $OCF_NOT_RUNNING
|
||||
+
|
||||
+ ocf_log debug "monitor: redis-server running under pid $pid"
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+function monitor() {
|
||||
+ local res
|
||||
+
|
||||
+ simple_status
|
||||
+ res=$?
|
||||
+ if (( res != OCF_SUCCESS )); then
|
||||
+ return $res
|
||||
+ fi
|
||||
+
|
||||
+ typeset -A info
|
||||
+ while read line; do
|
||||
+ [[ "$line" == "#"* ]] && continue
|
||||
+ [[ "$line" != *":"* ]] && continue
|
||||
+ IFS=':' read -r key value <<< "$line"
|
||||
+ info[$key]="$value"
|
||||
+ done < <(redis_client info)
|
||||
+ if [[ -z "${info[role]}" ]]; then
|
||||
+ ocf_log err "monitor: Could not get role from \`$REDIS_CLIENT -s $REDIS_SOCKET info\`"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ if ocf_is_ms; then
|
||||
+ # Here we see if a score has already been set.
|
||||
+ # If score isn't set we the redis setting 'slave_priority'.
|
||||
+ # If that isn't set, we default to 1000 for a master, and 1 for slave.
|
||||
+ # We then add 1 for each connected client
|
||||
+ score="$(crm_master_reboot --get-value --quiet 2>/dev/null)"
|
||||
+ if [[ -z "$score" ]]; then
|
||||
+ score=$(calculate_score "${info[slave_priority]}" "${info[connected_clients]}")
|
||||
+ set_score "$score"
|
||||
+ fi
|
||||
+
|
||||
+ if [[ "${info[role]}" == "master" ]]; then
|
||||
+ if ocf_is_probe; then
|
||||
+ set_master "$NODENAME"
|
||||
+ fi
|
||||
+ return $OCF_RUNNING_MASTER
|
||||
+ fi
|
||||
+
|
||||
+ if [ "$CHECK_SLAVE_STATE" -eq 1 ]; then
|
||||
+ if [[ "${info[master_link_status]}" != "up" ]]; then
|
||||
+ ocf_log info "monitor: Slave mode link has not yet been established (link=${info[master_link_status]})"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ if [[ "${info[master_host]}" != "$(last_known_master)" ]]; then
|
||||
+ ocf_log err "monitor: Slave mode current master does not match running master. current=${info[master_host]}, running=$(last_known_master)"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ fi
|
||||
+ fi
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+function start() {
|
||||
+ monitor
|
||||
+ status=$?
|
||||
+
|
||||
+ if (( status == OCF_SUCCESS )) || (( status == OCF_RUNNING_MASTER )); then
|
||||
+ ocf_log info "start: redis is already running"
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ [[ ! -d "$REDIS_RUNDIR" ]] && mkdir -p "$REDIS_RUNDIR"
|
||||
+ chown -R "$REDIS_USER" "$REDIS_RUNDIR"
|
||||
+
|
||||
+ ocf_log info "start: $REDIS_SERVER --daemonize yes --unixsocket '$REDIS_SOCKET' --pidfile '$REDIS_PIDFILE'"
|
||||
+ output="$(su "$REDIS_USER" -s /bin/sh -c "cd '$REDIS_RUNDIR'; exec '$REDIS_SERVER' '$REDIS_CONFIG' --daemonize yes --unixsocket '$REDIS_SOCKET' --pidfile '$REDIS_PIDFILE'" 2>&1)"
|
||||
+
|
||||
+ while true; do
|
||||
+ # wait for redis to start
|
||||
+ typeset -A info
|
||||
+ while read line; do
|
||||
+ [[ "$line" == "#"* ]] && continue
|
||||
+ [[ "$line" != *":"* ]] && continue
|
||||
+ IFS=':' read -r key value <<< "$line"
|
||||
+ info[$key]="$value"
|
||||
+ done < <(redis_client info)
|
||||
+
|
||||
+ if (( info[loading] == 0 )); then
|
||||
+ break
|
||||
+ elif (( info[loading] == 1 )); then
|
||||
+ sleep "${info[loading_eta_seconds]}"
|
||||
+ elif pidof "$REDIS_SERVER" >/dev/null; then
|
||||
+ # unknown error, but the process still exists.
|
||||
+ # This check is mainly because redis daemonizes before it starts listening, causing `redis-cli` to fail
|
||||
+ # See https://github.com/antirez/redis/issues/2368
|
||||
+ # It's possible that the `pidof` will pick up a different redis, but in that case, the start operation will just time out
|
||||
+ sleep 1
|
||||
+ else
|
||||
+ ocf_log err "start: Unknown error waiting for redis to start"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ done
|
||||
+
|
||||
+ ocf_is_ms && demote # pacemaker expects resources to start in slave mode
|
||||
+
|
||||
+ monitor
|
||||
+ status=$?
|
||||
+ if (( status == OCF_SUCCESS )) || (( status == OCF_RUNNING_MASTER )); then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ ocf_log err "start: Unknown error starting redis. output=${output//$'\n'/; }"
|
||||
+ return $status
|
||||
+}
|
||||
+
|
||||
+function stop() {
|
||||
+ monitor
|
||||
+ status=$?
|
||||
+
|
||||
+ if (( status == OCF_NOT_RUNNING )); then
|
||||
+ ocf_log info "stop: redis is already stopped"
|
||||
+ crm_master_reboot -D
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ pid="$(<"$REDIS_PIDFILE")"
|
||||
+ kill -TERM "$pid"
|
||||
+
|
||||
+ while true; do
|
||||
+ simple_status
|
||||
+ status=$?
|
||||
+ if (( status == OCF_NOT_RUNNING )); then
|
||||
+ crm_master_reboot -D
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+ sleep 1
|
||||
+ done
|
||||
+}
|
||||
+
|
||||
+function promote() {
|
||||
+ monitor
|
||||
+ status=$?
|
||||
+
|
||||
+ if (( status == OCF_RUNNING_MASTER )); then
|
||||
+ ocf_log info "promote: Already running as master"
|
||||
+ set_master "$NODENAME"
|
||||
+ return $OCF_SUCCESS
|
||||
+ elif (( status != OCF_SUCCESS )); then
|
||||
+ ocf_log err "promote: Node is not running as a slave"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ redis_client slaveof no one
|
||||
+
|
||||
+ monitor
|
||||
+ status=$?
|
||||
+ if (( status == OCF_RUNNING_MASTER )); then
|
||||
+ set_master "$NODENAME"
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ ocf_log err "promote: Unknown error while promoting to master (status=$status)"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+}
|
||||
+
|
||||
+function demote() {
|
||||
+ local master_host
|
||||
+ local master_port
|
||||
+
|
||||
+ CHECK_SLAVE_STATE=1
|
||||
+ monitor
|
||||
+ status=$?
|
||||
+
|
||||
+ if (( status == OCF_SUCCESS )); then
|
||||
+ ocf_log info "demote: Already running as slave"
|
||||
+ return $OCF_SUCCESS
|
||||
+ elif (( status == OCF_NOT_RUNNING )); then
|
||||
+ ocf_log err "demote: Failed to demote, redis not running."
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+
|
||||
+ master_host="$(last_known_master)"
|
||||
+ master_port="${REDIS_REPLICATION_PORT}"
|
||||
+
|
||||
+ # The elected master has to remain a slave during startup.
|
||||
+ # During this period a placeholder master host is assigned.
|
||||
+ if [ -z "$master_host" ] || [[ "$master_host" == "$NODENAME" ]]; then
|
||||
+ CHECK_SLAVE_STATE=0
|
||||
+ master_host="no-such-master"
|
||||
+ elif ! master_is_active; then
|
||||
+ # no master has been promoted yet. we'll be notified when the
|
||||
+ # master starts.
|
||||
+ CHECK_SLAVE_STATE=0
|
||||
+ master_host="no-such-master"
|
||||
+ fi
|
||||
+
|
||||
+ ocf_log info "demote: Setting master to '$master_host'"
|
||||
+
|
||||
+ redis_client slaveof "$master_host" "$master_port"
|
||||
+
|
||||
+ # wait briefly for the slave to connect to the master
|
||||
+ for (( c=1; c <= 20; c++ ))
|
||||
+ do
|
||||
+ monitor
|
||||
+ status=$?
|
||||
+ if (( status == OCF_SUCCESS )); then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+ sleep 1
|
||||
+ done
|
||||
+
|
||||
+ ocf_log err "demote: Unexpected error setting slave mode (status=$status)"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+}
|
||||
+
|
||||
+function notify() {
|
||||
+ mode="${OCF_RESKEY_CRM_meta_notify_type}-${OCF_RESKEY_CRM_meta_notify_operation}"
|
||||
+ case "$mode" in
|
||||
+ post-demote|post-promote) # change the master
|
||||
+ monitor
|
||||
+ status=$?
|
||||
+ if (( status == OCF_SUCCESS )); then # were a slave
|
||||
+ # calling demote updates the slave's connection
|
||||
+ # to the newly appointed Master instance.
|
||||
+ demote
|
||||
+ fi
|
||||
+ ;;
|
||||
+ esac
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+function validate() {
|
||||
+ if [[ -x "$REDIS_SERVER" ]]; then
|
||||
+ ocf_log err "validate: $REDIS_SERVER does not exist or is not executable"
|
||||
+ return $OCF_ERR_INSTALLED
|
||||
+ fi
|
||||
+ if [[ -x "$REDIS_CLIENT" ]]; then
|
||||
+ ocf_log err "validate: $REDIS_CLIENT does not exist or is not executable"
|
||||
+ return $OCF_ERR_INSTALLED
|
||||
+ fi
|
||||
+ if [[ -f "$REDIS_CONFIG" ]]; then
|
||||
+ ocf_log err "validate: $REDIS_CONFIG does not exist"
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ if ! getent passwd "$REDIS_USER" &>/dev/null; then
|
||||
+ ocf_log err "validate: $REDIS_USER is not a valid user"
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+NODENAME=$(ocf_local_nodename)
|
||||
+
|
||||
+ocf_log debug "action=${1:-$__OCF_ACTION} notify_type=${OCF_RESKEY_CRM_meta_notify_type} notify_operation=${OCF_RESKEY_CRM_meta_notify_operation} master_host=${OCF_RESKEY_CRM_meta_notify_master_uname} slave_host=${OCF_RESKEY_CRM_meta_notify_slave_uname} promote_host=${OCF_RESKEY_CRM_meta_notify_promote_uname} demote_host=${OCF_RESKEY_CRM_meta_notify_demote_uname}; params: bin=${OCF_RESKEY_bin} client_bin=${OCF_RESKEY_client_bin} config=${OCF_RESKEY_config} user=${OCF_RESKEY_user} rundir=${OCF_RESKEY_rundir} port=${OCF_RESKEY_port}"
|
||||
+
|
||||
+case "${1:-$__OCF_ACTION}" in
|
||||
+ status|monitor)
|
||||
+ monitor
|
||||
+ ;;
|
||||
+ start)
|
||||
+ start
|
||||
+ ;;
|
||||
+ stop)
|
||||
+ stop
|
||||
+ ;;
|
||||
+ restart)
|
||||
+ stop && start
|
||||
+ ;;
|
||||
+ promote)
|
||||
+ promote
|
||||
+ ;;
|
||||
+ demote)
|
||||
+ demote
|
||||
+ ;;
|
||||
+ notify)
|
||||
+ notify
|
||||
+ ;;
|
||||
+ meta-data)
|
||||
+ meta_data
|
||||
+ ;;
|
||||
+ validate-all)
|
||||
+ validate
|
||||
+ ;;
|
||||
+ *)
|
||||
+ echo "Usage: $0 {monitor|start|stop|restart|promote|demote|notify|validate-all|meta-data}"
|
||||
+ exit $OCF_ERR_UNIMPLEMENTED
|
||||
+ ;;
|
||||
+esac
|
||||
+status=$?
|
||||
+ocf_log debug "exit_status=$status"
|
||||
+exit $status
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
From b5ac7d0e49bb3b967c3865438067a95606db959a Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Mon, 27 Apr 2015 16:35:03 -0400
|
||||
Subject: [PATCH] High: clvm: activate_vgs option for enable/disable of
|
||||
automatic vg activation
|
||||
|
||||
---
|
||||
heartbeat/clvm | 18 ++++++++++++++++++
|
||||
1 file changed, 18 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/clvm b/heartbeat/clvm
|
||||
index 9d312cc..23e6f9f 100755
|
||||
--- a/heartbeat/clvm
|
||||
+++ b/heartbeat/clvm
|
||||
@@ -60,6 +60,18 @@ Options to clvmd. Refer to clvmd.8 for detailed descriptions.
|
||||
<shortdesc lang="en">Daemon Options</shortdesc>
|
||||
<content type="string" default="-d0"/>
|
||||
</parameter>
|
||||
+
|
||||
+<parameter name="activate_vgs" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Whether or not to activate all cluster volume groups after starting
|
||||
+the clvmd or not. Note that clustered volume groups will always be
|
||||
+deactivated before the clvmd stops regardless of what this option
|
||||
+is set to.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Activate volume groups</shortdesc>
|
||||
+<content type="boolean" default="true"/>
|
||||
+</parameter>
|
||||
+
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -77,6 +89,7 @@ END
|
||||
#######################################################################
|
||||
|
||||
: ${OCF_RESKEY_daemon_options:="-d0"}
|
||||
+: ${OCF_RESKEY_activate_vgs:="true"}
|
||||
|
||||
sbindir=$HA_SBIN_DIR
|
||||
if [ -z $sbindir ]; then
|
||||
@@ -322,6 +335,11 @@ start_process()
|
||||
|
||||
clvmd_activate_all()
|
||||
{
|
||||
+
|
||||
+ if ! ocf_is_true "$OCF_RESKEY_activate_vgs"; then
|
||||
+ ocf_log info "skipping vg activation, activate_vgs is set to $OCF_RESKEY_activate_vgs"
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
# Activate all volume groups by leaving the
|
||||
# "volume group name" parameter empty
|
||||
ocf_run ${LVM_VGCHANGE} -aay
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
From 3c383f3dbb3b5351b25d33aa6e516ab8fc04a26a Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Tue, 28 Apr 2015 11:47:21 -0500
|
||||
Subject: [PATCH] High: IPsrcaddr: return correct error code during stop when
|
||||
misconfigured
|
||||
|
||||
---
|
||||
heartbeat/IPsrcaddr | 45 +++++++++++++++++++++++++++++++--------------
|
||||
1 file changed, 31 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/IPsrcaddr b/heartbeat/IPsrcaddr
|
||||
index 8163c0c..33c5be6 100755
|
||||
--- a/heartbeat/IPsrcaddr
|
||||
+++ b/heartbeat/IPsrcaddr
|
||||
@@ -387,15 +387,27 @@ ip_status() {
|
||||
|
||||
srca_validate_all() {
|
||||
|
||||
- check_binary $AWK
|
||||
- check_binary $IFCONFIG
|
||||
+ if [ -z "$OCF_RESKEY_ipaddress" ]; then
|
||||
+ # usage
|
||||
+ ocf_exit_reason "Please set OCF_RESKEY_ipaddress to the preferred source IP address!"
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+
|
||||
+ if ! [ "x$SYSTYPE" = "xLinux" ]; then
|
||||
+ # checks after this point are only relevant for linux.
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ check_binary $AWK
|
||||
+ check_binary $IFCONFIG
|
||||
|
||||
# The IP address should be in good shape
|
||||
if CheckIP "$ipaddress"; then
|
||||
:
|
||||
else
|
||||
ocf_exit_reason "Invalid IP address [$ipaddress]"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
if ocf_is_probe; then
|
||||
@@ -407,8 +419,9 @@ srca_validate_all() {
|
||||
:
|
||||
else
|
||||
ocf_exit_reason "We are not serving [$ipaddress], hence can not make it a preferred source address"
|
||||
- exit $OCF_ERR_INSTALLED
|
||||
+ return $OCF_ERR_INSTALLED
|
||||
fi
|
||||
+ return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
if
|
||||
@@ -430,18 +443,22 @@ case $1 in
|
||||
;;
|
||||
esac
|
||||
|
||||
-if
|
||||
- [ -z "$OCF_RESKEY_ipaddress" ]
|
||||
-then
|
||||
-# usage
|
||||
- ocf_exit_reason "Please set OCF_RESKEY_ipaddress to the preferred source IP address!"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
-fi
|
||||
-
|
||||
ipaddress="$OCF_RESKEY_ipaddress"
|
||||
|
||||
-if [ "x$SYSTYPE" = "xLinux" ]; then
|
||||
- srca_validate_all
|
||||
+srca_validate_all
|
||||
+rc=$?
|
||||
+if [ $rc -ne $OCF_SUCCESS ]; then
|
||||
+ case $1 in
|
||||
+ # if we can't validate the configuration during a stop, that
|
||||
+ # means the resources isn't configured correctly. There's no way
|
||||
+ # to actually stop the resource in this situation because there's
|
||||
+ # no way it could have even started. Return success here
|
||||
+ # to indicate that the resource is not running, otherwise the
|
||||
+ # stop action will fail causing the node to be fenced just because
|
||||
+ # of a mis configuration.
|
||||
+ stop) exit $OCF_SUCCESS;;
|
||||
+ *) exit $rc;;
|
||||
+ esac
|
||||
fi
|
||||
|
||||
findif_out=`$FINDIF -C`
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
diff -uNr a/doc/man/Makefile.am b/doc/man/Makefile.am
|
||||
--- a/doc/man/Makefile.am 2016-06-06 10:32:26.889194520 +0200
|
||||
+++ b/doc/man/Makefile.am 2016-06-06 10:33:28.850643243 +0200
|
||||
@@ -118,6 +118,7 @@
|
||||
ocf_heartbeat_lxc.7 \
|
||||
ocf_heartbeat_mysql.7 \
|
||||
ocf_heartbeat_mysql-proxy.7 \
|
||||
+ ocf_heartbeat_nagios.7 \
|
||||
ocf_heartbeat_named.7 \
|
||||
ocf_heartbeat_nfsnotify.7 \
|
||||
ocf_heartbeat_nfsserver.7 \
|
||||
diff -uNr a/heartbeat/Makefile.am b/heartbeat/Makefile.am
|
||||
--- a/heartbeat/Makefile.am 2016-06-06 10:32:26.889194520 +0200
|
||||
+++ b/heartbeat/Makefile.am 2016-06-06 10:33:02.418878409 +0200
|
||||
@@ -97,6 +97,7 @@
|
||||
ManageVE \
|
||||
mysql \
|
||||
mysql-proxy \
|
||||
+ nagios \
|
||||
named \
|
||||
nfsnotify \
|
||||
nfsserver \
|
||||
diff -uNr a/heartbeat/nagios b/heartbeat/nagios
|
||||
--- a/heartbeat/nagios 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ b/heartbeat/nagios 2016-06-06 10:33:02.418878409 +0200
|
||||
@@ -0,0 +1,246 @@
|
||||
+#!/bin/sh
|
||||
+#
|
||||
+# License: GNU General Public License (GPL)
|
||||
+# (c) 2015 T.J. Yang, O. Albrigtsen
|
||||
+# and Linux-HA contributors
|
||||
+#
|
||||
+# -----------------------------------------------------------------------------
|
||||
+# O C F R E S O U R C E S C R I P T S P E C I F I C A T I O N
|
||||
+# -----------------------------------------------------------------------------
|
||||
+#
|
||||
+# NAME
|
||||
+# nagios : OCF resource agent script for Nagios Server
|
||||
+#
|
||||
+
|
||||
+# Initialization:
|
||||
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
+
|
||||
+# Defaults
|
||||
+OCF_RESKEY_user_default="nagios"
|
||||
+OCF_RESKEY_group_default="nagios"
|
||||
+OCF_RESKEY_binary_default="/usr/sbin/nagios"
|
||||
+OCF_RESKEY_config_default="/etc/nagios/nagios.cfg"
|
||||
+OCF_RESKEY_log_default="/var/log/nagios/nagios.log"
|
||||
+OCF_RESKEY_retention_default="/var/log/nagios/retention.dat"
|
||||
+OCF_RESKEY_command_default="/var/log/nagios/rw/nagios.cmd"
|
||||
+OCF_RESKEY_pid_default="/var/run/nagios.pid"
|
||||
+
|
||||
+: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}}
|
||||
+: ${OCF_RESKEY_group=${OCF_RESKEY_group_default}}
|
||||
+: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
|
||||
+: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
|
||||
+: ${OCF_RESKEY_log=${OCF_RESKEY_log_default}}
|
||||
+: ${OCF_RESKEY_retention=${OCF_RESKEY_retention_default}}
|
||||
+: ${OCF_RESKEY_command=${OCF_RESKEY_command_default}}
|
||||
+: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
|
||||
+
|
||||
+
|
||||
+nagios_usage() {
|
||||
+ cat <<END
|
||||
+ usage: $0 (start|stop|validate-all|meta-data|help|usage|monitor)
|
||||
+ $0 manages a Nagios instance as an OCF HA resource.
|
||||
+ The 'start' operation starts the instance.
|
||||
+ The 'stop' operation stops the instance.
|
||||
+ The 'status' operation reports whether the instance is running
|
||||
+ The 'monitor' operation reports whether the instance seems to be working
|
||||
+ The 'validate-all' operation reports whether the parameters are valid
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+nagios_meta_data() {
|
||||
+ cat <<END
|
||||
+<?xml version="1.0"?>
|
||||
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
+<resource-agent name="nagios">
|
||||
+<version>0.75</version>
|
||||
+
|
||||
+<longdesc lang="en">OCF Resource script for Nagios 3.x or 4.x. It manages a Nagios instance as a HA resource.</longdesc>
|
||||
+<shortdesc lang="en">Nagios resource agent</shortdesc>
|
||||
+
|
||||
+<parameters>
|
||||
+
|
||||
+<parameter name="user">
|
||||
+ <longdesc lang="en">User running Nagios daemon (for file permissions)</longdesc>
|
||||
+ <shortdesc lang="en">Nagios user</shortdesc>
|
||||
+ <content type="string" default="${OCF_RESKEY_user_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="group">
|
||||
+ <longdesc lang="en">Group running Nagios daemon (for file permissions)</longdesc>
|
||||
+ <shortdesc lang="en">Nagios group</shortdesc>
|
||||
+ <content type="string" default="${OCF_RESKEY_group_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="binary">
|
||||
+ <longdesc lang="en">Location of the Nagios binary</longdesc>
|
||||
+ <shortdesc lang="en">Nagios binary</shortdesc>
|
||||
+ <content type="string" default="${OCF_RESKEY_binary_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="config">
|
||||
+ <longdesc lang="en">Configuration file</longdesc>
|
||||
+ <shortdesc lang="en">Nagios config</shortdesc>
|
||||
+ <content type="string" default="${OCF_RESKEY_config_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="log">
|
||||
+ <longdesc lang="en">Location of the Nagios log</longdesc>
|
||||
+ <shortdesc lang="en">Nagios log</shortdesc>
|
||||
+ <content type="string" default="${OCF_RESKEY_log_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="retention">
|
||||
+ <longdesc lang="en">Location of the Nagios retention file</longdesc>
|
||||
+ <shortdesc lang="en">Nagios retention file</shortdesc>
|
||||
+ <content type="string" default="${OCF_RESKEY_retention_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="command">
|
||||
+ <longdesc lang="en">Location of the Nagios external command file</longdesc>
|
||||
+ <shortdesc lang="en">Nagios command file</shortdesc>
|
||||
+ <content type="string" default="${OCF_RESKEY_command_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="pid">
|
||||
+ <longdesc lang="en">Location of the Nagios pid/lock</longdesc>
|
||||
+ <shortdesc lang="en">Nagios pid file</shortdesc>
|
||||
+ <content type="string" default="${OCF_RESKEY_pid_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+</parameters>
|
||||
+
|
||||
+<actions>
|
||||
+<action name="start" timeout="20" />
|
||||
+<action name="stop" timeout="20" />
|
||||
+<action name="status" timeout="20" />
|
||||
+<action name="monitor" depth="0" timeout="20" interval="10" start-delay="10" />
|
||||
+<action name="validate-all" timeout="20" />
|
||||
+<action name="meta-data" timeout="20" />
|
||||
+</actions>
|
||||
+</resource-agent>
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+
|
||||
+nagios_start() {
|
||||
+ nagios_validate_all
|
||||
+ rc=$?
|
||||
+ if [ $rc -ne 0 ]; then
|
||||
+ return $rc
|
||||
+ fi
|
||||
+
|
||||
+
|
||||
+ # if resource is already running,no need to continue code after this.
|
||||
+ if nagios_monitor; then
|
||||
+ ocf_log info "Nagios is already running"
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ # Remove ${OCF_RESKEY_pid} if it exists
|
||||
+ rm -f ${OCF_RESKEY_pid}
|
||||
+
|
||||
+ ocf_run -q touch ${OCF_RESKEY_log} ${OCF_RESKEY_retention} ${OCF_RESKEY_pid}
|
||||
+ chown ${OCF_RESKEY_user}:${OCF_RESKEY_group} ${OCF_RESKEY_log} ${OCF_RESKEY_retention} ${OCF_RESKEY_pid}
|
||||
+ rm -f ${OCF_RESKEY_command}
|
||||
+ [ -x /sbin/restorecon ] && /sbin/restorecon ${OCF_RESKEY_pid}
|
||||
+ ocf_run -q ${OCF_RESKEY_binary} -d ${OCF_RESKEY_config}
|
||||
+
|
||||
+ while ! nagios_monitor; do
|
||||
+ sleep 1
|
||||
+ done
|
||||
+
|
||||
+ if [ $? -eq "0" ]; then
|
||||
+ ocf_log info "Nagios started"
|
||||
+ return ${OCF_SUCCESS}
|
||||
+ fi
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+nagios_stop() {
|
||||
+ nagios_monitor
|
||||
+ if [ "$?" -ne "$OCF_SUCCESS" ]; then
|
||||
+ # Currently not running. Nothing to do.
|
||||
+ ocf_log info "Resource is already stopped"
|
||||
+ rm -f ${OCF_RESKEY_pid}
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ kill `cat ${OCF_RESKEY_pid}`
|
||||
+
|
||||
+ # Wait for process to stop
|
||||
+ while nagios_monitor; do
|
||||
+ sleep 1
|
||||
+ done
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+nagios_monitor(){
|
||||
+ ocf_pidfile_status ${OCF_RESKEY_pid} > /dev/null 2>&1
|
||||
+ case "$?" in
|
||||
+ 0)
|
||||
+ rc=$OCF_SUCCESS
|
||||
+ ;;
|
||||
+ 1|2)
|
||||
+ rc=$OCF_NOT_RUNNING
|
||||
+ ;;
|
||||
+ *)
|
||||
+ rc=$OCF_ERR_GENERIC
|
||||
+ ;;
|
||||
+ esac
|
||||
+ return $rc
|
||||
+}
|
||||
+
|
||||
+nagios_validate_all(){
|
||||
+ check_binary ${OCF_RESKEY_binary}
|
||||
+
|
||||
+ if [ ! -f ${OCF_RESKEY_config} ]; then
|
||||
+ ocf_exit_reason "Configuration file ${OCF_RESKEY_config} not found"
|
||||
+ return ${OCF_ERR_INSTALLED}
|
||||
+ fi
|
||||
+
|
||||
+ ${OCF_RESKEY_binary} -v ${OCF_RESKEY_config} > /dev/null 2>&1;
|
||||
+ if [ $? -ne "0" ]; then
|
||||
+ ocf_exit_reason "Configuration check failed"
|
||||
+ return ${OCF_ERR_INSTALLED}
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+
|
||||
+# **************************** MAIN SCRIPT ************************************
|
||||
+
|
||||
+# Make sure meta-data and usage always succeed
|
||||
+case $__OCF_ACTION in
|
||||
+meta-data) nagios_meta_data
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+usage|help) nagios_usage
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+esac
|
||||
+
|
||||
+# This OCF agent script need to be run as root user.
|
||||
+if ! ocf_is_root; then
|
||||
+ echo "$0 agent script need to be run as root user."
|
||||
+ ocf_log debug "$0 agent script need to be run as root user."
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
+fi
|
||||
+
|
||||
+# Translate each action into the appropriate function call
|
||||
+case $__OCF_ACTION in
|
||||
+start) nagios_start;;
|
||||
+stop) nagios_stop;;
|
||||
+status|monitor) nagios_monitor;;
|
||||
+validate-all) nagios_validate_all;;
|
||||
+*) nagios_usage
|
||||
+ exit $OCF_ERR_UNIMPLEMENTED
|
||||
+ ;;
|
||||
+esac
|
||||
+rc=$?
|
||||
+
|
||||
+exit $rc
|
||||
+
|
||||
+# End of this script
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
From 3e969507468bea12e1d126b31b222ad248780a80 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Wed, 29 Apr 2015 11:13:26 -0500
|
||||
Subject: [PATCH 3/6] ethmonitor link_statys_only option
|
||||
|
||||
---
|
||||
heartbeat/ethmonitor | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/ethmonitor b/heartbeat/ethmonitor
|
||||
index a447391..d0ec4ef 100755
|
||||
--- a/heartbeat/ethmonitor
|
||||
+++ b/heartbeat/ethmonitor
|
||||
@@ -176,6 +176,14 @@ For infiniband devices, this is the port to monitor.
|
||||
<content type="integer" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="link_status_only">
|
||||
+<longdesc lang="en">
|
||||
+Only report success based on link status. Do not perform RX counter or arping related connectivity tests.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">link status check only</shortdesc>
|
||||
+<content type="boolean" default="false" />
|
||||
+</parameter>
|
||||
+
|
||||
</parameters>
|
||||
<actions>
|
||||
<action name="start" timeout="60s" />
|
||||
@@ -378,6 +386,11 @@ if_check () {
|
||||
return $OCF_NOT_RUNNING
|
||||
fi
|
||||
|
||||
+ # if using link_status_only, skip RX count and arping related tests
|
||||
+ if ocf_is_true "$OCF_RESKEY_link_status_only"; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
# watch for packet counter changes
|
||||
ocf_log debug "watch for packet counter changes"
|
||||
watch_pkt_counter
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,494 @@
|
|||
From 8c92227bce9cc4fe177eea5b2f7c9016e96434f9 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Mon, 29 Jun 2015 13:03:17 -0500
|
||||
Subject: [PATCH 1/3] bz1214360-NovaCompute-update1.patch
|
||||
|
||||
---
|
||||
doc/man/Makefile.am | 1 +
|
||||
heartbeat/Makefile.am | 3 +-
|
||||
heartbeat/NovaCompute | 73 ++++++------
|
||||
heartbeat/NovaEvacuate | 311 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 352 insertions(+), 36 deletions(-)
|
||||
create mode 100755 heartbeat/NovaEvacuate
|
||||
|
||||
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
|
||||
index 42a57fe..d32426b 100644
|
||||
--- a/doc/man/Makefile.am
|
||||
+++ b/doc/man/Makefile.am
|
||||
@@ -74,6 +74,7 @@ man_MANS = ocf_heartbeat_AoEtarget.7 \
|
||||
ocf_heartbeat_ManageRAID.7 \
|
||||
ocf_heartbeat_ManageVE.7 \
|
||||
ocf_heartbeat_NovaCompute.7 \
|
||||
+ ocf_heartbeat_NovaEvacuate.7 \
|
||||
ocf_heartbeat_Pure-FTPd.7 \
|
||||
ocf_heartbeat_Raid1.7 \
|
||||
ocf_heartbeat_Route.7 \
|
||||
diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am
|
||||
index 0bebf97..1034632 100644
|
||||
--- a/heartbeat/Makefile.am
|
||||
+++ b/heartbeat/Makefile.am
|
||||
@@ -52,7 +52,8 @@ send_ua_SOURCES = send_ua.c IPv6addr_utils.c
|
||||
IPv6addr_LDADD = -lplumb $(LIBNETLIBS)
|
||||
send_ua_LDADD = $(LIBNETLIBS)
|
||||
|
||||
-osp_SCRIPTS = NovaCompute
|
||||
+osp_SCRIPTS = NovaCompute \
|
||||
+ NovaEvacuate
|
||||
|
||||
ocf_SCRIPTS = ClusterMon \
|
||||
CTDB \
|
||||
diff --git a/heartbeat/NovaCompute b/heartbeat/NovaCompute
|
||||
index f71abeb..09eee38 100644
|
||||
--- a/heartbeat/NovaCompute
|
||||
+++ b/heartbeat/NovaCompute
|
||||
@@ -107,15 +107,26 @@ Disable shared storage recovery for instances. Use at your own risk!
|
||||
<content type="boolean" default="0" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="evacuation_delay" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+How long to wait for nova to finish evacuating instances elsewhere
|
||||
+before starting nova-compute. Only used when the agent detects
|
||||
+evacuations might be in progress.
|
||||
+
|
||||
+You may need to increase the start timeout when increasing this value.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Delay to allow evacuations time to complete</shortdesc>
|
||||
+<content type="integer" default="120" />
|
||||
+</parameter>
|
||||
+
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
-<action name="start" timeout="120" />
|
||||
+<action name="start" timeout="600" />
|
||||
<action name="stop" timeout="300" />
|
||||
<action name="monitor" timeout="20" interval="10" depth="0"/>
|
||||
<action name="validate-all" timeout="20" />
|
||||
<action name="meta-data" timeout="5" />
|
||||
-<action name="notify" timeout="600" />
|
||||
</actions>
|
||||
</resource-agent>
|
||||
END
|
||||
@@ -132,7 +143,7 @@ sigterm_handler() {
|
||||
|
||||
nova_usage() {
|
||||
cat <<END
|
||||
-usage: $0 {start|stop|monitor|notify|validate-all|meta-data}
|
||||
+usage: $0 {start|stop|monitor|validate-all|meta-data}
|
||||
|
||||
Expects to have a fully populated OCF RA-compliant environment set.
|
||||
END
|
||||
@@ -148,6 +159,26 @@ nova_start() {
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
+ state=$(attrd_updater -p -n evacute -N ${NOVA_HOST} | sed -e 's/.*value=//' | tr -d '"' )
|
||||
+ if [ "x$state" = x ]; then
|
||||
+ : never been fenced
|
||||
+
|
||||
+ elif [ "x$state" = xno ]; then
|
||||
+ : has been evacuated, however it could have been 1s ago
|
||||
+ ocf_log info "Pausing to give evacuations from ${NOVA_HOST} time to complete"
|
||||
+ sleep ${OCF_RESKEY_evacuation_delay}
|
||||
+
|
||||
+ else
|
||||
+ ocf_log info "Waiting for pending evacuations from ${NOVA_HOST}"
|
||||
+ while [ "x$state" != "xno" ]; do
|
||||
+ state=$(attrd_updater -p -n evacute -N ${NOVA_HOST} | sed -e 's/.*value=//' | tr -d '"' )
|
||||
+ sleep 5
|
||||
+ done
|
||||
+
|
||||
+ ocf_log info "Pausing to give evacuations from ${NOVA_HOST} time to complete"
|
||||
+ sleep ${OCF_RESKEY_evacuation_delay}
|
||||
+ fi
|
||||
+
|
||||
export LIBGUESTFS_ATTACH_METHOD=appliance
|
||||
su nova -s /bin/sh -c /usr/bin/nova-compute &
|
||||
|
||||
@@ -212,33 +243,7 @@ nova_monitor() {
|
||||
}
|
||||
|
||||
nova_notify() {
|
||||
- if [ "x${OCF_RESKEY_CRM_meta_notify_operation}" != "xstop" ]; then
|
||||
- return $OCF_SUCCESS
|
||||
- elif [ "x${OCF_RESKEY_CRM_meta_notify_type}" != "xpost" ]; then
|
||||
- return $OCF_SUCCESS
|
||||
- fi
|
||||
-
|
||||
- # Only the first node not stopping performs evacuates for now
|
||||
- # Can we allow all of them to do it? It would make this block much simpler.
|
||||
- for host in ${OCF_RESKEY_CRM_meta_notify_active_uname}; do
|
||||
- for stop in ${OCF_RESKEY_CRM_meta_notify_stop_uname}; do
|
||||
- if [ "$stop" = "$host" ]; then
|
||||
- : $host is one of the nodes that is stopping
|
||||
-
|
||||
- elif [ "x$(echo ${host} | awk -F. '{print $1}')" != "x$(uname -n | awk -F. '{print $1}')" ]; then
|
||||
- : We are not the first non-stopping node
|
||||
- return $OCF_SUCCESS
|
||||
-
|
||||
- else
|
||||
- # Also repeat for any peer NOT in active_uname somehow?
|
||||
- for node in $OCF_RESKEY_CRM_meta_notify_stop_uname; do
|
||||
- ocf_log info "Performing evacuations for $node"
|
||||
- fence_compute ${fence_options} -o reboot -n $node
|
||||
- done
|
||||
- return $OCF_SUCCESS
|
||||
- fi
|
||||
- done
|
||||
- done
|
||||
+ return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
nova_validate() {
|
||||
@@ -246,7 +251,6 @@ nova_validate() {
|
||||
fence_options=""
|
||||
|
||||
check_binary openstack-config
|
||||
- check_binary fence_compute
|
||||
check_binary nova-compute
|
||||
|
||||
if [ ! -f /etc/nova/nova.conf ]; then
|
||||
@@ -337,6 +341,7 @@ nova_validate() {
|
||||
return $rc
|
||||
}
|
||||
|
||||
+: ${OCF_RESKEY_evacuation_delay=120}
|
||||
case $__OCF_ACTION in
|
||||
meta-data) meta_data
|
||||
exit $OCF_SUCCESS
|
||||
@@ -346,12 +351,10 @@ usage|help) nova_usage
|
||||
;;
|
||||
esac
|
||||
|
||||
-nova_validate
|
||||
-
|
||||
case $__OCF_ACTION in
|
||||
-start) nova_start;;
|
||||
+start) nova_validate; nova_start;;
|
||||
stop) nova_stop;;
|
||||
-monitor) nova_monitor;;
|
||||
+monitor) nova_validate; nova_monitor;;
|
||||
notify) nova_notify;;
|
||||
validate-all) exit $OCF_SUCCESS;;
|
||||
*) nova_usage
|
||||
diff --git a/heartbeat/NovaEvacuate b/heartbeat/NovaEvacuate
|
||||
new file mode 100755
|
||||
index 0000000..f9a24f1
|
||||
--- /dev/null
|
||||
+++ b/heartbeat/NovaEvacuate
|
||||
@@ -0,0 +1,311 @@
|
||||
+#!/bin/sh
|
||||
+#
|
||||
+#
|
||||
+# NovaCompute agent manages compute daemons.
|
||||
+#
|
||||
+# Copyright (c) 2015
|
||||
+#
|
||||
+# 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.
|
||||
+#
|
||||
+
|
||||
+#######################################################################
|
||||
+# Initialization:
|
||||
+
|
||||
+###
|
||||
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
+###
|
||||
+
|
||||
+: ${__OCF_ACTION=$1}
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+meta_data() {
|
||||
+ cat <<END
|
||||
+<?xml version="1.0"?>
|
||||
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
+<resource-agent name="NovaEvacuate" version="1.0">
|
||||
+<version>1.0</version>
|
||||
+
|
||||
+<longdesc lang="en">
|
||||
+Facility for tacking a list of compute nodes and reliably evacuating the ones that fence_evacuate has flagged.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Evacuator for OpenStack Nova Compute Server</shortdesc>
|
||||
+
|
||||
+<parameters>
|
||||
+
|
||||
+<parameter name="auth_url" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Authorization URL for connecting to keystone in admin context
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Authorization URL</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="username" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Username for connecting to keystone in admin context
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Username</shortdesc>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="password" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Password for connecting to keystone in admin context
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Password</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="tenant_name" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Tenant name for connecting to keystone in admin context.
|
||||
+Note that with Keystone V3 tenant names are only unique within a domain.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Tenant name</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="endpoint_type" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Nova API location (internal, public or admin URL)
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Nova API location (internal, public or admin URL)</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="no_shared_storage" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Disable shared storage recovery for instances. Use at your own risk!
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Disable shared storage recovery for instances</shortdesc>
|
||||
+<content type="boolean" default="0" />
|
||||
+</parameter>
|
||||
+
|
||||
+</parameters>
|
||||
+
|
||||
+<actions>
|
||||
+<action name="start" timeout="20" />
|
||||
+<action name="stop" timeout="20" />
|
||||
+<action name="monitor" timeout="600" interval="10" depth="0"/>
|
||||
+<action name="validate-all" timeout="20" />
|
||||
+<action name="meta-data" timeout="5" />
|
||||
+</actions>
|
||||
+</resource-agent>
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+# don't exit on TERM, to test that lrmd makes sure that we do exit
|
||||
+trap sigterm_handler TERM
|
||||
+sigterm_handler() {
|
||||
+ ocf_log info "They use TERM to bring us down. No such luck."
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+evacuate_usage() {
|
||||
+ cat <<END
|
||||
+usage: $0 {start|stop|monitor|validate-all|meta-data}
|
||||
+
|
||||
+Expects to have a fully populated OCF RA-compliant environment set.
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+evacuate_stop() {
|
||||
+ rm -f "$statefile"
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+evacuate_start() {
|
||||
+ touch "$statefile"
|
||||
+ # Do not invole monitor here so that the start timeout can be low
|
||||
+ return $?
|
||||
+}
|
||||
+
|
||||
+update_evacuation() {
|
||||
+ attrd_updater -p -n evacute -Q -N ${1} -v ${2}
|
||||
+ arc=$?
|
||||
+ if [ ${arc} != 0 ]; then
|
||||
+ ocf_log warn "Can not set evacuation state of ${1} to ${2}: ${arc}"
|
||||
+ fi
|
||||
+ return ${arc}
|
||||
+}
|
||||
+
|
||||
+handle_evacuations() {
|
||||
+ while [ $# -gt 0 ]; do
|
||||
+ node=$1
|
||||
+ state=$2
|
||||
+ shift; shift;
|
||||
+ need_evacuate=0
|
||||
+
|
||||
+ case $state in
|
||||
+ "") ;;
|
||||
+ no) ocf_log debug "$node is either fine or already handled";;
|
||||
+ yes) need_evacuate=1;;
|
||||
+ *@*)
|
||||
+ where=$(echo $state | awk -F@ '{print $1}')
|
||||
+ when=$(echo $state | awk -F@ '{print $2}')
|
||||
+ now=$(date +%s)
|
||||
+
|
||||
+ if [ $(($now - $when)) -gt 60 ]; then
|
||||
+ ocf_log info "Processing partial evacuation of $node by $where at $when"
|
||||
+ need_evacuate=1
|
||||
+ else
|
||||
+ # Give some time for any in-flight evacuations to either complete or fail
|
||||
+ # Nova won't react well if there are two overlapping requests
|
||||
+ ocf_log info "Deferring processing partial evacuation of $node by $where at $when"
|
||||
+ fi
|
||||
+ ;;
|
||||
+ esac
|
||||
+
|
||||
+ if [ $need_evacuate = 1 ]; then
|
||||
+ found=0
|
||||
+ ocf_log notice "Initiating evacuation of $node"
|
||||
+
|
||||
+ for known in $(fence_compute ${fence_options} -o list | tr -d ','); do
|
||||
+ if [ ${known} = ${node} ]; then
|
||||
+ found=1
|
||||
+ break
|
||||
+ fi
|
||||
+ done
|
||||
+
|
||||
+ if [ $found = 0 ]; then
|
||||
+ ocf_log info "Nova does not know about ${node}"
|
||||
+ # Dont mark as no because perhaps nova is unavailable right now
|
||||
+ continue
|
||||
+ fi
|
||||
+
|
||||
+ update_evacuation ${node} "$(uname -n)@$(date +%s)"
|
||||
+ if [ $? != 0 ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ fence_compute ${fence_options} -o reboot -n $node
|
||||
+ rc=$?
|
||||
+
|
||||
+ if [ $rc = 0 ]; then
|
||||
+ update_evacuation ${node} no
|
||||
+ ocf_log notice "Completed evacuation of $node"
|
||||
+ else
|
||||
+ ocf_log warn "Evacuation of $node failed: $rc"
|
||||
+ update_evacuation ${node} yes
|
||||
+ fi
|
||||
+ fi
|
||||
+ done
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+evacuate_monitor() {
|
||||
+ if [ ! -f "$statefile" ]; then
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+
|
||||
+ handle_evacuations $(attrd_updater -n evacute -A | tr '="' ' ' | awk '{print $4" "$6}')
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+evacuate_validate() {
|
||||
+ rc=$OCF_SUCCESS
|
||||
+ fence_options=""
|
||||
+
|
||||
+ check_binary fence_compute
|
||||
+
|
||||
+ # Is the state directory writable?
|
||||
+ state_dir=$(dirname $statefile)
|
||||
+ touch "$state_dir/$$"
|
||||
+ if [ $? != 0 ]; then
|
||||
+ ocf_exit_reason "Invalid state directory: $state_dir"
|
||||
+ return $OCF_ERR_ARGS
|
||||
+ fi
|
||||
+ rm -f "$state_dir/$$"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_auth_url}" ]; then
|
||||
+ ocf_exit_reason "auth_url not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -k ${OCF_RESKEY_auth_url}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_username}" ]; then
|
||||
+ ocf_exit_reason "username not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -l ${OCF_RESKEY_username}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_password}" ]; then
|
||||
+ ocf_exit_reason "password not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -p ${OCF_RESKEY_password}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_tenant_name}" ]; then
|
||||
+ ocf_exit_reason "tenant_name not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -t ${OCF_RESKEY_tenant_name}"
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_no_shared_storage}" ]; then
|
||||
+ if ocf_is_true "${OCF_RESKEY_no_shared_storage}"; then
|
||||
+ fence_options="${fence_options} --no-shared-storage"
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_endpoint_type}" ]; then
|
||||
+ case ${OCF_RESKEY_endpoint_type} in
|
||||
+ adminURL|publicURL|internalURL) ;;
|
||||
+ *)
|
||||
+ ocf_exit_reason "endpoint_type ${OCF_RESKEY_endpoint_type} not valid. Use adminURL or publicURL or internalURL"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ ;;
|
||||
+ esac
|
||||
+ fence_options="${fence_options} -e ${OCF_RESKEY_endpoint_type}"
|
||||
+ fi
|
||||
+
|
||||
+ if [ $rc != $OCF_SUCCESS ]; then
|
||||
+ exit $rc
|
||||
+ fi
|
||||
+ return $rc
|
||||
+}
|
||||
+
|
||||
+statefile="${HA_RSCTMP}/${OCF_RESOURCE_INSTANCE}.active"
|
||||
+
|
||||
+case $__OCF_ACTION in
|
||||
+start) evacuate_validate; evacuate_start;;
|
||||
+stop) evacuate_stop;;
|
||||
+monitor) evacuate_validate; evacuate_monitor;;
|
||||
+meta-data) meta_data
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+usage|help) evacuate_usage
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+validate-all) exit $OCF_SUCCESS;;
|
||||
+*) evacuate_usage
|
||||
+ exit $OCF_ERR_UNIMPLEMENTED
|
||||
+ ;;
|
||||
+esac
|
||||
+rc=$?
|
||||
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
|
||||
+exit $rc
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
From 4e8c08a6d966f4e3deca03f4f1c4b5904939e640 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Thu, 25 Jun 2015 16:27:47 -0500
|
||||
Subject: [PATCH 2/3] bz1214781-lvm-partial-activation-fix.patch
|
||||
|
||||
---
|
||||
heartbeat/LVM | 26 ++++++++++++++++++++++++--
|
||||
1 file changed, 24 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/LVM b/heartbeat/LVM
|
||||
index 58cbe83..4b9c167 100755
|
||||
--- a/heartbeat/LVM
|
||||
+++ b/heartbeat/LVM
|
||||
@@ -568,8 +568,30 @@ LVM_validate_all() {
|
||||
##
|
||||
VGOUT=`vgck ${VOLUME} 2>&1`
|
||||
if [ $? -ne 0 ]; then
|
||||
- ocf_exit_reason "Volume group [$VOLUME] does not exist or contains error! ${VGOUT}"
|
||||
- exit $OCF_ERR_GENERIC
|
||||
+ # Inconsistency might be due to missing physical volumes, which doesn't
|
||||
+ # automatically mean we should fail. If partial_activation=true then
|
||||
+ # we should let start try to handle it, or if no PVs are listed as
|
||||
+ # "unknown device" then another node may have marked a device missing
|
||||
+ # where we have access to all of them and can start without issue.
|
||||
+ if vgs -o pv_attr --noheadings $OCF_RESKEY_volgrpname 2>/dev/null | grep 'm' > /dev/null 2>&1; then
|
||||
+ if vgs -o pv_name --noheadings $OCF_RESKEY_volgrpname 2>/dev/null | grep 'unknown device' > /dev/null 2>&1; then
|
||||
+ if ! ocf_is_true "$OCF_RESKEY_partial_activation" ; then
|
||||
+ # We are missing devices and cannot activate partially
|
||||
+ ocf_exit_reason "Volume group [$VOLUME] has devices missing. Consider partial_activation=true to attempt to activate partially"
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
+ else
|
||||
+ # We are missing devices but are allowed to activate partially.
|
||||
+ # Assume that caused the vgck failure and carry on
|
||||
+ ocf_log warn "Volume group inconsistency detected with missing device(s) and partial_activation enabled. Proceeding with requested action."
|
||||
+ fi
|
||||
+ fi
|
||||
+ # else the vg is partial but all devices are accounted for, so another
|
||||
+ # node must have marked the device missing. Proceed.
|
||||
+ else
|
||||
+ # vgck failure was for something other than missing devices
|
||||
+ ocf_exit_reason "Volume group [$VOLUME] does not exist or contains error! ${VGOUT}"
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
fi
|
||||
|
||||
##
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
From 72482ca1e117f426378a700a8b1e01443e0fb597 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Thu, 25 Jun 2015 16:30:20 -0500
|
||||
Subject: [PATCH 3/3] bz1223615-apache-includes-fix.patch
|
||||
|
||||
---
|
||||
heartbeat/apache-conf.sh | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/apache-conf.sh b/heartbeat/apache-conf.sh
|
||||
index dc3426f..a3c8930 100644
|
||||
--- a/heartbeat/apache-conf.sh
|
||||
+++ b/heartbeat/apache-conf.sh
|
||||
@@ -24,7 +24,9 @@ apachecat() {
|
||||
function procline() {
|
||||
split($0,a);
|
||||
if( a[1]~/^[Ii]nclude$/ ) {
|
||||
- procinclude(a[2]);
|
||||
+ includedir=a[2];
|
||||
+ gsub("\"","",includedir);
|
||||
+ procinclude(includedir);
|
||||
} else {
|
||||
if( a[1]=="ServerRoot" ) {
|
||||
rootdir=a[2];
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
From 6f8a0aa5c0f6c1e4965e4ce10d62ba83ae9f834e Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Mon, 29 Jun 2015 13:10:42 -0500
|
||||
Subject: [PATCH 3/3] bz1227293-dhcpd-chroot-fix.patch
|
||||
|
||||
---
|
||||
heartbeat/dhcpd | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/dhcpd b/heartbeat/dhcpd
|
||||
index 67b529e..89a9578 100755
|
||||
--- a/heartbeat/dhcpd
|
||||
+++ b/heartbeat/dhcpd
|
||||
@@ -38,6 +38,14 @@ OCF_RESKEY_leases_default="/db/dhcpd.leases"
|
||||
OCF_RESKEY_interface_default=""
|
||||
OCF_RESKEY_includes_default=""
|
||||
|
||||
+# On some systems, the chrooted default is slightly different.
|
||||
+# Lets do our best to support both by default.
|
||||
+if [ ! -d "$OCF_RESKEY_chrooted_path_default" ]; then
|
||||
+ if [ -d "/var/lib/dhcpd" ]; then
|
||||
+ OCF_RESKEY_chrooted_path_default="/var/lib/dhcpd"
|
||||
+ fi
|
||||
+fi
|
||||
+
|
||||
: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
|
||||
: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
|
||||
: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}}
|
||||
@@ -302,7 +310,7 @@ dhcpd_initialize_chroot() {
|
||||
{ ocf_exit_reason "could not copy $i to chroot jail"; return $OCF_ERR_GENERIC; }
|
||||
done
|
||||
|
||||
- libdir=$(basename $(echo /var/lib/dhcp/lib*))
|
||||
+ libdir=$(basename $(echo ${OCF_RESKEY_chrooted_path}/lib*))
|
||||
if test -x /usr/bin/ldd ; then
|
||||
get_ldd_deps()
|
||||
{
|
||||
@@ -327,7 +335,7 @@ dhcpd_initialize_chroot() {
|
||||
done | sort -u`
|
||||
for i in $cplibs ; do
|
||||
if [ -s "$i" ]; then
|
||||
- cp -pL "$i" "/var/lib/dhcp/$libdir/" ||
|
||||
+ cp -pL "$i" "${OCF_RESKEY_chrooted_path}/$libdir/" ||
|
||||
{ ocf_exit_reason "could not copy $i to chroot jail"; return $OCF_ERR_GENERIC; }
|
||||
fi
|
||||
done
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
From c982683ac8c2de64f69c5f47727242c65e00df90 Mon Sep 17 00:00:00 2001
|
||||
From: David Vossel <dvossel@redhat.com>
|
||||
Date: Mon, 29 Jun 2015 13:07:14 -0500
|
||||
Subject: [PATCH 2/3] bz1231032-redis-update.patch
|
||||
|
||||
---
|
||||
heartbeat/redis | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 46 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/redis b/heartbeat/redis
|
||||
index 6b479b2..b63a2b9 100644
|
||||
--- a/heartbeat/redis
|
||||
+++ b/heartbeat/redis
|
||||
@@ -20,6 +20,7 @@ fi
|
||||
|
||||
CHECK_SLAVE_STATE=0
|
||||
|
||||
+REDIS_CHECK_DUMP="/usr/bin/redis-check-dump"
|
||||
REDIS_SERVER="$OCF_RESKEY_bin"
|
||||
REDIS_CLIENT="$OCF_RESKEY_client_bin"
|
||||
REDIS_CONFIG="$OCF_RESKEY_config"
|
||||
@@ -29,6 +30,17 @@ REDIS_PIDFILE="$OCF_RESKEY_rundir/$OCF_RESKEY_pidfile_name"
|
||||
REDIS_SOCKET="$OCF_RESKEY_rundir/$OCF_RESKEY_socket_name"
|
||||
REDIS_REPLICATION_PORT="$OCF_RESKEY_port"
|
||||
|
||||
+if ! [ -f $REDIS_CHECK_DUMP ]; then
|
||||
+ REDIS_CHECK_DUMP="$(which redis-check-dump 2>/dev/null)"
|
||||
+fi
|
||||
+
|
||||
+if [ -f "$REDIS_CONFIG" ]; then
|
||||
+ REDIS_DUMP_DIR="$(cat $REDIS_CONFIG | grep "^\s*dir\s" | awk '{ print $2 }' 2>/dev/null)"
|
||||
+ REDIS_DUMP_FILE="$(cat $REDIS_CONFIG | grep "^\s*dbfilename\s" | awk '{ print $2 }' 2>/dev/null)"
|
||||
+fi
|
||||
+: ${REDIS_DUMP_DIR:=/var/lib/redis/}
|
||||
+: ${REDIS_DUMP_FILE:=dump.rdb}
|
||||
+
|
||||
function meta_data() {
|
||||
cat <<EOI
|
||||
<?xml version="1.0"?>
|
||||
@@ -289,6 +301,14 @@ function monitor() {
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
+function check_dump_file()
|
||||
+{
|
||||
+ if ! have_binary "$REDIS_CHECK_DUMP"; then
|
||||
+ return 0
|
||||
+ fi
|
||||
+ $REDIS_CHECK_DUMP ${REDIS_DUMP_DIR}/${REDIS_DUMP_FILE} 2>&1
|
||||
+}
|
||||
+
|
||||
function start() {
|
||||
monitor
|
||||
status=$?
|
||||
@@ -301,6 +321,16 @@ function start() {
|
||||
[[ ! -d "$REDIS_RUNDIR" ]] && mkdir -p "$REDIS_RUNDIR"
|
||||
chown -R "$REDIS_USER" "$REDIS_RUNDIR"
|
||||
|
||||
+ # check for 0 byte database dump file. This is an unrecoverable start
|
||||
+ # condition that we can avoid by deleting the 0 byte database file.
|
||||
+ if [ -f "${REDIS_DUMP_DIR}/${REDIS_DUMP_FILE}" ]; then
|
||||
+ local size="$(stat --format "%s" ${REDIS_DUMP_DIR}/${REDIS_DUMP_FILE})"
|
||||
+ if [ "$?" -eq "0" ] && [ "$size" -eq "0" ]; then
|
||||
+ ocf_log notice "Detected 0 byte ${REDIS_DUMP_FILE}, deleting zero length file to avoid start failure."
|
||||
+ rm -f ${REDIS_DUMP_DIR}/${REDIS_DUMP_FILE}
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
ocf_log info "start: $REDIS_SERVER --daemonize yes --unixsocket '$REDIS_SOCKET' --pidfile '$REDIS_PIDFILE'"
|
||||
output="$(su "$REDIS_USER" -s /bin/sh -c "cd '$REDIS_RUNDIR'; exec '$REDIS_SERVER' '$REDIS_CONFIG' --daemonize yes --unixsocket '$REDIS_SOCKET' --pidfile '$REDIS_PIDFILE'" 2>&1)"
|
||||
|
||||
@@ -325,7 +355,8 @@ function start() {
|
||||
# It's possible that the `pidof` will pick up a different redis, but in that case, the start operation will just time out
|
||||
sleep 1
|
||||
else
|
||||
- ocf_log err "start: Unknown error waiting for redis to start"
|
||||
+ check_output="$(check_dump_file)"
|
||||
+ ocf_log err "start: Unknown error waiting for redis to start. redis-check-dump output=${check_output//$'\n'/; }"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
done
|
||||
@@ -338,7 +369,8 @@ function start() {
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
- ocf_log err "start: Unknown error starting redis. output=${output//$'\n'/; }"
|
||||
+ check_output="$(check_dump_file)"
|
||||
+ ocf_log err "start: Unknown error starting redis. redis-server output=${output//$'\n'/; } redis-check-dump output=${check_output//$'\n'/; }"
|
||||
return $status
|
||||
}
|
||||
|
||||
@@ -427,14 +459,23 @@ function demote() {
|
||||
|
||||
redis_client slaveof "$master_host" "$master_port"
|
||||
|
||||
- # wait briefly for the slave to connect to the master
|
||||
- for (( c=1; c <= 20; c++ ))
|
||||
- do
|
||||
+ # Wait forever for the slave to connect to the master and finish the
|
||||
+ # sync. Timeout is controlled by Pacemaker "op start timeout=XX".
|
||||
+ #
|
||||
+ # hint: redis master_link_status will only come "up" when
|
||||
+ # the SYNC with the master has completed.
|
||||
+ # This can take an arbitraty time (data) and should
|
||||
+ # only be parametrized by the start operation timeout
|
||||
+ # by the administrator, not by this resource agent code
|
||||
+ while true; do
|
||||
+ # Wait infinite if replication is syncing
|
||||
+ # Then start/demote operation timeout determines timeout
|
||||
monitor
|
||||
status=$?
|
||||
if (( status == OCF_SUCCESS )); then
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
+
|
||||
sleep 1
|
||||
done
|
||||
|
||||
--
|
||||
1.8.4.2
|
||||
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
diff --git a/heartbeat/oracle b/heartbeat/oracle
|
||||
index 5ecc2f3..c629eb6 100755
|
||||
--- a/heartbeat/oracle
|
||||
+++ b/heartbeat/oracle
|
||||
@@ -27,6 +27,9 @@
|
||||
# OCF_RESKEY_ipcrm (optional; defaults to "instance")
|
||||
# OCF_RESKEY_clear_backupmode (optional; default to "false")
|
||||
# OCF_RESKEY_shutdown_method (optional; default to "checkpoint/abort")
|
||||
+# OCF_RESKEY_monuser (optional; defaults to "OCFMON")
|
||||
+# OCF_RESKEY_monpassword (optional; defaults to "OCFMON")
|
||||
+# OCF_RESKEY_monprofile (optional; defaults to "OCFMONPROFILE")
|
||||
#
|
||||
# Initialization:
|
||||
|
||||
@@ -56,6 +59,11 @@ oracle_usage() {
|
||||
!
|
||||
}
|
||||
|
||||
+# Defaults
|
||||
+OCF_RESKEY_monuser_default="OCFMON"
|
||||
+OCF_RESKEY_monpassword_default="OCFMON"
|
||||
+OCF_RESKEY_monprofile_default="OCFMONPROFILE"
|
||||
+
|
||||
oracle_meta_data() {
|
||||
cat <<END
|
||||
<?xml version="1.0"?>
|
||||
@@ -100,6 +108,39 @@ If this does not work for you, just set it explicitely.
|
||||
<content type="string" default="" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="monuser" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Monitoring user name. Every connection as
|
||||
+sysdba is logged in an audit log. This can
|
||||
+result in a large number of new files created.
|
||||
+A new user is created (if it doesn't exist) in
|
||||
+the start action and subsequently used in monitor.
|
||||
+It should have very limited rights. Make sure
|
||||
+that the password for this user does not expire.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">monuser</shortdesc>
|
||||
+<content type="string" default="$OCF_RESKEY_monuser_default" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="monpassword" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Password for the monitoring user. Make sure
|
||||
+that the password for this user does not expire.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">monpassword</shortdesc>
|
||||
+<content type="string" default="$OCF_RESKEY_monpassword_default" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="monprofile" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Profile used by the monitoring user. If the
|
||||
+profile does not exist, it will be created
|
||||
+with a non-expiring password.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">monprofile</shortdesc>
|
||||
+<content type="string" default="$OCF_RESKEY_monprofile_default" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="ipcrm" unique="0">
|
||||
<longdesc lang="en">
|
||||
Sometimes IPC objects (shared memory segments and semaphores)
|
||||
@@ -216,7 +257,7 @@ execsql() {
|
||||
if [ "$US" = "$ORACLE_OWNER" ]; then
|
||||
sqlplus -S /nolog
|
||||
else
|
||||
- su - $ORACLE_OWNER -c ". $ORA_ENVF; sqlplus -S /nolog"
|
||||
+ su - $ORACLE_OWNER -s /bin/sh -c ". $ORA_ENVF; sqlplus -S /nolog"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -250,7 +291,7 @@ dbasql() {
|
||||
runsql "connect / as sysdba" $*
|
||||
}
|
||||
monsql() {
|
||||
- runsql "connect $MONUSR/$MONUSR" $*
|
||||
+ runsql "connect $MONUSR/\"$MONPWD\"" $*
|
||||
}
|
||||
# use dbasql_one if the query should result in a single line output
|
||||
# at times people stuff commands in oracle .profile
|
||||
@@ -325,22 +366,73 @@ getipc() {
|
||||
echo "oradebug tracefile_name"
|
||||
echo "oradebug ipc"
|
||||
}
|
||||
+show_mon_profile() {
|
||||
+ echo "select PROFILE from dba_profiles where PROFILE='$MONPROFILE';"
|
||||
+}
|
||||
+mk_mon_profile() {
|
||||
+ cat<<EOF
|
||||
+create profile $MONPROFILE limit FAILED_LOGIN_ATTEMPTS UNLIMITED PASSWORD_LIFE_TIME UNLIMITED;
|
||||
+EOF
|
||||
+}
|
||||
show_mon_user() {
|
||||
echo "select USERNAME, ACCOUNT_STATUS from dba_users where USERNAME='$MONUSR';"
|
||||
}
|
||||
mk_mon_user() {
|
||||
cat<<EOF
|
||||
-create user $MONUSR identified by $MONUSR;
|
||||
+create user $MONUSR identified by "$MONPWD" profile $MONPROFILE;
|
||||
grant create session to $MONUSR;
|
||||
grant select on v_\$instance to $MONUSR;
|
||||
EOF
|
||||
}
|
||||
-check_mon_user() {
|
||||
+show_mon_user_profile() {
|
||||
+ echo "select PROFILE from dba_users where USERNAME='$MONUSR';"
|
||||
+}
|
||||
+set_mon_user_profile() {
|
||||
+ echo "alter user $MONUSR profile $MONPROFILE;"
|
||||
+}
|
||||
+reset_mon_user_password() {
|
||||
+ echo "alter user $MONUSR identified by $MONPWD;"
|
||||
+}
|
||||
+check_mon_profile() {
|
||||
local output
|
||||
- dbasql show_mon_user | grep -w "^$MONUSR" >/dev/null &&
|
||||
+ output=`dbasql show_mon_profile`
|
||||
+ if echo "$output" | grep -iw "^$MONPROFILE" >/dev/null; then
|
||||
return 0
|
||||
+ fi
|
||||
+ output=`dbasql mk_mon_profile show_mon_profile`
|
||||
+ if echo "$output" | grep -iw "^$MONPROFILE" >/dev/null; then
|
||||
+ return 0
|
||||
+ else
|
||||
+ ocf_log err "could not create $MONPROFILE oracle profile"
|
||||
+ ocf_log err "sqlplus output: $output"
|
||||
+ return 1
|
||||
+ fi
|
||||
+}
|
||||
+check_mon_user() {
|
||||
+ local output
|
||||
+ local output2
|
||||
+
|
||||
+ output=`dbasql show_mon_user`
|
||||
+ if echo "$output" | grep -iw "^$MONUSR" >/dev/null; then
|
||||
+ if echo "$output" | grep -w "EXPIRED" >/dev/null; then
|
||||
+ dbasql reset_mon_user_password
|
||||
+ fi
|
||||
+ output=`dbasql show_mon_user_profile`
|
||||
+ if echo "$output" | grep -iw "^$MONPROFILE" >/dev/null; then
|
||||
+ return 0
|
||||
+ else
|
||||
+ output=`dbasql set_mon_user_profile`
|
||||
+ output2=`dbasql show_mon_user_profile`
|
||||
+ if echo "$output2" | grep -iw "^$MONPROFILE" >/dev/null; then
|
||||
+ return 0
|
||||
+ fi
|
||||
+ ocf_log err "could not set profile for $MONUSR oracle user"
|
||||
+ ocf_log err "sqlplus output: $output( $output2 )"
|
||||
+ return 1
|
||||
+ fi
|
||||
+ fi
|
||||
output=`dbasql mk_mon_user show_mon_user`
|
||||
- if echo "$output" | grep -w "^$MONUSR" >/dev/null; then
|
||||
+ if echo "$output" | grep -iw "^$MONUSR" >/dev/null; then
|
||||
return 0
|
||||
else
|
||||
ocf_log err "could not create $MONUSR oracle user"
|
||||
@@ -417,7 +509,7 @@ ipcdesc() {
|
||||
}
|
||||
rmipc() {
|
||||
local what=$1 id=$2
|
||||
- ipcs -$what | filteroraipc | grep -w $id >/dev/null 2>&1 ||
|
||||
+ ipcs -$what | filteroraipc | grep -iw $id >/dev/null 2>&1 ||
|
||||
return
|
||||
ocf_log info "Removing `ipcdesc $what` $id."
|
||||
ipcrm -$what $id
|
||||
@@ -447,6 +539,8 @@ is_proc_running() {
|
||||
# instance in OPEN state?
|
||||
instance_live() {
|
||||
local status=`monsql_one dbstat`
|
||||
+ [ "$status" = OPEN ] && return 0
|
||||
+ status=`dbasql_one dbstat`
|
||||
if [ "$status" = OPEN ]; then
|
||||
return 0
|
||||
else
|
||||
@@ -473,7 +567,7 @@ ora_cleanup() {
|
||||
}
|
||||
|
||||
oracle_getconfig() {
|
||||
- ora_common_getconfig "$OCF_RESKEY_sid" "$OCF_RESKEY_home" "$OCF_RESKEY_user" "$OCF_RESKEY_tns_admin"
|
||||
+ ora_common_getconfig "$OCF_RESKEY_sid" "$OCF_RESKEY_home" "$OCF_RESKEY_user"
|
||||
|
||||
clear_backupmode=${OCF_RESKEY_clear_backupmode:-"false"}
|
||||
shutdown_method=${OCF_RESKEY_shutdown_method:-"checkpoint/abort"}
|
||||
@@ -493,7 +587,7 @@ oracle_getconfig() {
|
||||
oracle_start() {
|
||||
local status output
|
||||
if is_proc_running; then
|
||||
- status="`monsql_one dbstat`"
|
||||
+ status="`dbasql_one dbstat`"
|
||||
case "$status" in
|
||||
"OPEN")
|
||||
: nothing to be done, we can leave right now
|
||||
@@ -541,6 +635,11 @@ oracle_start() {
|
||||
fi
|
||||
output=`dbasql dbopen`
|
||||
|
||||
+ # check/create the monitor profile
|
||||
+ if ! check_mon_profile; then
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
# check/create the monitor user
|
||||
if ! check_mon_user; then
|
||||
return $OCF_ERR_GENERIC
|
||||
@@ -650,7 +749,12 @@ show_procs() {
|
||||
proc_pids() { show_procs | awk '{print $1}'; }
|
||||
PROCS_CLEANUP_TIME="30"
|
||||
|
||||
-MONUSR="OCFMON"
|
||||
+MONUSR=${OCF_RESKEY_monuser:-$OCF_RESKEY_monuser_default}
|
||||
+MONPWD=${OCF_RESKEY_monpassword:-$OCF_RESKEY_monpassword_default}
|
||||
+MONPROFILE=${OCF_RESKEY_monprofile_default:-$OCF_RESKEY_monprofile_default}
|
||||
+
|
||||
+MONUSR=$(echo $MONUSR | awk '{print toupper($0)}')
|
||||
+MONPROFILE=$(echo $MONPROFILE | awk '{print toupper($0)}')
|
||||
OCF_REQUIRED_PARAMS="sid"
|
||||
OCF_REQUIRED_BINARIES="sqlplus"
|
||||
ocf_rarun $*
|
||||
diff --git a/heartbeat/oralsnr b/heartbeat/oralsnr
|
||||
index 2409017..a91eeab 100755
|
||||
--- a/heartbeat/oralsnr
|
||||
+++ b/heartbeat/oralsnr
|
||||
@@ -158,7 +158,7 @@ runasdba() {
|
||||
(
|
||||
echo ". $ORA_ENVF"
|
||||
cat
|
||||
- ) | su - $ORACLE_OWNER
|
||||
+ ) | su -s $SH - $ORACLE_OWNER
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ oralsnr_validate_all() {
|
||||
# used in ora-common.sh
|
||||
show_procs() {
|
||||
ps -e -o pid,user,args |
|
||||
- grep '[t]nslsnr' | grep -w "$listener" | grep -w "$ORACLE_OWNER"
|
||||
+ grep '[t]nslsnr' | grep -i -w "$listener" | grep -w "$ORACLE_OWNER"
|
||||
}
|
||||
proc_pids() { show_procs | awk '{print $1}'; }
|
||||
PROCS_CLEANUP_TIME="10"
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
diff -uNr a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
--- a/heartbeat/VirtualDomain 2016-02-29 10:54:21.870787072 +0100
|
||||
+++ b/heartbeat/VirtualDomain 2016-02-29 14:02:23.260696550 +0100
|
||||
@@ -106,11 +106,28 @@
|
||||
|
||||
Note: Be sure this composed host name is locally resolveable and the
|
||||
associated IP is reachable through the favored network.
|
||||
+
|
||||
+See also the migrate_options parameter below.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">Migration network host name suffix</shortdesc>
|
||||
<content type="string" default="" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="migrate_options" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Extra virsh options for the guest live migration. You can also specify
|
||||
+here --migrateuri if the calculated migrate URI is unsuitable for your
|
||||
+environment. If --migrateuri is set then migration_network_suffix
|
||||
+and migrateport are effectively ignored. Use "%n" as the placeholder
|
||||
+for the target node name.
|
||||
+
|
||||
+Please refer to the libvirt documentation for details on guest
|
||||
+migration.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">live migrate options</shortdesc>
|
||||
+<content type="string" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="monitor_scripts" unique="0" required="0">
|
||||
<longdesc lang="en">
|
||||
To additionally monitor services within the virtual domain, add this
|
||||
@@ -485,14 +502,45 @@
|
||||
force_stop
|
||||
}
|
||||
|
||||
+mk_migrateuri() {
|
||||
+ local target_node
|
||||
+ local migrate_target
|
||||
+ local hypervisor
|
||||
+
|
||||
+ target_node="$OCF_RESKEY_CRM_meta_migrate_target"
|
||||
+
|
||||
+ # A typical migration URI via a special migration network looks
|
||||
+ # like "tcp://bar-mig:49152". The port would be randomly chosen
|
||||
+ # by libvirt from the range 49152-49215 if omitted, at least since
|
||||
+ # version 0.7.4 ...
|
||||
+ if [ -n "${OCF_RESKEY_migration_network_suffix}" ]; then
|
||||
+ hypervisor="${OCF_RESKEY_hypervisor%%[+:]*}"
|
||||
+ # Hostname might be a FQDN
|
||||
+ migrate_target=$(echo ${target_node} | sed -e "s,^\([^.]\+\),\1${OCF_RESKEY_migration_network_suffix},")
|
||||
+ case $hypervisor in
|
||||
+ qemu)
|
||||
+ # For quiet ancient libvirt versions a migration port is needed
|
||||
+ # and the URI must not contain the "//". Newer versions can handle
|
||||
+ # the "bad" URI.
|
||||
+ echo "tcp:${migrate_target}:${OCF_RESKEY_migrateport}"
|
||||
+ ;;
|
||||
+ xen)
|
||||
+ echo "xenmigr://${migrate_target}"
|
||||
+ ;;
|
||||
+ *)
|
||||
+ ocf_log warn "$DOMAIN_NAME: Migration via dedicated network currently not supported for ${hypervisor}."
|
||||
+ ;;
|
||||
+ esac
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
VirtualDomain_Migrate_To() {
|
||||
+ local rc
|
||||
local target_node
|
||||
local remoteuri
|
||||
local transport_suffix
|
||||
local migrateuri
|
||||
- local migrateport
|
||||
- local migrate_target
|
||||
- local hypervisor
|
||||
+ local migrate_opts
|
||||
|
||||
target_node="$OCF_RESKEY_CRM_meta_migrate_target"
|
||||
|
||||
@@ -503,38 +551,26 @@
|
||||
if [ -n "${OCF_RESKEY_migration_transport}" ]; then
|
||||
transport_suffix="+${OCF_RESKEY_migration_transport}"
|
||||
fi
|
||||
- # A typical migration URI via a special migration network looks
|
||||
- # like "tcp://bar-mig:49152". The port would be randomly chosen
|
||||
- # by libvirt from the range 49152-49215 if omitted, at least since
|
||||
- # version 0.7.4 ...
|
||||
- if [ -n "${OCF_RESKEY_migration_network_suffix}" ]; then
|
||||
- hypervisor="${OCF_RESKEY_hypervisor%%[+:]*}"
|
||||
- # Hostname might be a FQDN
|
||||
- migrate_target=$(echo ${target_node} | sed -e "s,^\([^.]\+\),\1${OCF_RESKEY_migration_network_suffix},")
|
||||
- case $hypervisor in
|
||||
- qemu)
|
||||
- # For quiet ancient libvirt versions a migration port is needed
|
||||
- # and the URI must not contain the "//". Newer versions can handle
|
||||
- # the "bad" URI.
|
||||
- migrateuri="tcp:${migrate_target}:${OCF_RESKEY_migrateport}"
|
||||
- ;;
|
||||
- xen)
|
||||
- migrateuri="xenmigr://${migrate_target}"
|
||||
- ;;
|
||||
- *)
|
||||
- ocf_log warn "$DOMAIN_NAME: Migration via dedicated network currently not supported for ${hypervisor}."
|
||||
- ;;
|
||||
- esac
|
||||
+
|
||||
+ # User defined migrateuri or do we make one?
|
||||
+ migrate_opts="$OCF_RESKEY_migrate_options"
|
||||
+ if echo "$migrate_opts" | fgrep -qs -- "--migrateuri="; then
|
||||
+ migrateuri=`echo "$migrate_opts" |
|
||||
+ sed "s/.*--migrateuri=\([^ ]*\).*/\1/;s/%n/$target_node/g"`
|
||||
+ migrate_opts=`echo "$migrate_opts" |
|
||||
+ sed "s/\(.*\)--migrateuri=[^ ]*\(.*\)/\1\3/"`
|
||||
+ else
|
||||
+ migrateuri=`mk_migrateuri`
|
||||
fi
|
||||
# Scared of that sed expression? So am I. :-)
|
||||
remoteuri=$(echo ${OCF_RESKEY_hypervisor} | sed -e "s,\(.*\)://[^/:]*\(:\?[0-9]*\)/\(.*\),\1${transport_suffix}://${target_node}\2/\3,")
|
||||
|
||||
# OK, we know where to connect to. Now do the actual migration.
|
||||
- ocf_log info "$DOMAIN_NAME: Starting live migration to ${target_node} (using remote hypervisor URI ${remoteuri} ${migrateuri})."
|
||||
- virsh ${VIRSH_OPTIONS} migrate --live $DOMAIN_NAME ${remoteuri} ${migrateuri}
|
||||
+ ocf_log info "$DOMAIN_NAME: Starting live migration to ${target_node} (using virsh ${VIRSH_OPTIONS} migrate --live $migrate_opts $DOMAIN_NAME $remoteuri $migrateuri)."
|
||||
+ virsh ${VIRSH_OPTIONS} migrate --live $migrate_opts $DOMAIN_NAME $remoteuri $migrateuri
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
- ocf_exit_reason "$DOMAIN_NAME: live migration to ${remoteuri} ${migrateuri} failed: $rc"
|
||||
+ ocf_exit_reason "$DOMAIN_NAME: live migration to ${target_node} failed: $rc"
|
||||
return $OCF_ERR_GENERIC
|
||||
else
|
||||
ocf_log info "$DOMAIN_NAME: live migration to ${target_node} succeeded."
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
diff -uNr a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
--- a/heartbeat/VirtualDomain 2015-11-20 11:52:58.314263831 +0100
|
||||
+++ b/heartbeat/VirtualDomain 2015-11-20 11:53:55.247196256 +0100
|
||||
@@ -340,13 +340,32 @@
|
||||
return $rc
|
||||
}
|
||||
|
||||
+# virsh undefine removes configuration files if they are in
|
||||
+# directories which are managed by libvirt. such directories
|
||||
+# include also subdirectories of /etc (for instance
|
||||
+# /etc/libvirt/*) which may be surprising. VirtualDomain didn't
|
||||
+# include the undefine call before, hence this wasn't an issue
|
||||
+# before.
|
||||
+#
|
||||
+# There seems to be no way to find out which directories are
|
||||
+# managed by libvirt.
|
||||
+#
|
||||
verify_undefined() {
|
||||
- for dom in `virsh --connect=${OCF_RESKEY_hypervisor} list --all --name 2>/dev/null`; do
|
||||
- if [ "$dom" = "$DOMAIN_NAME" ]; then
|
||||
+ local tmpf
|
||||
+ if virsh --connect=${OCF_RESKEY_hypervisor} list --all --name 2>/dev/null | grep -wqs "$DOMAIN_NAME"
|
||||
+ then
|
||||
+ tmpf=$(mktemp -t vmcfgsave.XXXXXX)
|
||||
+ if [ ! -r "$tmpf" ]; then
|
||||
+ ocf_log warn "unable to create temp file, disk full?"
|
||||
+ # we must undefine the domain
|
||||
virsh $VIRSH_OPTIONS undefine $DOMAIN_NAME > /dev/null 2>&1
|
||||
- return
|
||||
+ else
|
||||
+ cp -p $OCF_RESKEY_config $tmpf
|
||||
+ virsh $VIRSH_OPTIONS undefine $DOMAIN_NAME > /dev/null 2>&1
|
||||
+ [ -f $OCF_RESKEY_config ] || cp -f $tmpf $OCF_RESKEY_config
|
||||
+ rm -f $tmpf
|
||||
fi
|
||||
- done
|
||||
+ fi
|
||||
}
|
||||
|
||||
VirtualDomain_Start() {
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
diff -uNr a/heartbeat/rabbitmq-cluster b/heartbeat/rabbitmq-cluster
|
||||
--- a/heartbeat/rabbitmq-cluster 2016-02-22 11:09:48.989128414 +0100
|
||||
+++ b/heartbeat/rabbitmq-cluster 2016-02-22 11:10:12.011835745 +0100
|
||||
@@ -39,7 +39,14 @@
|
||||
RMQ_LOG_DIR="/var/log/rabbitmq"
|
||||
NODENAME=$(ocf_local_nodename)
|
||||
|
||||
+# this attr represents the current active local rmq node name.
|
||||
+# when rmq stops or the node is fenced, this attr disappears
|
||||
RMQ_CRM_ATTR_COOKIE="rmq-node-attr-${OCF_RESOURCE_INSTANCE}"
|
||||
+# this attr represents the last known active local rmq node name
|
||||
+# when rmp stops or the node is fenced, the attr stays forever so
|
||||
+# we can continue to map an offline pcmk node to it's rmq node name
|
||||
+# equivalent.
|
||||
+RMQ_CRM_ATTR_COOKIE_LAST_KNOWN="rmq-node-attr-last-known-${OCF_RESOURCE_INSTANCE}"
|
||||
|
||||
meta_data() {
|
||||
cat <<END
|
||||
@@ -79,7 +86,7 @@
|
||||
|
||||
rmq_usage() {
|
||||
cat <<END
|
||||
-usage: $0 {start|stop|monitor|migrate_to|migrate_from|validate-all|meta-data}
|
||||
+usage: $0 {start|stop|monitor|notify|validate-all|meta-data}
|
||||
|
||||
Expects to have a fully populated OCF RA-compliant environment set.
|
||||
END
|
||||
@@ -116,8 +123,13 @@
|
||||
exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
- # store the pcmknode to rmq node mapping as an attribute
|
||||
+ # store the pcmknode to rmq node mapping as a transient attribute. This allows
|
||||
+ # us to retrieve the join list with a simple xpath.
|
||||
${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "$RMQ_CRM_ATTR_COOKIE" -v "$node_name"
|
||||
+
|
||||
+ # the pcmknode to rmq node mapping as a permanent attribute as well. this lets
|
||||
+ # us continue to map offline nodes to their equivalent rmq node name
|
||||
+ ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l forever --name "$RMQ_CRM_ATTR_COOKIE_LAST_KNOWN" -v "$node_name"
|
||||
}
|
||||
|
||||
rmq_delete_nodename()
|
||||
@@ -262,6 +274,41 @@
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
+
|
||||
+rmq_notify() {
|
||||
+ node_list="${OCF_RESKEY_CRM_meta_notify_stop_uname}"
|
||||
+ mode="${OCF_RESKEY_CRM_meta_notify_type}-${OCF_RESKEY_CRM_meta_notify_operation}"
|
||||
+
|
||||
+
|
||||
+ # When notifications are on, this agent is going to "forget" nodes once they
|
||||
+ # leave the cluster. This is thought to resolve some issues where rabbitmq
|
||||
+ # blocks trying to sync with an offline node after a fencing action occurs.
|
||||
+ if ! [ "${mode}" = "post-stop" ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ rmq_monitor
|
||||
+ if [ $? -ne $OCF_SUCCESS ]; then
|
||||
+ # only run forget when we are for sure active
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ # forget each stopped rmq instance in the provided pcmk node in the list.
|
||||
+ for node in $(echo "$node_list"); do
|
||||
+ local rmq_node="$(${HA_SBIN_DIR}/crm_attribute -N $node -l forever --query --name $RMQ_CRM_ATTR_COOKIE_LAST_KNOWN -q)"
|
||||
+ if [ -z "$rmq_node" ]; then
|
||||
+ ocf_log warn "Unable to map pcmk node $node to a known rmq node."
|
||||
+ continue
|
||||
+ fi
|
||||
+ ocf_log notice "Forgetting stopped node $rmq_node"
|
||||
+ $RMQ_CTL forget_cluster_node $rmq_node
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ ocf_log warn "Unable to forget offline node $rmq_node."
|
||||
+ fi
|
||||
+ done
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
rmq_start() {
|
||||
local join_list=""
|
||||
local rc
|
||||
@@ -357,6 +404,7 @@
|
||||
stop) rmq_stop;;
|
||||
monitor) rmq_monitor;;
|
||||
validate-all) rmq_validate;;
|
||||
+notify) rmq_notify;;
|
||||
usage|help) rmq_usage
|
||||
exit $OCF_SUCCESS
|
||||
;;
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
diff --git a/heartbeat/tomcat b/heartbeat/tomcat
|
||||
index 8b7fe31..07a7ce4 100755
|
||||
--- a/heartbeat/tomcat
|
||||
+++ b/heartbeat/tomcat
|
||||
@@ -49,6 +49,13 @@
|
||||
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
|
||||
+# Use runuser if available for SELinux.
|
||||
+if [ -x /sbin/runuser ]; then
|
||||
+ SU=runuser
|
||||
+else
|
||||
+ SU=su
|
||||
+fi
|
||||
+
|
||||
############################################################################
|
||||
# Usage
|
||||
usage()
|
||||
@@ -143,7 +150,7 @@ monitor_tomcat()
|
||||
start_rotatelogs()
|
||||
{
|
||||
# -s is required because tomcat5.5's login shell is /bin/false
|
||||
- su - -s /bin/sh $RESOURCE_TOMCAT_USER \
|
||||
+ $SU - -s /bin/sh $RESOURCE_TOMCAT_USER \
|
||||
-c "$ROTATELOGS -l \"$CATALINA_BASE/logs/catalina_%F.log\" $CATALINA_ROTATETIME" \
|
||||
< "$CATALINA_OUT" > /dev/null 2>&1 &
|
||||
}
|
||||
@@ -154,7 +161,7 @@ rotate_catalina_out()
|
||||
{
|
||||
# Check catalina_%F.log is writable or not.
|
||||
CURRENT_ROTATELOG_SUFFIX=`date +"%F"`
|
||||
- su - -s /bin/sh $RESOURCE_TOMCAT_USER \
|
||||
+ $SU - -s /bin/sh $RESOURCE_TOMCAT_USER \
|
||||
-c "touch \"$CATALINA_BASE/logs/catalina_$CURRENT_ROTATELOG_SUFFIX.log\"" > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
ocf_exit_reason "$CATALINA_BASE/logs/catalina_$CURRENT_ROTATELOG_SUFFIX.log is not writable."
|
||||
@@ -205,7 +212,7 @@ attemptTomcatCommand()
|
||||
if [ "$RESOURCE_TOMCAT_USER" = root ]; then
|
||||
"$TOMCAT_START_SCRIPT" $@ >> "$TOMCAT_CONSOLE" 2>&1
|
||||
else
|
||||
- tomcatCommand $@ | su - -s /bin/sh "$RESOURCE_TOMCAT_USER" >> "$TOMCAT_CONSOLE" 2>&1
|
||||
+ tomcatCommand $@ | $SU - -s /bin/sh "$RESOURCE_TOMCAT_USER" >> "$TOMCAT_CONSOLE" 2>&1
|
||||
fi
|
||||
|
||||
if [ -n "$REDIRECT_DEFAULT_CONFIG" ]; then
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
From a1860a5bbe5c63c6a34d9160a8aacffc61a89dcf Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Fri, 16 Sep 2016 14:25:28 +0200
|
||||
Subject: [PATCH] tomcat: use systemd where available due to newer versions not
|
||||
generating PID-file
|
||||
|
||||
---
|
||||
heartbeat/tomcat | 44 ++++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 40 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/tomcat b/heartbeat/tomcat
|
||||
index 07a7ce4..813d280 100755
|
||||
--- a/heartbeat/tomcat
|
||||
+++ b/heartbeat/tomcat
|
||||
@@ -56,6 +56,10 @@ else
|
||||
SU=su
|
||||
fi
|
||||
|
||||
+if which systemctl > /dev/null 2>&1; then
|
||||
+ SYSTEMD=1
|
||||
+fi
|
||||
+
|
||||
############################################################################
|
||||
# Usage
|
||||
usage()
|
||||
@@ -90,6 +94,10 @@ isrunning_tomcat()
|
||||
#
|
||||
isalive_tomcat()
|
||||
{
|
||||
+ if ocf_is_true $SYSTEMD; then
|
||||
+ systemctl is-active tomcat@${TOMCAT_NAME} > /dev/null 2>&1
|
||||
+ return $?
|
||||
+ fi
|
||||
# As the server stops, the PID file disappears. To avoid race conditions,
|
||||
# we will have remembered the PID of a running instance on script entry.
|
||||
local pid=$rememberedPID
|
||||
@@ -184,9 +192,31 @@ rotate_catalina_out()
|
||||
}
|
||||
|
||||
############################################################################
|
||||
+# Create systemd configuration
|
||||
+create_systemd_config()
|
||||
+{
|
||||
+cat<<-EOF > /etc/sysconfig/tomcat@${TOMCAT_NAME}
|
||||
+JAVA_HOME=${JAVA_HOME}
|
||||
+JAVA_OPTS="${JAVA_OPTS}"
|
||||
+CATALINA_HOME=${CATALINA_HOME}
|
||||
+CATALINA_BASE=${CATALINA_BASE}
|
||||
+CATALINA_OUT=${CATALINA_OUT}
|
||||
+CATALINA_OPTS="${CATALINA_OPTS}"
|
||||
+CATALINA_TMPDIR="${CATALINA_TMPDIR}"
|
||||
+JAVA_ENDORSED_DIRS="${JAVA_ENDORSED_DIRS}"
|
||||
+LOGGING_CONFIG="${LOGGING_CONFIG}"
|
||||
+LOGGING_MANAGER="${LOGGING_MANAGER}"
|
||||
+TOMCAT_CFG=${TOMCAT_CFG}
|
||||
+EOF
|
||||
+}
|
||||
+
|
||||
+############################################################################
|
||||
# Tomcat Command
|
||||
tomcatCommand()
|
||||
{
|
||||
+ if ocf_is_true $SYSTEMD; then
|
||||
+ systemctl $@ tomcat@${TOMCAT_NAME}
|
||||
+ else
|
||||
cat<<-END_TOMCAT_COMMAND
|
||||
export JAVA_HOME=${JAVA_HOME}
|
||||
export JAVA_OPTS="${JAVA_OPTS}"
|
||||
@@ -202,6 +232,7 @@ cat<<-END_TOMCAT_COMMAND
|
||||
export TOMCAT_CFG=${TOMCAT_CFG}
|
||||
$TOMCAT_START_SCRIPT $@
|
||||
END_TOMCAT_COMMAND
|
||||
+ fi
|
||||
}
|
||||
attemptTomcatCommand()
|
||||
{
|
||||
@@ -209,7 +240,9 @@ attemptTomcatCommand()
|
||||
export TOMCAT_CFG=$(mktemp ${HA_RSCTMP}/tomcat-tmp-XXXXX.cfg)
|
||||
fi
|
||||
|
||||
- if [ "$RESOURCE_TOMCAT_USER" = root ]; then
|
||||
+ if ocf_is_true $SYSTEMD; then
|
||||
+ tomcatCommand $@
|
||||
+ elif [ "$RESOURCE_TOMCAT_USER" = root ]; then
|
||||
"$TOMCAT_START_SCRIPT" $@ >> "$TOMCAT_CONSOLE" 2>&1
|
||||
else
|
||||
tomcatCommand $@ | $SU - -s /bin/sh "$RESOURCE_TOMCAT_USER" >> "$TOMCAT_CONSOLE" 2>&1
|
||||
@@ -224,6 +257,9 @@ attemptTomcatCommand()
|
||||
# Start Tomcat
|
||||
start_tomcat()
|
||||
{
|
||||
+ if ocf_is_true $SYSTEMD; then
|
||||
+ create_systemd_config
|
||||
+ fi
|
||||
cd "$CATALINA_HOME/bin"
|
||||
|
||||
validate_all_tomcat || exit $?
|
||||
@@ -334,11 +370,11 @@ Resource script for Tomcat. It manages a Tomcat instance as a cluster resource.
|
||||
<parameters>
|
||||
|
||||
<parameter name="tomcat_name" unique="1" >
|
||||
-<longdesc lang="en"><![CDATA[
|
||||
+<longdesc lang="en">
|
||||
The name of the resource, added as a Java parameter in JAVA_OPTS:
|
||||
--Dname=<tomcat_name> to Tomcat process on start. Used to ensure
|
||||
+-Dname=<tomcat_name> to Tomcat process on start. Used to ensure
|
||||
process is still running and must be unique.
|
||||
-]]></longdesc>
|
||||
+</longdesc>
|
||||
<shortdesc>The name of the resource</shortdesc>
|
||||
<content type="string" default="" />
|
||||
</parameter>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,33 @@
|
|||
commit fe53056f225fadae184a0ab79f1f96430854812f
|
||||
Author: David Vossel <dvossel@redhat.com>
|
||||
Date: Thu Aug 13 14:11:30 2015 -0400
|
||||
|
||||
High: redis: use required client pass word when set
|
||||
|
||||
diff --git a/heartbeat/redis b/heartbeat/redis
|
||||
index e1d0795..65abb2a 100755
|
||||
--- a/heartbeat/redis
|
||||
+++ b/heartbeat/redis
|
||||
@@ -218,7 +218,11 @@ function set_score()
|
||||
|
||||
function redis_client() {
|
||||
ocf_log debug "redis_client: '$REDIS_CLIENT' -s '$REDIS_SOCKET' $@"
|
||||
- "$REDIS_CLIENT" -s "$REDIS_SOCKET" "$@" | sed 's/\r//'
|
||||
+ if [ -n "$clientpasswd" ]; then
|
||||
+ "$REDIS_CLIENT" -s "$REDIS_SOCKET" -a "$clientpasswd" "$@" | sed 's/\r//'
|
||||
+ else
|
||||
+ "$REDIS_CLIENT" -s "$REDIS_SOCKET" "$@" | sed 's/\r//'
|
||||
+ fi
|
||||
}
|
||||
|
||||
function simple_status() {
|
||||
@@ -487,6 +491,9 @@ function validate() {
|
||||
}
|
||||
|
||||
NODENAME=$(ocf_local_nodename)
|
||||
+if [ -f "$REDIS_CONFIG" ]; then
|
||||
+ clientpasswd="$(cat $REDIS_CONFIG | sed -n -e 's/^\s*requirepass\s*\(.*\)\s*$/\1/p' | tail -n 1)"
|
||||
+fi
|
||||
|
||||
ocf_log debug "action=${1:-$__OCF_ACTION} notify_type=${OCF_RESKEY_CRM_meta_notify_type} notify_operation=${OCF_RESKEY_CRM_meta_notify_operation} master_host=${OCF_RESKEY_CRM_meta_notify_master_uname} slave_host=${OCF_RESKEY_CRM_meta_notify_slave_uname} promote_host=${OCF_RESKEY_CRM_meta_notify_promote_uname} demote_host=${OCF_RESKEY_CRM_meta_notify_demote_uname}; params: bin=${OCF_RESKEY_bin} client_bin=${OCF_RESKEY_client_bin} config=${OCF_RESKEY_config} user=${OCF_RESKEY_user} rundir=${OCF_RESKEY_rundir} port=${OCF_RESKEY_port}"
|
||||
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
From fe55f9b909d81a0093dbfb1f00083706cf5d2cf1 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Krauth <alexander.krauth@basf.com>
|
||||
Date: Fri, 19 Feb 2016 18:00:58 +0100
|
||||
Subject: [PATCH] High: SAPDatabase: Add support for Oracle 12c
|
||||
|
||||
To work with Oracle 12c the agent needs an option
|
||||
to pass the new Database Username to the resource.
|
||||
|
||||
Example configuration:
|
||||
|
||||
primitive oracle-database SAPDatabase \
|
||||
params \
|
||||
SID=HAO \
|
||||
DBTYPE=ORA \
|
||||
DBOUSER=oracle \
|
||||
STRICT_MONITORING=1 \
|
||||
op monitor interval=120 timeout=60
|
||||
---
|
||||
heartbeat/SAPDatabase | 12 +++++++++++-
|
||||
heartbeat/sapdb.sh | 35 ++++++++++++++++++++++++++---------
|
||||
2 files changed, 37 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/SAPDatabase b/heartbeat/SAPDatabase
|
||||
index de7959f..641bd40 100755
|
||||
--- a/heartbeat/SAPDatabase
|
||||
+++ b/heartbeat/SAPDatabase
|
||||
@@ -18,6 +18,7 @@
|
||||
# OCF_RESKEY_DIR_EXECUTABLE (optional, well known directories will be searched by default)
|
||||
# OCF_RESKEY_DBTYPE (mandatory, one of the following values: ORA,ADA,DB6,SYB,HDB)
|
||||
# OCF_RESKEY_DBINSTANCE (optional, Database instance name, if not equal to SID)
|
||||
+# OCF_RESKEY_DBOSUSER (optional, the Linux user that owns the database processes on operating system level)
|
||||
# OCF_RESKEY_STRICT_MONITORING (optional, activate application level monitoring - with Oracle a failover will occur in case of an archiver stuck)
|
||||
# OCF_RESKEY_AUTOMATIC_RECOVER (optional, automatic startup recovery, default is false)
|
||||
# OCF_RESKEY_MONITOR_SERVICES (optional, default is to monitor all database services)
|
||||
@@ -69,7 +70,7 @@ meta_data() {
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
<resource-agent name="SAPDatabase">
|
||||
-<version>2.06</version>
|
||||
+<version>2.14</version>
|
||||
|
||||
<shortdesc lang="en">Manages a SAP database instance as an HA resource.</shortdesc>
|
||||
<longdesc lang="en">
|
||||
@@ -115,6 +116,11 @@ Usually you can leave this empty. Then the default: /usr/sap/hostctrl/exe is use
|
||||
<shortdesc lang="en">Database instance name, if not equal to SID</shortdesc>
|
||||
<content type="string" default="" />
|
||||
</parameter>
|
||||
+ <parameter name="DBOSUSER" unique="1" required="0">
|
||||
+ <longdesc lang="en">The parameter can be set, if the database processes on operating system level are not executed with the default user of the used database type. Defaults: ADA=taken from /etc/opt/sdb, DB6=db2SID, ORA=oraSID and oracle, SYB=sybSID, HDB=SIDadm</longdesc>
|
||||
+ <shortdesc lang="en">the Linux user that owns the database processes on operating system level</shortdesc>
|
||||
+ <content type="string" default="" />
|
||||
+ </parameter>
|
||||
<parameter name="NETSERVICENAME" unique="0" required="0">
|
||||
<longdesc lang="en">Deprecated - do not use anymore. This parameter will be deleted in one of the next releases.</longdesc>
|
||||
<shortdesc lang="en">deprecated - do not use anymore</shortdesc>
|
||||
@@ -305,6 +311,10 @@ DBTYPE=`echo "$OCF_RESKEY_DBTYPE" | tr '[:lower:]' '[:upper:]'`
|
||||
if saphostctrl_installed; then
|
||||
. ${OCF_FUNCTIONS_DIR}/sapdb.sh
|
||||
else
|
||||
+ if [ -n "${OCF_RESKEY_DBOSUSER}" ]; then
|
||||
+ ocf_exit_reason "Usage of parameter OCF_RESKEY_DBOSUSER is not possible without having SAP Host-Agent installed"
|
||||
+ exit $OCF_ERR_ARGS
|
||||
+ fi
|
||||
. ${OCF_FUNCTIONS_DIR}/sapdb-nosha.sh
|
||||
fi
|
||||
sapdatabase_init
|
||||
diff --git a/heartbeat/sapdb.sh b/heartbeat/sapdb.sh
|
||||
index 7edb4b8..33d2033 100755
|
||||
--- a/heartbeat/sapdb.sh
|
||||
+++ b/heartbeat/sapdb.sh
|
||||
@@ -210,7 +210,11 @@ sapdatabase_monitor() {
|
||||
then
|
||||
DBINST="-dbinstance $OCF_RESKEY_DBINSTANCE "
|
||||
fi
|
||||
- output=`$SAPHOSTCTRL -function GetDatabaseStatus -dbname $SID -dbtype $DBTYPE $DBINST`
|
||||
+ if [ -n "$OCF_RESKEY_DBOSUSER" ]
|
||||
+ then
|
||||
+ DBOSUSER="-dbuser $OCF_RESKEY_DBOSUSER "
|
||||
+ fi
|
||||
+ output=`$SAPHOSTCTRL -function GetDatabaseStatus -dbname $SID -dbtype $DBTYPE $DBINST $DBOSUSER`
|
||||
|
||||
# we have to parse the output, because the returncode doesn't tell anything about the instance status
|
||||
for SERVICE in `echo "$output" | grep -i 'Component[ ]*Name *[:=] [A-Za-z][A-Za-z0-9_]* (' | sed 's/^.*Component[ ]*Name *[:=] *\([A-Za-z][A-Za-z0-9_]*\).*$/\1/i'`
|
||||
@@ -255,30 +259,43 @@ sapdatabase_monitor() {
|
||||
# sapdatabase_status: Are there any database processes on this host ?
|
||||
#
|
||||
sapdatabase_status() {
|
||||
+ sid=`echo $SID | tr '[:upper:]' '[:lower:]'`
|
||||
+
|
||||
+ SUSER=${OCF_RESKEY_DBOSUSER:-""}
|
||||
+
|
||||
case $DBTYPE in
|
||||
ADA) SEARCH="$SID/db/pgm/kernel"
|
||||
- SUSER=`grep "^SdbOwner" /etc/opt/sdb | awk -F'=' '{print $2}'`
|
||||
+ [ -z "$SUSER" ] && SUSER=`grep "^SdbOwner" /etc/opt/sdb | awk -F'=' '{print $2}'`
|
||||
SNUM=2
|
||||
;;
|
||||
- ORA) SEARCH="ora_[a-z][a-z][a-z][a-z]_"
|
||||
- SUSER="ora`echo $SID | tr '[:upper:]' '[:lower:]'`"
|
||||
- SNUM=4
|
||||
+ ORA) DBINST=${OCF_RESKEY_DBINSTANCE}
|
||||
+ DBINST=${OCF_RESKEY_DBINSTANCE:-${SID}}
|
||||
+ SEARCH="ora_[a-z][a-z][a-z][a-z]_$DBINST"
|
||||
+
|
||||
+ if [ -z "$SUSER" ]; then
|
||||
+ id "oracle" > /dev/null 2> /dev/null && SUSER="oracle"
|
||||
+ id "ora${sid}" > /dev/null 2> /dev/null && SUSER="${SUSER:+${SUSER},}ora${sid}"
|
||||
+ fi
|
||||
+
|
||||
+ SNUM=4
|
||||
;;
|
||||
DB6) SEARCH="db2[a-z][a-z][a-z]"
|
||||
- SUSER="db2`echo $SID | tr '[:upper:]' '[:lower:]'`"
|
||||
+ [ -z "$SUSER" ] && SUSER="db2${sid}"
|
||||
SNUM=2
|
||||
;;
|
||||
SYB) SEARCH="dataserver"
|
||||
- SUSER="syb`echo $SID | tr '[:upper:]' '[:lower:]'`"
|
||||
+ [ -z "$SUSER" ] && SUSER="syb${sid}"
|
||||
SNUM=1
|
||||
;;
|
||||
HDB) SEARCH="hdb[a-z]*server"
|
||||
- SUSER="`echo $SID | tr '[:upper:]' '[:lower:]'`adm"
|
||||
+ [ -z "$SUSER" ] && SUSER="${sid}adm"
|
||||
SNUM=1
|
||||
;;
|
||||
esac
|
||||
|
||||
- cnt=`ps -u $SUSER -o args 2> /dev/null | grep -c $SEARCH`
|
||||
+ [ -z "$SUSER" ] && return $OCF_ERR_INSTALLED
|
||||
+
|
||||
+ cnt=`ps -u $SUSER -o args 2> /dev/null | grep -v grep | grep -c $SEARCH`
|
||||
[ $cnt -ge $SNUM ] && return $OCF_SUCCESS
|
||||
return $OCF_NOT_RUNNING
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
From af5863ecd255d2d514113d39bbf03ab95b5ccca2 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Kristoffer=20Gr=C3=B6nlund?= <krig@koru.se>
|
||||
Date: Mon, 16 Nov 2015 17:14:43 +0100
|
||||
Subject: [PATCH] SAPDatabase: Add Oracle 12 to list of supported databases
|
||||
(bsc#953991)
|
||||
|
||||
This agent has been tested to work with Oracle database version 12.
|
||||
---
|
||||
heartbeat/SAPDatabase | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/SAPDatabase b/heartbeat/SAPDatabase
|
||||
index 3b77206..de7959f 100755
|
||||
--- a/heartbeat/SAPDatabase
|
||||
+++ b/heartbeat/SAPDatabase
|
||||
@@ -78,7 +78,7 @@ Resource script for SAP databases. It manages a SAP database of any type as an H
|
||||
The purpose of the resource agent is to start, stop and monitor the database instance of a SAP system. Together with the RDBMS system it will also control the related network service for the database. Like the Oracle Listener and the xserver of MaxDB.
|
||||
The resource agent expects a standard SAP installation of the database and therefore needs less parameters to configure.
|
||||
The resource agent supports the following databases:
|
||||
-- Oracle 10.2 and 11.2
|
||||
+- Oracle 10.2, 11.2 and 12
|
||||
- DB/2 UDB for Windows and Unix 9.x
|
||||
- SAP-DB / MaxDB 7.x
|
||||
- Sybase ASE 15.7
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
diff -uNr a/heartbeat/mysql b/heartbeat/mysql
|
||||
--- a/heartbeat/mysql 2016-02-29 10:54:21.896786740 +0100
|
||||
+++ b/heartbeat/mysql 2016-02-29 10:59:13.377446910 +0100
|
||||
@@ -344,6 +344,7 @@
|
||||
|
||||
get_slave_info
|
||||
rc=$?
|
||||
+ rm -f $tmpfile
|
||||
|
||||
if [ $rc -eq 0 ]; then
|
||||
# show slave status is not empty
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
diff -uNr a/sap_redhat_cluster_connector-6353d27/sap_redhat_cluster_connector b/sap_redhat_cluster_connector-6353d27/sap_redhat_cluster_connector
|
||||
--- a/sap_redhat_cluster_connector-6353d27/sap_redhat_cluster_connector 2013-07-18 21:17:48.000000000 +0200
|
||||
+++ b/sap_redhat_cluster_connector-6353d27/sap_redhat_cluster_connector 2016-02-29 11:04:48.714352114 +0100
|
||||
@@ -251,13 +251,13 @@
|
||||
open CRMOUT, "$cmd_cibadmin --local -Q --xpath '//primitive[\@type=\"$sra\"]' --node-path 2>/dev/null |" || die "could not open cibadmin output";
|
||||
while (<CRMOUT>) {
|
||||
my $line = $_;
|
||||
- if ($line =~ /primitive..id='([a-zA-Z0-9_]+)'/) {
|
||||
+ if ($line =~ /primitive..id='([a-zA-Z0-9_-]+)'/) {
|
||||
($fname) = ($1);
|
||||
} else {
|
||||
next;
|
||||
}
|
||||
|
||||
- if ( $line =~ /[group|master|clone]..id='([a-zA-Z0-9_]+)'/) {
|
||||
+ if ( $line =~ /[group|master|clone]..id='([a-zA-Z0-9_-]+)'/) {
|
||||
($fgname) = ($1);
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@
|
||||
open RESOURCE1_OUT, "$cmd_cibadmin -Q --xpath \"//primitive[\@id='$fname']//nvpair[\@name='$sparam']\" 2>/dev/null |" || die "could not open cibadmin output";
|
||||
while (<RESOURCE1_OUT>) {
|
||||
my $result = $_;
|
||||
- if ($result =~ /value="([a-zA-Z0-9_]+)"/) {
|
||||
+ if ($result =~ /value="([a-zA-Z0-9_-]+)"/) {
|
||||
my $finstance=$1;
|
||||
if ( $1 =~ /^${sid}_[a-zA-Z0-9]+${ino}_[a-zA-Z0-9_-]+$/ ) {
|
||||
$foundRes=1;
|
||||
@@ -279,7 +279,7 @@
|
||||
open RESOURCE2_OUT, "$cmd_cibadmin -Q --xpath \"//primitive[\@id='$fname']//nvpair[\@name='$sparam2']\" 2>/dev/null |" || die "could not open cibadmin output";
|
||||
while (<RESOURCE2_OUT>) {
|
||||
my $result = $_;
|
||||
- if ($result =~ /value="([a-zA-Z0-9_]+)"/) {
|
||||
+ if ($result =~ /value="([a-zA-Z0-9_-]+)"/) {
|
||||
my $finstance=$1;
|
||||
if ( $1 =~ /^${sid}_[a-zA-Z0-9]+${ino}_[a-zA-Z0-9_-]+$/ ) {
|
||||
$foundRes=1;
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
diff -uNr a/heartbeat/IPaddr2 b/heartbeat/IPaddr2
|
||||
--- a/heartbeat/IPaddr2 2016-02-29 10:54:21.909786575 +0100
|
||||
+++ b/heartbeat/IPaddr2 2016-02-29 14:38:48.502852067 +0100
|
||||
@@ -673,19 +673,35 @@
|
||||
#
|
||||
run_send_ua() {
|
||||
local i
|
||||
- # Wait until the allocated IPv6 address gets ready by checking
|
||||
- # "tentative" flag is disappeared, otherwise send_ua can not
|
||||
- # send the unsolicited advertisement requests.
|
||||
- for i in 1 2 3 4 5; do
|
||||
- $IP2UTIL -o -f $FAMILY addr show dev $NIC \
|
||||
- | grep -q -e "$OCF_RESKEY_ip/$NETMASK .* tentative"
|
||||
- [ $? -ne 0 ] && break
|
||||
- if [ $i -eq 5 ]; then
|
||||
- ocf_log warn "$OCF_RESKEY_ip still has 'tentative' status. (ignored)"
|
||||
+
|
||||
+ # Duplicate Address Detection [DAD]
|
||||
+ # Kernel will flag the IP as 'tentative' until it ensured that
|
||||
+ # there is no duplicates.
|
||||
+ # If there is, it will flag it as 'dadfailed'
|
||||
+ for i in $(seq 1 10); do
|
||||
+ ipstatus=$($IP2UTIL -o -f $FAMILY addr show dev $NIC to $OCF_RESKEY_ip/$NETMASK)
|
||||
+ case "$ipstatus" in
|
||||
+ *dadfailed*)
|
||||
+ ocf_log err "IPv6 address collision $OCF_RESKEY_ip [DAD]"
|
||||
+ $IP2UTIL -f $FAMILY addr del dev $NIC $OCF_RESKEY_ip/$NETMASK
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ ocf_log err "Could not delete IPv6 address"
|
||||
+ fi
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ ;;
|
||||
+ *tentative*)
|
||||
+ if [ $i -eq 10 ]; then
|
||||
+ ofc_log warn "IPv6 address : DAD is still in tentative"
|
||||
+ fi
|
||||
+ ;;
|
||||
+ *)
|
||||
break
|
||||
- fi
|
||||
+ ;;
|
||||
+ esac
|
||||
sleep 1
|
||||
done
|
||||
+ # Now the address should be usable
|
||||
+
|
||||
ARGS="-i $OCF_RESKEY_arp_interval -c $OCF_RESKEY_arp_count $OCF_RESKEY_ip $NETMASK $NIC"
|
||||
ocf_log info "$SENDUA $ARGS"
|
||||
$SENDUA $ARGS || ocf_log err "Could not send ICMPv6 Unsolicited Neighbor Advertisements."
|
||||
@@ -838,6 +854,10 @@
|
||||
else
|
||||
if [ -x $SENDUA ]; then
|
||||
run_send_ua
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ ocf_exit_reason "run_send_ua failed."
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
|
@ -0,0 +1,728 @@
|
|||
diff -uNr a/doc/man/Makefile.am b/doc/man/Makefile.am
|
||||
--- a/doc/man/Makefile.am 2016-02-02 14:49:34.546698286 +0100
|
||||
+++ b/doc/man/Makefile.am 2016-02-02 14:50:29.893979453 +0100
|
||||
@@ -73,7 +73,7 @@
|
||||
ocf_heartbeat_MailTo.7 \
|
||||
ocf_heartbeat_ManageRAID.7 \
|
||||
ocf_heartbeat_ManageVE.7 \
|
||||
- ocf_heartbeat_NovaCompute.7 \
|
||||
+ ocf_heartbeat_nova-compute-wait.7 \
|
||||
ocf_heartbeat_NovaEvacuate.7 \
|
||||
ocf_heartbeat_Pure-FTPd.7 \
|
||||
ocf_heartbeat_Raid1.7 \
|
||||
diff -uNr a/heartbeat/Makefile.am b/heartbeat/Makefile.am
|
||||
--- a/heartbeat/Makefile.am 2016-02-02 14:49:34.546698286 +0100
|
||||
+++ b/heartbeat/Makefile.am 2016-02-02 14:50:29.894979440 +0100
|
||||
@@ -52,7 +52,7 @@
|
||||
IPv6addr_LDADD = -lplumb $(LIBNETLIBS)
|
||||
send_ua_LDADD = $(LIBNETLIBS)
|
||||
|
||||
-osp_SCRIPTS = NovaCompute \
|
||||
+osp_SCRIPTS = nova-compute-wait \
|
||||
NovaEvacuate
|
||||
|
||||
ocf_SCRIPTS = ClusterMon \
|
||||
diff -uNr a/heartbeat/NovaCompute b/heartbeat/NovaCompute
|
||||
--- a/heartbeat/NovaCompute 2016-02-02 14:49:34.541698351 +0100
|
||||
+++ b/heartbeat/NovaCompute 1970-01-01 01:00:00.000000000 +0100
|
||||
@@ -1,366 +0,0 @@
|
||||
-#!/bin/sh
|
||||
-#
|
||||
-#
|
||||
-# NovaCompute agent manages compute daemons.
|
||||
-#
|
||||
-# Copyright (c) 2015
|
||||
-#
|
||||
-# 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.
|
||||
-#
|
||||
-
|
||||
-#######################################################################
|
||||
-# Initialization:
|
||||
-
|
||||
-###
|
||||
-: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
-. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
-###
|
||||
-
|
||||
-: ${__OCF_ACTION=$1}
|
||||
-
|
||||
-#######################################################################
|
||||
-
|
||||
-meta_data() {
|
||||
- cat <<END
|
||||
-<?xml version="1.0"?>
|
||||
-<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
-<resource-agent name="NovaCompute" version="1.0">
|
||||
-<version>1.0</version>
|
||||
-
|
||||
-<longdesc lang="en">
|
||||
-OpenStack Nova Compute Server.
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">OpenStack Nova Compute Server</shortdesc>
|
||||
-
|
||||
-<parameters>
|
||||
-
|
||||
-<parameter name="auth_url" unique="0" required="1">
|
||||
-<longdesc lang="en">
|
||||
-Authorization URL for connecting to keystone in admin context
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">Authorization URL</shortdesc>
|
||||
-<content type="string" default="" />
|
||||
-</parameter>
|
||||
-
|
||||
-<parameter name="username" unique="0" required="1">
|
||||
-<longdesc lang="en">
|
||||
-Username for connecting to keystone in admin context
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">Username</shortdesc>
|
||||
-</parameter>
|
||||
-
|
||||
-<parameter name="password" unique="0" required="1">
|
||||
-<longdesc lang="en">
|
||||
-Password for connecting to keystone in admin context
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">Password</shortdesc>
|
||||
-<content type="string" default="" />
|
||||
-</parameter>
|
||||
-
|
||||
-<parameter name="tenant_name" unique="0" required="1">
|
||||
-<longdesc lang="en">
|
||||
-Tenant name for connecting to keystone in admin context.
|
||||
-Note that with Keystone V3 tenant names are only unique within a domain.
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">Tenant name</shortdesc>
|
||||
-<content type="string" default="" />
|
||||
-</parameter>
|
||||
-
|
||||
-<parameter name="domain" unique="0" required="0">
|
||||
-<longdesc lang="en">
|
||||
-DNS domain in which hosts live, useful when the cluster uses short names and nova uses FQDN
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">DNS domain</shortdesc>
|
||||
-<content type="string" default="" />
|
||||
-</parameter>
|
||||
-
|
||||
-<parameter name="endpoint_type" unique="0" required="0">
|
||||
-<longdesc lang="en">
|
||||
-Nova API location (internal, public or admin URL)
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">Nova API location (internal, public or admin URL)</shortdesc>
|
||||
-<content type="string" default="" />
|
||||
-</parameter>
|
||||
-
|
||||
-<parameter name="no_shared_storage" unique="0" required="0">
|
||||
-<longdesc lang="en">
|
||||
-Disable shared storage recovery for instances. Use at your own risk!
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">Disable shared storage recovery for instances</shortdesc>
|
||||
-<content type="boolean" default="0" />
|
||||
-</parameter>
|
||||
-
|
||||
-<parameter name="evacuation_delay" unique="0" required="0">
|
||||
-<longdesc lang="en">
|
||||
-How long to wait for nova to finish evacuating instances elsewhere
|
||||
-before starting nova-compute. Only used when the agent detects
|
||||
-evacuations might be in progress.
|
||||
-
|
||||
-You may need to increase the start timeout when increasing this value.
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">Delay to allow evacuations time to complete</shortdesc>
|
||||
-<content type="integer" default="120" />
|
||||
-</parameter>
|
||||
-
|
||||
-</parameters>
|
||||
-
|
||||
-<actions>
|
||||
-<action name="start" timeout="600" />
|
||||
-<action name="stop" timeout="300" />
|
||||
-<action name="monitor" timeout="20" interval="10" depth="0"/>
|
||||
-<action name="validate-all" timeout="20" />
|
||||
-<action name="meta-data" timeout="5" />
|
||||
-</actions>
|
||||
-</resource-agent>
|
||||
-END
|
||||
-}
|
||||
-
|
||||
-#######################################################################
|
||||
-
|
||||
-# don't exit on TERM, to test that lrmd makes sure that we do exit
|
||||
-trap sigterm_handler TERM
|
||||
-sigterm_handler() {
|
||||
- ocf_log info "They use TERM to bring us down. No such luck."
|
||||
- return
|
||||
-}
|
||||
-
|
||||
-nova_usage() {
|
||||
- cat <<END
|
||||
-usage: $0 {start|stop|monitor|validate-all|meta-data}
|
||||
-
|
||||
-Expects to have a fully populated OCF RA-compliant environment set.
|
||||
-END
|
||||
-}
|
||||
-
|
||||
-nova_pid() {
|
||||
- ps axf | grep python.*nova-compute | grep -v grep | awk '{print $1}'
|
||||
-}
|
||||
-
|
||||
-nova_start() {
|
||||
- nova_monitor
|
||||
- if [ $? = $OCF_SUCCESS ]; then
|
||||
- return $OCF_SUCCESS
|
||||
- fi
|
||||
-
|
||||
- state=$(attrd_updater -p -n evacute -N ${NOVA_HOST} | sed -e 's/.*value=//' | tr -d '"' )
|
||||
- if [ "x$state" = x ]; then
|
||||
- : never been fenced
|
||||
-
|
||||
- elif [ "x$state" = xno ]; then
|
||||
- : has been evacuated, however it could have been 1s ago
|
||||
- ocf_log info "Pausing to give evacuations from ${NOVA_HOST} time to complete"
|
||||
- sleep ${OCF_RESKEY_evacuation_delay}
|
||||
-
|
||||
- else
|
||||
- ocf_log info "Waiting for pending evacuations from ${NOVA_HOST}"
|
||||
- while [ "x$state" != "xno" ]; do
|
||||
- state=$(attrd_updater -p -n evacute -N ${NOVA_HOST} | sed -e 's/.*value=//' | tr -d '"' )
|
||||
- sleep 5
|
||||
- done
|
||||
-
|
||||
- ocf_log info "Pausing to give evacuations from ${NOVA_HOST} time to complete"
|
||||
- sleep ${OCF_RESKEY_evacuation_delay}
|
||||
- fi
|
||||
-
|
||||
- export LIBGUESTFS_ATTACH_METHOD=appliance
|
||||
- su nova -s /bin/sh -c /usr/bin/nova-compute &
|
||||
-
|
||||
- rc=$OCF_NOT_RUNNING
|
||||
- ocf_log info "Waiting for nova to start"
|
||||
- while [ $rc != $OCF_SUCCESS ]; do
|
||||
- nova_monitor
|
||||
- rc=$?
|
||||
- done
|
||||
-
|
||||
-## TEMPORARY disable call to "service enable" that seems to create
|
||||
-## issues and it is unnecessary since fence_compute doesn't disable
|
||||
-## the service
|
||||
-
|
||||
-# if [ "x${OCF_RESKEY_domain}" != x ]; then
|
||||
-# export service_host="${NOVA_HOST}.${OCF_RESKEY_domain}"
|
||||
-# else
|
||||
-# export service_host="${NOVA_HOST}"
|
||||
-# fi
|
||||
-
|
||||
-# python -c "import os; from novaclient import client as nova_client; nova = nova_client.Client('2', os.environ.get('OCF_RESKEY_username'), os.environ.get('OCF_RESKEY_password'), os.environ.get('OCF_RESKEY_tenant_name'), os.environ.get('OCF_RESKEY_auth_url')); nova.services.enable(os.environ.get('service_host'), 'nova-compute');"
|
||||
-
|
||||
-# rc=$?
|
||||
-# if [ $rc != 0 ]; then
|
||||
-# ocf_exit_reason "nova.services.enable failed $rc"
|
||||
-# exit $OCF_NOT_RUNNING
|
||||
-# fi
|
||||
-
|
||||
- return $OCF_SUCCESS
|
||||
-}
|
||||
-
|
||||
-nova_stop() {
|
||||
- pid=$(nova_pid)
|
||||
- if [ "x$pid" != x ]; then
|
||||
- su nova -c "kill -TERM $pid" -s /bin/bash
|
||||
- fi
|
||||
-
|
||||
- while [ "x$pid" != x ]; do
|
||||
- sleep 1
|
||||
- pid=$(nova_pid)
|
||||
- done
|
||||
-
|
||||
- return $OCF_SUCCESS
|
||||
-}
|
||||
-
|
||||
-nova_monitor() {
|
||||
- pid=$(nova_pid)
|
||||
- if [ "x$pid" != x ]; then
|
||||
- ## TEMPORARY disable call to fence_compute to avoid noise on first
|
||||
- ## first startup due to nova-compute not being fast enough to populate
|
||||
- ## the db and fence_compute checking if node exists and it's enabled
|
||||
- #state=$(fence_compute ${fence_options} -o status -n $NOVA_HOST | grep Status)
|
||||
- #if [ "x$state" = "xStatus: ON" ]; then
|
||||
- return $OCF_SUCCESS
|
||||
- #else
|
||||
- # ocf_exit_reason "Nova status: $state"
|
||||
- # return $OCF_ERR_GENERIC
|
||||
- #fi
|
||||
- fi
|
||||
-
|
||||
- return $OCF_NOT_RUNNING
|
||||
-}
|
||||
-
|
||||
-nova_notify() {
|
||||
- return $OCF_SUCCESS
|
||||
-}
|
||||
-
|
||||
-nova_validate() {
|
||||
- rc=$OCF_SUCCESS
|
||||
- fence_options=""
|
||||
-
|
||||
- check_binary openstack-config
|
||||
- check_binary nova-compute
|
||||
-
|
||||
- if [ ! -f /etc/nova/nova.conf ]; then
|
||||
- ocf_exit_reason "/etc/nova/nova.conf not found"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- if [ -z "${OCF_RESKEY_auth_url}" ]; then
|
||||
- ocf_exit_reason "auth_url not configured"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- fence_options="${fence_options} -k ${OCF_RESKEY_auth_url}"
|
||||
-
|
||||
- if [ -z "${OCF_RESKEY_username}" ]; then
|
||||
- ocf_exit_reason "username not configured"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- fence_options="${fence_options} -l ${OCF_RESKEY_username}"
|
||||
-
|
||||
- if [ -z "${OCF_RESKEY_password}" ]; then
|
||||
- ocf_exit_reason "password not configured"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- fence_options="${fence_options} -p ${OCF_RESKEY_password}"
|
||||
-
|
||||
- if [ -z "${OCF_RESKEY_tenant_name}" ]; then
|
||||
- ocf_exit_reason "tenant_name not configured"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- fence_options="${fence_options} -t ${OCF_RESKEY_tenant_name}"
|
||||
-
|
||||
- if [ -n "${OCF_RESKEY_domain}" ]; then
|
||||
- fence_options="${fence_options} -d ${OCF_RESKEY_domain}"
|
||||
- fi
|
||||
-
|
||||
- if [ -n "${OCF_RESKEY_no_shared_storage}" ]; then
|
||||
- if ocf_is_true "${OCF_RESKEY_no_shared_storage}"; then
|
||||
- fence_options="${fence_options} --no-shared-storage"
|
||||
- fi
|
||||
- fi
|
||||
-
|
||||
- if [ -n "${OCF_RESKEY_endpoint_type}" ]; then
|
||||
- case ${OCF_RESKEY_endpoint_type} in
|
||||
- adminURL|publicURL|internalURL) ;;
|
||||
- *)
|
||||
- ocf_exit_reason "endpoint_type ${OCF_RESKEY_endpoint_type} not valid. Use adminURL or publicURL or internalURL"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
- ;;
|
||||
- esac
|
||||
- fence_options="${fence_options} -e ${OCF_RESKEY_endpoint_type}"
|
||||
- fi
|
||||
-
|
||||
- # we take a chance here and hope that host is either not configured
|
||||
- # or configured in nova.conf
|
||||
-
|
||||
- NOVA_HOST=$(openstack-config --get /etc/nova/nova.conf DEFAULT host 2>/dev/null)
|
||||
- if [ $? = 1 ]; then
|
||||
- if [ "x${OCF_RESKEY_domain}" != x ]; then
|
||||
- NOVA_HOST=$(uname -n | awk -F. '{print $1}')
|
||||
- else
|
||||
- NOVA_HOST=$(uname -n)
|
||||
- fi
|
||||
- fi
|
||||
-
|
||||
- # We only need to check a configured value, calculated ones are fine
|
||||
- openstack-config --get /etc/nova/nova.conf DEFAULT host 2>/dev/null
|
||||
- if [ $? = 0 ]; then
|
||||
- if [ "x${OCF_RESKEY_domain}" != x ]; then
|
||||
- short_host=$(uname -n | awk -F. '{print $1}')
|
||||
- if [ "x$NOVA_HOST" != "x${short_host}" ]; then
|
||||
- ocf_exit_reason "Invalid Nova host name, must be ${short_host} in order for instance recovery to function"
|
||||
- rc=$OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- elif [ "x$NOVA_HOST" != "x$(uname -n)" ]; then
|
||||
- ocf_exit_reason "Invalid Nova host name, must be $(uname -n) in order for instance recovery to function"
|
||||
- rc=$OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
- fi
|
||||
-
|
||||
- if [ $rc != $OCF_SUCCESS ]; then
|
||||
- exit $rc
|
||||
- fi
|
||||
- return $rc
|
||||
-}
|
||||
-
|
||||
-: ${OCF_RESKEY_evacuation_delay=120}
|
||||
-case $__OCF_ACTION in
|
||||
-meta-data) meta_data
|
||||
- exit $OCF_SUCCESS
|
||||
- ;;
|
||||
-usage|help) nova_usage
|
||||
- exit $OCF_SUCCESS
|
||||
- ;;
|
||||
-esac
|
||||
-
|
||||
-case $__OCF_ACTION in
|
||||
-start) nova_validate; nova_start;;
|
||||
-stop) nova_stop;;
|
||||
-monitor) nova_validate; nova_monitor;;
|
||||
-notify) nova_notify;;
|
||||
-validate-all) exit $OCF_SUCCESS;;
|
||||
-*) nova_usage
|
||||
- exit $OCF_ERR_UNIMPLEMENTED
|
||||
- ;;
|
||||
-esac
|
||||
-rc=$?
|
||||
-ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
|
||||
-exit $rc
|
||||
diff -uNr a/heartbeat/nova-compute-wait b/heartbeat/nova-compute-wait
|
||||
--- a/heartbeat/nova-compute-wait 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ b/heartbeat/nova-compute-wait 2016-02-02 14:50:29.894979440 +0100
|
||||
@@ -0,0 +1,304 @@
|
||||
+#!/bin/sh
|
||||
+#
|
||||
+#
|
||||
+# nova-compute-wait agent manages compute daemons.
|
||||
+#
|
||||
+# Copyright (c) 2015
|
||||
+#
|
||||
+# 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.
|
||||
+#
|
||||
+
|
||||
+#######################################################################
|
||||
+# Initialization:
|
||||
+
|
||||
+###
|
||||
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
+###
|
||||
+
|
||||
+: ${__OCF_ACTION=$1}
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+meta_data() {
|
||||
+ cat <<END
|
||||
+<?xml version="1.0"?>
|
||||
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
+<resource-agent name="nova-compute-wait" version="1.0">
|
||||
+<version>1.0</version>
|
||||
+
|
||||
+<longdesc lang="en">
|
||||
+OpenStack Nova Compute Server.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">OpenStack Nova Compute Server</shortdesc>
|
||||
+
|
||||
+<parameters>
|
||||
+
|
||||
+<parameter name="auth_url" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Authorization URL for connecting to keystone in admin context
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Authorization URL</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="username" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Username for connecting to keystone in admin context
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Username</shortdesc>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="password" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Password for connecting to keystone in admin context
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Password</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="tenant_name" unique="0" required="1">
|
||||
+<longdesc lang="en">
|
||||
+Tenant name for connecting to keystone in admin context.
|
||||
+Note that with Keystone V3 tenant names are only unique within a domain.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Tenant name</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="domain" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+DNS domain in which hosts live, useful when the cluster uses short names and nova uses FQDN
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">DNS domain</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="endpoint_type" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Nova API location (internal, public or admin URL)
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Nova API location (internal, public or admin URL)</shortdesc>
|
||||
+<content type="string" default="" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="no_shared_storage" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Disable shared storage recovery for instances. Use at your own risk!
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Disable shared storage recovery for instances</shortdesc>
|
||||
+<content type="boolean" default="0" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="evacuation_delay" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+How long to wait for nova to finish evacuating instances elsewhere
|
||||
+before starting nova-compute. Only used when the agent detects
|
||||
+evacuations might be in progress.
|
||||
+
|
||||
+You may need to increase the start timeout when increasing this value.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Delay to allow evacuations time to complete</shortdesc>
|
||||
+<content type="integer" default="120" />
|
||||
+</parameter>
|
||||
+
|
||||
+</parameters>
|
||||
+
|
||||
+<actions>
|
||||
+<action name="start" timeout="600" />
|
||||
+<action name="stop" timeout="300" />
|
||||
+<action name="monitor" timeout="20" interval="10" depth="0"/>
|
||||
+<action name="validate-all" timeout="20" />
|
||||
+<action name="meta-data" timeout="5" />
|
||||
+</actions>
|
||||
+</resource-agent>
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+# don't exit on TERM, to test that lrmd makes sure that we do exit
|
||||
+trap sigterm_handler TERM
|
||||
+sigterm_handler() {
|
||||
+ ocf_log info "They use TERM to bring us down. No such luck."
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+nova_usage() {
|
||||
+ cat <<END
|
||||
+usage: $0 {start|stop|monitor|validate-all|meta-data}
|
||||
+
|
||||
+Expects to have a fully populated OCF RA-compliant environment set.
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+nova_start() {
|
||||
+ state=$(attrd_updater -p -n evacuate -N ${NOVA_HOST} | sed -e 's/.*value=//' | tr -d '"' )
|
||||
+ if [ "x$state" = x ]; then
|
||||
+ : never been fenced
|
||||
+
|
||||
+ elif [ "x$state" = xno ]; then
|
||||
+ : has been evacuated, however it could have been 1s ago
|
||||
+ ocf_log info "Pausing to give evacuations from ${NOVA_HOST} time to complete"
|
||||
+ sleep ${OCF_RESKEY_evacuation_delay}
|
||||
+
|
||||
+ else
|
||||
+ ocf_log info "Waiting for pending evacuations from ${NOVA_HOST}"
|
||||
+ while [ "x$state" != "xno" ]; do
|
||||
+ state=$(attrd_updater -p -n evacuate -N ${NOVA_HOST} | sed -e 's/.*value=//' | tr -d '"' )
|
||||
+ sleep 5
|
||||
+ done
|
||||
+
|
||||
+ ocf_log info "Pausing to give evacuations from ${NOVA_HOST} time to complete"
|
||||
+ sleep ${OCF_RESKEY_evacuation_delay}
|
||||
+ fi
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+nova_stop() {
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+nova_monitor() {
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+nova_notify() {
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+nova_validate() {
|
||||
+ rc=$OCF_SUCCESS
|
||||
+ fence_options=""
|
||||
+
|
||||
+ check_binary openstack-config
|
||||
+ check_binary nova-compute
|
||||
+
|
||||
+ if [ ! -f /etc/nova/nova.conf ]; then
|
||||
+ ocf_exit_reason "/etc/nova/nova.conf not found"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_auth_url}" ]; then
|
||||
+ ocf_exit_reason "auth_url not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -k ${OCF_RESKEY_auth_url}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_username}" ]; then
|
||||
+ ocf_exit_reason "username not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -l ${OCF_RESKEY_username}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_password}" ]; then
|
||||
+ ocf_exit_reason "password not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -p ${OCF_RESKEY_password}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_tenant_name}" ]; then
|
||||
+ ocf_exit_reason "tenant_name not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -t ${OCF_RESKEY_tenant_name}"
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_domain}" ]; then
|
||||
+ fence_options="${fence_options} -d ${OCF_RESKEY_domain}"
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_no_shared_storage}" ]; then
|
||||
+ if ocf_is_true "${OCF_RESKEY_no_shared_storage}"; then
|
||||
+ fence_options="${fence_options} --no-shared-storage"
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_endpoint_type}" ]; then
|
||||
+ case ${OCF_RESKEY_endpoint_type} in
|
||||
+ adminURL|publicURL|internalURL) ;;
|
||||
+ *)
|
||||
+ ocf_exit_reason "endpoint_type ${OCF_RESKEY_endpoint_type} not valid. Use adminURL or publicURL or internalURL"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ ;;
|
||||
+ esac
|
||||
+ fence_options="${fence_options} -e ${OCF_RESKEY_endpoint_type}"
|
||||
+ fi
|
||||
+
|
||||
+ # we take a chance here and hope that host is either not configured
|
||||
+ # or configured in nova.conf
|
||||
+
|
||||
+ NOVA_HOST=$(openstack-config --get /etc/nova/nova.conf DEFAULT host 2>/dev/null)
|
||||
+ if [ $? = 1 ]; then
|
||||
+ if [ "x${OCF_RESKEY_domain}" != x ]; then
|
||||
+ NOVA_HOST=$(uname -n | awk -F. '{print $1}')
|
||||
+ else
|
||||
+ NOVA_HOST=$(uname -n)
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ # We only need to check a configured value, calculated ones are fine
|
||||
+ openstack-config --get /etc/nova/nova.conf DEFAULT host 2>/dev/null
|
||||
+ if [ $? = 0 ]; then
|
||||
+ if [ "x${OCF_RESKEY_domain}" != x ]; then
|
||||
+ short_host=$(uname -n | awk -F. '{print $1}')
|
||||
+ if [ "x$NOVA_HOST" != "x${short_host}" ]; then
|
||||
+ ocf_exit_reason "Invalid Nova host name, must be ${short_host} in order for instance recovery to function"
|
||||
+ rc=$OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ elif [ "x$NOVA_HOST" != "x$(uname -n)" ]; then
|
||||
+ ocf_exit_reason "Invalid Nova host name, must be $(uname -n) in order for instance recovery to function"
|
||||
+ rc=$OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if [ $rc != $OCF_SUCCESS ]; then
|
||||
+ exit $rc
|
||||
+ fi
|
||||
+ return $rc
|
||||
+}
|
||||
+
|
||||
+: ${OCF_RESKEY_evacuation_delay=120}
|
||||
+case $__OCF_ACTION in
|
||||
+meta-data) meta_data
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+usage|help) nova_usage
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+esac
|
||||
+
|
||||
+case $__OCF_ACTION in
|
||||
+start) nova_validate; nova_start;;
|
||||
+stop) nova_stop;;
|
||||
+monitor) nova_validate; nova_monitor;;
|
||||
+notify) nova_notify;;
|
||||
+validate-all) exit $OCF_SUCCESS;;
|
||||
+*) nova_usage
|
||||
+ exit $OCF_ERR_UNIMPLEMENTED
|
||||
+ ;;
|
||||
+esac
|
||||
+rc=$?
|
||||
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
|
||||
+exit $rc
|
||||
diff -uNr a/heartbeat/NovaEvacuate b/heartbeat/NovaEvacuate
|
||||
--- a/heartbeat/NovaEvacuate 2016-02-02 14:49:34.541698351 +0100
|
||||
+++ b/heartbeat/NovaEvacuate 2016-02-02 14:50:22.768072003 +0100
|
||||
@@ -141,7 +141,7 @@
|
||||
}
|
||||
|
||||
update_evacuation() {
|
||||
- attrd_updater -p -n evacute -Q -N ${1} -v ${2}
|
||||
+ attrd_updater -p -n evacuate -Q -N ${1} -v ${2}
|
||||
arc=$?
|
||||
if [ ${arc} != 0 ]; then
|
||||
ocf_log warn "Can not set evacuation state of ${1} to ${2}: ${arc}"
|
||||
@@ -219,7 +219,12 @@
|
||||
return $OCF_NOT_RUNNING
|
||||
fi
|
||||
|
||||
- handle_evacuations $(attrd_updater -n evacute -A | tr '="' ' ' | awk '{print $4" "$6}')
|
||||
+ handle_evacuations $(
|
||||
+ attrd_updater -n evacuate -A |
|
||||
+ sed 's/ value=""/ value="no"/' |
|
||||
+ tr '="' ' ' |
|
||||
+ awk '{print $4" "$6}'
|
||||
+ )
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
From d9833b68498e306d181be11adf9eee14b646a899 Mon Sep 17 00:00:00 2001
|
||||
From: Damien Ciabrini <dciabrin@redhat.com>
|
||||
Date: Tue, 2 Feb 2016 14:34:36 +0100
|
||||
Subject: [PATCH] galera: force crash recovery if needed during last commit
|
||||
detection
|
||||
|
||||
---
|
||||
heartbeat/galera | 90 +++++++++++++++++++++++++++++++++++++-------------------
|
||||
1 file changed, 60 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/galera b/heartbeat/galera
|
||||
index 7be2b00..ca94c21 100755
|
||||
--- a/heartbeat/galera
|
||||
+++ b/heartbeat/galera
|
||||
@@ -525,6 +525,58 @@ detect_first_master()
|
||||
set_bootstrap_node $best_node
|
||||
}
|
||||
|
||||
+detect_last_commit()
|
||||
+{
|
||||
+ local last_commit
|
||||
+ local recover_args="--defaults-file=$OCF_RESKEY_config \
|
||||
+ --pid-file=$OCF_RESKEY_pid \
|
||||
+ --socket=$OCF_RESKEY_socket \
|
||||
+ --datadir=$OCF_RESKEY_datadir \
|
||||
+ --user=$OCF_RESKEY_user"
|
||||
+ local recovered_position_regex='s/.*WSREP\:\s*[R|r]ecovered\s*position.*\:\(.*\)\s*$/\1/p'
|
||||
+
|
||||
+ ocf_log info "attempting to detect last commit version by reading ${OCF_RESKEY_datadir}/grastate.dat"
|
||||
+ last_commit="$(cat ${OCF_RESKEY_datadir}/grastate.dat | sed -n 's/^seqno.\s*\(.*\)\s*$/\1/p')"
|
||||
+ if [ -z "$last_commit" ] || [ "$last_commit" = "-1" ]; then
|
||||
+ local tmp=$(mktemp)
|
||||
+ local tmperr=$(mktemp)
|
||||
+
|
||||
+ ocf_log info "now attempting to detect last commit version using 'mysqld_safe --wsrep-recover'"
|
||||
+
|
||||
+ ${OCF_RESKEY_binary} $recover_args --wsrep-recover > $tmp 2> $tmperr
|
||||
+
|
||||
+ last_commit="$(cat $tmp | sed -n $recovered_position_regex)"
|
||||
+ if [ -z "$last_commit" ]; then
|
||||
+ # Galera uses InnoDB's 2pc transactions internally. If
|
||||
+ # server was stopped in the middle of a replication, the
|
||||
+ # recovery may find a "prepared" XA transaction in the
|
||||
+ # redo log, and mysql won't recover automatically
|
||||
+
|
||||
+ cat $tmperr | grep -q -E '\[ERROR\]\s+Found\s+[0-9]+\s+prepared\s+transactions!' 2>/dev/null
|
||||
+ if [ $? -eq 0 ]; then
|
||||
+ # we can only rollback the transaction, but that's OK
|
||||
+ # since the DB will get resynchronized anyway
|
||||
+ ocf_log warn "local node <${NODENAME}> was not shutdown properly. Rollback stuck transaction with --tc-heuristic-recover"
|
||||
+ ${OCF_RESKEY_binary} $recover_args --wsrep-recover \
|
||||
+ --tc-heuristic-recover=rollback > $tmp 2>/dev/null
|
||||
+
|
||||
+ last_commit="$(cat $tmp | sed -n $recovered_position_regex)"
|
||||
+ fi
|
||||
+ fi
|
||||
+ rm -f $tmp $tmperr
|
||||
+ fi
|
||||
+
|
||||
+ if [ ! -z "$last_commit" ]; then
|
||||
+ ocf_log info "Last commit version found: $last_commit"
|
||||
+ set_last_commit $last_commit
|
||||
+ return $OCF_SUCCESS
|
||||
+ else
|
||||
+ ocf_exit_reason "Unable to detect last known write sequence number"
|
||||
+ clear_last_commit
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
# For galera, promote is really start
|
||||
galera_promote()
|
||||
{
|
||||
@@ -569,13 +620,15 @@ galera_demote()
|
||||
clear_bootstrap_node
|
||||
clear_last_commit
|
||||
|
||||
- # record last commit by "starting" galera. start is just detection of the last sequence number
|
||||
- galera_start
|
||||
+ # record last commit for next promotion
|
||||
+ detect_last_commit
|
||||
+ rc=$?
|
||||
+ return $rc
|
||||
}
|
||||
|
||||
galera_start()
|
||||
{
|
||||
- local last_commit
|
||||
+ local rc
|
||||
|
||||
echo $OCF_RESKEY_wsrep_cluster_address | grep -q $NODENAME
|
||||
if [ $? -ne 0 ]; then
|
||||
@@ -591,34 +644,11 @@ galera_start()
|
||||
|
||||
mysql_common_prepare_dirs
|
||||
|
||||
- ocf_log info "attempting to detect last commit version by reading ${OCF_RESKEY_datadir}/grastate.dat"
|
||||
- last_commit="$(cat ${OCF_RESKEY_datadir}/grastate.dat | sed -n 's/^seqno.\s*\(.*\)\s*$/\1/p')"
|
||||
- if [ -z "$last_commit" ] || [ "$last_commit" = "-1" ]; then
|
||||
- ocf_log info "now attempting to detect last commit version using 'mysqld_safe --wsrep-recover'"
|
||||
- local tmp=$(mktemp)
|
||||
- ${OCF_RESKEY_binary} --defaults-file=$OCF_RESKEY_config \
|
||||
- --pid-file=$OCF_RESKEY_pid \
|
||||
- --socket=$OCF_RESKEY_socket \
|
||||
- --datadir=$OCF_RESKEY_datadir \
|
||||
- --user=$OCF_RESKEY_user \
|
||||
- --wsrep-recover > $tmp 2>&1
|
||||
-
|
||||
- last_commit="$(cat $tmp | sed -n 's/.*WSREP\:\s*[R|r]ecovered\s*position.*\:\(.*\)\s*$/\1/p')"
|
||||
- rm -f $tmp
|
||||
-
|
||||
- if [ "$last_commit" = "-1" ]; then
|
||||
- last_commit="0"
|
||||
- fi
|
||||
- fi
|
||||
-
|
||||
- if [ -z "$last_commit" ]; then
|
||||
- ocf_exit_reason "Unable to detect last known write sequence number"
|
||||
- clear_last_commit
|
||||
- return $OCF_ERR_GENERIC
|
||||
+ detect_last_commit
|
||||
+ rc=$?
|
||||
+ if [ $rc -ne $OCF_SUCCESS ]; then
|
||||
+ return $rc
|
||||
fi
|
||||
- ocf_log info "Last commit version found: $last_commit"
|
||||
-
|
||||
- set_last_commit $last_commit
|
||||
|
||||
master_exists
|
||||
if [ $? -eq 0 ]; then
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
From 4d98bbcdadda60166faf7ccc512b9095b439e2bd Mon Sep 17 00:00:00 2001
|
||||
From: Damien Ciabrini <dciabrin@redhat.com>
|
||||
Date: Tue, 2 Feb 2016 16:29:10 +0100
|
||||
Subject: [PATCH] galera: prevent recovered nodes from bootstrapping cluster
|
||||
when possible
|
||||
|
||||
---
|
||||
heartbeat/README.galera | 19 ++++++++++++++++++-
|
||||
heartbeat/galera | 41 +++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 59 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/galera b/heartbeat/galera
|
||||
index ca94c21..84c92fd 100755
|
||||
--- a/heartbeat/galera
|
||||
+++ b/heartbeat/galera
|
||||
@@ -276,6 +276,22 @@ is_bootstrap()
|
||||
|
||||
}
|
||||
|
||||
+set_heuristic_recovered()
|
||||
+{
|
||||
+ ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-heuristic-recovered" -v "true"
|
||||
+}
|
||||
+
|
||||
+clear_heuristic_recovered()
|
||||
+{
|
||||
+ ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-heuristic-recovered" -D
|
||||
+}
|
||||
+
|
||||
+is_heuristic_recovered()
|
||||
+{
|
||||
+ local node=$1
|
||||
+ ${HA_SBIN_DIR}/crm_attribute -N $node -l reboot --name "${INSTANCE_ATTR_NAME}-heuristic-recovered" -Q 2>/dev/null
|
||||
+}
|
||||
+
|
||||
clear_last_commit()
|
||||
{
|
||||
${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-last-committed" -D
|
||||
@@ -398,8 +414,19 @@ detect_first_master()
|
||||
local best_node="$NODENAME"
|
||||
local last_commit=0
|
||||
local missing_nodes=0
|
||||
+ local nodes=""
|
||||
+ local nodes_recovered=""
|
||||
|
||||
+ # avoid selecting a recovered node as bootstrap if possible
|
||||
for node in $(echo "$OCF_RESKEY_wsrep_cluster_address" | sed 's/gcomm:\/\///g' | tr -d ' ' | tr -s ',' ' '); do
|
||||
+ if is_heuristic_recovered $node; then
|
||||
+ nodes_recovered="$nodes_recovered $node"
|
||||
+ else
|
||||
+ nodes="$nodes $node"
|
||||
+ fi
|
||||
+ done
|
||||
+
|
||||
+ for node in $nodes_recovered $nodes; do
|
||||
last_commit=$(get_last_commit $node)
|
||||
|
||||
if [ -z "$last_commit" ]; then
|
||||
@@ -466,6 +493,12 @@ detect_last_commit()
|
||||
--tc-heuristic-recover=rollback > $tmp 2>/dev/null
|
||||
|
||||
last_commit="$(cat $tmp | sed -n $recovered_position_regex)"
|
||||
+ if [ ! -z "$last_commit" ]; then
|
||||
+ ocf_log warn "State recovered. force SST at next restart for full resynchronization"
|
||||
+ rm -f ${OCF_RESKEY_datadir}/grastate.dat
|
||||
+ # try not to use this node if bootstrap is needed
|
||||
+ set_heuristic_recovered
|
||||
+ fi
|
||||
fi
|
||||
fi
|
||||
rm -f $tmp $tmperr
|
||||
@@ -549,11 +582,17 @@ galera_promote()
|
||||
if ocf_is_true $bootstrap; then
|
||||
promote_everyone
|
||||
clear_bootstrap_node
|
||||
+ # clear attribute heuristic-recovered. if last shutdown was
|
||||
+ # not clean, we cannot be extra-cautious by requesting a SST
|
||||
+ # since this is the bootstrap node
|
||||
+ clear_heuristic_recovered
|
||||
ocf_log info "Bootstrap complete, promoting the rest of the galera instances."
|
||||
else
|
||||
# if this is not the bootstrap node, make sure this instance
|
||||
# syncs with the rest of the cluster before promotion returns.
|
||||
wait_for_sync
|
||||
+ # sync is done, clear info about last recovery
|
||||
+ clear_heuristic_recovered
|
||||
fi
|
||||
|
||||
ocf_log info "Galera started"
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
From 422ef6a2018ebf9d6765e1f2965778f42c6a9d9c Mon Sep 17 00:00:00 2001
|
||||
From: Damien Ciabrini <dciabrin@redhat.com>
|
||||
Date: Tue, 15 Mar 2016 18:45:13 +0100
|
||||
Subject: [PATCH] galera: don't bootstrap from a node with no grastate.dat when
|
||||
possible
|
||||
|
||||
---
|
||||
heartbeat/README.galera | 9 ++++-----
|
||||
heartbeat/galera | 36 ++++++++++++++++++++++--------------
|
||||
2 files changed, 26 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/galera b/heartbeat/galera
|
||||
index 72add3c..e4495be 100755
|
||||
--- a/heartbeat/galera
|
||||
+++ b/heartbeat/galera
|
||||
@@ -276,20 +276,20 @@ is_bootstrap()
|
||||
|
||||
}
|
||||
|
||||
-set_heuristic_recovered()
|
||||
+set_no_grastate()
|
||||
{
|
||||
- ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-heuristic-recovered" -v "true"
|
||||
+ ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-no-grastate" -v "true"
|
||||
}
|
||||
|
||||
-clear_heuristic_recovered()
|
||||
+clear_no_grastate()
|
||||
{
|
||||
- ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-heuristic-recovered" -D
|
||||
+ ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-no-grastate" -D
|
||||
}
|
||||
|
||||
-is_heuristic_recovered()
|
||||
+is_no_grastate()
|
||||
{
|
||||
local node=$1
|
||||
- ${HA_SBIN_DIR}/crm_attribute -N $node -l reboot --name "${INSTANCE_ATTR_NAME}-heuristic-recovered" -Q 2>/dev/null
|
||||
+ ${HA_SBIN_DIR}/crm_attribute -N $node -l reboot --name "${INSTANCE_ATTR_NAME}-no-grastate" -Q 2>/dev/null
|
||||
}
|
||||
|
||||
clear_last_commit()
|
||||
@@ -419,7 +419,7 @@ detect_first_master()
|
||||
|
||||
# avoid selecting a recovered node as bootstrap if possible
|
||||
for node in $(echo "$OCF_RESKEY_wsrep_cluster_address" | sed 's/gcomm:\/\///g' | tr -d ' ' | tr -s ',' ' '); do
|
||||
- if is_heuristic_recovered $node; then
|
||||
+ if is_no_grastate $node; then
|
||||
nodes_recovered="$nodes_recovered $node"
|
||||
else
|
||||
nodes="$nodes $node"
|
||||
@@ -473,6 +473,12 @@ detect_last_commit()
|
||||
local tmp=$(mktemp)
|
||||
local tmperr=$(mktemp)
|
||||
|
||||
+ # if we pass here because grastate.dat doesn't exist,
|
||||
+ # try not to bootstrap from this node if possible
|
||||
+ if [ ! -f ${OCF_RESKEY_datadir}/grastate.dat ]; then
|
||||
+ set_no_grastate
|
||||
+ fi
|
||||
+
|
||||
ocf_log info "now attempting to detect last commit version using 'mysqld_safe --wsrep-recover'"
|
||||
|
||||
${OCF_RESKEY_binary} $recover_args --wsrep-recover > $tmp 2> $tmperr
|
||||
@@ -496,8 +502,8 @@ detect_last_commit()
|
||||
if [ ! -z "$last_commit" ]; then
|
||||
ocf_log warn "State recovered. force SST at next restart for full resynchronization"
|
||||
rm -f ${OCF_RESKEY_datadir}/grastate.dat
|
||||
- # try not to use this node if bootstrap is needed
|
||||
- set_heuristic_recovered
|
||||
+ # try not to bootstrap from this node if possible
|
||||
+ set_no_grastate
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -582,17 +588,17 @@ galera_promote()
|
||||
if ocf_is_true $bootstrap; then
|
||||
promote_everyone
|
||||
clear_bootstrap_node
|
||||
- # clear attribute heuristic-recovered. if last shutdown was
|
||||
+ # clear attribute no-grastate. if last shutdown was
|
||||
# not clean, we cannot be extra-cautious by requesting a SST
|
||||
# since this is the bootstrap node
|
||||
- clear_heuristic_recovered
|
||||
+ clear_no_grastate
|
||||
ocf_log info "Bootstrap complete, promoting the rest of the galera instances."
|
||||
else
|
||||
# if this is not the bootstrap node, make sure this instance
|
||||
# syncs with the rest of the cluster before promotion returns.
|
||||
wait_for_sync
|
||||
- # sync is done, clear info about last recovery
|
||||
- clear_heuristic_recovered
|
||||
+ # sync is done, clear info about last startup
|
||||
+ clear_no_grastate
|
||||
fi
|
||||
|
||||
ocf_log info "Galera started"
|
||||
@@ -611,6 +617,7 @@ galera_demote()
|
||||
# if this node was previously a bootstrap node, that is no longer the case.
|
||||
clear_bootstrap_node
|
||||
clear_last_commit
|
||||
+ clear_no_grastate
|
||||
|
||||
# record last commit for next promotion
|
||||
detect_last_commit
|
||||
@@ -722,6 +729,7 @@ galera_stop()
|
||||
clear_last_commit
|
||||
clear_master_score
|
||||
clear_bootstrap_node
|
||||
+ clear_no_grastate
|
||||
return $rc
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
From 5e9310bbbcd5086ea9a3edf85d523c4c2a57f1c3 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Beekhof <andrew@beekhof.net>
|
||||
Date: Tue, 8 Dec 2015 13:54:12 +1100
|
||||
Subject: [PATCH] NovaEvacuate should invoke fence_compute with action 'off'
|
||||
|
||||
Conceptually we are resurrecting in one direction only (off) and not
|
||||
bringing it back to the current host afterwards (on)
|
||||
|
||||
Also it will overwrite the attrd variable too soon.
|
||||
|
||||
Change-Id: I9694945ca7eedae4f5cb6758fe1e8ce7f72ae808
|
||||
---
|
||||
ocf/NovaEvacuate | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/NovaEvacuate b/heartbeat/NovaEvacuate
|
||||
index a17a159..0e22d7e 100644
|
||||
--- a/heartbeat/NovaEvacuate
|
||||
+++ b/heartbeat/NovaEvacuate
|
||||
@@ -198,7 +198,7 @@ handle_evacuations() {
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
- fence_compute ${fence_options} -o reboot -n $node
|
||||
+ fence_compute ${fence_options} -o off -n $node
|
||||
rc=$?
|
||||
|
||||
if [ $rc = 0 ]; then
|
||||
--
|
||||
1.9.1
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
diff -uNr a/heartbeat/NovaEvacuate b/heartbeat/NovaEvacuate
|
||||
--- a/heartbeat/NovaEvacuate 2016-02-29 10:54:21.933786269 +0100
|
||||
+++ b/heartbeat/NovaEvacuate 2016-02-29 13:29:27.000139496 +0100
|
||||
@@ -177,17 +177,10 @@
|
||||
esac
|
||||
|
||||
if [ $need_evacuate = 1 ]; then
|
||||
- found=0
|
||||
ocf_log notice "Initiating evacuation of $node"
|
||||
|
||||
- for known in $(fence_compute ${fence_options} -o list | tr -d ','); do
|
||||
- if [ ${known} = ${node} ]; then
|
||||
- found=1
|
||||
- break
|
||||
- fi
|
||||
- done
|
||||
-
|
||||
- if [ $found = 0 ]; then
|
||||
+ fence_compute ${fence_options} -o status -n ${node}
|
||||
+ if [ $? != 0 ]; then
|
||||
ocf_log info "Nova does not know about ${node}"
|
||||
# Dont mark as no because perhaps nova is unavailable right now
|
||||
continue
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,101 @@
|
|||
diff -uNr a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
--- a/heartbeat/VirtualDomain 2016-03-04 14:41:22.001333979 +0100
|
||||
+++ b/heartbeat/VirtualDomain 2016-03-04 14:42:34.516395470 +0100
|
||||
@@ -17,12 +17,16 @@
|
||||
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
|
||||
# Defaults
|
||||
+OCF_RESKEY_migration_downtime_default=0
|
||||
+OCF_RESKEY_migration_speed_default=0
|
||||
OCF_RESKEY_force_stop_default=0
|
||||
OCF_RESKEY_autoset_utilization_cpu_default="true"
|
||||
OCF_RESKEY_autoset_utilization_hv_memory_default="true"
|
||||
OCF_RESKEY_migrateport_default=$(( 49152 + $(ocf_maybe_random) % 64 ))
|
||||
OCF_RESKEY_CRM_meta_timeout_default=90000
|
||||
|
||||
+: ${OCF_RESKEY_migration_downtime=${OCF_RESKEY_migration_downtime_default}}
|
||||
+: ${OCF_RESKEY_migration_speed=${OCF_RESKEY_migration_speed_default}}
|
||||
: ${OCF_RESKEY_force_stop=${OCF_RESKEY_force_stop_default}}
|
||||
: ${OCF_RESKEY_autoset_utilization_cpu=${OCF_RESKEY_autoset_utilization_cpu_default}}
|
||||
: ${OCF_RESKEY_autoset_utilization_hv_memory=${OCF_RESKEY_autoset_utilization_hv_memory_default}}
|
||||
@@ -96,6 +100,22 @@
|
||||
<content type="string" default="" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="migration_downtime" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Define max downtime during live migration in milliseconds
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Live migration downtime</shortdesc>
|
||||
+<content type="integer" default="${OCF_RESKEY_migration_downtime_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="migration_speed" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Define live migration speed per resource in MiB/s
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Live migration speed</shortdesc>
|
||||
+<content type="integer" default="${OCF_RESKEY_migration_speed_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="migration_network_suffix" unique="0" required="0">
|
||||
<longdesc lang="en">
|
||||
Use a dedicated migration network. The migration URI is composed by
|
||||
@@ -562,6 +582,7 @@
|
||||
local transport_suffix
|
||||
local migrateuri
|
||||
local migrate_opts
|
||||
+ local migrate_pid
|
||||
|
||||
target_node="$OCF_RESKEY_CRM_meta_migrate_target"
|
||||
|
||||
@@ -586,9 +607,28 @@
|
||||
# Scared of that sed expression? So am I. :-)
|
||||
remoteuri=$(echo ${OCF_RESKEY_hypervisor} | sed -e "s,\(.*\)://[^/:]*\(:\?[0-9]*\)/\(.*\),\1${transport_suffix}://${target_node}\2/\3,")
|
||||
|
||||
+ # Live migration speed limit
|
||||
+ if [ ${OCF_RESKEY_migration_speed} -ne 0 ]; then
|
||||
+ ocf_log info "$DOMAIN_NAME: Setting live migration speed limit for $DOMAIN_NAME (using: virsh ${VIRSH_OPTIONS} migrate-setspeed $DOMAIN_NAME ${OCF_RESKEY_migration_speed})."
|
||||
+ virsh ${VIRSH_OPTIONS} migrate-setspeed $DOMAIN_NAME ${OCF_RESKEY_migration_speed}
|
||||
+ fi
|
||||
+
|
||||
# OK, we know where to connect to. Now do the actual migration.
|
||||
- ocf_log info "$DOMAIN_NAME: Starting live migration to ${target_node} (using virsh ${VIRSH_OPTIONS} migrate --live $migrate_opts $DOMAIN_NAME $remoteuri $migrateuri)."
|
||||
- virsh ${VIRSH_OPTIONS} migrate --live $migrate_opts $DOMAIN_NAME $remoteuri $migrateuri
|
||||
+ ocf_log info "$DOMAIN_NAME: Starting live migration to ${target_node} (using: virsh ${VIRSH_OPTIONS} migrate --live $migrate_opts $DOMAIN_NAME $remoteuri $migrateuri)."
|
||||
+ virsh ${VIRSH_OPTIONS} migrate --live $migrate_opts $DOMAIN_NAME $remoteuri $migrateuri &
|
||||
+
|
||||
+ migrate_pid=${!}
|
||||
+
|
||||
+ # Live migration downtime interval
|
||||
+ # Note: You can set downtime only while live migration is in progress
|
||||
+ if [ ${OCF_RESKEY_migration_downtime} -ne 0 ]; then
|
||||
+ sleep 2
|
||||
+ ocf_log info "$DOMAIN_NAME: Setting live migration downtime for $DOMAIN_NAME (using: virsh ${VIRSH_OPTIONS} migrate-setmaxdowntime $DOMAIN_NAME ${OCF_RESKEY_migration_downtime})."
|
||||
+ virsh ${VIRSH_OPTIONS} migrate-setmaxdowntime $DOMAIN_NAME ${OCF_RESKEY_migration_downtime}
|
||||
+ fi
|
||||
+
|
||||
+ wait ${migrate_pid}
|
||||
+
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
ocf_exit_reason "$DOMAIN_NAME: live migration to ${target_node} failed: $rc"
|
||||
@@ -671,6 +711,18 @@
|
||||
return $OCF_ERR_INSTALLED
|
||||
fi
|
||||
fi
|
||||
+
|
||||
+ # Check if migration_speed is a decimal value
|
||||
+ if ! ocf_is_decimal ${OCF_RESKEY_migration_speed}; then
|
||||
+ ocf_exit_reason "migration_speed has to be a decimal value"
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ # Check if migration_downtime is a decimal value
|
||||
+ if ! ocf_is_decimal ${OCF_RESKEY_migration_downtime}; then
|
||||
+ ocf_exit_reason "migration_downtime has to be a decimal value"
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
}
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
From cbccff5ed9b1fc5641063f05ad531f897d366fa4 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Bayer <mike_mp@zzzcomputing.com>
|
||||
Date: Tue, 15 Sep 2015 14:54:05 -0400
|
||||
Subject: [PATCH] galera: add support for MYSQL_HOST and MYSQL_PORT from
|
||||
clustercheck
|
||||
|
||||
---
|
||||
heartbeat/galera | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/galera b/heartbeat/galera
|
||||
index 920507b..1a1a4ce 100755
|
||||
--- a/heartbeat/galera
|
||||
+++ b/heartbeat/galera
|
||||
@@ -704,6 +704,18 @@ if [ -n "${OCF_RESKEY_check_passwd}" ]; then
|
||||
MYSQL_OPTIONS_CHECK="$MYSQL_OPTIONS_CHECK --password=${OCF_RESKEY_check_passwd}"
|
||||
fi
|
||||
|
||||
+# This value is automatically sourced from /etc/sysconfig/checkcluster if available
|
||||
+if [ -n "${MYSQL_HOST}" ]; then
|
||||
+ MYSQL_OPTIONS_CHECK="$MYSQL_OPTIONS_CHECK -h ${MYSQL_HOST}"
|
||||
+fi
|
||||
+
|
||||
+# This value is automatically sourced from /etc/sysconfig/checkcluster if available
|
||||
+if [ -n "${MYSQL_PORT}" ]; then
|
||||
+ MYSQL_OPTIONS_CHECK="$MYSQL_OPTIONS_CHECK -P ${MYSQL_PORT}"
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+
|
||||
# What kind of method was invoked?
|
||||
case "$1" in
|
||||
start) galera_start;;
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
diff -uNr a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
--- a/heartbeat/VirtualDomain 2016-01-25 12:05:30.437008638 +0100
|
||||
+++ b/heartbeat/VirtualDomain 2016-01-25 12:25:06.850256377 +0100
|
||||
@@ -282,12 +282,13 @@
|
||||
status="no state"
|
||||
while [ "$status" = "no state" ]; do
|
||||
try=$(($try + 1 ))
|
||||
- status=$(virsh $VIRSH_OPTIONS domstate $DOMAIN_NAME 2>&1 | tr 'A-Z' 'a-z')
|
||||
+ status=$(LANG=C virsh $VIRSH_OPTIONS domstate $DOMAIN_NAME 2>&1 | tr 'A-Z' 'a-z')
|
||||
case "$status" in
|
||||
- *"error:"*"domain not found"*|"shut off")
|
||||
+ *"error:"*"domain not found"|*"error:"*"failed to get domain"*|"shut off")
|
||||
# shut off: domain is defined, but not started, will not happen if
|
||||
# domain is created but not defined
|
||||
- # Domain not found: domain is not defined and thus not started
|
||||
+ # "Domain not found" or "failed to get domain": domain is not defined
|
||||
+ # and thus not started
|
||||
ocf_log debug "Virtual domain $DOMAIN_NAME is not running: $(echo $status | sed s/error://g)"
|
||||
rc=$OCF_NOT_RUNNING
|
||||
;;
|
||||
@@ -415,11 +416,12 @@
|
||||
local status=0
|
||||
|
||||
ocf_log info "Issuing forced shutdown (destroy) request for domain ${DOMAIN_NAME}."
|
||||
- out=$(virsh $VIRSH_OPTIONS destroy ${DOMAIN_NAME} 2>&1|tr 'A-Z' 'a-z')
|
||||
+ out=$(LANG=C virsh $VIRSH_OPTIONS destroy ${DOMAIN_NAME} 2>&1|tr 'A-Z' 'a-z')
|
||||
ex=$?
|
||||
echo >&2 "$out"
|
||||
case $ex$out in
|
||||
- *"error:"*"domain is not running"*|*"error:"*"domain not found"*)
|
||||
+ *"error:"*"domain is not running"*|*"error:"*"domain not found"*|\
|
||||
+ *"error:"*"failed to get domain"*)
|
||||
: ;; # unexpected path to the intended outcome, all is well
|
||||
[!0]*)
|
||||
ocf_exit_reason "forced stop failed"
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
diff -uNr a/heartbeat/portblock b/heartbeat/portblock
|
||||
--- a/heartbeat/portblock 2013-06-18 15:22:27.000000000 +0200
|
||||
+++ b/heartbeat/portblock 2016-02-29 13:51:22.205860012 +0100
|
||||
@@ -24,8 +24,10 @@
|
||||
|
||||
# Defaults
|
||||
OCF_RESKEY_ip_default="0.0.0.0/0"
|
||||
+OCF_RESKEY_reset_local_on_unblock_stop_default="false"
|
||||
|
||||
: ${OCF_RESKEY_ip=${OCF_RESKEY_ip_default}}
|
||||
+: ${OCF_RESKEY_reset_local_on_unblock_stop=${OCF_RESKEY_reset_local_on_unblock_stop_default}}
|
||||
#######################################################################
|
||||
CMD=`basename $0`
|
||||
TICKLETCP=$HA_BIN/tickle_tcp
|
||||
@@ -37,16 +39,22 @@
|
||||
|
||||
$CMD is used to temporarily block ports using iptables.
|
||||
|
||||
- It can be used to turn off a port before bringing
|
||||
+ It can be used to blackhole a port before bringing
|
||||
up an IP address, and enable it after a service is started.
|
||||
- To do that for samba, the following resource line can be used:
|
||||
+ To do that for samba, the following can be used:
|
||||
|
||||
- $CMD::tcp::137,138::block \\
|
||||
- 10.10.10.20 \\
|
||||
- nmbd smbd \\
|
||||
- $CMD::tcp::137,138::unblock
|
||||
+ crm configure <<EOF
|
||||
+ primitive portblock-samba ocf:heartbeat:portblock \\
|
||||
+ params protocol=tcp portno=137,138 action=block
|
||||
+ primitive portunblock-samba ocf:heartbeat:portblock \\
|
||||
+ params protocol=tcp portno=137,138 action=unblock
|
||||
+ primitive samba-vip ocf:heartbeat:IPaddr2 \\
|
||||
+ params ip=10.10.10.20
|
||||
+ group g-samba \\
|
||||
+ portblock-samba samba-vip nmbd smbd portunblock-samba
|
||||
+ EOF
|
||||
|
||||
- This will do the follwing things:
|
||||
+ This will do the following things:
|
||||
|
||||
- DROP all incoming packets for TCP ports 137 and 138
|
||||
- Bring up the IP alias 10.10.10.20
|
||||
@@ -54,13 +62,16 @@
|
||||
- Re-enable TCP ports 137 and 138
|
||||
(enable normal firewall rules on those ports)
|
||||
|
||||
- This prevents clients from getting ICMP port unreachable
|
||||
- if they try to reconnect to the service after the alias is
|
||||
- enabled but before nmbd and smbd are running. These packets
|
||||
- will cause some clients to give up attempting to reconnect to
|
||||
- the server.
|
||||
+ This prevents clients from getting TCP RST if they try to reconnect
|
||||
+ to the service after the alias is enabled but before nmbd and smbd
|
||||
+ are running. These packets will cause some clients to give up
|
||||
+ attempting to reconnect to the server.
|
||||
+
|
||||
+ Attempts to connect to UDP and other non-TCP ports which have nothing
|
||||
+ listening can result in ICMP port unreachable responses, which can
|
||||
+ have the same undesirable affect on some clients.
|
||||
|
||||
- NOTE: iptables is linux-specific...
|
||||
+ NOTE: iptables is Linux-specific.
|
||||
|
||||
An additional feature in the portblock RA is the tickle ACK function
|
||||
enabled by specifying the tickle_dir parameter. The tickle ACK
|
||||
@@ -138,7 +149,7 @@
|
||||
The port number used to be blocked/unblocked.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">portno</shortdesc>
|
||||
-<content type="integer" default="" />
|
||||
+<content type="string" default="" />
|
||||
</parameter>
|
||||
|
||||
<parameter name="action" unique="0" required="1">
|
||||
@@ -149,6 +160,26 @@
|
||||
<content type="string" default="" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="reset_local_on_unblock_stop" unique="0" required="0">
|
||||
+<content type="boolean" default="${OCF_RESKEY_reset_local_on_unblock_stop_default}" />
|
||||
+<shortdesc lang="en">(try to) reset server TCP sessions when unblock stops</shortdesc>
|
||||
+<longdesc>
|
||||
+If for some reason the long lived server side TCP sessions won't be cleaned up
|
||||
+by a reconfiguration/flush/stop of whatever services this portblock protects,
|
||||
+they would linger in the connection table, even after the IP is gone
|
||||
+and services have been switched over to an other node.
|
||||
+
|
||||
+An example would be the default NFS kernel server.
|
||||
+
|
||||
+These "known" connections may seriously confuse and delay a later switchback.
|
||||
+
|
||||
+Enabling this option will cause this agent to try to get rid of these connections
|
||||
+by injecting a temporary iptables rule to TCP-reset outgoing packets from the
|
||||
+blocked ports, and additionally tickle them locally,
|
||||
+just before it starts to DROP incoming packets on "unblock stop".
|
||||
+</longdesc>
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="ip" unique="0" required="0">
|
||||
<longdesc lang="en">
|
||||
The IP address used to be blocked/unblocked.
|
||||
@@ -233,12 +264,34 @@
|
||||
fi
|
||||
}
|
||||
|
||||
-run_tickle_tcp()
|
||||
+tickle_remote()
|
||||
{
|
||||
[ -z "$OCF_RESKEY_tickle_dir" ] && return
|
||||
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
|
||||
f=$OCF_RESKEY_tickle_dir/$OCF_RESKEY_ip
|
||||
- [ -f $f ] && cat $f | $TICKLETCP -n 3
|
||||
+ [ -r $f ] || return
|
||||
+ $TICKLETCP -n 3 < $f
|
||||
+}
|
||||
+
|
||||
+tickle_local()
|
||||
+{
|
||||
+ [ -z "$OCF_RESKEY_tickle_dir" ] && return
|
||||
+ f=$OCF_RESKEY_tickle_dir/$OCF_RESKEY_ip
|
||||
+ [ -r $f ] || return
|
||||
+ # swap "local" and "remote" address,
|
||||
+ # so we tickle ourselves.
|
||||
+ # We set up a REJECT with tcp-reset before we do so, so we get rid of
|
||||
+ # the no longer wanted potentially long lived "ESTABLISHED" connection
|
||||
+ # entries on the IP we are going to delet in a sec. These would get in
|
||||
+ # the way if we switch-over and then switch-back in quick succession.
|
||||
+ local i
|
||||
+ awk '{ print $2, $1; }' $f | $TICKLETCP
|
||||
+ netstat -tn | grep -Fw $OCF_RESKEY_ip || return
|
||||
+ for i in 0.1 0.5 1 2 4 ; do
|
||||
+ sleep $i
|
||||
+ awk '{ print $2, $1; }' $f | $TICKLETCP
|
||||
+ netstat -tn | grep -Fw $OCF_RESKEY_ip || break
|
||||
+ done
|
||||
}
|
||||
|
||||
SayActive()
|
||||
@@ -304,15 +357,30 @@
|
||||
#IptablesBLOCK {udp|tcp} portno,portno ip
|
||||
IptablesBLOCK()
|
||||
{
|
||||
+ local rc=0
|
||||
+ local try_reset=false
|
||||
+ if [ "$1/$4/$__OCF_ACTION" = tcp/unblock/stop ] &&
|
||||
+ ocf_is_true $reset_local_on_unblock_stop
|
||||
+ then
|
||||
+ try_reset=true
|
||||
+ fi
|
||||
if
|
||||
chain_isactive "$1" "$2" "$3"
|
||||
then
|
||||
: OK -- chain already active
|
||||
else
|
||||
+ if $try_reset ; then
|
||||
+ $IPTABLES -I OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset
|
||||
+ tickle_local
|
||||
+ fi
|
||||
$IPTABLES -I INPUT -p "$1" -d "$3" -m multiport --dports "$2" -j DROP
|
||||
+ rc=$?
|
||||
+ if $try_reset ; then
|
||||
+ $IPTABLES -D OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset
|
||||
+ fi
|
||||
fi
|
||||
|
||||
- return $?
|
||||
+ return $rc
|
||||
}
|
||||
|
||||
#IptablesUNBLOCK {udp|tcp} portno,portno ip
|
||||
@@ -338,7 +406,7 @@
|
||||
unblock)
|
||||
IptablesUNBLOCK "$@"
|
||||
rc=$?
|
||||
- run_tickle_tcp
|
||||
+ tickle_remote
|
||||
#ignore run_tickle_tcp exit code!
|
||||
return $rc
|
||||
;;
|
||||
@@ -411,6 +479,17 @@
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
;;
|
||||
esac
|
||||
+
|
||||
+ if ocf_is_true $reset_local_on_unblock_stop; then
|
||||
+ if [ $action != unblock ] ; then
|
||||
+ ocf_log err "reset_local_on_unblock_stop is only relevant with action=unblock"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ if [ -z $OCF_RESKEY_tickle_dir ] ; then
|
||||
+ ocf_log warn "reset_local_on_unblock_stop works best with tickle_dir enabled as well"
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
@@ -451,6 +530,7 @@
|
||||
portno=$OCF_RESKEY_portno
|
||||
action=$OCF_RESKEY_action
|
||||
ip=$OCF_RESKEY_ip
|
||||
+reset_local_on_unblock_stop=$OCF_RESKEY_reset_local_on_unblock_stop
|
||||
|
||||
case $1 in
|
||||
start)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
From 8ac05986ac7ef354456253edbd22cbb4a2d96e90 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Fri, 16 Sep 2016 10:19:38 +0200
|
||||
Subject: [PATCH] portblock: create tickle_dir if it doesnt exist
|
||||
|
||||
---
|
||||
heartbeat/portblock | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/portblock b/heartbeat/portblock
|
||||
index c480954..c97488b 100755
|
||||
--- a/heartbeat/portblock
|
||||
+++ b/heartbeat/portblock
|
||||
@@ -466,8 +466,7 @@ IptablesValidateAll()
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
if [ ! -d "$OCF_RESKEY_tickle_dir" ]; then
|
||||
- ocf_log err "The tickle dir doesn't exist!"
|
||||
- exit $OCF_ERR_INSTALLED
|
||||
+ mkdir -p $OCF_RESKEY_tickle_dir
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -534,6 +533,7 @@ reset_local_on_unblock_stop=$OCF_RESKEY_reset_local_on_unblock_stop
|
||||
|
||||
case $1 in
|
||||
start)
|
||||
+ IptablesValidateAll
|
||||
IptablesStart $protocol $portno $ip $action
|
||||
;;
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
From: Peter Lemenkov <lemenkov@redhat.com>
|
||||
Date: Mon, 29 Feb 2016 12:46:50 +0100
|
||||
Subject: [PATCH] Backup and restore rabbitmq users during resource restart
|
||||
|
||||
Signed-off-by: Peter Lemenkov <lemenkov@redhat.com>
|
||||
|
||||
diff --git a/heartbeat/rabbitmq-cluster b/heartbeat/rabbitmq-cluster
|
||||
index cc45f09..4545495 100755
|
||||
--- a/heartbeat/rabbitmq-cluster
|
||||
+++ b/heartbeat/rabbitmq-cluster
|
||||
@@ -289,7 +289,19 @@ rmq_start() {
|
||||
rmq_stop
|
||||
rmq_wipe_data
|
||||
rmq_join_existing "$join_list"
|
||||
- if [ $? -ne 0 ]; then
|
||||
+ rc=$?
|
||||
+
|
||||
+ # Restore users (if any)
|
||||
+ BaseDataDir=`dirname $RMQ_DATA_DIR`
|
||||
+ if [ -f $BaseDataDir/users.erl ] ; then
|
||||
+ rabbitmqctl eval "
|
||||
+ {ok, [Users]} = file:consult(\"$BaseDataDir/users.erl\"),
|
||||
+ lists:foreach(fun(X) -> mnesia:dirty_write(rabbit_user, X) end, Users).
|
||||
+ "
|
||||
+ rm -f $BaseDataDir/users.erl
|
||||
+ fi
|
||||
+
|
||||
+ if [ $rc -ne 0 ]; then
|
||||
ocf_log info "node failed to join even after reseting local data. Check SELINUX policy"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
@@ -299,6 +311,13 @@ rmq_start() {
|
||||
}
|
||||
|
||||
rmq_stop() {
|
||||
+ # Backup users
|
||||
+ BaseDataDir=`dirname $RMQ_DATA_DIR`
|
||||
+ rabbitmqctl eval "
|
||||
+ Users = mnesia:dirty_select(rabbit_user, [{ {internal_user, '\\\$1', '_', '_'}, [{'/=', '\\\$1', <<\"guest\">>}], ['\\\$_'] } ]),
|
||||
+ file:write_file(\"$BaseDataDir/users.erl\", io_lib:fwrite(\"~p.~n\", [Users])).
|
||||
+ "
|
||||
+
|
||||
rmq_monitor
|
||||
if [ $? -eq $OCF_NOT_RUNNING ]; then
|
||||
return $OCF_SUCCESS
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
diff -uNr a/heartbeat/nova-compute-wait b/heartbeat/nova-compute-wait
|
||||
--- a/heartbeat/nova-compute-wait 2017-02-02 11:23:38.263510362 +0100
|
||||
+++ b/heartbeat/nova-compute-wait 2017-02-02 11:28:27.181650906 +0100
|
||||
@@ -1,30 +1,15 @@
|
||||
#!/bin/sh
|
||||
+# Copyright 2015 Red Hat, Inc.
|
||||
#
|
||||
+# Description: Manages compute daemons
|
||||
#
|
||||
-# nova-compute-wait agent manages compute daemons.
|
||||
+# Authors: Andrew Beekhof
|
||||
#
|
||||
-# Copyright (c) 2015
|
||||
-#
|
||||
-# 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.
|
||||
+# Support: openstack@lists.openstack.org
|
||||
+# License: Apache Software License (ASL) 2.0
|
||||
#
|
||||
|
||||
+
|
||||
#######################################################################
|
||||
# Initialization:
|
||||
|
||||
@@ -137,6 +122,8 @@
|
||||
}
|
||||
|
||||
nova_start() {
|
||||
+ build_unfence_overlay
|
||||
+
|
||||
state=$(attrd_updater -p -n evacuate -N ${NOVA_HOST} | sed -e 's/.*value=//' | tr -d '"' )
|
||||
if [ "x$state" = x ]; then
|
||||
: never been fenced
|
||||
@@ -147,8 +134,8 @@
|
||||
sleep ${OCF_RESKEY_evacuation_delay}
|
||||
|
||||
else
|
||||
- ocf_log info "Waiting for pending evacuations from ${NOVA_HOST}"
|
||||
while [ "x$state" != "xno" ]; do
|
||||
+ ocf_log info "Waiting for pending evacuations from ${NOVA_HOST}"
|
||||
state=$(attrd_updater -p -n evacuate -N ${NOVA_HOST} | sed -e 's/.*value=//' | tr -d '"' )
|
||||
sleep 5
|
||||
done
|
||||
@@ -156,14 +143,22 @@
|
||||
ocf_log info "Pausing to give evacuations from ${NOVA_HOST} time to complete"
|
||||
sleep ${OCF_RESKEY_evacuation_delay}
|
||||
fi
|
||||
+
|
||||
+ touch "$statefile"
|
||||
+
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
nova_stop() {
|
||||
+ rm -f "$statefile"
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
nova_monitor() {
|
||||
+ if [ ! -f "$statefile" ]; then
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
@@ -171,17 +166,113 @@
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
+build_unfence_overlay() {
|
||||
+ fence_options=""
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_auth_url}" ]; then
|
||||
+ candidates=$(/usr/sbin/stonith_admin -l ${NOVA_HOST})
|
||||
+ for candidate in ${candidates}; do
|
||||
+ pcs stonith show $d | grep -q fence_compute
|
||||
+ if [ $? = 0 ]; then
|
||||
+ ocf_log info "Unfencing nova based on: $candidate"
|
||||
+ fence_auth=$(pcs stonith show $candidate | grep Attributes: | sed -e s/Attributes:// -e s/-/_/g -e 's/[^ ]\+=/OCF_RESKEY_\0/g' -e s/passwd/password/g)
|
||||
+ eval "export $fence_auth"
|
||||
+ break
|
||||
+ fi
|
||||
+ done
|
||||
+ fi
|
||||
+
|
||||
+ # Copied from NovaEvacuate
|
||||
+ if [ -z "${OCF_RESKEY_auth_url}" ]; then
|
||||
+ ocf_exit_reason "auth_url not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -k ${OCF_RESKEY_auth_url}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_username}" ]; then
|
||||
+ ocf_exit_reason "username not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -l ${OCF_RESKEY_username}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_password}" ]; then
|
||||
+ ocf_exit_reason "password not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -p ${OCF_RESKEY_password}"
|
||||
+
|
||||
+ if [ -z "${OCF_RESKEY_tenant_name}" ]; then
|
||||
+ ocf_exit_reason "tenant_name not configured"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ fence_options="${fence_options} -t ${OCF_RESKEY_tenant_name}"
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_domain}" ]; then
|
||||
+ fence_options="${fence_options} -d ${OCF_RESKEY_domain}"
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_region_name}" ]; then
|
||||
+ fence_options="${fence_options} \
|
||||
+ --region-name ${OCF_RESKEY_region_name}"
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_insecure}" ]; then
|
||||
+ if ocf_is_true "${OCF_RESKEY_insecure}"; then
|
||||
+ fence_options="${fence_options} --insecure"
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_no_shared_storage}" ]; then
|
||||
+ if ocf_is_true "${OCF_RESKEY_no_shared_storage}"; then
|
||||
+ fence_options="${fence_options} --no-shared-storage"
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ if [ -n "${OCF_RESKEY_endpoint_type}" ]; then
|
||||
+ case ${OCF_RESKEY_endpoint_type} in
|
||||
+ adminURL|publicURL|internalURL)
|
||||
+ ;;
|
||||
+ *)
|
||||
+ ocf_exit_reason "endpoint_type ${OCF_RESKEY_endpoint_type}" \
|
||||
+ "not valid. Use adminURL or publicURL or internalURL"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ ;;
|
||||
+ esac
|
||||
+ fence_options="${fence_options} -e ${OCF_RESKEY_endpoint_type}"
|
||||
+ fi
|
||||
+
|
||||
+ mkdir -p /run/systemd/system/openstack-nova-compute.service.d
|
||||
+ cat<<EOF>/run/systemd/system/openstack-nova-compute.service.d/unfence-20.conf
|
||||
+[Service]
|
||||
+ExecStartPost=/sbin/fence_compute ${fence_options} -o on -n ${NOVA_HOST}
|
||||
+EOF
|
||||
+}
|
||||
+
|
||||
nova_validate() {
|
||||
rc=$OCF_SUCCESS
|
||||
|
||||
check_binary crudini
|
||||
check_binary nova-compute
|
||||
+ check_binary fence_compute
|
||||
|
||||
if [ ! -f /etc/nova/nova.conf ]; then
|
||||
ocf_exit_reason "/etc/nova/nova.conf not found"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
+ # Is the state directory writable?
|
||||
+ state_dir=$(dirname $statefile)
|
||||
+ touch "$state_dir/$$"
|
||||
+ if [ $? != 0 ]; then
|
||||
+ ocf_exit_reason "Invalid state directory: $state_dir"
|
||||
+ return $OCF_ERR_ARGS
|
||||
+ fi
|
||||
+ rm -f "$state_dir/$$"
|
||||
+
|
||||
NOVA_HOST=$(crudini --get /etc/nova/nova.conf DEFAULT host 2>/dev/null)
|
||||
if [ $? = 1 ]; then
|
||||
short_host=$(uname -n | awk -F. '{print $1}')
|
||||
@@ -198,6 +289,8 @@
|
||||
return $rc
|
||||
}
|
||||
|
||||
+statefile="${HA_RSCTMP}/${OCF_RESOURCE_INSTANCE}.active"
|
||||
+
|
||||
: ${OCF_RESKEY_evacuation_delay=120}
|
||||
case $__OCF_ACTION in
|
||||
meta-data) meta_data
|
||||
@@ -221,3 +314,4 @@
|
||||
rc=$?
|
||||
ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
|
||||
exit $rc
|
||||
+
|
||||
diff -uNr a/heartbeat/NovaEvacuate b/heartbeat/NovaEvacuate
|
||||
--- a/heartbeat/NovaEvacuate 2017-02-02 11:23:38.253510461 +0100
|
||||
+++ b/heartbeat/NovaEvacuate 2017-02-02 11:28:49.262432371 +0100
|
||||
@@ -1,30 +1,16 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
+# Copyright 2015 Red Hat, Inc.
|
||||
#
|
||||
-# NovaCompute agent manages compute daemons.
|
||||
+# Description: Manages evacuation of nodes running nova-compute
|
||||
#
|
||||
-# Copyright (c) 2015
|
||||
+# Authors: Andrew Beekhof
|
||||
#
|
||||
-# 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.
|
||||
+# Support: openstack@lists.openstack.org
|
||||
+# License: Apache Software License (ASL) 2.0
|
||||
#
|
||||
|
||||
+
|
||||
#######################################################################
|
||||
# Initialization:
|
||||
|
||||
@@ -180,7 +166,7 @@
|
||||
ocf_log notice "Initiating evacuation of $node"
|
||||
|
||||
fence_compute ${fence_options} -o status -n ${node}
|
||||
- if [ $? != 0 ]; then
|
||||
+ if [ $? = 1 ]; then
|
||||
ocf_log info "Nova does not know about ${node}"
|
||||
# Dont mark as no because perhaps nova is unavailable right now
|
||||
continue
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
From f1c2249ef5e8524ddb986f0df879d5f18e935da3 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Fri, 20 Jan 2017 09:17:15 +0100
|
||||
Subject: [PATCH] redis: use "CLIENT KILL type normal" to notify clients of
|
||||
master being demoted
|
||||
|
||||
---
|
||||
heartbeat/redis | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/redis b/heartbeat/redis
|
||||
index 1ea0025..d08e57a 100755
|
||||
--- a/heartbeat/redis
|
||||
+++ b/heartbeat/redis
|
||||
@@ -436,6 +436,11 @@ function demote() {
|
||||
local master_host
|
||||
local master_port
|
||||
|
||||
+ # client kill is only supported in Redis 2.8.12 or greater
|
||||
+ version=$(redis_client -v | awk '{print $NF}')
|
||||
+ ocf_version_cmp "$version" "2.8.11"
|
||||
+ client_kill=$?
|
||||
+
|
||||
CHECK_SLAVE_STATE=1
|
||||
monitor
|
||||
status=$?
|
||||
@@ -478,9 +483,15 @@ function demote() {
|
||||
while true; do
|
||||
# Wait infinite if replication is syncing
|
||||
# Then start/demote operation timeout determines timeout
|
||||
+ if [ "$client_kill" -eq 2 ]; then
|
||||
+ redis_client CLIENT PAUSE 2000
|
||||
+ fi
|
||||
monitor
|
||||
status=$?
|
||||
if (( status == OCF_SUCCESS )); then
|
||||
+ if [ "$client_kill" -eq 2 ]; then
|
||||
+ redis_client CLIENT KILL type normal
|
||||
+ fi
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
diff -uNr a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
--- a/heartbeat/VirtualDomain 2016-04-26 12:22:22.345053246 +0200
|
||||
+++ b/heartbeat/VirtualDomain 2016-04-26 12:24:27.479535075 +0200
|
||||
@@ -263,8 +263,6 @@
|
||||
|
||||
if [ -n "$emulator" ]; then
|
||||
basename $emulator
|
||||
- else
|
||||
- ocf_log error "Unable to determine emulator for $DOMAIN_NAME"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -301,6 +299,7 @@
|
||||
;;
|
||||
# This can be expanded to check for additional emulators
|
||||
*)
|
||||
+ ocf_log error "Unable to determine emulator for $DOMAIN_NAME"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
diff -uNr a/configure.ac b/configure.ac
|
||||
--- a/configure.ac 2017-05-03 10:00:54.396040173 +0200
|
||||
+++ b/configure.ac 2017-05-03 10:07:28.969236697 +0200
|
||||
@@ -65,6 +65,21 @@
|
||||
AM_CONDITIONAL(OCFT_FEDORA_CASES, test "x$OCFT_TEST_CASES" = "xfedora" )
|
||||
AM_CONDITIONAL(OCFT_DEFAULT_CASES, test "x$OCFT_TEST_CASES" = "xdefault" )
|
||||
|
||||
+AC_ARG_WITH([systemdsystemunitdir],
|
||||
+ [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],,
|
||||
+ [with_systemdsystemunitdir=auto])
|
||||
+AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [
|
||||
+ def_systemdsystemunitdir=$($PKGCONFIG --variable=systemdsystemunitdir systemd)
|
||||
+
|
||||
+ AS_IF([test "x$def_systemdsystemunitdir" = "x"],
|
||||
+ [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"],
|
||||
+ [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])])
|
||||
+ with_systemdsystemunitdir=no],
|
||||
+ [with_systemdsystemunitdir="$def_systemdsystemunitdir"])])
|
||||
+AS_IF([test "x$with_systemdsystemunitdir" != "xno"],
|
||||
+ [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])])
|
||||
+AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"])
|
||||
+
|
||||
dnl
|
||||
dnl AM_INIT_AUTOMAKE([1.11.1 foreign dist-bzip2 dist-xz])
|
||||
dnl
|
||||
@@ -857,6 +872,7 @@
|
||||
heartbeat/ocf-directories \
|
||||
heartbeat/ocf-shellfuncs \
|
||||
heartbeat/shellfuncs \
|
||||
+systemd/Makefile \
|
||||
tools/Makefile \
|
||||
tools/ocf-tester \
|
||||
tools/ocft/Makefile \
|
||||
diff -uNr a/heartbeat/clvm b/heartbeat/clvm
|
||||
--- a/heartbeat/clvm 2017-05-03 10:00:54.560038569 +0200
|
||||
+++ b/heartbeat/clvm 2017-05-03 10:01:13.309855171 +0200
|
||||
@@ -353,6 +353,18 @@
|
||||
return $?
|
||||
fi
|
||||
|
||||
+ # systemd drop-in to stop process before storage services during
|
||||
+ # shutdown/reboot
|
||||
+ if ps -p 1 | grep -q systemd ; then
|
||||
+ systemdrundir="/run/systemd/system/resource-agents-deps.target.d"
|
||||
+ mkdir "$systemdrundir"
|
||||
+ cat > "$systemdrundir/99-clvmd.conf" <<EOF
|
||||
+[Unit]
|
||||
+After=blk-availability.service
|
||||
+EOF
|
||||
+ systemctl daemon-reload
|
||||
+ fi
|
||||
+
|
||||
clvmd_status
|
||||
if [ $? -eq $OCF_SUCCESS ]; then
|
||||
ocf_log debug "$DAEMON already started"
|
||||
diff -uNr a/heartbeat/LVM b/heartbeat/LVM
|
||||
--- a/heartbeat/LVM 2017-05-03 10:00:54.558038589 +0200
|
||||
+++ b/heartbeat/LVM 2017-05-03 10:01:13.309855171 +0200
|
||||
@@ -452,6 +452,18 @@
|
||||
local vg=$1
|
||||
local clvmd=0
|
||||
|
||||
+ # systemd drop-in to stop process before storage services during
|
||||
+ # shutdown/reboot
|
||||
+ if ps -p 1 | grep -q systemd ; then
|
||||
+ systemdrundir="/run/systemd/system/resource-agents-deps.target.d"
|
||||
+ mkdir "$systemdrundir"
|
||||
+ cat > "$systemdrundir/99-LVM.conf" <<EOF
|
||||
+[Unit]
|
||||
+After=blk-availability.service
|
||||
+EOF
|
||||
+ systemctl daemon-reload
|
||||
+ fi
|
||||
+
|
||||
# TODO: This MUST run vgimport as well
|
||||
ocf_log info "Activating volume group $vg"
|
||||
if [ "$LVM_MAJOR" -eq "1" ]; then
|
||||
diff -uNr a/Makefile.am b/Makefile.am
|
||||
--- a/Makefile.am 2013-06-18 15:22:27.000000000 +0200
|
||||
+++ b/Makefile.am 2017-05-03 10:01:13.308855181 +0200
|
||||
@@ -37,7 +37,7 @@
|
||||
endif
|
||||
|
||||
if BUILD_LINUX_HA
|
||||
-SUBDIRS += include heartbeat tools ldirectord doc
|
||||
+SUBDIRS += include heartbeat tools ldirectord doc systemd
|
||||
LINUX_HA = without
|
||||
else
|
||||
LINUX_HA = with
|
||||
diff -uNr a/resource-agents.spec.in b/resource-agents.spec.in
|
||||
--- a/resource-agents.spec.in 2017-05-03 10:00:54.384040291 +0200
|
||||
+++ b/resource-agents.spec.in 2017-05-03 10:01:13.309855171 +0200
|
||||
@@ -231,6 +231,10 @@
|
||||
/usr/lib/ocf/resource.d/redhat
|
||||
%endif
|
||||
|
||||
+%if %{defined _unitdir}
|
||||
+%{_unitdir}/resource-agents-deps.target
|
||||
+%endif
|
||||
+
|
||||
%dir %{_datadir}/%{name}
|
||||
%dir %{_datadir}/%{name}/ocft
|
||||
%{_datadir}/%{name}/ocft/configs
|
||||
diff -uNr a/systemd/Makefile.am b/systemd/Makefile.am
|
||||
--- a/systemd/Makefile.am 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ b/systemd/Makefile.am 2017-05-03 10:01:13.311855152 +0200
|
||||
@@ -0,0 +1,23 @@
|
||||
+#
|
||||
+# Copyright (C) 2017 Oyvind Albrigtsen
|
||||
+#
|
||||
+# 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
|
||||
+
|
||||
+if HAVE_SYSTEMD
|
||||
+dist_systemdsystemunit_DATA = resource-agents-deps.target
|
||||
+endif
|
||||
diff -uNr a/systemd/resource-agents-deps.target b/systemd/resource-agents-deps.target
|
||||
--- a/systemd/resource-agents-deps.target 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ b/systemd/resource-agents-deps.target 2017-05-03 10:01:13.311855152 +0200
|
||||
@@ -0,0 +1,2 @@
|
||||
+[Unit]
|
||||
+Description=resource-agents dependencies
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue