diff options
author | dcorbacho <dparracorbacho@piotal.io> | 2020-11-18 14:27:41 +0000 |
---|---|---|
committer | dcorbacho <dparracorbacho@piotal.io> | 2020-11-18 14:27:41 +0000 |
commit | f23a51261d9502ec39df0f8db47ba6b22aa7659f (patch) | |
tree | 53dcdf46e7dc2c14e81ee960bce8793879b488d3 /scripts | |
parent | afa2c2bf6c7e0e9b63f4fb53dc931c70388e1c82 (diff) | |
parent | 9f6d64ec4a4b1eeac24d7846c5c64fd96798d892 (diff) | |
download | rabbitmq-server-git-stream-timestamp-offset.tar.gz |
Merge remote-tracking branch 'origin/master' into stream-timestamp-offsetstream-timestamp-offset
Diffstat (limited to 'scripts')
27 files changed, 2953 insertions, 1522 deletions
diff --git a/scripts/bash_autocomplete.sh b/scripts/bash_autocomplete.sh new file mode 100644 index 0000000000..a7b174c8bf --- /dev/null +++ b/scripts/bash_autocomplete.sh @@ -0,0 +1,15 @@ +_rabbitmqctl_complete() { + if [ -x /usr/lib/rabbitmq/bin/rabbitmqctl ]; then + COMPREPLY=() + local LANG=en_US.UTF-8 + local word="${COMP_WORDS[COMP_CWORD]}" + local completions="$(export LANG=en_US.UTF-8; export LC_CTYPE=en_US.UTF-8; /usr/lib/rabbitmq/bin/rabbitmqctl --auto-complete $COMP_LINE)" + COMPREPLY=( $(compgen -W "$completions" -- "$word") ) + fi +} + +complete -f -F _rabbitmqctl_complete rabbitmqctl + +complete -f -F _rabbitmqctl_complete rabbitmq-plugins + +complete -f -F _rabbitmqctl_complete rabbitmq-diagnostics
\ No newline at end of file diff --git a/scripts/rabbitmq-defaults b/scripts/rabbitmq-defaults deleted file mode 100755 index 41d72c7da4..0000000000 --- a/scripts/rabbitmq-defaults +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh -e -## This Source Code Form is subject to the terms of the Mozilla Public -## License, v. 2.0. If a copy of the MPL was not distributed with this -## file, You can obtain one at https://mozilla.org/MPL/2.0/. -## -## Copyright (c) 2012-2020 VMware, Inc. or its affiliates. All rights reserved. -## - -### next line potentially updated in package install steps -SYS_PREFIX= - -CLEAN_BOOT_FILE=start_clean -SASL_BOOT_FILE=start_sasl -BOOT_MODULE="rabbit" - -if test -z "$CONF_ENV_FILE" && test -z "$RABBITMQ_CONF_ENV_FILE"; then - CONF_ENV_FILE=${SYS_PREFIX}/etc/rabbitmq/rabbitmq-env.conf -fi diff --git a/scripts/rabbitmq-defaults.bat b/scripts/rabbitmq-defaults.bat deleted file mode 100644 index 41b3d2b47c..0000000000 --- a/scripts/rabbitmq-defaults.bat +++ /dev/null @@ -1,21 +0,0 @@ -@echo off
-
-set SASL_BOOT_FILE=start_sasl
-set CLEAN_BOOT_FILE=start_clean
-set BOOT_MODULE=rabbit
-
-if "!RABBITMQ_BASE!"=="" (
- set RABBITMQ_BASE=!APPDATA!\RabbitMQ
-) else (
- set RABBITMQ_BASE=!RABBITMQ_BASE:"=!
-)
-
-if not exist "!RABBITMQ_BASE!" (
- mkdir "!RABBITMQ_BASE!"
-)
-
-if "!RABBITMQ_CONF_ENV_FILE!"=="" (
- if "!CONF_ENV_FILE!"=="" (
- set CONF_ENV_FILE=!RABBITMQ_BASE!\rabbitmq-env-conf.bat
- )
-)
diff --git a/scripts/rabbitmq-diagnostics b/scripts/rabbitmq-diagnostics deleted file mode 100755 index 7101f3cc9b..0000000000 --- a/scripts/rabbitmq-diagnostics +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -## This Source Code Form is subject to the terms of the Mozilla Public -## License, v. 2.0. If a copy of the MPL was not distributed with this -## file, You can obtain one at https://mozilla.org/MPL/2.0/. -## -## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. -## - -# Exit immediately if a pipeline, which may consist of a single simple command, -# a list, or a compound command returns a non-zero status -set -e - -# Each variable or function that is created or modified is given the export -# attribute and marked for export to the environment of subsequent commands. -set -a - -# shellcheck source=/dev/null -# -# TODO: when shellcheck adds support for relative paths, change to -# shellcheck source=./rabbitmq-env -. "${0%/*}"/rabbitmq-env - -run_escript rabbitmqctl_escript "${ESCRIPT_DIR:?must be defined}"/rabbitmq-diagnostics "$@" diff --git a/scripts/rabbitmq-diagnostics.bat b/scripts/rabbitmq-diagnostics.bat deleted file mode 100644 index af2982559c..0000000000 --- a/scripts/rabbitmq-diagnostics.bat +++ /dev/null @@ -1,55 +0,0 @@ -@echo off
-REM This Source Code Form is subject to the terms of the Mozilla Public
-REM License, v. 2.0. If a copy of the MPL was not distributed with this
-REM file, You can obtain one at https://mozilla.org/MPL/2.0/.
-REM
-REM Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved.
-REM
-
-REM Scopes the variables to the current batch file
-setlocal
-
-rem Preserve values that might contain exclamation marks before
-rem enabling delayed expansion
-set TDP0=%~dp0
-set STAR=%*
-setlocal enabledelayedexpansion
-
-REM Get default settings with user overrides for (RABBITMQ_)<var_name>
-REM Non-empty defaults should be set in rabbitmq-env
-call "%TDP0%\rabbitmq-env.bat" %~n0
-
-if not exist "!ERLANG_HOME!\bin\erl.exe" (
- echo.
- echo ******************************
- echo ERLANG_HOME not set correctly.
- echo ******************************
- echo.
- echo Please either set ERLANG_HOME to point to your Erlang installation or place the
- echo RabbitMQ server distribution in the Erlang lib folder.
- echo.
- exit /B 1
-)
-
-REM Disable erl_crash.dump by default for control scripts.
-if not defined ERL_CRASH_DUMP_SECONDS (
- set ERL_CRASH_DUMP_SECONDS=0
-)
-
-"!ERLANG_HOME!\bin\erl.exe" +B ^
--boot !CLEAN_BOOT_FILE! ^
--noinput -noshell -hidden -smp enable ^
-!RABBITMQ_CTL_ERL_ARGS! ^
--kernel inet_dist_listen_min !RABBITMQ_CTL_DIST_PORT_MIN! ^
--kernel inet_dist_listen_max !RABBITMQ_CTL_DIST_PORT_MAX! ^
--run escript start ^
--escript main rabbitmqctl_escript ^
--extra "%RABBITMQ_HOME%\escript\rabbitmq-diagnostics" !STAR!
-
-if ERRORLEVEL 1 (
- exit /B %ERRORLEVEL%
-)
-
-EXIT /B 0
-
-endlocal
diff --git a/scripts/rabbitmq-echopid.bat b/scripts/rabbitmq-echopid.bat deleted file mode 100644 index 98080afd1f..0000000000 --- a/scripts/rabbitmq-echopid.bat +++ /dev/null @@ -1,57 +0,0 @@ -@echo off
-
-REM Usage: rabbitmq-echopid.bat <rabbitmq_nodename>
-REM
-REM <rabbitmq_nodename> (s)name of the erlang node to connect to (required)
-
-setlocal
-
-set TDP0=%~dp0
-
-REM Get default settings with user overrides for (RABBITMQ_)<var_name>
-REM Non-empty defaults should be set in rabbitmq-env
-call "%TDP0%\rabbitmq-env.bat" %~n0
-
-if "%1"=="" goto argfail
-
-:: set timeout vars ::
-set TIMEOUT=10
-set TIMER=1
-
-:: check that wmic exists ::
-set WMIC_PATH=%SYSTEMROOT%\System32\Wbem\wmic.exe
-if not exist "%WMIC_PATH%" (
- goto fail
-)
-
-:getpid
-for /f "usebackq tokens=* skip=1" %%P IN (`%%WMIC_PATH%% process where "name='erl.exe' and commandline like '%%%RABBITMQ_NAME_TYPE% %1%%'" get processid 2^>nul`) do (
- set PID=%%P
- goto echopid
-)
-
-:echopid
-:: check for pid not found ::
-if "%PID%" == "" (
- PING 127.0.0.1 -n 2 > nul
- set /a TIMER+=1
- if %TIMEOUT%==%TIMER% goto fail
- goto getpid
-)
-
-:: show pid ::
-echo %PID%
-
-:: all done ::
-:ok
-endlocal
-EXIT /B 0
-
-:: argument is required ::
-:argfail
-echo Please provide your RabbitMQ node name as the argument to this script.
-
-:: something went wrong ::
-:fail
-endlocal
-EXIT /B 1
diff --git a/scripts/rabbitmq-env b/scripts/rabbitmq-env deleted file mode 100755 index 90702c43bb..0000000000 --- a/scripts/rabbitmq-env +++ /dev/null @@ -1,190 +0,0 @@ -#!/bin/sh -e -## This Source Code Form is subject to the terms of the Mozilla Public -## License, v. 2.0. If a copy of the MPL was not distributed with this -## file, You can obtain one at https://mozilla.org/MPL/2.0/. -## -## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. -## - -if [ "$RABBITMQ_ENV_LOADED" = 1 ]; then - return 0; -fi - -if [ -z "$RABBITMQ_SCRIPTS_DIR" ]; then - # We set +e here since since our test for "readlink -f" below needs to - # be able to fail. - set +e - # Determine where this script is really located (if this script is - # invoked from another script, this is the location of the caller) - SCRIPT_PATH="$0" - while [ -h "$SCRIPT_PATH" ] ; do - # Determine if readlink -f is supported at all. TODO clean this up. - FULL_PATH=`readlink -f $SCRIPT_PATH 2>/dev/null` - if [ "$?" != "0" ]; then - REL_PATH=`readlink $SCRIPT_PATH` - if expr "$REL_PATH" : '/.*' > /dev/null; then - SCRIPT_PATH="$REL_PATH" - else - SCRIPT_PATH="`dirname "$SCRIPT_PATH"`/$REL_PATH" - fi - else - SCRIPT_PATH=$FULL_PATH - fi - done - set -e - - RABBITMQ_SCRIPTS_DIR=`dirname $SCRIPT_PATH` -fi - -_rmq_env_now() -{ - date '+%Y-%m-%d %H:%M:%S' -} - -_rmq_env_print() -{ - _rmq_env_tmp="$1" - _rmq_env_tmp_len="${#_rmq_env_tmp}" - shift - printf '%s %s %s\n' "$(_rmq_env_now)" "$_rmq_env_tmp" "$1" 1>&2 - shift - _rmq_env_print_line='' - _rmq_env_indent="$((_rmq_env_tmp_len + 21))" - for _rmq_env_print_line in "$@" - do - printf "%${_rmq_env_indent}s%s\n" ' ' "$_rmq_env_print_line" 1>&2 - done - unset _rmq_env_print_line - unset _rmq_env_indent - unset _rmq_env_tmp_len - unset _rmq_env_tmp -} - -_rmq_env_perr() -{ - _rmq_env_print '[error]' "$@" -} - -_rmq_env_pwarn() -{ - _rmq_env_print '[warning]' "$@" -} - -rmq_realpath() { - local path=$1 - - if [ -d "$path" ]; then - cd "$path" && pwd - elif [ -f "$path" ]; then - cd "$(dirname "$path")" && echo $(pwd)/$(basename "$path") - else - echo "$path" - fi -} - -RABBITMQ_HOME="$(rmq_realpath "${RABBITMQ_SCRIPTS_DIR}/..")" -ESCRIPT_DIR="${RABBITMQ_HOME}/escript" - -## Set defaults -. ${RABBITMQ_SCRIPTS_DIR}/rabbitmq-defaults - -# We save the current value of $RABBITMQ_PID_FILE in case it was set by -# an init script. If $CONF_ENV_FILE overrides it again, we must ignore -# it and warn the user. -saved_RABBITMQ_PID_FILE="$RABBITMQ_PID_FILE" - -## Get configuration variables from the configure environment file -[ "x" = "x$RABBITMQ_CONF_ENV_FILE" ] && RABBITMQ_CONF_ENV_FILE=${CONF_ENV_FILE} -if [ -f "${RABBITMQ_CONF_ENV_FILE}" ]; then - CONF_ENV_FILE_PHASE=rabbitmq-env - . ${RABBITMQ_CONF_ENV_FILE} || true -fi - -[ -n "$ERL_EPMD_PORT" ] && export ERL_EPMD_PORT -[ -n "$ERL_EPMD_ADDRESS" ] && export ERL_EPMD_ADDRESS - -DEFAULT_SCHEDULER_BIND_TYPE="db" -[ -n "$SCHEDULER_BIND_TYPE" ] || SCHEDULER_BIND_TYPE="$DEFAULT_SCHEDULER_BIND_TYPE" -[ -n "$RABBITMQ_SCHEDULER_BIND_TYPE" ] || RABBITMQ_SCHEDULER_BIND_TYPE="$SCHEDULER_BIND_TYPE" - -DEFAULT_DISTRIBUTION_BUFFER_SIZE=128000 -[ -n "$DISTRIBUTION_BUFFER_SIZE" ] || DISTRIBUTION_BUFFER_SIZE="$DEFAULT_DISTRIBUTION_BUFFER_SIZE" -[ -n "$RABBITMQ_DISTRIBUTION_BUFFER_SIZE" ] || RABBITMQ_DISTRIBUTION_BUFFER_SIZE="$DISTRIBUTION_BUFFER_SIZE" - -DEFAULT_MAX_NUMBER_OF_PROCESSES=1048576 -[ -n "$MAX_NUMBER_OF_PROCESSES" ] || MAX_NUMBER_OF_PROCESSES="$DEFAULT_MAX_NUMBER_OF_PROCESSES" -[ -n "$RABBITMQ_MAX_NUMBER_OF_PROCESSES" ] || RABBITMQ_MAX_NUMBER_OF_PROCESSES="$MAX_NUMBER_OF_PROCESSES" - -DEFAULT_MAX_NUMBER_OF_ATOMS=5000000 -[ -n "$MAX_NUMBER_OF_ATOMS" ] || MAX_NUMBER_OF_ATOMS="$DEFAULT_MAX_NUMBER_OF_ATOMS" -[ -n "$RABBITMQ_MAX_NUMBER_OF_ATOMS" ] || RABBITMQ_MAX_NUMBER_OF_ATOMS="$MAX_NUMBER_OF_ATOMS" - -## Common server defaults -SERVER_ERL_ARGS=" +P $RABBITMQ_MAX_NUMBER_OF_PROCESSES +t $RABBITMQ_MAX_NUMBER_OF_ATOMS +stbt $RABBITMQ_SCHEDULER_BIND_TYPE +zdbbl $RABBITMQ_DISTRIBUTION_BUFFER_SIZE " - -##--- Set environment vars RABBITMQ_<var_name> to defaults if not set - -[ "x" = "x$RABBITMQ_CTL_ERL_ARGS" ] && RABBITMQ_CTL_ERL_ARGS="$CTL_ERL_ARGS" -[ "x" = "x$RABBITMQ_CTL_DIST_PORT_MIN" ] && RABBITMQ_CTL_DIST_PORT_MIN="$CTL_DIST_PORT_MIN" -[ "x" = "x$RABBITMQ_CTL_DIST_PORT_MAX" ] && RABBITMQ_CTL_DIST_PORT_MAX="$CTL_DIST_PORT_MAX" -[ "x" = "x$RABBITMQ_CTL_DIST_PORT_MIN" ] && RABBITMQ_CTL_DIST_PORT_MIN='35672' -[ "x" = "x$RABBITMQ_CTL_DIST_PORT_MAX" ] && RABBITMQ_CTL_DIST_PORT_MAX="$(($RABBITMQ_CTL_DIST_PORT_MIN + 10))" - -[ "x" = "x$RABBITMQ_SERVER_ERL_ARGS" ] && RABBITMQ_SERVER_ERL_ARGS=${SERVER_ERL_ARGS} -[ "x" = "x$RABBITMQ_SERVER_START_ARGS" ] && RABBITMQ_SERVER_START_ARGS=${SERVER_START_ARGS} -[ "x" = "x$RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS" ] && RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS=${SERVER_ADDITIONAL_ERL_ARGS} -[ "x" = "x$RABBITMQ_SERVER_CODE_PATH" ] && RABBITMQ_SERVER_CODE_PATH=${SERVER_CODE_PATH} -[ "x" = "x$RABBITMQ_IGNORE_SIGINT" ] && RABBITMQ_IGNORE_SIGINT="true" -[ "xtrue" = "x$RABBITMQ_IGNORE_SIGINT" ] && RABBITMQ_IGNORE_SIGINT_FLAG="+B i" - -if [ -n "$saved_RABBITMQ_PID_FILE" ] && \ - [ "$saved_RABBITMQ_PID_FILE" != "$RABBITMQ_PID_FILE" ] -then - _rmq_env_pwarn 'RABBITMQ_PID_FILE was already set by the init script to:' \ - "$saved_RABBITMQ_PID_FILE" \ - 'The value set in rabbitmq-env.conf is ignored because it would break the init script.' - - RABBITMQ_PID_FILE="$saved_RABBITMQ_PID_FILE" -fi - -[ "x" = "x$RABBITMQ_BOOT_MODULE" ] && RABBITMQ_BOOT_MODULE=${BOOT_MODULE} - -##--- End of overridden <var_name> variables - -_rmq_env_set_erl_libs() -{ - if [ -n "$ERL_LIBS" ] - then - export ERL_LIBS="$RABBITMQ_HOME/plugins:$ERL_LIBS" - else - export ERL_LIBS="$RABBITMQ_HOME/plugins" - fi -} - -run_escript() -{ - escript_main="${1:?escript_main must be defined}" - shift - escript="${1:?escript must be defined}" - shift - - _rmq_env_set_erl_libs - - # Important: do not quote RABBITMQ_CTL_ERL_ARGS as they must be - # word-split - # shellcheck disable=SC2086 - exec erl +B \ - -boot "$CLEAN_BOOT_FILE" \ - -noinput -noshell -hidden -smp enable \ - $RABBITMQ_CTL_ERL_ARGS \ - -kernel inet_dist_listen_min "$RABBITMQ_CTL_DIST_PORT_MIN" \ - -kernel inet_dist_listen_max "$RABBITMQ_CTL_DIST_PORT_MAX" \ - -run escript start \ - -escript main "$escript_main" \ - -extra "$escript" "$@" -} - -RABBITMQ_ENV_LOADED=1 - -# Since we source this elsewhere, don't accidentally stop execution -true diff --git a/scripts/rabbitmq-env.bat b/scripts/rabbitmq-env.bat deleted file mode 100644 index 1db57b33c5..0000000000 --- a/scripts/rabbitmq-env.bat +++ /dev/null @@ -1,173 +0,0 @@ -@echo off
-
-REM Scopes the variables to the current batch file
-REM setlocal
-
-rem Preserve values that might contain exclamation marks before
-rem enabling delayed expansion
-set TDP0=%~dp0
-REM setlocal enabledelayedexpansion
-
-REM SCRIPT_DIR=`dirname $SCRIPT_PATH`
-REM RABBITMQ_HOME="${SCRIPT_DIR}/.."
-set SCRIPT_DIR=%TDP0%
-set SCRIPT_NAME=%1
-for /f "delims=" %%F in ("%SCRIPT_DIR%..") do set RABBITMQ_HOME=%%~dpF%%~nF%%~xF
-
-if defined ERL_LIBS (
- set "ERL_LIBS=%RABBITMQ_HOME%\plugins;%ERL_LIBS%"
-) else (
- set "ERL_LIBS=%RABBITMQ_HOME%\plugins"
-)
-
-REM If ERLANG_HOME is not defined, check if "erl.exe" is available in
-REM the path and use that.
-if not defined ERLANG_HOME (
- for /f "delims=" %%F in ('powershell.exe -NoLogo -NoProfile -NonInteractive -Command "(Get-Command erl.exe).Definition"') do @set ERL_PATH=%%F
- if exist "!ERL_PATH!" (
- for /f "delims=" %%F in ("!ERL_PATH!") do set ERL_DIRNAME=%%~dpF
- for /f "delims=" %%F in ("!ERL_DIRNAME!\..") do @set ERLANG_HOME=%%~dpF%%~nF%%~xF
- )
- set ERL_PATH=
- set ERL_DIRNAME=
-)
-
-REM ## Set defaults
-call "%SCRIPT_DIR%\rabbitmq-defaults.bat"
-
-if "!RABBITMQ_CONF_ENV_FILE!"=="" (
- set RABBITMQ_CONF_ENV_FILE=!CONF_ENV_FILE:"=!
-) else (
- set RABBITMQ_CONF_ENV_FILE=!RABBITMQ_CONF_ENV_FILE:"=!
-)
-
-if exist "!RABBITMQ_CONF_ENV_FILE!" (
- call "!RABBITMQ_CONF_ENV_FILE!"
-)
-
-rem Bump ETS table limit to 50000
-if "!ERL_MAX_ETS_TABLES!"=="" (
- set ERL_MAX_ETS_TABLES=50000
-)
-
-rem Default is defined here:
-rem https://github.com/erlang/otp/blob/master/erts/emulator/beam/erl_port.h
-if "!ERL_MAX_PORTS!"=="" (
- set ERL_MAX_PORTS=65536
-)
-
-set DEFAULT_SCHEDULER_BIND_TYPE=db
-if "!RABBITMQ_SCHEDULER_BIND_TYPE!"=="" (
- set RABBITMQ_SCHEDULER_BIND_TYPE=!SCHEDULER_BIND_TYPE!
-)
-if "!RABBITMQ_SCHEDULER_BIND_TYPE!"=="" (
- set RABBITMQ_SCHEDULER_BIND_TYPE=!DEFAULT_SCHEDULER_BIND_TYPE!
-)
-
-set DEFAULT_DISTRIBUTION_BUFFER_SIZE=128000
-if "!RABBITMQ_DISTRIBUTION_BUFFER_SIZE!"=="" (
- set RABBITMQ_DISTRIBUTION_BUFFER_SIZE=!DISTRIBUTION_BUFFER_SIZE!
-)
-if "!RABBITMQ_DISTRIBUTION_BUFFER_SIZE!"=="" (
- set RABBITMQ_DISTRIBUTION_BUFFER_SIZE=!DEFAULT_DISTRIBUTION_BUFFER_SIZE!
-)
-
-set DEFAULT_MAX_NUMBER_OF_PROCESSES=1048576
-if "!RABBITMQ_MAX_NUMBER_OF_PROCESSES!"=="" (
- set RABBITMQ_MAX_NUMBER_OF_PROCESSES=!MAX_NUMBER_OF_PROCESSES!
-)
-if "!RABBITMQ_MAX_NUMBER_OF_PROCESSES!"=="" (
- set RABBITMQ_MAX_NUMBER_OF_PROCESSES=!DEFAULT_MAX_NUMBER_OF_PROCESSES!
-)
-
-set DEFAULT_MAX_NUMBER_OF_ATOMS=5000000
-if "!RABBITMQ_MAX_NUMBER_OF_ATOMS!"=="" (
- set RABBITMQ_MAX_NUMBER_OF_ATOMS=!MAX_NUMBER_OF_ATOMS!
-)
-if "!RABBITMQ_MAX_NUMBER_OF_ATOMS!"=="" (
- set RABBITMQ_MAX_NUMBER_OF_ATOMS=!DEFAULT_MAX_NUMBER_OF_ATOMS!
-)
-
-REM Common server defaults
-set SERVER_ERL_ARGS=+P !RABBITMQ_MAX_NUMBER_OF_PROCESSES! +t !RABBITMQ_MAX_NUMBER_OF_ATOMS! +stbt !RABBITMQ_SCHEDULER_BIND_TYPE! +zdbbl !RABBITMQ_DISTRIBUTION_BUFFER_SIZE!
-
-REM ##--- Set environment vars RABBITMQ_<var_name> to defaults if not set
-
-REM [ "x" = "x$RABBITMQ_SERVER_ERL_ARGS" ] && RABBITMQ_SERVER_ERL_ARGS=${SERVER_ERL_ARGS}
-if "!RABBITMQ_SERVER_ERL_ARGS!"=="" (
- set RABBITMQ_SERVER_ERL_ARGS=!SERVER_ERL_ARGS!
-)
-
-REM [ "x" = "x$RABBITMQ_SERVER_START_ARGS" ] && RABBITMQ_SERVER_START_ARGS=${SERVER_START_ARGS}
-if "!RABBITMQ_SERVER_START_ARGS!"=="" (
- if not "!SERVER_START_ARGS!"=="" (
- set RABBITMQ_SERVER_START_ARGS=!SERVER_START_ARGS!
- )
-)
-
-REM [ "x" = "x$RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS" ] && RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS=${SERVER_ADDITIONAL_ERL_ARGS}
-if "!RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS!"=="" (
- if not "!SERVER_ADDITIONAL_ERL_ARGS!"=="" (
- set RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS=!SERVER_ADDITIONAL_ERL_ARGS!
- )
-)
-
-REM [ "x" = "x$RABBITMQ_BOOT_MODULE" ] && RABBITMQ_BOOT_MODULE=${BOOT_MODULE}
-if "!RABBITMQ_BOOT_MODULE!"=="" (
- if "!BOOT_MODULE!"=="" (
- set RABBITMQ_BOOT_MODULE=rabbit
- ) else (
- set RABBITMQ_BOOT_MODULE=!BOOT_MODULE!
- )
-)
-
-REM [ "x" = "x$RABBITMQ_CTL_ERL_ARGS" ] && RABBITMQ_CTL_ERL_ARGS=${CTL_ERL_ARGS}
-if "!RABBITMQ_CTL_ERL_ARGS!"=="" (
- if not "!CTL_ERL_ARGS!"=="" (
- set RABBITMQ_CTL_ERL_ARGS=!CTL_ERL_ARGS!
- )
-)
-
-if "!RABBITMQ_CTL_DIST_PORT_MIN!"=="" (
- if not "!CTL_DIST_PORT_MIN!"=="" (
- set RABBITMQ_CTL_DIST_PORT_MIN=!CTL_DIST_PORT_MIN!
- )
-)
-if "!RABBITMQ_CTL_DIST_PORT_MAX!"=="" (
- if not "!CTL_DIST_PORT_MAX!"=="" (
- set RABBITMQ_CTL_DIST_PORT_MAX=!CTL_DIST_PORT_MAX!
- )
-)
-if "!RABBITMQ_CTL_DIST_PORT_MIN!"=="" (
- set RABBITMQ_CTL_DIST_PORT_MIN=35672
-)
-if "!RABBITMQ_CTL_DIST_PORT_MAX!"=="" (
- set /a RABBITMQ_CTL_DIST_PORT_MAX=10+!RABBITMQ_CTL_DIST_PORT_MIN!
-)
-
-REM ADDITIONAL WINDOWS ONLY CONFIG ITEMS
-
-if "!RABBITMQ_SERVICENAME!"=="" (
- if "!SERVICENAME!"=="" (
- set RABBITMQ_SERVICENAME=RabbitMQ
- ) else (
- set RABBITMQ_SERVICENAME=!SERVICENAME!
- )
-)
-
-REM Environment cleanup
-set BOOT_MODULE=
-set CONFIG_FILE=
-set FEATURE_FLAGS_FILE=
-set ENABLED_PLUGINS_FILE=
-set LOG_BASE=
-set MNESIA_BASE=
-set PLUGINS_DIR=
-set SCRIPT_DIR=
-set SCRIPT_NAME=
-set TDP0=
-
-REM ##--- End of overridden <var_name> variables
-
-REM # Since we source this elsewhere, don't accidentally stop execution
-REM true
diff --git a/scripts/rabbitmq-plugins b/scripts/rabbitmq-plugins deleted file mode 100755 index 1ec15b2ee9..0000000000 --- a/scripts/rabbitmq-plugins +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -## This Source Code Form is subject to the terms of the Mozilla Public -## License, v. 2.0. If a copy of the MPL was not distributed with this -## file, You can obtain one at https://mozilla.org/MPL/2.0/. -## -## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. -## - -# Exit immediately if a pipeline, which may consist of a single simple command, -# a list, or a compound command returns a non-zero status -set -e - -# Each variable or function that is created or modified is given the export -# attribute and marked for export to the environment of subsequent commands. -set -a - -# shellcheck source=/dev/null -# -# TODO: when shellcheck adds support for relative paths, change to -# shellcheck source=./rabbitmq-env -. "${0%/*}"/rabbitmq-env - -run_escript rabbitmqctl_escript "${ESCRIPT_DIR:?must be defined}"/rabbitmq-plugins "$@" diff --git a/scripts/rabbitmq-plugins.bat b/scripts/rabbitmq-plugins.bat deleted file mode 100644 index e1f13b7073..0000000000 --- a/scripts/rabbitmq-plugins.bat +++ /dev/null @@ -1,56 +0,0 @@ -@echo off
-
-REM This Source Code Form is subject to the terms of the Mozilla Public
-REM License, v. 2.0. If a copy of the MPL was not distributed with this
-REM file, You can obtain one at https://mozilla.org/MPL/2.0/.
-REM
-REM Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved.
-REM
-
-setlocal
-
-rem Preserve values that might contain exclamation marks before
-rem enabling delayed expansion
-set TDP0=%~dp0
-set STAR=%*
-setlocal enabledelayedexpansion
-
-REM Get default settings with user overrides for (RABBITMQ_)<var_name>
-REM Non-empty defaults should be set in rabbitmq-env
-call "!TDP0!\rabbitmq-env.bat" %~n0
-
-if not exist "!ERLANG_HOME!\bin\erl.exe" (
- echo.
- echo ******************************
- echo ERLANG_HOME not set correctly.
- echo ******************************
- echo.
- echo Please either set ERLANG_HOME to point to your Erlang installation or place the
- echo RabbitMQ server distribution in the Erlang lib folder.
- echo.
- exit /B 1
-)
-
-REM Disable erl_crash.dump by default for control scripts.
-if not defined ERL_CRASH_DUMP_SECONDS (
- set ERL_CRASH_DUMP_SECONDS=0
-)
-
-"!ERLANG_HOME!\bin\erl.exe" +B ^
--boot !CLEAN_BOOT_FILE! ^
--noinput -noshell -hidden -smp enable ^
-!RABBITMQ_CTL_ERL_ARGS! ^
--kernel inet_dist_listen_min !RABBITMQ_CTL_DIST_PORT_MIN! ^
--kernel inet_dist_listen_max !RABBITMQ_CTL_DIST_PORT_MAX! ^
--run escript start ^
--escript main rabbitmqctl_escript ^
--extra "%RABBITMQ_HOME%\escript\rabbitmq-plugins" !STAR!
-
-if ERRORLEVEL 1 (
- exit /B %ERRORLEVEL%
-)
-
-EXIT /B 0
-
-endlocal
-endlocal
diff --git a/scripts/rabbitmq-queues b/scripts/rabbitmq-queues deleted file mode 100755 index 680076f962..0000000000 --- a/scripts/rabbitmq-queues +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -## This Source Code Form is subject to the terms of the Mozilla Public -## License, v. 2.0. If a copy of the MPL was not distributed with this -## file, You can obtain one at https://mozilla.org/MPL/2.0/. -## -## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. -## - -# Exit immediately if a pipeline, which may consist of a single simple command, -# a list, or a compound command returns a non-zero status -set -e - -# Each variable or function that is created or modified is given the export -# attribute and marked for export to the environment of subsequent commands. -set -a - -# shellcheck source=/dev/null -# -# TODO: when shellcheck adds support for relative paths, change to -# shellcheck source=./rabbitmq-env -. "${0%/*}"/rabbitmq-env - -run_escript rabbitmqctl_escript "${ESCRIPT_DIR:?must be defined}"/rabbitmq-queues "$@" diff --git a/scripts/rabbitmq-queues.bat b/scripts/rabbitmq-queues.bat deleted file mode 100644 index 99fce6479f..0000000000 --- a/scripts/rabbitmq-queues.bat +++ /dev/null @@ -1,56 +0,0 @@ -@echo off
-REM This Source Code Form is subject to the terms of the Mozilla Public
-REM License, v. 2.0. If a copy of the MPL was not distributed with this
-REM file, You can obtain one at https://mozilla.org/MPL/2.0/.
-REM
-REM Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved.
-REM
-
-REM Scopes the variables to the current batch file
-setlocal
-
-rem Preserve values that might contain exclamation marks before
-rem enabling delayed expansion
-set TDP0=%~dp0
-set STAR=%*
-setlocal enabledelayedexpansion
-
-REM Get default settings with user overrides for (RABBITMQ_)<var_name>
-REM Non-empty defaults should be set in rabbitmq-env
-call "%TDP0%\rabbitmq-env.bat" %~n0
-
-if not exist "!ERLANG_HOME!\bin\erl.exe" (
- echo.
- echo ******************************
- echo ERLANG_HOME not set correctly.
- echo ******************************
- echo.
- echo Please either set ERLANG_HOME to point to your Erlang installation or place the
- echo RabbitMQ server distribution in the Erlang lib folder.
- echo.
- exit /B 1
-)
-
-REM Disable erl_crash.dump by default for control scripts.
-if not defined ERL_CRASH_DUMP_SECONDS (
- set ERL_CRASH_DUMP_SECONDS=0
-)
-
-"!ERLANG_HOME!\bin\erl.exe" +B ^
--boot !CLEAN_BOOT_FILE! ^
--noinput -noshell -hidden -smp enable ^
-!RABBITMQ_CTL_ERL_ARGS! ^
--kernel inet_dist_listen_min !RABBITMQ_CTL_DIST_PORT_MIN! ^
--kernel inet_dist_listen_max !RABBITMQ_CTL_DIST_PORT_MAX! ^
--run escript start ^
--escript main rabbitmqctl_escript ^
--extra "%RABBITMQ_HOME%\escript\rabbitmq-queues" !STAR!
-
-if ERRORLEVEL 1 (
- exit /B %ERRORLEVEL%
-)
-
-EXIT /B 0
-
-endlocal
-endlocal
diff --git a/scripts/rabbitmq-rel b/scripts/rabbitmq-rel deleted file mode 100755 index a96ec78764..0000000000 --- a/scripts/rabbitmq-rel +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env escript -%% vim:ft=erlang:sw=2:et: - -main(["show-rel"]) -> - Rel = get_rel(), - io:format("~p.~n", [Rel]); -main(["gen-boot"]) -> - generate_rel(), - generate_boot(). - -get_rel() -> - ok = application:load(rabbit), - Apps0 = get_apps(rabbit), - Apps1 = lists:sort( - fun - (_, rabbitmq_prelaunch) -> false; - (rabbitmq_prelaunch, _) -> true; - (_, mnesia) -> true; - (mnesia, _) -> false; - (A, B) -> A =< B - end, Apps0), - Apps = [{App, get_vsn(App)} || App <- Apps1], - - ERTSVersion = erlang:system_info(version), - RabbitVersion = get_vsn(rabbit), - - {release, - {"RabbitMQ", RabbitVersion}, - {erts, ERTSVersion}, - Apps}. - -get_apps(App) -> - ok = load_app(App), - {ok, DirectDeps} = application:get_key(App, applications), - lists:umerge( - [lists:usort(get_apps(Dep)) || Dep <- DirectDeps] ++ - [lists:usort([kernel, stdlib, sasl, App, mnesia])]). - -load_app(App) -> - case application:load(App) of - ok -> ok; - {error, {already_loaded, App}} -> ok - end. - -generate_rel() -> - Rel = get_rel(), - io:format("~p.~n", [Rel]), - Output = io_lib:format("~p.~n", [Rel]), - ok = file:write_file("rabbit.rel", Output). - -generate_boot() -> - Options = [local, {path, code:get_path()}], - ok = systools:make_script("rabbit", Options). - -get_vsn(App) -> - load_app(App), - {ok, Vsn} = application:get_key(App, vsn), - Vsn. diff --git a/scripts/rabbitmq-script-wrapper b/scripts/rabbitmq-script-wrapper new file mode 100644 index 0000000000..da8fe252e7 --- /dev/null +++ b/scripts/rabbitmq-script-wrapper @@ -0,0 +1,111 @@ +#!/bin/sh + +## This Source Code Form is subject to the terms of the Mozilla Public +## License, v. 2.0. If a copy of the MPL was not distributed with this +## file, You can obtain one at https://mozilla.org/MPL/2.0/. +## +## Copyright (c) 2018-2020 VMware, Inc. or its affiliates. All rights reserved. +## + +SCRIPT="$(basename "$0")" + +main() { + ensure_we_are_in_a_readable_dir + if current_user_is_rabbitmq && calling_rabbitmq_server + then + exec_rabbitmq_server "$@" + elif current_user_is_rabbitmq && ! calling_rabbitmq_plugins + then + exec_script_as_rabbitmq "$@" + elif current_user_is_root && calling_rabbitmq_plugins + then + run_script_as_rabbitmq "$@" + _result="$?" + maybe_fixup_erlang_cookie + exit "$_result" + elif current_user_is_root + then + exec_script_as_root "$@" + else + run_script_help_and_fail + fi +} + +maybe_fixup_erlang_cookie() { + # rabbitmq/rabbitmq-server-release#85 + _rabbitmq_home="$(cd ~rabbitmq && pwd)" + _erlang_cookie="$_rabbitmq_home/.erlang.cookie" + if [ -f "$_erlang_cookie" ] + then + chown @RABBITMQ_USER@:@RABBITMQ_GROUP@ "$_erlang_cookie" + chmod 400 "$_erlang_cookie" + fi +} + +ensure_we_are_in_a_readable_dir() { + # shellcheck disable=SC2164 + cd ~rabbitmq || cd / +} + +current_user_is_rabbitmq() { + [ "$(id -un)" = "rabbitmq" ] +} + +current_user_is_root() { + [ "$(id -u)" = 0 ] +} + +calling_rabbitmq_server() { + [ "$SCRIPT" = "rabbitmq-server" ] +} + +calling_rabbitmq_plugins() { + [ "$SCRIPT" = "rabbitmq-plugins" ] +} + +exec_rabbitmq_server() { + exec /usr/lib/rabbitmq/bin/rabbitmq-server "$@" +} + +run_script_as_rabbitmq() { + HOME="$(cd ~rabbitmq && pwd)" "/usr/lib/rabbitmq/bin/$SCRIPT" "$@" +} + +exec_script_as_rabbitmq() { + HOME="$(cd ~rabbitmq && pwd)" exec "/usr/lib/rabbitmq/bin/$SCRIPT" "$@" +} + +exec_script_as_root() { + if [ -x /sbin/runuser ] + then + # TODO: + # At some point all of the RabbitMQ supported distributions will be using + # the util-linux version of /sbin/runuser, as it has been removed from GNU + # coreutils as of 2012. At that point the first clause of the following + # if statement can become the only statement used and the if/then + # removed + if /sbin/runuser --version | grep -qF util-linux + then + exec /sbin/runuser -u rabbitmq -- "/usr/lib/rabbitmq/bin/$SCRIPT" "$@" + else + exec /sbin/runuser -s /bin/sh -- rabbitmq "/usr/lib/rabbitmq/bin/$SCRIPT" "$@" + fi + elif [ -x /bin/su ] + then + exec /bin/su -s /bin/sh rabbitmq -- "/usr/lib/rabbitmq/bin/$SCRIPT" "$@" + else + echo "Please ensure /bin/su or /sbin/runuser exists and can be executed by $USER." 1>&2 + exit 1 + fi +} + +run_script_help_and_fail() { + "/usr/lib/rabbitmq/bin/$SCRIPT" help + + echo " +Only root or rabbitmq can run $SCRIPT +" + exit 1 +} + +main "$@" diff --git a/scripts/rabbitmq-server b/scripts/rabbitmq-server deleted file mode 100755 index 82058dcb26..0000000000 --- a/scripts/rabbitmq-server +++ /dev/null @@ -1,155 +0,0 @@ -#!/bin/sh -# vim:sw=4:et: -## This Source Code Form is subject to the terms of the Mozilla Public -## License, v. 2.0. If a copy of the MPL was not distributed with this -## file, You can obtain one at https://mozilla.org/MPL/2.0/. -## -## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. -## - -set -e - -# Get default settings with user overrides for (RABBITMQ_)<var_name> -# Non-empty defaults should be set in rabbitmq-env -SCRIPTS_DIR=$(dirname "$0") -. "$SCRIPTS_DIR/rabbitmq-env" - -[ "$NOTIFY_SOCKET" ] && RUNNING_UNDER_SYSTEMD=true - -RABBITMQ_DEFAULT_ALLOC_ARGS="+MBas ageffcbf +MHas ageffcbf +MBlmbcs 512 +MHlmbcs 512 +MMmcs 30" - -# Bump ETS table limit to 50000 -if [ "x" = "x$ERL_MAX_ETS_TABLES" ]; then - ERL_MAX_ETS_TABLES=50000 -fi - -check_start_params() { - check_not_empty RABBITMQ_BOOT_MODULE - check_not_empty SASL_BOOT_FILE -} - -check_not_empty() { - local name="${1:?}" - local value - eval value=\$$name - if [ -z "$value" ]; then - echo "Error: ENV variable should be defined: $1. - Please check rabbitmq-env, rabbitmq-defaults, and ${RABBITMQ_CONF_ENV_FILE} script files" - exit 78 - fi -} - -start_rabbitmq_server() { - set -e - - _rmq_env_set_erl_libs - - RABBITMQ_START_RABBIT= - [ "x" = "x$RABBITMQ_ALLOW_INPUT" ] && RABBITMQ_START_RABBIT=" -noinput" - if test -z "$RABBITMQ_NODE_ONLY"; then - if test "$USE_RABBIT_BOOT_SCRIPT"; then - # TODO: This is experimental and undocumented at this point. - # It is here just to do simple checks while playing with how - # RabbitMQ is started. - "$SCRIPTS_DIR/rabbitmq-rel" gen-boot - SASL_BOOT_FILE=rabbit - test -f "$SASL_BOOT_FILE.boot" - RABBITMQ_START_RABBIT="$RABBITMQ_START_RABBIT -init_debug" - else - RABBITMQ_START_RABBIT="$RABBITMQ_START_RABBIT -s $RABBITMQ_BOOT_MODULE boot" - fi - fi - - # We need to turn off path expansion because some of the vars, - # notably RABBITMQ_SERVER_ERL_ARGS, contain terms that look like - # globs and there is no other way of preventing their expansion. - set -f - - export ERL_MAX_ETS_TABLES \ - SYS_PREFIX - - check_start_params - - exec erl \ - -pa "$RABBITMQ_SERVER_CODE_PATH" \ - ${RABBITMQ_START_RABBIT} \ - -boot "${SASL_BOOT_FILE}" \ - +W w \ - ${RABBITMQ_DEFAULT_ALLOC_ARGS} \ - ${RABBITMQ_SERVER_ERL_ARGS} \ - ${RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS} \ - ${RABBITMQ_SERVER_START_ARGS} \ - -lager crash_log false \ - -lager handlers '[]' \ - "$@" -} - -stop_rabbitmq_server() { - if test "$rabbitmq_server_pid"; then - kill -TERM "$rabbitmq_server_pid" - wait "$rabbitmq_server_pid" || true - fi -} - -if [ "$RABBITMQ_ALLOW_INPUT" -o "$RUNNING_UNDER_SYSTEMD" -o "$detached" ]; then - # Run erlang VM directly, completely replacing current shell - # process - so the pid file written in the code above will be - # valid (unless detached, which is also handled in the code - # above). - # - # And also this is the correct mode to run the broker under - # systemd - there is no need in a proxy process that converts - # signals to graceful shutdown command, the unit file should already - # contain instructions for graceful shutdown. Also by removing - # this additional process we could simply use value returned by - # `os:getpid/0` for a systemd ready notification. - start_rabbitmq_server "$@" -else - # When RabbitMQ runs in the foreground but the Erlang shell is - # disabled, we setup signal handlers to stop RabbitMQ properly. This - # is at least useful in the case of Docker. - # The Erlang VM should ignore SIGINT. - RABBITMQ_SERVER_START_ARGS="${RABBITMQ_SERVER_START_ARGS} ${RABBITMQ_IGNORE_SIGINT_FLAG}" - - # Signal handlers. They all stop RabbitMQ properly, using - # rabbitmqctl stop. This script will exit with different exit codes: - # SIGHUP, SIGTSTP + SIGCONT - # Ignored until we implement a useful behavior. - # SIGTERM - # Exits 0 since this is considered a normal process termination. - # SIGINT - # Exits 128 + $signal_number where $signal_number is 2 for SIGINT (see - # https://pubs.opengroup.org/onlinepubs/009695399/utilities/kill.html). - # This is considered an abnormal process termination. Normally, we - # don't need to specify this exit code because the shell propagates it. - # Unfortunately, the signal handler doesn't work as expected in Dash, - # thus we need to explicitly restate the exit code. - # - # The behaviors below should remain consistent with the - # equivalent signal handlers in the Erlang code - # (see apps/rabbitmq_prelaunch/src/rabbit_prelaunch_sighandler.erl). - trap '' HUP TSTP CONT - trap "stop_rabbitmq_server; exit 0" TERM - trap "stop_rabbitmq_server; exit 130" INT - - start_rabbitmq_server "$@" & - export rabbitmq_server_pid=$! - - # Block until RabbitMQ exits or a signal is caught. - # Waits for last command (which is start_rabbitmq_server) - # - # The "|| true" is here to work around an issue with Dash. Normally - # in a Bourne shell, if `wait` is interrupted by a signal, the - # signal handlers defined above are executed and the script - # terminates with the exit code of `wait` (unless the signal handler - # overrides that). - # In the case of Dash, it looks like `set -e` (set at the beginning - # of this script) gets precedence over signal handling. Therefore, - # when `wait` is interrupted, its exit code is non-zero and because - # of `set -e`, the script terminates immediately without running the - # signal handler. To work around this issue, we use "|| true" to - # force that statement to succeed and the signal handler to properly - # execute. Because the statement below has an exit code of 0, the - # signal handler has to restate the expected exit code. - wait "$rabbitmq_server_pid" || true -fi diff --git a/scripts/rabbitmq-server-ha.ocf b/scripts/rabbitmq-server-ha.ocf new file mode 100755 index 0000000000..fd9a3c4b29 --- /dev/null +++ b/scripts/rabbitmq-server-ha.ocf @@ -0,0 +1,2423 @@ +#!/bin/sh +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# See usage() function below for more details ... +# +# Note that the script uses an external file to setup RabbitMQ policies +# so make sure to create it from an example shipped with the package. +# +####################################################################### +# Initialization: + +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} +. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs + +####################################################################### + +# Fill in some defaults if no values are specified + +PATH=/sbin:/usr/sbin:/bin:/usr/bin + +OCF_RESKEY_binary_default="/usr/sbin/rabbitmq-server" +OCF_RESKEY_ctl_default="/usr/sbin/rabbitmqctl" +OCF_RESKEY_debug_default=false +OCF_RESKEY_username_default="rabbitmq" +OCF_RESKEY_groupname_default="rabbitmq" +OCF_RESKEY_admin_user_default="guest" +OCF_RESKEY_admin_password_default="guest" +OCF_RESKEY_definitions_dump_file_default="/etc/rabbitmq/definitions" +OCF_RESKEY_pid_file_default="/var/run/rabbitmq/pid" +OCF_RESKEY_log_dir_default="/var/log/rabbitmq" +OCF_RESKEY_mnesia_base_default="/var/lib/rabbitmq/mnesia" +OCF_RESKEY_mnesia_schema_base_default="/var/lib/rabbitmq" +OCF_RESKEY_host_ip_default="127.0.0.1" +OCF_RESKEY_node_port_default=5672 +OCF_RESKEY_default_vhost_default="/" +OCF_RESKEY_erlang_cookie_default=false +OCF_RESKEY_erlang_cookie_file_default="/var/lib/rabbitmq/.erlang.cookie" +OCF_RESKEY_use_fqdn_default=false +OCF_RESKEY_fqdn_prefix_default="" +OCF_RESKEY_max_rabbitmqctl_timeouts_default=3 +OCF_RESKEY_policy_file_default="/usr/local/sbin/set_rabbitmq_policy" +OCF_RESKEY_rmq_feature_health_check_default=true +OCF_RESKEY_rmq_feature_local_list_queues_default=true +OCF_RESKEY_limit_nofile_default=65535 +OCF_RESKEY_avoid_using_iptables_default=false + +: ${HA_LOGTAG="lrmd"} +: ${HA_LOGFACILITY="daemon"} +: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}} +: ${OCF_RESKEY_ctl=${OCF_RESKEY_ctl_default}} +: ${OCF_RESKEY_debug=${OCF_RESKEY_debug_default}} +: ${OCF_RESKEY_username=${OCF_RESKEY_username_default}} +: ${OCF_RESKEY_groupname=${OCF_RESKEY_groupname_default}} +: ${OCF_RESKEY_admin_user=${OCF_RESKEY_admin_user_default}} +: ${OCF_RESKEY_admin_password=${OCF_RESKEY_admin_password_default}} +: ${OCF_RESKEY_definitions_dump_file=${OCF_RESKEY_definitions_dump_file_default}} +: ${OCF_RESKEY_log_dir=${OCF_RESKEY_log_dir_default}} +: ${OCF_RESKEY_mnesia_base=${OCF_RESKEY_mnesia_base_default}} +: ${OCF_RESKEY_mnesia_schema_base=${OCF_RESKEY_mnesia_schema_base_default}} +: ${OCF_RESKEY_pid_file=${OCF_RESKEY_pid_file_default}} +: ${OCF_RESKEY_node_port=${OCF_RESKEY_node_port_default}} +: ${OCF_RESKEY_default_vhost=${OCF_RESKEY_default_vhost_default}} +: ${OCF_RESKEY_erlang_cookie=${OCF_RESKEY_erlang_cookie_default}} +: ${OCF_RESKEY_erlang_cookie_file=${OCF_RESKEY_erlang_cookie_file_default}} +: ${OCF_RESKEY_use_fqdn=${OCF_RESKEY_use_fqdn_default}} +: ${OCF_RESKEY_fqdn_prefix=${OCF_RESKEY_fqdn_prefix_default}} +: ${OCF_RESKEY_max_rabbitmqctl_timeouts=${OCF_RESKEY_max_rabbitmqctl_timeouts_default}} +: ${OCF_RESKEY_policy_file=${OCF_RESKEY_policy_file_default}} +: ${OCF_RESKEY_rmq_feature_health_check=${OCF_RESKEY_rmq_feature_health_check_default}} +: ${OCF_RESKEY_rmq_feature_local_list_queues=${OCF_RESKEY_rmq_feature_local_list_queues_default}} +: ${OCF_RESKEY_limit_nofile=${OCF_RESKEY_limit_nofile_default}} +: ${OCF_RESKEY_avoid_using_iptables=${OCF_RESKEY_avoid_using_iptables_default}} + +####################################################################### + +OCF_RESKEY_start_time_default=$((OCF_RESKEY_CRM_meta_timeout / 6000 + 2)) +: ${OCF_RESKEY_start_time=${OCF_RESKEY_start_time_default}} +OCF_RESKEY_stop_time_default=${OCF_RESKEY_start_time_default} +: ${OCF_RESKEY_stop_time=${OCF_RESKEY_start_time_default}} +OCF_RESKEY_command_timeout_default="" +: ${OCF_RESKEY_command_timeout=${OCF_RESKEY_command_timeout_default}} +TIMEOUT_ARG=$((OCF_RESKEY_CRM_meta_timeout / 6000 + 30)) +COMMAND_TIMEOUT="/usr/bin/timeout ${OCF_RESKEY_command_timeout} ${TIMEOUT_ARG}" +RESOURCE_NAME=`echo $OCF_RESOURCE_INSTANCE | cut -d ":" -f 1` + +####################################################################### + +usage() { + cat <<UEND + usage: $0 (start|stop|validate-all|meta-data|status|monitor) + + $0 manages an ${OCF_RESKEY_binary} process as an HA resource + + The 'start' operation starts the networking service. + The 'stop' operation stops the networking service. + The 'validate-all' operation reports whether the parameters are valid + The 'meta-data' operation reports this RA's meta-data information + The 'status' operation reports whether the networking service is running + The 'monitor' operation reports whether the networking service seems to be working + +UEND +} + +meta_data() { + # The EXTENDED_OCF_PARAMS parameter below does not exist by default + # and hence converted to an empty string unless overridden. It + # could be used by an extention script to add new parameters. For + # example see https://review.openstack.org/#/c/249180/10 + + cat <<END +<?xml version="1.0"?> +<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> +<resource-agent name="${OCF_RESKEY_binary}"> +<version>1.0</version> + +<longdesc lang="en"> +Resource agent for ${OCF_RESKEY_binary} +</longdesc> +<shortdesc lang="en">Resource agent for ${OCF_RESKEY_binary}</shortdesc> +<parameters> + +<parameter name="binary" unique="0" required="0"> +<longdesc lang="en"> +RabbitMQ binary +</longdesc> +<shortdesc lang="en">RabbitMQ binary</shortdesc> +<content type="string" default="${OCF_RESKEY_binary_default}" /> +</parameter> + +<parameter name="ctl" unique="0" required="0"> +<longdesc lang="en"> +rabbitctl binary +</longdesc> +<shortdesc lang="en">rabbitctl binary binary</shortdesc> +<content type="string" default="${OCF_RESKEY_ctl_default}" /> +</parameter> + +<parameter name="pid_file" unique="0" required="0"> +<longdesc lang="en"> +RabbitMQ PID file +</longdesc> +<shortdesc lang="en">RabbitMQ PID file</shortdesc> +<content type="string" default="${OCF_RESKEY_pid_file_default}" /> +</parameter> + +<parameter name="log_dir" unique="0" required="0"> +<longdesc lang="en"> +RabbitMQ log directory +</longdesc> +<shortdesc lang="en">RabbitMQ log directory</shortdesc> +<content type="string" default="${OCF_RESKEY_log_dir_default}" /> +</parameter> + +<parameter name="username" unique="0" required="0"> +<longdesc lang="en"> +RabbitMQ user name +</longdesc> +<shortdesc lang="en">RabbitMQ user name</shortdesc> +<content type="string" default="${OCF_RESKEY_username_default}" /> +</parameter> + +<parameter name="groupname" unique="0" required="0"> +<longdesc lang="en"> +RabbitMQ group name +</longdesc> +<shortdesc lang="en">RabbitMQ group name</shortdesc> +<content type="string" default="${OCF_RESKEY_groupname_default}" /> +</parameter> + +<parameter name="admin_user" unique="0" required="0"> +<longdesc lang="en"> +RabbitMQ default admin user for API +</longdesc> +<shortdesc lang="en">RabbitMQ admin user</shortdesc> +<content type="string" default="${OCF_RESKEY_admin_user_default}" /> +</parameter> + +<parameter name="admin_password" unique="0" required="0"> +<longdesc lang="en"> +RabbitMQ default admin user password for API +</longdesc> +<shortdesc lang="en">RabbitMQ admin password</shortdesc> +<content type="string" default="${OCF_RESKEY_admin_password_default}" /> +</parameter> + +<parameter name="definitions_dump_file" unique="0" required="0"> +<longdesc lang="en"> +RabbitMQ default definitions dump file +</longdesc> +<shortdesc lang="en">RabbitMQ definitions dump file</shortdesc> +<content type="string" default="${OCF_RESKEY_definitions_dump_file}" /> +</parameter> + +<parameter name="command_timeout" unique="0" required="0"> +<longdesc lang="en"> +Timeout command arguments for issued commands termination (value is auto evaluated) +</longdesc> +<shortdesc lang="en">Arguments for timeout wrapping command</shortdesc> +<content type="string" default="${OCF_RESKEY_command_timeout_default}" /> +</parameter> + +<parameter name="start_time" unique="0" required="0"> +<longdesc lang="en"> +Timeout for start rabbitmq server +</longdesc> +<shortdesc lang="en">Timeout for start rabbitmq server</shortdesc> +<content type="string" default="${OCF_RESKEY_start_time_default}" /> +</parameter> + +<parameter name="stop_time" unique="0" required="0"> +<longdesc lang="en"> +Timeout for stopping rabbitmq server +</longdesc> +<shortdesc lang="en">Timeout for stopping rabbitmq server</shortdesc> +<content type="string" default="${OCF_RESKEY_stop_time_default}" /> +</parameter> + +<parameter name="debug" unique="0" required="0"> +<longdesc lang="en"> +The debug flag for agent (${OCF_RESKEY_binary}) instance. +In the /tmp/ directory will be created rmq-* files for log +some operations and ENV values inside OCF-script. +</longdesc> +<shortdesc lang="en">AMQP server (${OCF_RESKEY_binary}) debug flag</shortdesc> +<content type="boolean" default="${OCF_RESKEY_debug_default}" /> +</parameter> + +<parameter name="mnesia_base" unique="0" required="0"> +<longdesc lang="en"> +Base directory for storing Mnesia files +</longdesc> +<shortdesc lang="en">Base directory for storing Mnesia files</shortdesc> +<content type="boolean" default="${OCF_RESKEY_mnesia_base_default}" /> +</parameter> + +<parameter name="mnesia_schema_base" unique="0" required="0"> +<longdesc lang="en"> +Parent directory for Mnesia schema directory +</longdesc> +<shortdesc lang="en">Parent directory for Mnesia schema directory</shortdesc> +<content type="string" default="${OCF_RESKEY_mnesia_schema_base_default}" /> +</parameter> + +<parameter name="host_ip" unique="0" required="0"> +<longdesc lang="en"> +${OCF_RESKEY_binary} should listen on this IP address +</longdesc> +<shortdesc lang="en">${OCF_RESKEY_binary} should listen on this IP address</shortdesc> +<content type="boolean" default="${OCF_RESKEY_host_ip_default}" /> +</parameter> + +<parameter name="node_port" unique="0" required="0"> +<longdesc lang="en"> +${OCF_RESKEY_binary} should listen on this port +</longdesc> +<shortdesc lang="en">${OCF_RESKEY_binary} should listen on this port</shortdesc> +<content type="boolean" default="${OCF_RESKEY_node_port_default}" /> +</parameter> + +<parameter name="default_vhost" unique="0" required="0"> +<longdesc lang="en"> +Default virtual host used for monitoring if a node is fully synchronized with +the rest of the cluster. In normal operation, the resource agent will wait for +queues from this virtual host on this node to be synchronized elsewhere before +stopping RabbitMQ. This also means queues in other virtual hosts may not be +fully synchronized on stop operations. +</longdesc> +<shortdesc lang="en">Default virtual host used for waiting for synchronization</shortdesc> +<content type="string" default="${OCF_RESKEY_default_vhost_default}" /> +</parameter> + +<parameter name="erlang_cookie" unique="0" required="0"> +<longdesc lang="en"> +Erlang cookie for clustering. If specified, will be updated at the mnesia reset +</longdesc> +<shortdesc lang="en">Erlang cookie</shortdesc> +<content type="boolean" default="${OCF_RESKEY_erlang_cookie_default}" /> +</parameter> + +<parameter name="erlang_cookie_file" unique="0" required="0"> +<longdesc lang="en"> +Erlang cookie file path where the cookie will be put, if requested +</longdesc> +<shortdesc lang="en">Erlang cookie file</shortdesc> +<content type="boolean" default="${OCF_RESKEY_erlang_cookie_file_default}" /> +</parameter> + +<parameter name="use_fqdn" unique="0" required="0"> +<longdesc lang="en"> +Either to use FQDN or a shortname for the rabbitmq node +</longdesc> +<shortdesc lang="en">Use FQDN</shortdesc> +<content type="boolean" default="${OCF_RESKEY_use_fqdn_default}" /> +</parameter> + +<parameter name="fqdn_prefix" unique="0" required="0"> +<longdesc lang="en"> +Optional FQDN prefix for RabbitMQ nodes in cluster. +FQDN prefix can be specified to host multiple RabbitMQ instances on a node or +in case of RabbitMQ running in dedicated network/interface. +</longdesc> +<shortdesc lang="en">FQDN prefix</shortdesc> +<content type="string" default="${OCF_RESKEY_fqdn_prefix_default}" /> +</parameter> + +<parameter name="max_rabbitmqctl_timeouts" unique="0" required="0"> +<longdesc lang="en"> +If during monitor call rabbitmqctl times out, the timeout is ignored +unless it is Nth timeout in a row. Here N is the value of the current parameter. +If too many timeouts happen in a raw, the monitor call will return with error. +</longdesc> +<shortdesc lang="en">Fail only if that many rabbitmqctl timeouts in a row occurred</shortdesc> +<content type="string" default="${OCF_RESKEY_max_rabbitmqctl_timeouts_default}" /> +</parameter> + +<parameter name="policy_file" unique="0" required="0"> +<longdesc lang="en"> +A path to the shell script to setup RabbitMQ policies +</longdesc> +<shortdesc lang="en">A policy file path</shortdesc> +<content type="string" default="${OCF_RESKEY_policy_file_default}" /> +</parameter> + +<parameter name="rmq_feature_health_check" unique="0" required="0"> +<longdesc lang="en"> +Since rabbit 3.6.4 list_queues/list_channels-based monitoring should +be replaced with "node_health_check" command, as it creates no network +load at all. +</longdesc> +<shortdesc lang="en">Use node_health_check for monitoring</shortdesc> +<content type="boolean" default="${OCF_RESKEY_rmq_feature_health_check_default}" /> +</parameter> + +<parameter name="rmq_feature_local_list_queues" unique="0" required="0"> +<longdesc lang="en"> +For rabbit version that implements --local flag for list_queues, this +can greatly reduce network overhead in cases when node is +stopped/demoted. +</longdesc> +<shortdesc lang="en">Use --local option for list_queues</shortdesc> +<content type="boolean" default="${OCF_RESKEY_rmq_feature_local_list_queues_default}" /> +</parameter> + +<parameter name="limit_nofile" unique="0" required="0"> +<longdesc lang="en"> +Soft and hard limit for NOFILE +</longdesc> +<shortdesc lang="en">NOFILE limit</shortdesc> +<content type="string" default="${OCF_RESKEY_limit_nofile_default}" /> +</parameter> + +<parameter name="avoid_using_iptables" unique="0" required="0"> +<longdesc lang="en"> +When set to true the iptables calls to block client access become +noops. This is useful when we run inside containers. +</longdesc> +<shortdesc lang="en">Disable iptables use entirely</shortdesc> +<content type="boolean" default="${OCF_RESKEY_avoid_using_iptables_default}" /> +</parameter> + +$EXTENDED_OCF_PARAMS + +</parameters> + +<actions> +<action name="start" timeout="20" /> +<action name="stop" timeout="20" /> +<action name="status" timeout="20" /> +<action name="monitor" depth="0" timeout="30" interval="5" /> +<action name="monitor" depth="0" timeout="30" interval="3" role="Master"/> +<action name="promote" timeout="30" /> +<action name="demote" timeout="30" /> +<action name="notify" timeout="20" /> +<action name="validate-all" timeout="5" /> +<action name="meta-data" timeout="5" /> +</actions> +</resource-agent> +END +} + + +MIN_MASTER_SCORE=100 +BEST_MASTER_SCORE=1000 + + +####################################################################### +# Functions invoked by resource manager actions + +#TODO(bogdando) move proc_kill, proc_stop to shared OCF functions +# to be shipped with HA cluster packages +########################################################### +# Attempts to kill a process with retries and checks procfs +# to make sure the process is stopped. +# +# Globals: +# LL +# Arguments: +# $1 - pid of the process to try and kill +# $2 - service name used for logging and match-based kill, if the pid is "none" +# $3 - signal to use, defaults to SIGTERM +# $4 - number of retries, defaults to 5 +# $5 - time to sleep between retries, defaults to 2 +# Returns: +# 0 - if successful +# 1 - if process is still running according to procfs +# 2 - if invalid parameters passed in +########################################################### +proc_kill() +{ + local pid="${1}" + local service_name="${2}" + local signal="${3:-SIGTERM}" + local count="${4:-5}" + local process_sleep="${5:-2}" + local LH="${LL} proc_kill():" + local pgrp="$(ps -o pgid= ${pid} 2>/dev/null | tr -d '[[:space:]]')" + + if [ "${pid}" -a "${pgrp}" = "1" ] ; then + ocf_log err "${LH} shall not kill by the bad pid 1 (init)!" + return 2 + fi + + if [ "${pid}" = "none" ]; then + local matched + matched="$(pgrep -fla ${service_name})" + if [ -z "${matched}" ] ; then + ocf_log info "${LH} cannot find any processes matching the ${service_name}, considering target process to be already dead" + return 0 + fi + ocf_log debug "${LH} no pid provided, will try the ${service_name}, matched list: ${matched}" + while [ $count -gt 0 ]; do + if [ -z "${matched}" ]; then + break + else + matched="$(pgrep -fla ${service_name})" + ocf_log debug "${LH} Stopping ${service_name} with ${signal}..." + ocf_run pkill -f -"${signal}" "${service_name}" + fi + sleep $process_sleep + count=$(( count-1 )) + done + pgrep -f "${service_name}" > /dev/null + if [ $? -ne 0 ] ; then + ocf_log debug "${LH} Stopped ${service_name} with ${signal}" + return 0 + else + ocf_log warn "${LH} Failed to stop ${service_name} with ${signal}" + return 1 + fi + else + # pid is not none + while [ $count -gt 0 ]; do + if [ ! -d "/proc/${pid}" ]; then + break + else + ocf_log debug "${LH} Stopping ${service_name} with ${signal}..." + ocf_run pkill -"${signal}" -g "${pgrp}" + fi + sleep $process_sleep + count=$(( count-1 )) + done + + # Check if the process ended after the last sleep + if [ ! -d "/proc/${pid}" ] ; then + ocf_log debug "${LH} Stopped ${service_name} with ${signal}" + return 0 + fi + + ocf_log warn "${LH} Failed to stop ${service_name} with ${signal}" + return 1 + fi +} + +########################################################### +# Attempts to kill a process with the given pid or pid file +# using proc_kill and will retry with sigkill if sigterm is +# unsuccessful. +# +# Globals: +# OCF_ERR_GENERIC +# OCF_SUCCESS +# LL +# Arguments: +# $1 - pidfile or pid or 'none', if stopping by the name matching +# $2 - service name used for logging or for the failback stopping method +# $3 - stop process timeout (in sec), used to determine how many times we try +# SIGTERM and an upper limit on how long this function should try and +# stop the process. Defaults to 15. +# Returns: +# OCF_SUCCESS - if successful +# OCF_ERR_GENERIC - if process is still running according to procfs +########################################################### +proc_stop() +{ + local pid_param="${1}" + local service_name="${2}" + local timeout="${3:-15}" + local LH="${LL} proc_stop():" + local i + local pid + local pidfile + if [ "${pid_param}" = "none" ] ; then + pid="none" + else + # check if provide just a number + echo "${pid_param}" | egrep -q '^[0-9]+$' + if [ $? -eq 0 ]; then + pid="${pid_param}" + elif [ -e "${pid_param}" ]; then # check if passed in a pid file + pidfile="${pid_param}" + pid=$(cat "${pidfile}" 2>/dev/null | tr -s " " "\n" | sort -u) + else + ocf_log warn "${LH} pid param ${pid_param} is not a file or a number, try match by ${service_name}" + pid="none" + fi + fi + # number of times to try a SIGTEM is (timeout - 5 seconds) / 2 seconds + local stop_count=$(( ($timeout-5)/2 )) + + # make sure we stop at least once + if [ $stop_count -le 0 ]; then + stop_count=1 + fi + + if [ -z "${pid}" ] ; then + ocf_log warn "${LH} unable to get PID from ${pidfile}, try match by ${service_name}" + pid="none" + fi + + if [ -n "${pid}" ]; then + for i in ${pid} ; do + [ "${i}" ] || break + ocf_log info "${LH} Stopping ${service_name} by PID ${i}" + proc_kill "${i}" "${service_name}" SIGTERM $stop_count + if [ $? -ne 0 ]; then + # SIGTERM failed, send a single SIGKILL + proc_kill "${i}" "${service_name}" SIGKILL 1 2 + if [ $? -ne 0 ]; then + ocf_log err "${LH} ERROR: could not stop ${service_name}" + return "${OCF_ERR_GENERIC}" + fi + fi + done + fi + + # Remove the pid file here which will remove empty pid files as well + if [ -n "${pidfile}" ]; then + rm -f "${pidfile}" + fi + + ocf_log info "${LH} Stopped ${service_name}" + return "${OCF_SUCCESS}" +} + +# Invokes the given command as a rabbitmq user and wrapped in the +# timeout command. +su_rabbit_cmd() { + local timeout + if [ "$1" = "-t" ]; then + timeout="/usr/bin/timeout ${OCF_RESKEY_command_timeout} $2" + shift 2 + else + timeout=$COMMAND_TIMEOUT + fi + local cmd="${1:-status}" + local LH="${LL} su_rabbit_cmd():" + local rc=1 + local user=$OCF_RESKEY_username + local mail=/var/spool/mail/rabbitmq + local pwd=/var/lib/rabbitmq + local home=/var/lib/rabbitmq + + ocf_log debug "${LH} invoking a command: ${cmd}" + su $user -s /bin/sh -c "USER=${user} MAIL=${mail} PWD=${pwd} HOME=${home} LOGNAME=${user} \ + ${timeout} ${cmd}" + rc=$? + ocf_log info "${LH} the invoked command exited ${rc}: ${cmd}" + return $rc +} + +now() { + date -u +%s +} + +set_limits() { + local current_limit=$(su $OCF_RESKEY_username -s /bin/sh -c "ulimit -n") + if [ ! -z $OCF_RESKEY_limit_nofile -a $OCF_RESKEY_limit_nofile -gt $current_limit ] ; then + ulimit -n $OCF_RESKEY_limit_nofile + fi +} + +master_score() { + local LH="${LL} master_score():" + local score=$1 + if [ -z $score ] ; then + score=0 + fi + ocf_log info "${LH} Updating master score attribute with ${score}" + ocf_run crm_master -N $THIS_PCMK_NODE -l reboot -v $score || return $OCF_ERR_GENERIC + return $OCF_SUCCESS +} + +# Return either FQDN or shortname, depends on the OCF_RESKEY_use_fqdn. +get_hostname() { + if [ "${OCF_RESKEY_use_fqdn}" = 'false' ] ; then + echo "$(hostname -s)" + else + echo "$(hostname -f)" + fi +} + +# Strip the FQDN to the shortname, if OCF_RESKEY_use_fqdn was set; +# Prepend prefix to the hostname +process_fqdn() { + if [ "${OCF_RESKEY_use_fqdn}" = 'false' ] ; then + echo "${OCF_RESKEY_fqdn_prefix}$1" | awk -F. '{print $1}' + else + echo "${OCF_RESKEY_fqdn_prefix}$1" + fi +} + +# Return OCF_SUCCESS, if current host is in the list of given hosts. +# Otherwise, return 10 +my_host() { + local hostlist="$1" + local hostname + local hn + local rc=10 + local LH="${LL} my_host():" + + hostname=$(process_fqdn $(get_hostname)) + ocf_log info "${LH} hostlist is: $hostlist" + for host in $hostlist ; do + hn=$(process_fqdn "${host}") + ocf_log debug "${LH} comparing '$hostname' with '$hn'" + if [ "${hostname}" = "${hn}" ] ; then + rc=$OCF_SUCCESS + break + fi + done + + return $rc +} + +get_integer_node_attr() { + local value + value=$(crm_attribute -N $1 -l reboot --name "$2" --query 2>/dev/null | awk '{ split($3, vals, "="); if (vals[2] != "(null)") print vals[2] }') + if [ $? -ne 0 -o -z "$value" ] ; then + value=0 + fi + echo $value +} + +get_node_start_time() { + get_integer_node_attr $1 'rabbit-start-time' +} + +get_node_master_score() { + get_integer_node_attr $1 "master-${RESOURCE_NAME}" +} + +# Return either rabbit node name as FQDN or shortname, depends on the OCF_RESKEY_use_fqdn. +rabbit_node_name() { + echo "rabbit@$(process_fqdn $(ocf_attribute_target $1))" +} + +rmq_setup_env() { + local H + local dir + H="$(get_hostname)" + export RABBITMQ_NODENAME=$(rabbit_node_name $H) + export RABBITMQ_NODE_PORT=$OCF_RESKEY_node_port + export RABBITMQ_PID_FILE=$OCF_RESKEY_pid_file + MNESIA_FILES="${OCF_RESKEY_mnesia_base}/$(rabbit_node_name $H)" + RMQ_START_TIME="${MNESIA_FILES}/ocf_server_start_time.txt" + MASTER_FLAG_FILE="${MNESIA_FILES}/ocf_master_for_${OCF_RESOURCE_INSTANCE}" + THIS_PCMK_NODE=$(ocf_attribute_target) + TOTALVMEM=`free -mt | awk '/Total:/ {print $2}'` + # check and make PID file dir + local PID_DIR=$( dirname $OCF_RESKEY_pid_file ) + if [ ! -d ${PID_DIR} ] ; then + mkdir -p ${PID_DIR} + chown -R ${OCF_RESKEY_username}:${OCF_RESKEY_groupname} ${PID_DIR} + chmod 755 ${PID_DIR} + fi + + # Regardless of whether we just created the directory or it + # already existed, check whether it is writable by the configured + # user + for dir in ${PID_DIR} "${OCF_RESKEY_mnesia_base}" "${OCF_RESKEY_log_dir}"; do + if test -e ${dir}; then + local files + files=$(su -s /bin/sh - $OCF_RESKEY_username -c "find ${dir} ! -writable") + if [ "${files}" ]; then + ocf_log warn "Directory ${dir} is not writable by ${OCF_RESKEY_username}, chowning." + chown -R ${OCF_RESKEY_username}:${OCF_RESKEY_groupname} "${dir}" + fi + fi + done + + export LL="${OCF_RESOURCE_INSTANCE}[$$]:" + update_cookie +} + +# Return a RabbitMQ node to its virgin state. +# For reset and force_reset to succeed the RabbitMQ application must have been stopped. +# If the app cannot be stopped, beam will be killed and mnesia files will be removed. +reset_mnesia() { + local LH="${LL} reset_mnesia():" + local make_amnesia=false + local rc=$OCF_ERR_GENERIC + + # check status of a beam process + get_status + rc=$? + if [ $rc -eq 0 ] ; then + # beam is running + # check status of rabbit app and stop it, if it is running + get_status rabbit + rc=$? + if [ $rc -eq 0 ] ; then + # rabbit app is running, have to stop it + ocf_log info "${LH} Stopping RMQ-app prior to reset the mnesia." + stop_rmq_server_app + rc=$? + if [ $rc -ne 0 ] ; then + ocf_log warn "${LH} RMQ-app can't be stopped." + make_amnesia=true + fi + fi + + if ! $make_amnesia ; then + # rabbit app is not running, reset mnesia + ocf_log info "${LH} Execute reset with timeout: ${TIMEOUT_ARG}" + su_rabbit_cmd "${OCF_RESKEY_ctl} reset" + rc=$? + if [ $rc -ne 0 ] ; then + ocf_log info "${LH} Execute force_reset with timeout: ${TIMEOUT_ARG}" + su_rabbit_cmd "${OCF_RESKEY_ctl} force_reset" + rc=$? + if [ $rc -ne 0 ] ; then + ocf_log warn "${LH} Mnesia couldn't cleaned, even by force-reset command." + make_amnesia=true + fi + fi + fi + else + # there is no beam running + make_amnesia=true + ocf_log warn "${LH} There is no Beam process running." + fi + + # remove mnesia files, if required + if $make_amnesia ; then + kill_rmq_and_remove_pid + ocf_run rm -rf "${MNESIA_FILES}" + mnesia_schema_location="${OCF_RESKEY_mnesia_schema_base}/Mnesia.$(rabbit_node_name $(get_hostname))" + ocf_run rm -rf "$mnesia_schema_location" + ocf_log warn "${LH} Mnesia files appear corrupted and have been removed from ${MNESIA_FILES} and $mnesia_schema_location" + fi + # always return OCF SUCCESS + return $OCF_SUCCESS +} + + +block_client_access() +{ + # When OCF_RESKEY_avoid_using_iptables is true iptables calls are noops + if [ "${OCF_RESKEY_avoid_using_iptables}" == 'true' ] ; then + return $OCF_SUCCESS + fi + # do not add temporary RMQ blocking rule, if it is already exist + # otherwise, try to add a blocking rule with max of 5 retries + local tries=5 + until $(iptables -nvL --wait | grep -q 'temporary RMQ block') || [ $tries -eq 0 ]; do + tries=$((tries-1)) + iptables --wait -I INPUT -p tcp -m tcp --dport ${OCF_RESKEY_node_port} -m state --state NEW,RELATED,ESTABLISHED \ + -m comment --comment 'temporary RMQ block' -j REJECT --reject-with tcp-reset + sleep 1 + done + if [ $tries -eq 0 ]; then + return $OCF_ERR_GENERIC + else + return $OCF_SUCCESS + fi +} + +unblock_client_access() +{ + # When OCF_RESKEY_avoid_using_iptables is true iptables calls are noops + if [ "${OCF_RESKEY_avoid_using_iptables}" == 'true' ] ; then + return + fi + # remove all temporary RMQ blocking rules, if there are more than one exist + for i in $(iptables -nvL --wait --line-numbers | awk '/temporary RMQ block/ {print $1}'); do + iptables --wait -D INPUT -p tcp -m tcp --dport ${OCF_RESKEY_node_port} -m state --state NEW,RELATED,ESTABLISHED \ + -m comment --comment 'temporary RMQ block' -j REJECT --reject-with tcp-reset + done +} + +get_nodes__base(){ + local infotype='' + local rc=$OCF_ERR_GENERIC + local c_status + + if [ "$1" = 'nodes' ] + then + infotype='db_nodes' + elif [ "$1" = 'running' ] + then + infotype='running_db_nodes' + fi + c_status=`${OCF_RESKEY_ctl} eval "mnesia:system_info(${infotype})." 2>/dev/null` + rc=$? + if [ $rc -ne 0 ] ; then + echo '' + return $OCF_ERR_GENERIC + fi + # translate line like '{running_nodes,['rabbit@node-1','rabbit@node-2','rabbit@node-3']},' to node_list + echo $(echo "${c_status}" | awk -F, '{ for (i=1;i<=NF;i++) { if ($i ~ /@/) { gsub(/[\[\]}{]/,"",$i); print $i; } }}' | tr -d "\'") + return $OCF_SUCCESS +} + +get_nodes() { + echo $(get_nodes__base nodes) + return $? +} + +get_running_nodes() { + echo $(get_nodes__base running) + return $? +} + +# Get alive cluster nodes in visible partition, but the specified one +get_alive_pacemaker_nodes_but() +{ + if [ -z "$1" ]; then + echo `crm_node -l -p | sed -e '/(null)/d'` + else + echo `crm_node -l -p | sed -e "s/${1}//g" | sed -e '/(null)/d'` + fi +} + +# Get current master. If a parameter is provided, +# do not check node with that name +get_master_name_but() +{ + local node + for node in $(get_alive_pacemaker_nodes_but "$@") + do + ocf_log info "${LH} looking if $node is master" + + if is_master $node; then + ocf_log info "${LH} master is $node" + echo $node + break + fi + done +} + +# Evals some erlang code on current node +erl_eval() { + local fmt="${1:?}" + shift + + $COMMAND_TIMEOUT ${OCF_RESKEY_ctl} eval "$(printf "$fmt" "$@")" +} + +# Returns 0 if we are clustered with provideded node +is_clustered_with() +{ + local LH="${LH}: is_clustered_with: " + local node_name + local rc + node_name=$(rabbit_node_name $1) + + local seen_as_running + seen_as_running=$(erl_eval "lists:member('%s', rabbit_mnesia:cluster_nodes(running))." "$node_name") + rc=$? + if [ "$rc" -ne 0 ]; then + ocf_log err "${LH} Failed to check whether '$node_name' is considered running by us" + # We had a transient local error; that doesn't mean the remote node is + # not part of the cluster, so ignore this + elif [ "$seen_as_running" != true ]; then + ocf_log info "${LH} Node $node_name is not running, considering it not clustered with us" + return 1 + fi + + local seen_as_partitioned + seen_as_partitioned=$(erl_eval "lists:member('%s', rabbit_node_monitor:partitions())." "$node_name") + rc=$? + if [ "$rc" -ne 0 ]; then + ocf_log err "${LH} Failed to check whether '$node_name' is partitioned with us" + # We had a transient local error; that doesn't mean the remote node is + # partitioned with us, so ignore this + elif [ "$seen_as_partitioned" != false ]; then + ocf_log info "${LH} Node $node_name is partitioned from us" + return 1 + fi + + return $? +} + + +check_need_join_to() { + local join_to + local node + local running_nodes + local rc=$OCF_ERR_GENERIC + + rc=0 + join_to=$(rabbit_node_name $1) + running_nodes=$(get_running_nodes) + for node in $running_nodes ; do + if [ "${join_to}" = "${node}" ] ; then + rc=1 + break + fi + done + + return $rc +} + +# Update erlang cookie, if it has been specified +update_cookie() { + local cookie_file_content + if [ "${OCF_RESKEY_erlang_cookie}" != 'false' ] ; then + if [ -f "${OCF_RESKEY_erlang_cookie_file}" ]; then + # First line of cookie file without newline + cookie_file_content=$(head -n1 "${OCF_RESKEY_erlang_cookie_file}" | perl -pe chomp) + fi + # As there is a brief period of time when the file is empty + # (shell redirection has already opened and truncated file, + # and echo hasn't finished its job), we are doing this write + # only when cookie has changed. + if [ "${OCF_RESKEY_erlang_cookie}" != "${cookie_file_content}" ]; then + echo "${OCF_RESKEY_erlang_cookie}" > "${OCF_RESKEY_erlang_cookie_file}" + fi + # And this are idempotent operations, so we don't have to + # check any preconditions for running them. + chown ${OCF_RESKEY_username}:${OCF_RESKEY_groupname} "${OCF_RESKEY_erlang_cookie_file}" + chmod 600 "${OCF_RESKEY_erlang_cookie_file}" + fi + return $OCF_SUCCESS +} + +# Stop rmq beam process by pid and by rabbit node name match. Returns SUCCESS/ERROR +kill_rmq_and_remove_pid() { + local LH="${LL} kill_rmq_and_remove_pid():" + # Stop the rabbitmq-server by its pidfile, use the name matching as a fallback, + # and ignore the exit code + proc_stop "${OCF_RESKEY_pid_file}" "beam.*${RABBITMQ_NODENAME}" "${OCF_RESKEY_stop_time}" + # Ensure the beam.smp stopped by the rabbit node name matching as well + proc_stop none "beam.*${RABBITMQ_NODENAME}" "${OCF_RESKEY_stop_time}" + if [ $? -eq 0 ] ; then + return $OCF_SUCCESS + else + return $OCF_ERR_GENERIC + fi +} + +trim_var(){ + local string="$*" + echo ${string%% } +} + +action_validate() { + # todo(sv): validate some incoming parameters + OCF_RESKEY_CRM_meta_notify_post=$(trim_var $OCF_RESKEY_CRM_meta_notify_post) + OCF_RESKEY_CRM_meta_notify_pre=$(trim_var $OCF_RESKEY_CRM_meta_notify_pre) + OCF_RESKEY_CRM_meta_notify_start=$(trim_var $OCF_RESKEY_CRM_meta_notify_start) + OCF_RESKEY_CRM_meta_notify_stop=$(trim_var $OCF_RESKEY_CRM_meta_notify_stop) + OCF_RESKEY_CRM_meta_notify_start_resource=$(trim_var $OCF_RESKEY_CRM_meta_notify_start_resource) + OCF_RESKEY_CRM_meta_notify_stop_resource=$(trim_var $OCF_RESKEY_CRM_meta_notify_stop_resource) + OCF_RESKEY_CRM_meta_notify_active_resource=$(trim_var $OCF_RESKEY_CRM_meta_notify_active_resource) + OCF_RESKEY_CRM_meta_notify_inactive_resource=$(trim_var $OCF_RESKEY_CRM_meta_notify_inactive_resource) + OCF_RESKEY_CRM_meta_notify_start_uname=$(trim_var $OCF_RESKEY_CRM_meta_notify_start_uname) + OCF_RESKEY_CRM_meta_notify_stop_uname=$(trim_var $OCF_RESKEY_CRM_meta_notify_stop_uname) + OCF_RESKEY_CRM_meta_notify_active_uname=$(trim_var $OCF_RESKEY_CRM_meta_notify_active_uname) + OCF_RESKEY_CRM_meta_notify_master_resource=$(trim_var $OCF_RESKEY_CRM_meta_notify_master_resource) + OCF_RESKEY_CRM_meta_notify_master_uname=$(trim_var $OCF_RESKEY_CRM_meta_notify_master_uname) + OCF_RESKEY_CRM_meta_notify_demote_resource=$(trim_var $OCF_RESKEY_CRM_meta_notify_demote_resource) + OCF_RESKEY_CRM_meta_notify_demote_uname=$(trim_var $OCF_RESKEY_CRM_meta_notify_demote_uname) + OCF_RESKEY_CRM_meta_notify_slave_resource=$(trim_var $OCF_RESKEY_CRM_meta_notify_slave_resource) + OCF_RESKEY_CRM_meta_notify_slave_uname=$(trim_var $OCF_RESKEY_CRM_meta_notify_slave_uname) + OCF_RESKEY_CRM_meta_notify_promote_resource=$(trim_var $OCF_RESKEY_CRM_meta_notify_promote_resource) + OCF_RESKEY_CRM_meta_notify_promote_uname=$(trim_var $OCF_RESKEY_CRM_meta_notify_promote_uname) + return $OCF_SUCCESS +} + +update_rabbit_start_time_if_rc() { + local nowtime + local rc=$1 + if [ $rc -eq 0 ]; then + nowtime="$(now)" + ocf_log info "${LH} Rabbit app started successfully. Updating start time attribute with ${nowtime}" + ocf_run crm_attribute -N $THIS_PCMK_NODE -l reboot --name 'rabbit-start-time' --update "${nowtime}" + fi +} + +join_to_cluster() { + local node="$1" + local rmq_node + local rc=$OCF_ERR_GENERIC + local LH="${LL} join_to_cluster():" + + ocf_log info "${LH} start." + + rmq_node=$(rabbit_node_name $node) + ocf_log info "${LH} Joining to cluster by node '${rmq_node}'." + get_status rabbit + rc=$? + if [ $rc -eq $OCF_SUCCESS ] ; then + ocf_log info "${LH} rabbitmq app will be stopped." + stop_rmq_server_app + rc=$? + if [ $rc -ne 0 ] ; then + ocf_log err "${LH} Can't stop rabbitmq app by stop_app command. Stopping." + action_stop + return $OCF_ERR_GENERIC + fi + fi + ocf_log info "${LH} Execute join_cluster with timeout: ${TIMEOUT_ARG}" + su_rabbit_cmd "${OCF_RESKEY_ctl} join_cluster $rmq_node" + rc=$? + if [ $rc -ne 0 ] ; then + ocf_log err "${LH} Can't join to cluster by node '${rmq_node}'. Stopping." + action_stop + return $OCF_ERR_GENERIC + fi + sleep 2 + try_to_start_rmq_app + rc=$? + if [ $rc -ne 0 ] ; then + ocf_log err "${LH} Can't start RMQ app after join to cluster. Stopping." + action_stop + return $OCF_ERR_GENERIC + else + update_rabbit_start_time_if_rc 0 + ocf_log info "${LH} Joined to cluster succesfully." + fi + + ocf_log info "${LH} end." + return $rc +} + +unjoin_nodes_from_cluster() { + # node names of the nodes where the pcs resource is being stopped + local nodelist="$1" + local hostname + local nodename + local rc=$OCF_ERR_GENERIC + local rnode + # nodes in rabbit cluster db + local nodes_in_cluster + local LH="${LL} unjoin_nodes_from_cluster():" + + nodes_in_cluster=$(get_nodes) + rc=$? + if [ $rc -ne 0 ] ; then + # no nodes in node list, nothing to do + return $OCF_SUCCESS + fi + + # unjoin all cluster nodes which are being stopped (i.e. recieved post-stop notify), except *this* node + # before to unjoin the nodes, make sure they were disconnected from *this* node + for hostname in $nodelist ; do + nodename=$(rabbit_node_name $hostname) + if [ "${nodename}" = "${RABBITMQ_NODENAME}" ] ; then + continue + fi + for rnode in $nodes_in_cluster ; do + if [ "${nodename}" = "${rnode}" ] ; then + # disconnect node being unjoined from this node + ocf_run ${OCF_RESKEY_ctl} eval "disconnect_node(list_to_atom(\"${nodename}\"))." 2>&1 + rc=$? + if [ $rc -eq $OCF_SUCCESS ] ; then + ocf_log info "${LH} node '${nodename}' disconnected succesfully." + else + ocf_log info "${LH} disconnecting node '${nodename}' failed." + fi + + # unjoin node + # when the rabbit node went down, its status + # remains 'running' for a while, so few retries are required + local tries=0 + until [ $tries -eq 5 ]; do + tries=$((tries+1)) + if is_clustered_with $nodename; then + ocf_log info "${LH} the ${nodename} is alive and cannot be kicked from the cluster yet" + else + break + fi + sleep 10 + done + ocf_log info "${LH} Execute forget_cluster_node with timeout: ${TIMEOUT_ARG}" + su_rabbit_cmd "${OCF_RESKEY_ctl} forget_cluster_node ${nodename}" + rc=$? + if [ $rc -eq 0 ] ; then + ocf_log info "${LH} node '${nodename}' unjoined succesfully." + else + ocf_log warn "${LH} unjoining node '${nodename}' failed." + fi + fi + done + done + return $OCF_SUCCESS +} + +# Stop RMQ beam server process. Returns SUCCESS/ERROR +stop_server_process() { + local pid + local rc=$OCF_ERR_GENERIC + local LH="${LL} stop_server_process():" + + pid=$(cat ${OCF_RESKEY_pid_file}) + rc=$? + if [ $rc -ne 0 ] ; then + # Try to stop without known PID + ocf_log err "${LH} RMQ-server process PIDFILE was not found!" + su_rabbit_cmd "${OCF_RESKEY_ctl} stop >> \"${OCF_RESKEY_log_dir}/shutdown_log\" 2>&1" + if [ $? -eq 0 ] ; then + ocf_log info "${LH} RMQ-server process stopped succesfully, although there was no PIDFILE found." + ocf_log info "${LH} grant a graceful termintation window ${OCF_RESKEY_stop_time} to end its beam" + sleep "${OCF_RESKEY_stop_time}" + else + kill_rmq_and_remove_pid + fi + elif [ "${pid}" ] ; then + # Try to stop gracefully by known PID + ocf_log info "${LH} Execute stop with timeout: ${TIMEOUT_ARG}" + su_rabbit_cmd "${OCF_RESKEY_ctl} stop ${OCF_RESKEY_pid_file} >> \"${OCF_RESKEY_log_dir}/shutdown_log\" 2>&1" + [ $? -eq 0 ] && ocf_log info "${LH} RMQ-server process (PID=${pid}) stopped succesfully." + fi + + # Ensure there is no beam process and pidfile left + pgrep -f "beam.*${RABBITMQ_NODENAME}" > /dev/null + rc=$? + if [ -f ${OCF_RESKEY_pid_file} -o $rc -eq 0 ] ; then + ocf_log warn "${LH} The pidfile or beam's still exist, forcing the RMQ-server cleanup" + kill_rmq_and_remove_pid + return $? + else + return $OCF_SUCCESS + fi +} + +# Stop RMQ-app. Return OCF_SUCCESS, if the app was stopped, +# otherwise return OCF_ERR_GENERIC +stop_rmq_server_app() { + local rc=$OCF_ERR_GENERIC + + # if the beam process isn't running, then rabbit app is stopped as well + get_status + rc=$? + if [ $rc -ne 0 ] ; then + return $OCF_SUCCESS + fi + + # stop the app + ocf_log info "${LH} Execute stop_app with timeout: ${TIMEOUT_ARG}" + su_rabbit_cmd "${OCF_RESKEY_ctl} stop_app >> \"${OCF_RESKEY_log_dir}/shutdown_log\" 2>&1" + rc=$? + if [ $rc -ne 0 ] ; then + ocf_log err "${LH} RMQ-server app cannot be stopped." + return $OCF_ERR_GENERIC + fi + + get_status rabbit + rc=$? + if [ $rc -ne $OCF_SUCCESS ] ; then + ocf_log info "${LH} RMQ-server app stopped succesfully." + rc=$OCF_SUCCESS + else + ocf_log err "${LH} RMQ-server app cannot be stopped." + rc=$OCF_ERR_GENERIC + fi + + return $rc +} + +start_beam_process() { + local command + local rc=$OCF_ERR_GENERIC + local ts_end + local pf_end + local pid + local LH="${LL} start_beam_process():" + + # remove old PID-file if it exists + if [ -f "${OCF_RESKEY_pid_file}" ] ; then + ocf_log warn "${LH} found old PID-file '${OCF_RESKEY_pid_file}'." + pid=$(cat ${OCF_RESKEY_pid_file}) + if [ "${pid}" -a -d "/proc/${pid}" ] ; then + ocf_run cat /proc/${pid}/cmdline | grep -c 'bin/beam' > /dev/null 2>&1 + rc=$? + if [ $rc -eq $OCF_SUCCESS ] ; then + ocf_log warn "${LH} found beam process with PID=${pid}, killing...'." + ocf_run kill -TERM $pid + else + ocf_log err "${LH} found unknown process with PID=${pid} from '${OCF_RESKEY_pid_file}'." + return $OCF_ERR_GENERIC + fi + fi + ocf_run rm -f $OCF_RESKEY_pid_file + fi + + [ -f /etc/default/rabbitmq-server ] && . /etc/default/rabbitmq-server + + # RabbitMQ requires high soft and hard limits for NOFILE + set_limits + + # run beam process + command="${OCF_RESKEY_binary} >> \"${OCF_RESKEY_log_dir}/startup_log\" 2>/dev/null" + RABBITMQ_NODE_ONLY=1 su rabbitmq -s /bin/sh -c "${command}"& + ts_end=$(( $(now) + ${OCF_RESKEY_start_time} )) + rc=$OCF_ERR_GENERIC + while [ $(now) -lt ${ts_end} ]; do + # waiting for normal start of beam + pid=0 + pf_end=$(( $(now) + 3 )) + while [ $(now) -lt ${pf_end} ]; do + # waiting for OCF_RESKEY_pid_file of beam process + if [ -f "${OCF_RESKEY_pid_file}" ] ; then + pid=$(cat ${OCF_RESKEY_pid_file}) + break + fi + sleep 1 + done + if [ "${pid}" != "0" -a -d "/proc/${pid}" ] ; then + rc=$OCF_SUCCESS + break + fi + sleep 2 + done + if [ $rc -ne $OCF_SUCCESS ]; then + if [ "${pid}" = "0" ] ; then + ocf_log warn "${LH} PID-file '${OCF_RESKEY_pid_file}' not found" + fi + ocf_log err "${LH} RMQ-runtime (beam) didn't start succesfully (rc=${rc})." + fi + + return $rc +} + +check_plugins() { + # Check if it's safe to load plugins and if we need to do so. Logic is: + # if (EnabledPlugins > 0) and (ActivePlugins == 0) ; then it's safe to load + # If we have at least one active plugin, then it's not safe to re-load them + # because plugins:setup() would remove existing dependency plugins in plugins_expand_dir. + ${OCF_RESKEY_ctl} eval '{ok, EnabledFile} = application:get_env(rabbit, enabled_plugins_file), EnabledPlugins = rabbit_plugins:read_enabled(EnabledFile), ActivePlugins = rabbit_plugins:active(), if length(EnabledPlugins)>0 -> if length(ActivePlugins)==0 -> erlang:error("need_to_load_plugins"); true -> false end; true -> false end.' + return $? +} + +load_plugins() { + check_plugins + local rc=$? + if [ $rc -eq 0 ] ; then + return 0 + else + ${OCF_RESKEY_ctl} eval 'ToBeLoaded = rabbit_plugins:setup(), ok = app_utils:load_applications(ToBeLoaded), StartupApps = app_utils:app_dependency_order(ToBeLoaded,false), app_utils:start_applications(StartupApps).' + return $? + fi +} + +list_active_plugins() { + local list + list=`${OCF_RESKEY_ctl} eval 'rabbit_plugins:active().'` + echo "${list}" +} + +try_to_start_rmq_app() { + local startup_log="${1:-${OCF_RESKEY_log_dir}/startup_log}" + local rc=$OCF_ERR_GENERIC + local LH="${LL} try_to_start_rmq_app():" + + get_status + rc=$? + if [ $rc -ne $OCF_SUCCESS ] ; then + ocf_log info "${LH} RMQ-runtime (beam) not started, starting..." + start_beam_process + rc=$? + if [ $rc -ne $OCF_SUCCESS ]; then + ocf_log err "${LH} Failed to start beam - returning from the function" + return $OCF_ERR_GENERIC + fi + fi + + + if [ -z "${startup_log}" ] ; then + startup_log="${OCF_RESKEY_log_dir}/startup_log" + fi + + ocf_log info "${LH} begin." + ocf_log info "${LH} Execute start_app with timeout: ${TIMEOUT_ARG}" + su_rabbit_cmd "${OCF_RESKEY_ctl} start_app >>${startup_log} 2>&1" + rc=$? + if [ $rc -eq 0 ] ; then + ocf_log info "${LH} start_app was successful." + ocf_log info "${LH} waiting for start to finish with timeout: ${TIMEOUT_ARG}" + su_rabbit_cmd "${OCF_RESKEY_ctl} wait ${OCF_RESKEY_pid_file}" + rc=$? + if [ $rc -ne 0 ] ; then + ocf_log err "${LH} RMQ-server app failed to wait for start." + return $OCF_ERR_GENERIC + fi + rc=$OCF_SUCCESS + # Loading enabled modules + ocf_log info "${LH} start plugins." + load_plugins + local mrc=$? + if [ $mrc -eq 0 ] ; then + local mlist + mlist=`list_active_plugins` + ocf_log info "${LH} Starting plugins: ${mlist}" + else + ocf_log info "${LH} Starting plugins: failed." + fi + else + ocf_log info "${LH} start_app failed." + rc=$OCF_ERR_GENERIC + fi + return $rc +} + +start_rmq_server_app() { + local rc=$OCF_ERR_GENERIC + local startup_log="${OCF_RESKEY_log_dir}/startup_log" + local startup_output + local LH="${LL} start_rmq_server_app():" + local a + + #We are performing initial start check. + #We are not ready to provide service. + #Clients should not have access. + + + ocf_log info "${LH} begin." + # Safe-unblock the rules, if there are any + unblock_client_access + # Apply the blocking rule + block_client_access + rc=$? + if [ $rc -eq $OCF_SUCCESS ]; then + ocf_log info "${LH} blocked access to RMQ port" + else + ocf_log err "${LH} cannot block access to RMQ port!" + return $OCF_ERR_GENERIC + fi + get_status + rc=$? + if [ $rc -ne $OCF_SUCCESS ] ; then + ocf_log info "${LH} RMQ-runtime (beam) not started, starting..." + start_beam_process + rc=$? + if [ $rc -ne $OCF_SUCCESS ]; then + unblock_client_access + ocf_log info "${LH} unblocked access to RMQ port" + return $OCF_ERR_GENERIC + fi + fi + + ocf_log info "${LH} RMQ-server app not started, starting..." + try_to_start_rmq_app "$startup_log" + rc=$? + if [ $rc -eq $OCF_SUCCESS ] ; then + # rabbitmq-server started successfuly as master of cluster + master_score $MIN_MASTER_SCORE + stop_rmq_server_app + rc=$? + if [ $rc -ne 0 ] ; then + ocf_log err "${LH} RMQ-server app can't be stopped. Beam will be killed." + kill_rmq_and_remove_pid + unblock_client_access + ocf_log info "${LH} unblocked access to RMQ port" + return $OCF_ERR_GENERIC + fi + else + # error at start RMQ-server + ocf_log warn "${LH} RMQ-server app can't start without Mnesia cleaning." + for a in $(seq 1 10) ; do + rc=$OCF_ERR_GENERIC + reset_mnesia || break + try_to_start_rmq_app "$startup_log" + rc=$? + if [ $rc -eq $OCF_SUCCESS ]; then + stop_rmq_server_app + rc=$? + if [ $rc -eq $OCF_SUCCESS ]; then + ocf_log info "${LH} RMQ-server app Mnesia cleaned successfully." + rc=$OCF_SUCCESS + master_score $MIN_MASTER_SCORE + break + else + ocf_log err "${LH} RMQ-server app can't be stopped during Mnesia cleaning. Beam will be killed." + kill_rmq_and_remove_pid + unblock_client_access + ocf_log info "${LH} unblocked access to RMQ port" + return $OCF_ERR_GENERIC + fi + fi + done + fi + if [ $rc -eq $OCF_ERR_GENERIC ] ; then + ocf_log err "${LH} RMQ-server can't be started while many tries. Beam will be killed." + kill_rmq_and_remove_pid + fi + ocf_log info "${LH} end." + unblock_client_access + ocf_log info "${LH} unblocked access to RMQ port" + return $rc +} + +# check status of rabbit beam process or a rabbit app, if rabbit arg specified +# by default, test if the kernel app is running, otherwise consider it is "not running" +get_status() { + local what="${1:-kernel}" + local rc=$OCF_NOT_RUNNING + local LH="${LL} get_status():" + local body + local beam_running + + body=$( ${COMMAND_TIMEOUT} ${OCF_RESKEY_ctl} eval 'rabbit_misc:which_applications().' 2>&1 ) + rc=$? + + pgrep -f "beam.*${RABBITMQ_NODENAME}" > /dev/null + beam_running=$? + # report not running only if the which_applications() reported an error AND the beam is not running + if [ $rc -ne 0 -a $beam_running -ne 0 ] ; then + ocf_log info "${LH} failed with code ${rc}. Command output: ${body}" + return $OCF_NOT_RUNNING + # return a generic error, if there were errors and beam is found running + elif [ $rc -ne 0 ] ; then + ocf_log info "${LH} found the beam process running but failed with code ${rc}. Command output: ${body}" + return $OCF_ERR_GENERIC + fi + + # try to parse the which_applications() output only if it exited w/o errors + if [ "${what}" -a $rc -eq 0 ] ; then + rc=$OCF_NOT_RUNNING + echo "$body" | grep "\{${what}," > /dev/null 2>&1 && rc=$OCF_SUCCESS + + if [ $rc -ne $OCF_SUCCESS ] ; then + ocf_log info "${LH} app ${what} was not found in command output: ${body}" + fi + fi + + [ $rc -ne $OCF_SUCCESS ] && rc=$OCF_NOT_RUNNING + return $rc +} + +action_status() { + local rc=$OCF_ERR_GENERIC + + get_status + rc=$? + return $rc +} + +# return 0, if given node has a master attribute in CIB, +# otherwise, return 1 +is_master() { + local result + result=`crm_attribute -N "${1}" -l reboot --name 'rabbit-master' --query 2>/dev/null |\ + awk '{print $3}' | awk -F "=" '{print $2}' | sed -e '/(null)/d'` + if [ "${result}" != 'true' ] ; then + return 1 + fi + return 0 +} + +# Verify if su_rabbit_cmd exited by timeout by checking its return code. +# If it did not, return 0. If it did AND it is +# $OCF_RESKEY_max_rabbitmqctl_timeouts'th timeout in a row, +# return 2 to signal get_monitor that it should +# exit with error. Otherwise return 1 to signal that there was a timeout, +# but it should be ignored. Timeouts for different operations are tracked +# separately. The second argument is used to distingush them. +check_timeouts() { + local op_rc=$1 + local timeouts_attr_name=$2 + local op_name=$3 + + # 75 is EX_TEMPFAIL from sysexits, and is used by rabbitmqctl to signal about + # timeout. + if [ $op_rc -ne 124 -a $op_rc -ne 137 -a $op_rc -ne 75 ]; then + ocf_update_private_attr $timeouts_attr_name 0 + return 0 + fi + + local count + count=$(ocf_get_private_attr $timeouts_attr_name 0) + + count=$((count+1)) + # There is a slight chance that this piece of code will be executed twice simultaneously. + # As a result, $timeouts_attr_name's value will be one less than it should be. But we don't need + # precise calculation here. + ocf_update_private_attr $timeouts_attr_name $count + + if [ $count -lt $OCF_RESKEY_max_rabbitmqctl_timeouts ]; then + ocf_log warn "${LH} 'rabbitmqctl $op_name' timed out $count of max. $OCF_RESKEY_max_rabbitmqctl_timeouts time(s) in a row. Doing nothing for now." + return 1 + else + ocf_log err "${LH} 'rabbitmqctl $op_name' timed out $count of max. $OCF_RESKEY_max_rabbitmqctl_timeouts time(s) in a row and is not responding. The resource is failed." + return 2 + fi +} + +wait_sync() { + local wait_time=$1 + local queues + local opt_arg="" + + if [ "$OCF_RESKEY_rmq_feature_local_list_queues" = "true" ]; then + opt_arg="--local" + fi + + queues="${COMMAND_TIMEOUT} ${OCF_RESKEY_ctl} -p ${OCF_RESKEY_default_vhost} list_queues $opt_arg name state" + + su_rabbit_cmd -t "${wait_time}" "sh -c \"while ${queues} | grep -q 'syncing,'; \ + do sleep 2; done\"" + + return $? +} + +get_monitor() { + local rc=$OCF_ERR_GENERIC + local LH="${LL} get_monitor():" + local status_master=1 + local rabbit_running + local name + local node + local node_start_time + local nowtime + local partitions_report + local node_partitions + + ocf_log info "${LH} CHECK LEVEL IS: ${OCF_CHECK_LEVEL}" + get_status + rc=$? + if [ $rc -eq $OCF_NOT_RUNNING ] ; then + ocf_log info "${LH} get_status() returns ${rc}." + ocf_log info "${LH} ensuring this slave does not get promoted." + master_score 0 + return $OCF_NOT_RUNNING + elif [ $rc -eq $OCF_SUCCESS ] ; then + ocf_log info "${LH} get_status() returns ${rc}." + ocf_log info "${LH} also checking if we are master." + get_status rabbit + rabbit_running=$? + is_master $THIS_PCMK_NODE + status_master=$? + ocf_log info "${LH} master attribute is ${status_master}" + if [ $status_master -eq 0 -a $rabbit_running -eq $OCF_SUCCESS ] + then + ocf_log info "${LH} We are the running master" + rc=$OCF_RUNNING_MASTER + elif [ $status_master -eq 0 -a $rabbit_running -ne $OCF_SUCCESS ] ; then + ocf_log err "${LH} We are the master and RMQ-runtime (beam) is not running. this is a failure" + exit $OCF_FAILED_MASTER + fi + fi + get_status rabbit + rabbit_running=$? + ocf_log info "${LH} checking if rabbit app is running" + + if [ $rc -eq $OCF_RUNNING_MASTER ]; then + if [ $rabbit_running -eq $OCF_SUCCESS ]; then + ocf_log info "${LH} rabbit app is running and is master of cluster" + else + ocf_log err "${LH} we are the master and rabbit app is not running. This is a failure" + exit $OCF_FAILED_MASTER + fi + else + start_time=$((180 + $(ocf_get_private_attr 'rabbit-start-phase-1-time' 0))) + restart_order_time=$((60 + $(ocf_get_private_attr 'rabbit-ordered-to-restart' 0))) + nowtime=$(now) + + # If we started more than 3 minutes ago, and + # we got order to restart less than 1 minute ago + if [ $nowtime -lt $restart_order_time ]; then + if [ $nowtime -gt $start_time ]; then + ocf_log err "${LH} failing because we have received an order to restart from the master" + stop_server_process + rc=$OCF_ERR_GENERIC + else + ocf_log warn "${LH} received an order to restart from the master, ignoring it because we have just started" + fi + fi + fi + + if [ $rc -eq $OCF_ERR_GENERIC ]; then + ocf_log err "${LH} get_status() returns generic error ${rc}" + ocf_log info "${LH} ensuring this slave does not get promoted." + master_score 0 + return $OCF_ERR_GENERIC + fi + + # Recounting our master score + ocf_log info "${LH} preparing to update master score for node" + local our_start_time + local new_score + local node_start_time + local node_score + + our_start_time=$(get_node_start_time $THIS_PCMK_NODE) + + if [ $our_start_time -eq 0 ]; then + new_score=$MIN_MASTER_SCORE + else + new_score=$BEST_MASTER_SCORE + for node in $(get_alive_pacemaker_nodes_but $THIS_PCMK_NODE) + do + node_start_time=$(get_node_start_time $node) + node_score=$(get_node_master_score $node) + + ocf_log info "${LH} comparing us (start time: $our_start_time, score: $new_score) with $node (start time: $node_start_time, score: $node_score)" + if [ $node_start_time -ne 0 -a $node_score -ne 0 -a $node_start_time -lt $our_start_time ]; then + new_score=$((node_score - 10 < new_score ? node_score - 10 : new_score )) + elif [ $node_start_time -ne 0 -a $node_score -ne 0 -a $node_start_time -eq $our_start_time ]; then + # Do not get promoted if the other node is already master and we have the same start time + if is_master $node; then + new_score=$((node_score - 10 < new_score ? node_score - 10 : new_score )) + fi + fi + done + fi + + if [ "$new_score" -ne "$(get_node_master_score $THIS_PCMK_NODE)" ]; then + master_score $new_score + fi + ocf_log info "${LH} our start time is $our_start_time and score is $new_score" + + # Skip all other checks if rabbit app is not running + if [ $rabbit_running -ne $OCF_SUCCESS ]; then + ocf_log info "${LH} RabbitMQ is not running, get_monitor function ready to return ${rc}" + return $rc + fi + + # rc can be SUCCESS or RUNNING_MASTER, don't touch it unless there + # is some error uncovered by node_health_check + if ! node_health_check; then + rc=$OCF_ERR_GENERIC + fi + + if [ $rc -eq $OCF_RUNNING_MASTER ] ; then + # If we are the master and healthy, perform various + # connectivity checks for other nodes in the cluster. + # Order a member to restart if something fishy happens with it. + # All cross-node checks MUST happen only here. + + partitions_report="$(partitions_report)" + + for node in $(get_alive_pacemaker_nodes_but $THIS_PCMK_NODE); do + # Restart node if we don't consider ourselves clustered with it + if ! is_clustered_with $node; then + ocf_log warn "${LH} node $node is not connected with us" + order_node_restart "$node" + continue + fi + + # Restart node if it has any unresolved partitions + node_partitions=$(grep_partitions_report $node "$partitions_report") + if [ ! -z "$node_partitions" ]; then + ocf_log warn "${LH} Node $node thinks that it is partitoned with $node_partitions" + order_node_restart "$node" + continue + fi + done + fi + + ocf_log info "${LH} get_monitor function ready to return ${rc}" + return $rc +} + +order_node_restart() { + local node=${1:?} + ocf_log warn "${LH} Ordering node '$node' to restart" + ocf_update_private_attr 'rabbit-ordered-to-restart' "$(now)" "$node" +} + +# Checks whether node is mentioned somewhere in report returned by +# partitions_report() +grep_partitions_report() { + local node="${1:?}" + local report="${2:?}" + local rabbit_node + rabbit_node=$(rabbit_node_name "$node") + echo "$report" | grep "PARTITIONED $rabbit_node:" | sed -e 's/^[^:]\+: //' +} + +# Report partitions (if any) from viewpoint of every running node in cluster. +# It is parseable/grepable version of `rabbitmqctl cluster_status`. +# +# If node sees partition, report will contain the line like: +# PARTITIONED node-name: list-of-nodes, which-node-name-considers, itself-partitioned-with +partitions_report() { + $COMMAND_TIMEOUT xargs -0 ${OCF_RESKEY_ctl} eval <<EOF +RpcTimeout = 10, + +Nodes = rabbit_mnesia:cluster_nodes(running), + +{Replies, _BadNodes} = gen_server:multi_call(Nodes, rabbit_node_monitor, partitions, RpcTimeout * 1000), + +lists:foreach(fun ({_, []}) -> ok; + ({Node, Partitions}) -> + PartitionsStr = string:join([atom_to_list(Part) || Part <- Partitions], + ", "), + io:format("PARTITIONED ~s: ~s~n", + [Node, PartitionsStr]) + end, Replies), + +ok. +EOF +} + +# Check if the rabbitmqctl control plane is alive. +node_health_check() { + local rc + if [ "$OCF_RESKEY_rmq_feature_health_check" = true ]; then + node_health_check_local + rc=$? + else + node_health_check_legacy + rc=$? + fi + return $rc +} + +node_health_check_local() { + local LH="${LH} node_health_check_local():" + local rc + local rc_timeouts + + # Give node_health_check some time to handle timeout by itself. + # By using internal rabbitmqctl timeouts, we allow it to print + # more useful diagnostics + local timeout=$((TIMEOUT_ARG - 2)) + su_rabbit_cmd "${OCF_RESKEY_ctl} node_health_check -t $timeout" + rc=$? + + check_timeouts $rc "rabbit_node_health_check_timeouts" "node_health_check" + rc_timeouts=$? + + if [ "$rc_timeouts" -eq 2 ]; then + master_score 0 + ocf_log info "${LH} node_health_check timed out, retry limit reached" + return $OCF_ERR_GENERIC + elif [ "$rc_timeouts" -eq 1 ]; then + ocf_log info "${LH} node_health_check timed out, going to retry" + return $OCF_SUCCESS + fi + + if [ "$rc" -ne 0 ]; then + ocf_log err "${LH} rabbitmqctl node_health_check exited with errors." + return $OCF_ERR_GENERIC + else + return $OCF_SUCCESS + fi +} + +node_health_check_legacy() { + local rc_alive + local timeout_alive + su_rabbit_cmd "${OCF_RESKEY_ctl} list_channels > /dev/null 2>&1" + rc_alive=$? + [ $rc_alive -eq 137 -o $rc_alive -eq 124 ] && ocf_log err "${LH} 'rabbitmqctl list_channels' timed out, per-node explanation: $(enhanced_list_channels)" + check_timeouts $rc_alive "rabbit_list_channels_timeouts" "list_channels" + timeout_alive=$? + + if [ $timeout_alive -eq 2 ]; then + master_score 0 + return $OCF_ERR_GENERIC + elif [ $timeout_alive -eq 0 ]; then + if [ $rc_alive -ne 0 ]; then + ocf_log err "${LH} rabbitmqctl list_channels exited with errors." + rc=$OCF_ERR_GENERIC + fi + fi + + # Check for memory alarms for this Master or Slave node. + # If alert found, reset the alarm + # and restart the resource as it likely means a dead end situation + # when rabbitmq cluster is running with blocked publishing due + # to high memory watermark exceeded. + local alarms + local rc_alarms + local timeout_alarms + alarms=`su_rabbit_cmd "${OCF_RESKEY_ctl} -q eval 'rabbit_alarm:get_alarms().'"` + rc_alarms=$? + check_timeouts $rc_alarms "rabbit_get_alarms_timeouts" "get_alarms" + timeout_alarms=$? + + if [ $timeout_alarms -eq 2 ]; then + master_score 0 + return $OCF_ERR_GENERIC + + elif [ $timeout_alarms -eq 0 ]; then + if [ $rc_alarms -ne 0 ]; then + ocf_log err "${LH} rabbitmqctl get_alarms exited with errors." + rc=$OCF_ERR_GENERIC + + elif [ -n "${alarms}" ]; then + for node in ${alarms}; do + name=`echo ${node} | perl -n -e "m/memory,'(?<n>\S+)+'/ && print \"$+{n}\n\""` + if [ "${name}" = "${RABBITMQ_NODENAME}" ] ; then + ocf_log err "${LH} Found raised memory alarm. Erasing the alarm and restarting." + su_rabbit_cmd "${OCF_RESKEY_ctl} set_vm_memory_high_watermark 10 > /dev/null 2>&1" + rc=$OCF_ERR_GENERIC + break + fi + done + fi + fi + + if ! is_cluster_status_ok ; then + rc=$OCF_ERR_GENERIC + fi + + # Check if the list of all queues is available, + # Also report some queues stats and total virtual memory. + local queues + local rc_queues + local timeout_queues + queues=`su_rabbit_cmd "${OCF_RESKEY_ctl} -q -p ${OCF_RESKEY_default_vhost} list_queues memory messages consumer_utilisation"` + rc_queues=$? + check_timeouts $rc_queues "rabbit_list_queues_timeouts" "list_queues" + timeout_queues=$? + + if [ $timeout_queues -eq 2 ]; then + master_score 0 + return $OCF_ERR_GENERIC + + elif [ $timeout_queues -eq 0 ]; then + if [ $rc_queues -ne 0 ]; then + ocf_log err "${LH} rabbitmqctl list_queues exited with errors." + rc=$OCF_ERR_GENERIC + + elif [ -n "${queues}" ]; then + local q_c + q_c=`printf %b "${queues}\n" | wc -l` + local mem + mem=`printf %b "${queues}\n" | awk -v sum=0 '{sum+=$1} END {print (sum/1048576)}'` + local mes + mes=`printf %b "${queues}\n" | awk -v sum=0 '{sum+=$2} END {print sum}'` + local c_u + c_u=`printf %b "${queues}\n" | awk -v sum=0 -v cnt=${q_c} '{sum+=$3} END {print (sum+1)/(cnt+1)}'` + local status + status=`echo $(su_rabbit_cmd "${OCF_RESKEY_ctl} -q status")` + ocf_log info "${LH} RabbitMQ is running ${q_c} queues consuming ${mem}m of ${TOTALVMEM}m total, with ${mes} queued messages, average consumer utilization ${c_u}" + ocf_log info "${LH} RabbitMQ status: ${status}" + fi + fi + + return $rc +} + +ocf_get_private_attr() { + local attr_name="${1:?}" + local attr_default_value="${2:?}" + local nodename="${3:-$THIS_PCMK_NODE}" + local count + count=$(attrd_updater -p --name "$attr_name" --node "$nodename" --query) + if [ $? -ne 0 ]; then + echo $attr_default_value + else + echo "$count" | awk -vdef_val="$attr_default_value" '{ gsub(/"/, "", $3); split($3, vals, "="); if (vals[2] != "") print vals[2]; else print def_val }' + fi +} + +ocf_update_private_attr() { + local attr_name="${1:?}" + local attr_value="${2:?}" + local nodename="${3:-$THIS_PCMK_NODE}" + ocf_run attrd_updater -p --name "$attr_name" --node "$nodename" --update "$attr_value" +} + +rabbitmqctl_with_timeout_check() { + local command="${1:?}" + local timeout_attr_name="${2:?}" + + su_rabbit_cmd "${OCF_RESKEY_ctl} $command" + local rc=$? + + check_timeouts $rc $timeout_attr_name "$command" + local has_timed_out=$? + + case "$has_timed_out" in + 0) + return $rc;; + 1) + return 0;; + 2) + return 1;; + esac +} + +is_cluster_status_ok() { + local LH="${LH}: is_cluster_status_ok:" + rabbitmqctl_with_timeout_check cluster_status rabbit_cluster_status_timeouts > /dev/null 2>&1 +} + +action_monitor() { + local rc=$OCF_ERR_GENERIC + local LH="${LL} monitor:" + ocf_log debug "${LH} action start." + if [ "${OCF_RESKEY_debug}" = 'true' ] ; then + d=`date '+%Y%m%d %H:%M:%S'` + echo $d >> /tmp/rmq-monitor.log + env >> /tmp/rmq-monitor.log + echo "$d [monitor] start='${OCF_RESKEY_CRM_meta_notify_start_uname}' stop='${OCF_RESKEY_CRM_meta_notify_stop_uname}' active='${OCF_RESKEY_CRM_meta_notify_active_uname}' inactive='${OCF_RESKEY_CRM_meta_notify_inactive_uname}'" >> /tmp/rmq-ocf.log + fi + get_monitor + rc=$? + ocf_log debug "${LH} role: ${OCF_RESKEY_CRM_meta_role}" + ocf_log debug "${LH} result: $rc" + ocf_log debug "${LH} action end." + return $rc +} + + +action_start() { + local rc=$OCF_ERR_GENERIC + local LH="${LL} start:" + local nowtime + + if [ "${OCF_RESKEY_debug}" = 'true' ] ; then + d=`date '+%Y%m%d %H:%M:%S'` + echo $d >> /tmp/rmq-start.log + env >> /tmp/rmq-start.log + echo "$d [start] start='${OCF_RESKEY_CRM_meta_notify_start_uname}' stop='${OCF_RESKEY_CRM_meta_notify_stop_uname}' active='${OCF_RESKEY_CRM_meta_notify_active_uname}' inactive='${OCF_RESKEY_CRM_meta_notify_inactive_uname}'" >> /tmp/rmq-ocf.log + fi + + ocf_log info "${LH} action begin." + + get_status + rc=$? + if [ $rc -eq $OCF_SUCCESS ] ; then + ocf_log warn "${LH} RMQ-runtime (beam) already started." + return $OCF_SUCCESS + fi + + local attrs_to_zero="rabbit_list_channels_timeouts rabbit_get_alarms_timeouts rabbit_list_queues_timeouts rabbit_cluster_status_timeouts rabbit_node_health_check_timeouts" + local attr_name_to_reset + for attr_name_to_reset in $attrs_to_zero; do + ocf_update_private_attr $attr_name_to_reset 0 + done + + nowtime=$(now) + ocf_log info "${LH} Setting phase 1 one start time to $nowtime" + ocf_update_private_attr 'rabbit-start-phase-1-time' "$nowtime" + ocf_log info "${LH} Deleting start time attribute" + ocf_run crm_attribute -N $THIS_PCMK_NODE -l reboot --name 'rabbit-start-time' --delete + ocf_log info "${LH} Deleting master attribute" + ocf_run crm_attribute -N $THIS_PCMK_NODE -l reboot --name 'rabbit-master' --delete + + ocf_log info "${LH} RMQ going to start." + start_rmq_server_app + rc=$? + if [ $rc -eq $OCF_SUCCESS ] ; then + ocf_log info "${LH} RMQ prepared for start succesfully." + fi + + ocf_log info "${LH} action end." + return $rc +} + + +action_stop() { + local rc=$OCF_ERR_GENERIC + local LH="${LL} stop:" + + if [ "${OCF_RESKEY_debug}" = 'true' ] ; then + d=$(date '+%Y%m%d %H:%M:%S') + echo $d >> /tmp/rmq-stop.log + env >> /tmp/rmq-stop.log + echo "$d [stop] start='${OCF_RESKEY_CRM_meta_notify_start_uname}' stop='${OCF_RESKEY_CRM_meta_notify_stop_uname}' active='${OCF_RESKEY_CRM_meta_notify_active_uname}' inactive='${OCF_RESKEY_CRM_meta_notify_inactive_uname}'" >> /tmp/rmq-ocf.log + fi + + ocf_log info "${LH} action begin." + + ocf_log info "${LH} Deleting master attribute" + ocf_run crm_attribute -N $THIS_PCMK_NODE -l reboot --name 'rabbit-master' --delete + master_score 0 + ocf_log info "${LH} Deleting start time attribute" + ocf_run crm_attribute -N $THIS_PCMK_NODE -l reboot --name 'rabbit-start-time' --delete + + # Wait for synced state first + ocf_log info "${LH} waiting $((OCF_RESKEY_stop_time/2)) to sync" + wait_sync $((OCF_RESKEY_stop_time/2)) + + ocf_log info "${LH} RMQ-runtime (beam) going to down." + stop_server_process + + if [ $? -ne $OCF_SUCCESS ] ; then + ocf_log err "RMQ-runtime (beam) couldn't be stopped and will likely became unmanaged. Take care of it manually!" + ocf_log info "${LH} action end." + exit $OCF_ERR_GENERIC + fi + + ocf_log info "${LH} RMQ-runtime (beam) not running." + ocf_log info "${LH} action end." + return $OCF_SUCCESS +} + +####################################################################### +# Enhanced list_channels: +# - nodes are processed in parallel +# - report contains information about which nodes timed out +# +# 'list_channels' is used as a healh-check for current node, but it +# actually checks overall health of all node in cluster. And there were +# some bugs where only one (non-local) channel became stuck, but OCF +# script was wrongfully killing local node. +# +# Hopefully all such bugs are fixed, but if not - it will allow to +# detect such conditions. +# +# Somewhat strange implementation is due to the following reasons: +# - ability to support older versions of RabbitMQ which have reached +# end-of-life with single version of the script +# - zero dependencies - for older versions this functionality could be +# implemented as a plugin, but it'll require this plugin installation +enhanced_list_channels() { + # One second less than timeout of su_rabbit_cmd + local timeout=$((${TIMEOUT_ARG:-5} - 1)) + + su_rabbit_cmd "xargs -0 ${OCF_RESKEY_ctl} eval" <<EOF +SecondsToCompletion = $timeout, + +%% Milliseconds since unix epoch +Now = fun() -> + {Mega, Secs, Micro} = os:timestamp(), + Mili = Micro div 1000, + Mili + 1000 * (Secs + 1000000 * Mega) + end, + +%% We shouldn't continue execution past this time +ShouldEndAt = Now() + SecondsToCompletion * 1000, + +%% How many milliseconds we still have +Timeout = fun() -> + case ShouldEndAt - Now() of + Past when Past =< 0 -> + 0; + Timeout -> + Timeout + end + end, + +%% Lambda combinator - for defining anonymous recursive functions +Y = fun(F) -> + (fun (X) -> F(fun(Y) -> (X(X))(Y) end) end)( + fun (X) -> F(fun(Y) -> (X(X))(Y) end) end) + end, + +Parent = self(), + +ListChannels = Y(fun(Rec) -> + fun (({Node, [], OkChannelsCount})) -> + Parent ! {Node, ok, OkChannelsCount}; + ({Node, [Chan|Rest], OkChannelsCount}) -> + case catch rpc:call(Node, rabbit_channel, info, [Chan], Timeout()) of + Infos when is_list(Infos) -> + Rec({Node, Rest, OkChannelsCount + 1}); + {badrpc, {'EXIT', {noproc, _}}} -> + %% Channel became dead before we could request it's status, don't care + Rec({Node, Rest, OkChannelsCount}); + Err -> + Parent ! {Node, Err, OkChannelsCount} + end + end + end), + +SingleNodeListing = fun(Node) -> + case catch rpc:call(Node, pg_local, get_members, [rabbit_channels], Timeout()) of + LocalChannels when is_list(LocalChannels) -> + ListChannels({Node, LocalChannels, 0}); + Err -> + Parent ! {Node, Err, 0} + end + end, + +AllNodes = rabbit_mnesia:cluster_nodes(running), +[ spawn(fun() -> SingleNodeListing(Node) end) || Node <- AllNodes ], + +WaitForNodes = Y(fun(Rec) -> + fun ({[], Acc}) -> + Acc; + ({RemainingNodes, Acc}) -> + receive + {Node, _Status, _ChannelCount} = Smth -> + RemainingNodes1 = lists:delete(Node, RemainingNodes), + Rec({RemainingNodes1, [Smth|Acc]}) + after Timeout() + 100 -> + Acc + end + end + end), + +Result = WaitForNodes({AllNodes, []}), + +ExpandedResult = [ case lists:keysearch(Node, 1, Result) of + {value, NodeResult} -> + NodeResult; + false -> + {Node, no_data_collected, 0} + end || Node <- AllNodes ], + +ExpandedResult. +EOF +} + +####################################################################### +# Join the cluster and return OCF_SUCCESS, if joined. +# Return 10, if node is trying to join to itself or empty destination. +# Return OCF_ERR_GENERIC, if cannot join. +jjj_join () { + local join_to="$1" + local rc=$OCF_ERR_GENERIC + local LH="${LL} jjj_join:" + + my_host ${join_to} + rc=$? + ocf_log debug "${LH} node='${join_to}' rc='${rc}'" + + # Check whether we are joining to ourselves + # or master host is not given + if [ $rc -ne 0 -a "${join_to}" ] ; then + ocf_log info "${LH} Joining to cluster by node '${join_to}'" + join_to_cluster "${join_to}" + rc=$? + if [ $rc -ne $OCF_SUCCESS ] ; then + ocf_log err "${LH} Failed to join the cluster. The mnesia will be reset." + reset_mnesia + rc=$OCF_ERR_GENERIC + fi + fi + return $rc +} + +action_notify() { + local rc_join=$OCF_SUCCESS + local rc=$OCF_ERR_GENERIC + local rc2=$OCF_ERR_GENERIC + local LH="${LL} notify:" + local nodelist + + if [ "${OCF_RESKEY_debug}" = 'true' ] ; then + d=`date '+%Y%m%d %H:%M:%S'` + echo $d >> /tmp/rmq-notify.log + env >> /tmp/rmq-notify.log + echo "$d [notify] ${OCF_RESKEY_CRM_meta_notify_type}-${OCF_RESKEY_CRM_meta_notify_operation} promote='${OCF_RESKEY_CRM_meta_notify_promote_uname}' demote='${OCF_RESKEY_CRM_meta_notify_demote_uname}' master='${OCF_RESKEY_CRM_meta_notify_master_uname}' slave='${OCF_RESKEY_CRM_meta_notify_slave_uname}' start='${OCF_RESKEY_CRM_meta_notify_start_uname}' stop='${OCF_RESKEY_CRM_meta_notify_stop_uname}' active='${OCF_RESKEY_CRM_meta_notify_active_uname}' inactive='${OCF_RESKEY_CRM_meta_notify_inactive_uname}'" >> /tmp/rmq-ocf.log + fi + + if [ "${OCF_RESKEY_CRM_meta_notify_type}" = 'post' ] ; then + # POST- anything notify section + case "$OCF_RESKEY_CRM_meta_notify_operation" in + promote) + ocf_log info "${LH} post-promote begin." + + rc=$OCF_SUCCESS + + # Do nothing, if the list of nodes being promoted reported empty. + # Delegate recovery, if needed, to the "running out of the cluster" monitor's logic + if [ -z "${OCF_RESKEY_CRM_meta_notify_promote_uname}" ] ; then + ocf_log warn "${LH} there are no nodes to join to reported on post-promote. Nothing to do." + + elif my_host "${OCF_RESKEY_CRM_meta_notify_promote_uname}"; then + ocf_log info "${LH} ignoring post-promote of self" + + elif is_clustered_with "${OCF_RESKEY_CRM_meta_notify_promote_uname}"; then + if get_status rabbit; then + ocf_log info "${LH} we are already clustered with master - ${OCF_RESKEY_CRM_meta_notify_promote_uname}. Nothing to do." + else + ocf_log info "${LH} we are already clustered with master - ${OCF_RESKEY_CRM_meta_notify_promote_uname}. We only need to start the app." + + try_to_start_rmq_app + rc2=$? + update_rabbit_start_time_if_rc $rc2 + fi + + else + # Note, this should fail when the mnesia is inconsistent. + # For example, when the "old" master processing the promition of the new one. + # Later this ex-master node will rejoin the cluster at post-start. + jjj_join "${OCF_RESKEY_CRM_meta_notify_promote_uname}" + rc=$? + if [ $rc -eq $OCF_ERR_GENERIC ] ; then + ocf_log err "${LH} Failed to join the cluster on post-promote. The resource will be restarted." + fi + fi + + ocf_log info "${LH} post-promote end." + return $rc + ;; + start) + ocf_log info "${LH} post-start begin." + # Do nothing, if the list of nodes being started or running reported empty + # Delegate recovery, if needed, to the "running out of the cluster" monitor's logic + if [ -z "${OCF_RESKEY_CRM_meta_notify_start_uname}" -a -z "${OCF_RESKEY_CRM_meta_notify_active_uname}" ] ; then + ocf_log warn "${LH} I'm a last man standing and I must survive!" + ocf_log info "${LH} post-start end." + return $OCF_SUCCESS + fi + # check did this event from this host + my_host "${OCF_RESKEY_CRM_meta_notify_start_uname}" + rc=$? + # Do nothing, if there is no master reported + # Delegate recovery, if needed, to the "running out of the cluster" monitor's logic + if [ -z "${OCF_RESKEY_CRM_meta_notify_master_uname}" ] ; then + ocf_log warn "${LH} there are no nodes to join to reported on post-start. Nothing to do." + ocf_log info "${LH} post-start end." + return $OCF_SUCCESS + fi + if [ $rc -eq $OCF_SUCCESS ] ; then + # Now we need to: + # a. join to the cluster if we are not joined yet + # b. start the RabbitMQ application, which is always + # stopped after start action finishes + check_need_join_to ${OCF_RESKEY_CRM_meta_notify_master_uname} + rc_join=$? + if [ $rc_join -eq $OCF_SUCCESS ]; then + ocf_log warn "${LH} Going to join node ${OCF_RESKEY_CRM_meta_notify_master_uname}" + jjj_join "${OCF_RESKEY_CRM_meta_notify_master_uname}" + rc2=$? + else + ocf_log warn "${LH} We are already clustered with node ${OCF_RESKEY_CRM_meta_notify_master_uname}" + + try_to_start_rmq_app + rc2=$? + update_rabbit_start_time_if_rc $rc2 + fi + if [ -s "${OCF_RESKEY_definitions_dump_file}" ] ; then + ocf_log info "File ${OCF_RESKEY_definitions_dump_file} exists" + ocf_run curl --silent --show-error --request POST --user $OCF_RESKEY_admin_user:$OCF_RESKEY_admin_password $OCF_RESKEY_host_ip:15672/api/definitions --header "Content-Type:application/json" --data @$OCF_RESKEY_definitions_dump_file + rc=$? + if [ $rc -eq $OCF_SUCCESS ] ; then + ocf_log info "RMQ definitions have imported succesfully." + else + ocf_log err "RMQ definitions have not imported." + fi + fi + if [ $rc2 -eq $OCF_ERR_GENERIC ] ; then + ocf_log warn "${LH} Failed to join the cluster on post-start. The resource will be restarted." + ocf_log info "${LH} post-start end." + return $OCF_ERR_GENERIC + fi + fi + ocf_log info "${LH} post-start end." + ;; + stop) + # if rabbitmq-server stops on any another node, we should remove it from cluster (as ordinary operation) + ocf_log info "${LH} post-stop begin." + # Report not running, if there are no nodes being stopped reported + if [ -z "${OCF_RESKEY_CRM_meta_notify_stop_uname}" ] ; then + ocf_log warn "${LH} there are no nodes being stopped reported on post-stop. The resource will be restarted." + ocf_log info "${LH} post-stop end." + return $OCF_ERR_GENERIC + fi + my_host "${OCF_RESKEY_CRM_meta_notify_stop_uname}" + rc=$? + if [ $rc -ne $OCF_SUCCESS ] ; then + # Wait for synced state first + ocf_log info "${LH} waiting $((OCF_RESKEY_stop_time/2)) to sync" + wait_sync $((OCF_RESKEY_stop_time/2)) + # On other nodes processing the post-stop, make sure the stopped node will be forgotten + unjoin_nodes_from_cluster "${OCF_RESKEY_CRM_meta_notify_stop_uname}" + else + # On the nodes being stopped, reset the master score + ocf_log info "${LH} resetting the master score." + master_score 0 + fi + # always returns OCF_SUCCESS + ocf_log info "${LH} post-stop end." + ;; + *) ;; + esac + fi + + return $OCF_SUCCESS +} + + +action_promote() { + local rc=$OCF_ERR_GENERIC + local LH="${LL} promote:" + + if [ "${OCF_RESKEY_debug}" = 'true' ] ; then + d=$(date '+%Y%m%d %H:%M:%S') + echo $d >> /tmp/rmq-promote.log + env >> /tmp/rmq-promote.log + echo "$d [promote] start='${OCF_RESKEY_CRM_meta_notify_start_uname}' stop='${OCF_RESKEY_CRM_meta_notify_stop_uname}' active='${OCF_RESKEY_CRM_meta_notify_active_uname}' inactive='${OCF_RESKEY_CRM_meta_notify_inactive_uname}'" >> /tmp/rmq-ocf.log + fi + + ocf_log info "${LH} action begin." + + get_monitor + rc=$? + ocf_log info "${LH} get_monitor returns ${rc}" + case "$rc" in + "$OCF_SUCCESS") + # Running as slave. Normal, expected behavior. + ocf_log info "${LH} Resource is currently running as Slave" + # rabbitmqctl start_app if need + get_status rabbit + rc=$? + ocf_log info "${LH} Updating cluster master attribute" + ocf_run crm_attribute -N $THIS_PCMK_NODE -l reboot --name 'rabbit-master' --update 'true' + if [ $rc -ne $OCF_SUCCESS ] ; then + ocf_log info "${LH} RMQ app is not started. Starting..." + start_rmq_server_app + rc=$? + if [ $rc -eq 0 ] ; then + try_to_start_rmq_app + rc=$? + if [ $rc -ne 0 ] ; then + ocf_log err "${LH} Can't start RMQ app. Master resource is failed." + ocf_log info "${LH} action end." + exit $OCF_FAILED_MASTER + fi + + [ -f "${OCF_RESKEY_policy_file}" ] && . "${OCF_RESKEY_policy_file}" + + update_rabbit_start_time_if_rc $rc + + ocf_log info "${LH} Checking master status" + get_monitor + rc=$? + ocf_log info "${LH} Master status is $rc" + if [ $rc = $OCF_RUNNING_MASTER ] + then + rc=$OCF_SUCCESS + else + ocf_log err "${LH} Master resource is failed." + ocf_log info "${LH} action end." + exit $OCF_FAILED_MASTER + fi + else + ocf_log err "${LH} Can't start RMQ-runtime." + rc=$OCF_ERR_GENERIC + fi + fi + return $rc + ;; + "$OCF_RUNNING_MASTER") + # Already a master. Unexpected, but not a problem. + ocf_log warn "${LH} Resource is already running as Master" + rc=$OCF_SUCCESS + ;; + + "$OCF_FAILED_MASTER") + # Master failed. + ocf_log err "${LH} Master resource is failed and not running" + ocf_log info "${LH} action end." + exit $OCF_FAILED_MASTER + ;; + + "$OCF_NOT_RUNNING") + # Currently not running. + ocf_log err "${LH} Resource is currently not running" + rc=$OCF_NOT_RUNNING + ;; + *) + # Failed resource. Let the cluster manager recover. + ocf_log err "${LH} Unexpected error, cannot promote" + ocf_log info "${LH} action end." + exit $rc + ;; + esac + + # transform slave RMQ-server to master + + ocf_log info "${LH} action end." + return $rc +} + + +action_demote() { + local LH="${LL} demote:" + ocf_log info "${LH} action begin." + ocf_run crm_attribute -N $THIS_PCMK_NODE -l reboot --name 'rabbit-master' --delete + ocf_log info "${LH} action end." + return $OCF_SUCCESS +} +####################################################################### + +rmq_setup_env + +case "$1" in + meta-data) meta_data + exit $OCF_SUCCESS;; + usage|help) usage + exit $OCF_SUCCESS;; +esac + +# Anything except meta-data and help must pass validation +action_validate || exit $? + +# What kind of method was invoked? +case "$1" in + start) action_start;; + stop) action_stop;; + status) action_status;; + monitor) action_monitor;; + validate) action_validate;; + promote) action_promote;; + demote) action_demote;; + notify) action_notify;; + validate-all) action_validate;; + *) usage;; +esac +### diff --git a/scripts/rabbitmq-server.bat b/scripts/rabbitmq-server.bat deleted file mode 100644 index 3a386b63c4..0000000000 --- a/scripts/rabbitmq-server.bat +++ /dev/null @@ -1,91 +0,0 @@ -@echo off
-REM This Source Code Form is subject to the terms of the Mozilla Public
-REM License, v. 2.0. If a copy of the MPL was not distributed with this
-REM file, You can obtain one at https://mozilla.org/MPL/2.0/.
-REM
-REM Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved.
-REM
-
-setlocal
-
-rem Preserve values that might contain exclamation marks before
-rem enabling delayed expansion
-set TDP0=%~dp0
-set STAR=%*
-set CONF_SCRIPT_DIR=%~dp0
-setlocal enabledelayedexpansion
-setlocal enableextensions
-
-if ERRORLEVEL 1 (
- echo "Failed to enable command extensions!"
- exit /B 1
-)
-
-REM Get default settings with user overrides for (RABBITMQ_)<var_name>
-REM Non-empty defaults should be set in rabbitmq-env
-call "%TDP0%\rabbitmq-env.bat" %~n0
-
-if not exist "!ERLANG_HOME!\bin\erl.exe" (
- echo.
- echo ******************************
- echo ERLANG_HOME not set correctly.
- echo ******************************
- echo.
- echo Please either set ERLANG_HOME to point to your Erlang installation or place the
- echo RabbitMQ server distribution in the Erlang lib folder.
- echo.
- exit /B 1
-)
-
-set RABBITMQ_DEFAULT_ALLOC_ARGS=+MBas ageffcbf +MHas ageffcbf +MBlmbcs 512 +MHlmbcs 512 +MMmcs 30
-
-set RABBITMQ_START_RABBIT=
-if "!RABBITMQ_ALLOW_INPUT!"=="" (
- set RABBITMQ_START_RABBIT=!RABBITMQ_START_RABBIT! -noinput
-)
-if "!RABBITMQ_NODE_ONLY!"=="" (
- set RABBITMQ_START_RABBIT=!RABBITMQ_START_RABBIT! -s "!RABBITMQ_BOOT_MODULE!" boot
-)
-
-set ENV_OK=true
-CALL :check_not_empty "RABBITMQ_BOOT_MODULE" !RABBITMQ_BOOT_MODULE!
-
-if "!ENV_OK!"=="false" (
- EXIT /b 78
-)
-
-if "!RABBITMQ_ALLOW_INPUT!"=="" (
- set ERL_CMD=erl.exe
-) else (
- set ERL_CMD=werl.exe
-)
-
-"!ERLANG_HOME!\bin\!ERL_CMD!" ^
-!RABBITMQ_START_RABBIT! ^
--boot "!SASL_BOOT_FILE!" ^
-+W w ^
-!RABBITMQ_DEFAULT_ALLOC_ARGS! ^
-!RABBITMQ_SERVER_ERL_ARGS! ^
-!RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS! ^
-!RABBITMQ_SERVER_START_ARGS! ^
--lager crash_log false ^
--lager handlers "[]" ^
-!STAR!
-
-if ERRORLEVEL 1 (
- exit /B %ERRORLEVEL%
-)
-
-EXIT /B 0
-
-:check_not_empty
-if "%~2"=="" (
- ECHO "Error: ENV variable should be defined: %1. Please check rabbitmq-env and rabbitmq-defaults, and !RABBITMQ_CONF_ENV_FILE! script files. Check also your Environment Variables settings"
- set ENV_OK=false
- EXIT /B 78
- )
-EXIT /B 0
-
-endlocal
-endlocal
-endlocal
diff --git a/scripts/rabbitmq-server.ocf b/scripts/rabbitmq-server.ocf new file mode 100755 index 0000000000..7bf3fff368 --- /dev/null +++ b/scripts/rabbitmq-server.ocf @@ -0,0 +1,385 @@ +#!/bin/sh + +## This Source Code Form is subject to the terms of the Mozilla Public +## License, v. 2.0. If a copy of the MPL was not distributed with this +## file, You can obtain one at https://mozilla.org/MPL/2.0/. +## +## Copyright (c) 2018-2020 VMware, Inc. or its affiliates. All rights reserved. +## + +## +## OCF Resource Agent compliant rabbitmq-server resource script. +## + +## OCF instance parameters +## OCF_RESKEY_server +## OCF_RESKEY_ctl +## OCF_RESKEY_nodename +## OCF_RESKEY_ip +## OCF_RESKEY_port +## OCF_RESKEY_config_file +## OCF_RESKEY_log_base +## OCF_RESKEY_mnesia_base +## OCF_RESKEY_server_start_args +## OCF_RESKEY_pid_file +## OCF_RESKEY_limit_nofile + +####################################################################### +# Initialization: + +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat} +. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs + +####################################################################### + +OCF_RESKEY_server_default="/usr/sbin/rabbitmq-server" +OCF_RESKEY_ctl_default="/usr/sbin/rabbitmqctl" +OCF_RESKEY_nodename_default="rabbit@localhost" +OCF_RESKEY_log_base_default="/var/log/rabbitmq" +OCF_RESKEY_pid_file_default="/var/run/rabbitmq/pid" +OCF_RESKEY_limit_nofile_default=65535 +: ${OCF_RESKEY_server=${OCF_RESKEY_server_default}} +: ${OCF_RESKEY_ctl=${OCF_RESKEY_ctl_default}} +: ${OCF_RESKEY_nodename=${OCF_RESKEY_nodename_default}} +: ${OCF_RESKEY_log_base=${OCF_RESKEY_log_base_default}} +: ${OCF_RESKEY_pid_file=${OCF_RESKEY_pid_file_default}} +: ${OCF_RESKEY_limit_nofile=${OCF_RESKEY_limit_nofile_default}} + +meta_data() { + cat <<END +<?xml version="1.0"?> +<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> +<resource-agent name="rabbitmq-server"> +<version>1.0</version> + +<longdesc lang="en"> +Resource agent for RabbitMQ-server +</longdesc> + +<shortdesc lang="en">Resource agent for RabbitMQ-server</shortdesc> + +<parameters> +<parameter name="server" unique="0" required="0"> +<longdesc lang="en"> +The path to the rabbitmq-server script +</longdesc> +<shortdesc lang="en">Path to rabbitmq-server</shortdesc> +<content type="string" default="${OCF_RESKEY_server_default}" /> +</parameter> + +<parameter name="ctl" unique="0" required="0"> +<longdesc lang="en"> +The path to the rabbitmqctl script +</longdesc> +<shortdesc lang="en">Path to rabbitmqctl</shortdesc> +<content type="string" default="${OCF_RESKEY_ctl_default}" /> +</parameter> + +<parameter name="nodename" unique="0" required="0"> +<longdesc lang="en"> +The node name for rabbitmq-server +</longdesc> +<shortdesc lang="en">Node name</shortdesc> +<content type="string" default="${OCF_RESKEY_nodename_default}" /> +</parameter> + +<parameter name="ip" unique="0" required="0"> +<longdesc lang="en"> +The IP address for rabbitmq-server to listen on +</longdesc> +<shortdesc lang="en">IP Address</shortdesc> +<content type="string" default="" /> +</parameter> + +<parameter name="port" unique="0" required="0"> +<longdesc lang="en"> +The IP Port for rabbitmq-server to listen on +</longdesc> +<shortdesc lang="en">IP Port</shortdesc> +<content type="integer" default="" /> +</parameter> + +<parameter name="config_file" unique="0" required="0"> +<longdesc lang="en"> +Location of the config file (without the .config suffix) +</longdesc> +<shortdesc lang="en">Config file path (without the .config suffix)</shortdesc> +<content type="string" default="" /> +</parameter> + +<parameter name="log_base" unique="0" required="0"> +<longdesc lang="en"> +Location of the directory under which logs will be created +</longdesc> +<shortdesc lang="en">Log base path</shortdesc> +<content type="string" default="${OCF_RESKEY_log_base_default}" /> +</parameter> + +<parameter name="mnesia_base" unique="0" required="0"> +<longdesc lang="en"> +Location of the directory under which mnesia will store data +</longdesc> +<shortdesc lang="en">Mnesia base path</shortdesc> +<content type="string" default="" /> +</parameter> + +<parameter name="server_start_args" unique="0" required="0"> +<longdesc lang="en"> +Additional arguments provided to the server on startup +</longdesc> +<shortdesc lang="en">Server start arguments</shortdesc> +<content type="string" default="" /> +</parameter> + +<parameter name="pid_file" unique="0" required="0"> +<longdesc lang="en"> +Location of the file in which the pid will be stored +</longdesc> +<shortdesc lang="en">Pid file path</shortdesc> +<content type="string" default="${OCF_RESKEY_pid_file_default}" /> +</parameter> + +<parameter name="limit_nofile" unique="0" required="0"> +<longdesc lang="en"> +Soft and hard limit for NOFILE +</longdesc> +<shortdesc lang="en">NOFILE limit</shortdesc> +<content type="string" default="${OCF_RESKEY_limit_nofile_default}" /> +</parameter> + +</parameters> + +<actions> +<action name="start" timeout="600" /> +<action name="stop" timeout="120" /> +<action name="status" timeout="20" interval="10" /> +<action name="monitor" timeout="20" interval="10" /> +<action name="validate-all" timeout="30" /> +<action name="meta-data" timeout="5" /> +</actions> +</resource-agent> +END +} + +rabbit_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 +} + +RABBITMQ_SERVER=$OCF_RESKEY_server +RABBITMQ_CTL=$OCF_RESKEY_ctl +RABBITMQ_NODENAME=$OCF_RESKEY_nodename +RABBITMQ_NODE_IP_ADDRESS=$OCF_RESKEY_ip +RABBITMQ_NODE_PORT=$OCF_RESKEY_port +RABBITMQ_CONFIG_FILE=$OCF_RESKEY_config_file +RABBITMQ_LOG_BASE=$OCF_RESKEY_log_base +RABBITMQ_MNESIA_BASE=$OCF_RESKEY_mnesia_base +RABBITMQ_SERVER_START_ARGS=$OCF_RESKEY_server_start_args +RABBITMQ_PID_FILE=$OCF_RESKEY_pid_file +RABBITMQ_LIMIT_NOFILE=$OCF_RESKEY_limit_nofile +[ ! -z $RABBITMQ_NODENAME ] && NODENAME_ARG="-n $RABBITMQ_NODENAME" +[ ! -z $RABBITMQ_NODENAME ] && export RABBITMQ_NODENAME + +ensure_pid_dir () { + PID_DIR=`dirname ${RABBITMQ_PID_FILE}` + if [ ! -d ${PID_DIR} ] ; then + mkdir -p ${PID_DIR} + chown -R rabbitmq:rabbitmq ${PID_DIR} + chmod 755 ${PID_DIR} + fi + return $OCF_SUCCESS +} + +remove_pid () { + rm -f ${RABBITMQ_PID_FILE} + rmdir `dirname ${RABBITMQ_PID_FILE}` || : +} + +export_vars() { + [ ! -z $RABBITMQ_NODE_IP_ADDRESS ] && export RABBITMQ_NODE_IP_ADDRESS + [ ! -z $RABBITMQ_NODE_PORT ] && export RABBITMQ_NODE_PORT + [ ! -z $RABBITMQ_CONFIG_FILE ] && export RABBITMQ_CONFIG_FILE + [ ! -z $RABBITMQ_LOG_BASE ] && export RABBITMQ_LOG_BASE + [ ! -z $RABBITMQ_MNESIA_BASE ] && export RABBITMQ_MNESIA_BASE + [ ! -z $RABBITMQ_SERVER_START_ARGS ] && export RABBITMQ_SERVER_START_ARGS + [ ! -z $RABBITMQ_PID_FILE ] && ensure_pid_dir && export RABBITMQ_PID_FILE +} + +set_limits() { + local current_limit=$(su rabbitmq -s /bin/sh -c "ulimit -n") + if [ ! -z $RABBITMQ_LIMIT_NOFILE -a $RABBITMQ_LIMIT_NOFILE -gt $current_limit ] ; then + ulimit -n $RABBITMQ_LIMIT_NOFILE + fi +} + +rabbit_validate_partial() { + if [ ! -x $RABBITMQ_SERVER ]; then + ocf_log err "rabbitmq-server server $RABBITMQ_SERVER does not exist or is not executable"; + exit $OCF_ERR_INSTALLED; + fi + + if [ ! -x $RABBITMQ_CTL ]; then + ocf_log err "rabbitmq-server ctl $RABBITMQ_CTL does not exist or is not executable"; + exit $OCF_ERR_INSTALLED; + fi +} + +rabbit_validate_full() { + if [ ! -z $RABBITMQ_CONFIG_FILE ] && [ ! -e "${RABBITMQ_CONFIG_FILE}.config" ]; then + ocf_log err "rabbitmq-server config_file ${RABBITMQ_CONFIG_FILE}.config does not exist or is not a file"; + exit $OCF_ERR_INSTALLED; + fi + + if [ ! -z $RABBITMQ_LOG_BASE ] && [ ! -d $RABBITMQ_LOG_BASE ]; then + ocf_log err "rabbitmq-server log_base $RABBITMQ_LOG_BASE does not exist or is not a directory"; + exit $OCF_ERR_INSTALLED; + fi + + if [ ! -z $RABBITMQ_MNESIA_BASE ] && [ ! -d $RABBITMQ_MNESIA_BASE ]; then + ocf_log err "rabbitmq-server mnesia_base $RABBITMQ_MNESIA_BASE does not exist or is not a directory"; + exit $OCF_ERR_INSTALLED; + fi + + rabbit_validate_partial + + return $OCF_SUCCESS +} + +rabbit_status() { + rabbitmqctl_action "status" +} + +rabbit_wait() { + rabbitmqctl_action "wait" $1 +} + +rabbitmqctl_action() { + local rc + local action + action=$@ + ocf_run -q -info $RABBITMQ_CTL $NODENAME_ARG $action + rc=$? + case "$rc" in + 0) + ocf_log debug "RabbitMQ server is running normally" + return $OCF_SUCCESS + ;; + 1|2|69) + ocf_log debug "RabbitMQ server is not running" + return $OCF_NOT_RUNNING + ;; + *) + ocf_log err "Unexpected return from rabbitmqctl $NODENAME_ARG $action: $rc" + exit $OCF_ERR_GENERIC + esac +} + +rabbit_start() { + local rc + + if rabbit_status; then + ocf_log info "Resource already running." + return $OCF_SUCCESS + fi + + export_vars + + # RabbitMQ requires high soft and hard limits for NOFILE + set_limits + + setsid sh -c "$RABBITMQ_SERVER > ${RABBITMQ_LOG_BASE}/startup_log 2> ${RABBITMQ_LOG_BASE}/startup_err" & + + # Wait for the server to come up. + # Let the CRM/LRM time us out if required + rabbit_wait $RABBITMQ_PID_FILE + rc=$? + if [ "$rc" != $OCF_SUCCESS ]; then + remove_pid + ocf_log info "rabbitmq-server start failed: $rc" + exit $OCF_ERR_GENERIC + fi + + return $OCF_SUCCESS +} + +rabbit_stop() { + local rc + + if ! rabbit_status; then + ocf_log info "Resource not running." + return $OCF_SUCCESS + fi + + rabbitmqctl_action stop ${RABBITMQ_PID_FILE} + rc=$? + + if [ "$rc" != 0 ]; then + ocf_log err "rabbitmq-server stop command failed: $RABBITMQ_CTL stop, $rc" + return $rc + fi + + # Spin waiting for the server to shut down. + # Let the CRM/LRM time us out if required + stop_wait=1 + while [ $stop_wait = 1 ]; do + rabbit_status + rc=$? + if [ "$rc" = $OCF_NOT_RUNNING ]; then + remove_pid + stop_wait=0 + break + elif [ "$rc" != $OCF_SUCCESS ]; then + ocf_log info "rabbitmq-server stop failed: $rc" + exit $OCF_ERR_GENERIC + fi + sleep 1 + done + + return $OCF_SUCCESS +} + +rabbit_monitor() { + rabbit_status + return $? +} + +case $__OCF_ACTION in + meta-data) + meta_data + exit $OCF_SUCCESS + ;; + usage|help) + rabbit_usage + exit $OCF_SUCCESS + ;; +esac + +if ocf_is_probe; then + rabbit_validate_partial +else + rabbit_validate_full +fi + +case $__OCF_ACTION in + start) + rabbit_start + ;; + stop) + rabbit_stop + ;; + status|monitor) + rabbit_monitor + ;; + validate-all) + exit $OCF_SUCCESS + ;; + *) + rabbit_usage + exit $OCF_ERR_UNIMPLEMENTED + ;; +esac + +exit $? diff --git a/scripts/rabbitmq-service.bat b/scripts/rabbitmq-service.bat deleted file mode 100644 index 0b7906d4bf..0000000000 --- a/scripts/rabbitmq-service.bat +++ /dev/null @@ -1,271 +0,0 @@ -@echo off
-REM This Source Code Form is subject to the terms of the Mozilla Public
-REM License, v. 2.0. If a copy of the MPL was not distributed with this
-REM file, You can obtain one at https://mozilla.org/MPL/2.0/.
-REM
-REM Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved.
-REM
-
-setlocal
-
-rem Preserve values that might contain exclamation marks before
-rem enabling delayed expansion
-set TN0=%~n0
-set TDP0=%~dp0
-set CONF_SCRIPT_DIR=%~dp0
-set P1=%1
-setlocal enabledelayedexpansion
-setlocal enableextensions
-
-if ERRORLEVEL 1 (
- echo "Failed to enable command extensions!"
- exit /B 1
-)
-
-REM Get default settings with user overrides for (RABBITMQ_)<var_name>
-REM Non-empty defaults should be set in rabbitmq-env
-call "%TDP0%\rabbitmq-env.bat" %~n0
-
-REM Check for the short names here too
-if "!RABBITMQ_USE_LONGNAME!"=="true" (
- set RABBITMQ_NAME_TYPE=-name
- set NAMETYPE=longnames
-) else (
- if "!USE_LONGNAME!"=="true" (
- set RABBITMQ_USE_LONGNAME=true
- set RABBITMQ_NAME_TYPE=-name
- set NAMETYPE=longnames
- ) else (
- set RABBITMQ_USE_LONGNAME=false
- set RABBITMQ_NAME_TYPE=-sname
- set NAMETYPE=shortnames
- )
-)
-
-REM [ "x" = "x$RABBITMQ_NODENAME" ] && RABBITMQ_NODENAME=${NODENAME}
-if "!RABBITMQ_NODENAME!"=="" (
- if "!NODENAME!"=="" (
- REM We use Erlang to query the local hostname because
- REM !COMPUTERNAME! and Erlang may return different results.
- REM Start erl with -sname to make sure epmd is started.
- call "%ERLANG_HOME%\bin\erl.exe" -A0 -noinput -boot start_clean -sname rabbit-prelaunch-epmd -eval "init:stop()." >nul 2>&1
- for /f "delims=" %%F in ('call "%ERLANG_HOME%\bin\erl.exe" -A0 -noinput -boot start_clean -eval "net_kernel:start([list_to_atom(""rabbit-gethostname-"" ++ os:getpid()), %NAMETYPE%]), [_, H] = string:tokens(atom_to_list(node()), ""@""), io:format(""~s~n"", [H]), init:stop()."') do @set HOSTNAME=%%F
- set RABBITMQ_NODENAME=rabbit@!HOSTNAME!
- set HOSTNAME=
- ) else (
- set RABBITMQ_NODENAME=!NODENAME!
- )
-)
-set NAMETYPE=
-
-REM Set Erlang distribution port, based on the AMQP TCP port.
-REM
-REM We do this only for the Windows service because in this case, the node has
-REM to start with the distribution enabled on the command line. For all other
-REM cases, distribution is configured at runtime.
-if "!RABBITMQ_NODE_PORT!"=="" (
- if not "!NODE_PORT!"=="" (
- set RABBITMQ_NODE_PORT=!NODE_PORT!
- ) else (
- set RABBITMQ_NODE_PORT=5672
- )
-)
-
-if "!RABBITMQ_DIST_PORT!"=="" (
- if "!DIST_PORT!"=="" (
- if "!RABBITMQ_NODE_PORT!"=="" (
- set RABBITMQ_DIST_PORT=25672
- ) else (
- set /a RABBITMQ_DIST_PORT=20000+!RABBITMQ_NODE_PORT!
- )
- ) else (
- set RABBITMQ_DIST_PORT=!DIST_PORT!
- )
-)
-
-set RABBITMQ_DIST_ARG=-kernel inet_dist_listen_min !RABBITMQ_DIST_PORT! -kernel inet_dist_listen_max !RABBITMQ_DIST_PORT!
-
-set STARVAR=
-shift
-:loop1
-if "%1"=="" goto after_loop
- set STARVAR=%STARVAR% %1
- shift
-goto loop1
-:after_loop
-
-if "!ERLANG_SERVICE_MANAGER_PATH!"=="" (
- if not exist "!ERLANG_HOME!\bin\erl.exe" (
- echo.
- echo ******************************
- echo ERLANG_HOME not set correctly.
- echo ******************************
- echo.
- echo Please either set ERLANG_HOME to point to your Erlang installation or place the
- echo RabbitMQ server distribution in the Erlang lib folder.
- echo.
- exit /B
- )
- for /f "delims=" %%i in ('dir /ad/b "!ERLANG_HOME!"') do if exist "!ERLANG_HOME!\%%i\bin\erlsrv.exe" (
- set ERLANG_SERVICE_MANAGER_PATH=!ERLANG_HOME!\%%i\bin
- )
-)
-
-set CONSOLE_FLAG=
-set CONSOLE_LOG_VALID=
-for %%i in (new reuse) do if "%%i" == "!RABBITMQ_CONSOLE_LOG!" set CONSOLE_LOG_VALID=TRUE
-if "!CONSOLE_LOG_VALID!" == "TRUE" (
- set CONSOLE_FLAG=-debugtype !RABBITMQ_CONSOLE_LOG!
-)
-
-rem *** End of configuration ***
-
-if not exist "!ERLANG_SERVICE_MANAGER_PATH!\erlsrv.exe" (
- echo.
- echo **********************************************
- echo ERLANG_SERVICE_MANAGER_PATH not set correctly.
- echo **********************************************
- echo.
- echo "!ERLANG_SERVICE_MANAGER_PATH!\erlsrv.exe" not found
- echo Please set ERLANG_SERVICE_MANAGER_PATH to the folder containing "erlsrv.exe".
- echo.
- exit /B 1
-)
-
-if "!P1!" == "install" goto INSTALL_SERVICE
-for %%i in (start stop) do if "%%i" == "!P1!" goto START_STOP_SERVICE
-for %%i in (disable enable list remove) do if "%%i" == "!P1!" goto MODIFY_SERVICE
-
-echo.
-echo *********************
-echo Service control usage
-echo *********************
-echo.
-echo !TN0! help - Display this help
-echo !TN0! install - Install the !RABBITMQ_SERVICENAME! service
-echo !TN0! remove - Remove the !RABBITMQ_SERVICENAME! service
-echo.
-echo The following actions can also be accomplished by using
-echo Windows Services Management Console (services.msc):
-echo.
-echo !TN0! start - Start the !RABBITMQ_SERVICENAME! service
-echo !TN0! stop - Stop the !RABBITMQ_SERVICENAME! service
-echo !TN0! disable - Disable the !RABBITMQ_SERVICENAME! service
-echo !TN0! enable - Enable the !RABBITMQ_SERVICENAME! service
-echo.
-exit /B
-
-
-:INSTALL_SERVICE
-
-if not exist "!RABBITMQ_BASE!" (
- echo Creating base directory !RABBITMQ_BASE! & mkdir "!RABBITMQ_BASE!"
-)
-
-"!ERLANG_SERVICE_MANAGER_PATH!\erlsrv" list !RABBITMQ_SERVICENAME! 2>NUL 1>NUL
-if errorlevel 1 (
- "!ERLANG_SERVICE_MANAGER_PATH!\erlsrv" add !RABBITMQ_SERVICENAME! -internalservicename !RABBITMQ_SERVICENAME!
-) else (
- echo !RABBITMQ_SERVICENAME! service is already present - only updating service parameters
-)
-
-set RABBITMQ_DEFAULT_ALLOC_ARGS=+MBas ageffcbf +MHas ageffcbf +MBlmbcs 512 +MHlmbcs 512 +MMmcs 30
-
-set RABBITMQ_START_RABBIT=
-if "!RABBITMQ_NODE_ONLY!"=="" (
- set RABBITMQ_START_RABBIT=-s "!RABBITMQ_BOOT_MODULE!" boot
-)
-
-if "!RABBITMQ_SERVICE_RESTART!"=="" (
- set RABBITMQ_SERVICE_RESTART=restart
-)
-
-set ENV_OK=true
-CALL :check_not_empty "RABBITMQ_BOOT_MODULE" !RABBITMQ_BOOT_MODULE!
-CALL :check_not_empty "RABBITMQ_NAME_TYPE" !RABBITMQ_NAME_TYPE!
-CALL :check_not_empty "RABBITMQ_NODENAME" !RABBITMQ_NODENAME!
-
-if "!ENV_OK!"=="false" (
- EXIT /b 78
-)
-
-set ERLANG_SERVICE_ARGUMENTS= ^
-!RABBITMQ_START_RABBIT! ^
--boot "!SASL_BOOT_FILE!" ^
-+W w ^
-!RABBITMQ_DEFAULT_ALLOC_ARGS! ^
-!RABBITMQ_SERVER_ERL_ARGS! ^
-!RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS! ^
-!RABBITMQ_SERVER_START_ARGS! ^
-!RABBITMQ_DIST_ARG! ^
--lager crash_log false ^
--lager handlers "[]" ^
-!STARVAR!
-
-set ERLANG_SERVICE_ARGUMENTS=!ERLANG_SERVICE_ARGUMENTS:\=\\!
-set ERLANG_SERVICE_ARGUMENTS=!ERLANG_SERVICE_ARGUMENTS:"=\"!
-
-rem We resolve %APPDATA% at install time so that the user's %APPDATA%
-rem is passed to `rabbit_env` at runtime (instead of the service's
-rem %APPDAT%).
-rem
-rem The goal is to keep the same behavior as when RabbitMQ data
-rem locations were decided in `rabbitmq-env.bat` (sourced by this
-rem script), even if now, we compute everything in `rabbit_env` at
-rem runtime.
-rem
-rem We may revisit this in the future so that no data is stored in a
-rem user-specific directory.
-"!ERLANG_SERVICE_MANAGER_PATH!\erlsrv" set !RABBITMQ_SERVICENAME! ^
--onfail !RABBITMQ_SERVICE_RESTART! ^
--machine "!ERLANG_SERVICE_MANAGER_PATH!\erl.exe" ^
--env APPDATA="!APPDATA!" ^
--env ERL_LIBS="!ERL_LIBS!" ^
--env ERL_MAX_ETS_TABLES="!ERL_MAX_ETS_TABLES!" ^
--env ERL_MAX_PORTS="!ERL_MAX_PORTS!" ^
--workdir "!RABBITMQ_BASE!" ^
--stopaction "rabbit:stop_and_halt()." ^
-!RABBITMQ_NAME_TYPE! !RABBITMQ_NODENAME! ^
-!CONSOLE_FLAG! ^
--comment "Multi-protocol open source messaging broker" ^
--args "!ERLANG_SERVICE_ARGUMENTS!" > NUL
-
-if ERRORLEVEL 1 (
- EXIT /B 1
-)
-goto END
-
-
-:MODIFY_SERVICE
-
-"!ERLANG_SERVICE_MANAGER_PATH!\erlsrv" !P1! !RABBITMQ_SERVICENAME!
-if ERRORLEVEL 1 (
- EXIT /B 1
-)
-goto END
-
-
-:START_STOP_SERVICE
-
-REM start and stop via erlsrv reports no error message. Using net instead
-net !P1! !RABBITMQ_SERVICENAME!
-if ERRORLEVEL 1 (
- EXIT /B 1
-)
-goto END
-
-:END
-
-EXIT /B 0
-
-:check_not_empty
-if "%~2"=="" (
- ECHO "Error: ENV variable should be defined: %1. Please check rabbitmq-env, rabbitmq-default, and !RABBITMQ_CONF_ENV_FILE! script files. Check also your Environment Variables settings"
- set ENV_OK=false
- EXIT /B 78
- )
-EXIT /B 0
-
-endlocal
-endlocal
-endlocal
diff --git a/scripts/rabbitmq-streams b/scripts/rabbitmq-streams deleted file mode 100755 index 376cc497df..0000000000 --- a/scripts/rabbitmq-streams +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -## The contents of this file are subject to the Mozilla Public License -## Version 1.1 (the "License"); you may not use this file except in -## compliance with the License. You may obtain a copy of the License -## at https://www.mozilla.org/MPL/ -## -## Software distributed under the License is distributed on an "AS IS" -## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -## the License for the specific language governing rights and -## limitations under the License. -## -## The Original Code is RabbitMQ. -## -## The Initial Developer of the Original Code is GoPivotal, Inc. -## Copyright (c) 2007-2020 Pivotal Software, Inc. All rights reserved. -## - -# Exit immediately if a pipeline, which may consist of a single simple command, -# a list, or a compound command returns a non-zero status -set -e - -# Each variable or function that is created or modified is given the export -# attribute and marked for export to the environment of subsequent commands. -set -a - -# shellcheck source=/dev/null -# -# TODO: when shellcheck adds support for relative paths, change to -# shellcheck source=./rabbitmq-env -. "${0%/*}"/rabbitmq-env - -run_escript rabbitmqctl_escript "${ESCRIPT_DIR:?must be defined}"/rabbitmq-streams "$@" diff --git a/scripts/rabbitmq-streams.bat b/scripts/rabbitmq-streams.bat deleted file mode 100644 index 83572a8d62..0000000000 --- a/scripts/rabbitmq-streams.bat +++ /dev/null @@ -1,63 +0,0 @@ -@echo off
-REM The contents of this file are subject to the Mozilla Public License
-REM Version 1.1 (the "License"); you may not use this file except in
-REM compliance with the License. You may obtain a copy of the License
-REM at https://www.mozilla.org/MPL/
-REM
-REM Software distributed under the License is distributed on an "AS IS"
-REM basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-REM the License for the specific language governing rights and
-REM limitations under the License.
-REM
-REM The Original Code is RabbitMQ.
-REM
-REM The Initial Developer of the Original Code is GoPivotal, Inc.
-REM Copyright (c) 2007-2020 Pivotal Software, Inc. All rights reserved.
-REM
-
-REM Scopes the variables to the current batch file
-setlocal
-
-rem Preserve values that might contain exclamation marks before
-rem enabling delayed expansion
-set TDP0=%~dp0
-set STAR=%*
-setlocal enabledelayedexpansion
-
-REM Get default settings with user overrides for (RABBITMQ_)<var_name>
-REM Non-empty defaults should be set in rabbitmq-env
-call "%TDP0%\rabbitmq-env.bat" %~n0
-
-if not exist "!ERLANG_HOME!\bin\erl.exe" (
- echo.
- echo ******************************
- echo ERLANG_HOME not set correctly.
- echo ******************************
- echo.
- echo Please either set ERLANG_HOME to point to your Erlang installation or place the
- echo RabbitMQ server distribution in the Erlang lib folder.
- echo.
- exit /B 1
-)
-
-REM Disable erl_crash.dump by default for control scripts.
-if not defined ERL_CRASH_DUMP_SECONDS (
- set ERL_CRASH_DUMP_SECONDS=0
-)
-
-"!ERLANG_HOME!\bin\erl.exe" +B ^
--boot !CLEAN_BOOT_FILE! ^
--noinput -noshell -hidden -smp enable ^
-!RABBITMQ_CTL_ERL_ARGS! ^
--run escript start ^
--escript main rabbitmqctl_escript ^
--extra "%RABBITMQ_HOME%\escript\rabbitmq-streams" !STAR!
-
-if ERRORLEVEL 1 (
- exit /B %ERRORLEVEL%
-)
-
-EXIT /B 0
-
-endlocal
-endlocal
diff --git a/scripts/rabbitmq-upgrade b/scripts/rabbitmq-upgrade deleted file mode 100755 index 6d2bc3f948..0000000000 --- a/scripts/rabbitmq-upgrade +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -## This Source Code Form is subject to the terms of the Mozilla Public -## License, v. 2.0. If a copy of the MPL was not distributed with this -## file, You can obtain one at https://mozilla.org/MPL/2.0/. -## -## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. -## - -# Exit immediately if a pipeline, which may consist of a single simple command, -# a list, or a compound command returns a non-zero status -set -e - -# Each variable or function that is created or modified is given the export -# attribute and marked for export to the environment of subsequent commands. -set -a - -# shellcheck source=/dev/null -# -# TODO: when shellcheck adds support for relative paths, change to -# shellcheck source=./rabbitmq-env -. "${0%/*}"/rabbitmq-env - -run_escript rabbitmqctl_escript "${ESCRIPT_DIR:?must be defined}"/rabbitmq-upgrade "$@" diff --git a/scripts/rabbitmq-upgrade.bat b/scripts/rabbitmq-upgrade.bat deleted file mode 100644 index 70b0eeee62..0000000000 --- a/scripts/rabbitmq-upgrade.bat +++ /dev/null @@ -1,55 +0,0 @@ -@echo off -REM This Source Code Form is subject to the terms of the Mozilla Public -REM License, v. 2.0. If a copy of the MPL was not distributed with this -REM file, You can obtain one at https://mozilla.org/MPL/2.0/. -REM -REM Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. -REM - -REM Scopes the variables to the current batch file -setlocal - -rem Preserve values that might contain exclamation marks before -rem enabling delayed expansion -set TDP0=%~dp0 -set STAR=%* -setlocal enabledelayedexpansion - -REM Get default settings with user overrides for (RABBITMQ_)<var_name> -REM Non-empty defaults should be set in rabbitmq-env -call "%TDP0%\rabbitmq-env.bat" %~n0 - -if not exist "!ERLANG_HOME!\bin\erl.exe" ( - echo. - echo ****************************** - echo ERLANG_HOME not set correctly. - echo ****************************** - echo. - echo Please either set ERLANG_HOME to point to your Erlang installation or place the - echo RabbitMQ server distribution in the Erlang lib folder. - echo. - exit /B 1 -) - -REM Disable erl_crash.dump by default for control scripts. -if not defined ERL_CRASH_DUMP_SECONDS ( - set ERL_CRASH_DUMP_SECONDS=0 -) - -"!ERLANG_HOME!\bin\erl.exe" +B ^ --boot !CLEAN_BOOT_FILE! ^ --noinput -noshell -hidden -smp enable ^ -!RABBITMQ_CTL_ERL_ARGS! ^ --kernel inet_dist_listen_min !RABBITMQ_CTL_DIST_PORT_MIN! ^ --kernel inet_dist_listen_max !RABBITMQ_CTL_DIST_PORT_MAX! ^ --run escript start ^ --escript main rabbitmqctl_escript ^ --extra "%RABBITMQ_HOME%\escript\rabbitmq-upgrade" !STAR! - -if ERRORLEVEL 1 ( - exit /B %ERRORLEVEL% -) - -EXIT /B 0 - -endlocal diff --git a/scripts/rabbitmqctl b/scripts/rabbitmqctl deleted file mode 100755 index 8016dbe282..0000000000 --- a/scripts/rabbitmqctl +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -## This Source Code Form is subject to the terms of the Mozilla Public -## License, v. 2.0. If a copy of the MPL was not distributed with this -## file, You can obtain one at https://mozilla.org/MPL/2.0/. -## -## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. -## - -# Exit immediately if a pipeline, which may consist of a single simple command, -# a list, or a compound command returns a non-zero status -set -e - -# Each variable or function that is created or modified is given the export -# attribute and marked for export to the environment of subsequent commands. -set -a - -# shellcheck source=/dev/null -# -# TODO: when shellcheck adds support for relative paths, change to -# shellcheck source=./rabbitmq-env -. "${0%/*}"/rabbitmq-env - -run_escript rabbitmqctl_escript "${ESCRIPT_DIR:?must be defined}"/rabbitmqctl "$@" diff --git a/scripts/rabbitmqctl-autocomplete.sh b/scripts/rabbitmqctl-autocomplete.sh new file mode 100644 index 0000000000..36b724cc59 --- /dev/null +++ b/scripts/rabbitmqctl-autocomplete.sh @@ -0,0 +1,3 @@ +if [ -n "$BASH_VERSION" ]; then + . /usr/lib/rabbitmq/autocomplete/bash_autocomplete.sh +fi
\ No newline at end of file diff --git a/scripts/rabbitmqctl.bat b/scripts/rabbitmqctl.bat deleted file mode 100644 index 711ec6e990..0000000000 --- a/scripts/rabbitmqctl.bat +++ /dev/null @@ -1,56 +0,0 @@ -@echo off
-REM This Source Code Form is subject to the terms of the Mozilla Public
-REM License, v. 2.0. If a copy of the MPL was not distributed with this
-REM file, You can obtain one at https://mozilla.org/MPL/2.0/.
-REM
-REM Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved.
-REM
-
-REM Scopes the variables to the current batch file
-setlocal
-
-rem Preserve values that might contain exclamation marks before
-rem enabling delayed expansion
-set TDP0=%~dp0
-set STAR=%*
-setlocal enabledelayedexpansion
-
-REM Get default settings with user overrides for (RABBITMQ_)<var_name>
-REM Non-empty defaults should be set in rabbitmq-env
-call "%TDP0%\rabbitmq-env.bat" %~n0
-
-if not exist "!ERLANG_HOME!\bin\erl.exe" (
- echo.
- echo ******************************
- echo ERLANG_HOME not set correctly.
- echo ******************************
- echo.
- echo Please either set ERLANG_HOME to point to your Erlang installation or place the
- echo RabbitMQ server distribution in the Erlang lib folder.
- echo.
- exit /B 1
-)
-
-REM Disable erl_crash.dump by default for control scripts.
-if not defined ERL_CRASH_DUMP_SECONDS (
- set ERL_CRASH_DUMP_SECONDS=0
-)
-
-"!ERLANG_HOME!\bin\erl.exe" +B ^
--boot !CLEAN_BOOT_FILE! ^
--noinput -noshell -hidden -smp enable ^
-!RABBITMQ_CTL_ERL_ARGS! ^
--kernel inet_dist_listen_min !RABBITMQ_CTL_DIST_PORT_MIN! ^
--kernel inet_dist_listen_max !RABBITMQ_CTL_DIST_PORT_MAX! ^
--run escript start ^
--escript main rabbitmqctl_escript ^
--extra "%RABBITMQ_HOME%\escript\rabbitmqctl" !STAR!
-
-if ERRORLEVEL 1 (
- exit /B %ERRORLEVEL%
-)
-
-EXIT /B 0
-
-endlocal
-endlocal
diff --git a/scripts/zsh_autocomplete.sh b/scripts/zsh_autocomplete.sh new file mode 100644 index 0000000000..b027571379 --- /dev/null +++ b/scripts/zsh_autocomplete.sh @@ -0,0 +1,16 @@ +_rabbitmqctl_complete() { + if [ -x /usr/lib/rabbitmq/bin/rabbitmqctl ]; then + local word completions a + local LANG=en_US.UTF-8 + read -cl a + word="$1" + completions="$(export LANG=en_US.UTF-8; export LC_CTYPE=en_US.UTF-8; /usr/lib/rabbitmq/bin/rabbitmqctl --auto-complete ${=a})" + reply=( "${(ps:\n:)completions}" ) + fi +} + +compctl -f -K _rabbitmqctl_complete rabbitmqctl + +compctl -f -K _rabbitmqctl_complete rabbitmq-plugins + +compctl -f -K _rabbitmqctl_complete rabbitmq-diagnostics
\ No newline at end of file |