![basebuilder@powerel.org](/assets/img/avatar_default.png)
203 changed files with 45896 additions and 0 deletions
@ -0,0 +1,418 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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