diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 07:52:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 07:52:36 +0000 |
commit | 7de03e4e519705301265c0415b3c0af85263a7ac (patch) | |
tree | 29d819c5227e3619d18a67d2a5dde963b3229dbe /heartbeat/CTDB.in | |
parent | Initial commit. (diff) | |
download | resource-agents-7de03e4e519705301265c0415b3c0af85263a7ac.tar.xz resource-agents-7de03e4e519705301265c0415b3c0af85263a7ac.zip |
Adding upstream version 1:4.13.0.upstream/1%4.13.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'heartbeat/CTDB.in')
-rwxr-xr-x | heartbeat/CTDB.in | 996 |
1 files changed, 996 insertions, 0 deletions
diff --git a/heartbeat/CTDB.in b/heartbeat/CTDB.in new file mode 100755 index 0000000..b4af66b --- /dev/null +++ b/heartbeat/CTDB.in @@ -0,0 +1,996 @@ +#!@BASH_SHELL@ +# +# OCF Resource Agent for managing CTDB +# +# Copyright (c) 2009-2010 Novell Inc., Tim Serong +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Further, this software is distributed without any warranty that it is +# free of the rightful claim of any third person regarding infringement +# or the like. Any license provided herein, whether implied or +# otherwise, applies only to this software file. Patent licenses, if +# any, provided herein do not apply to combinations of this program with +# other software, or any other product whatsoever. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# +# OVERVIEW +# +# When run by itself, CTDB can handle IP failover and includes scripts +# to manage various services (Samba, Winbind, HTTP, etc.). When run as +# a resource in a Pacemaker cluster, this additional functionality +# should not be used; instead one should define separate resources for +# CTDB, Samba, Winbind, IP addresses, etc. +# +# As of 2010-11-17, there is no separate OCF Samba or Winbind RA, so +# it is still possible to configure CTDB so that it manages these +# resources itself. In future, once Samba and Winbind RAs are +# available, this ability will be deprecated and ultimately removed. +# +# This RA intentionally provides no ability to configure CTDB such that +# it manages IP failover, HTTP, NFS, etc. +# +# +# TODO: +# - ctdb_stop doesn't really support multiple independent CTDB instances, +# unless they're running from distinct ctdbd binaries (it uses pkill +# $OCF_RESKEY_ctdbd_binary if "ctdb stop" doesn't work, which it might +# not under heavy load - this will kill all ctdbd instances on the +# system). OTOH, running multiple CTDB instances per node is, well, +# AFAIK, completely crazy. Can't run more than one in a vanilla CTDB +# cluster, with the CTDB init script. So it might be nice to address +# this for complete semantic correctness of the RA, but shouldn't +# actually cause any trouble in real life. +# - As much as possible, get rid of auto config generation +# - Especially smb.conf +# - Verify timeouts are sane +# - Monitor differentiate between error and not running? +# - Do we need to verify globally unique setting? +# - Should set CTDB_NODES to ${HA_RSCTMP}/ctdb (generated based on +# current nodes) +# - Look at enabling set_ctdb_variables() if necessary. +# - Probably possible for sysconfig file to not be restored if +# CTDB dies unexpectedly. +# +####################################################################### +# Initialization: + +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} +. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs + +####################################################################### +# Default parameter values: + +# Some distro's ctdb package stores the persistent db in /var/lib/ctdb, +# others store in /var/ctdb. This attempts to detect the correct default +# directory. +var_prefix="/var/lib/ctdb" +if [ ! -d "$var_prefix" ] && [ -d "/var/ctdb" ]; then + var_prefix="/var/ctdb" +fi + +run_prefix="/run" +if [ ! -d "$var_prefix" ] && [ -d "/var/run" ]; then + var_prefix="/var/run" +fi + +# Parameter defaults + +OCF_RESKEY_ctdb_recovery_lock_default="" +OCF_RESKEY_ctdb_manages_samba_default="no" +OCF_RESKEY_ctdb_manages_winbind_default="no" +OCF_RESKEY_ctdb_service_smb_default="" +OCF_RESKEY_ctdb_service_nmb_default="" +OCF_RESKEY_ctdb_service_winbind_default="" +OCF_RESKEY_ctdb_samba_skip_share_check_default="yes" +OCF_RESKEY_ctdb_monitor_free_memory_default="100" +OCF_RESKEY_ctdb_start_as_disabled_default="no" + +: ${OCF_RESKEY_ctdb_recovery_lock=${OCF_RESKEY_ctdb_recovery_lock_default}} +: ${OCF_RESKEY_ctdb_manages_samba=${OCF_RESKEY_ctdb_manages_samba_default}} +: ${OCF_RESKEY_ctdb_manages_winbind=${OCF_RESKEY_ctdb_manages_winbind_default}} +: ${OCF_RESKEY_ctdb_service_smb=${OCF_RESKEY_ctdb_service_smb_default}} +: ${OCF_RESKEY_ctdb_service_nmb=${OCF_RESKEY_ctdb_service_nmb_default}} +: ${OCF_RESKEY_ctdb_service_winbind=${OCF_RESKEY_ctdb_service_winbind_default}} +: ${OCF_RESKEY_ctdb_samba_skip_share_check=${OCF_RESKEY_ctdb_samba_skip_share_check_default}} +: ${OCF_RESKEY_ctdb_monitor_free_memory=${OCF_RESKEY_ctdb_monitor_free_memory_default}} +: ${OCF_RESKEY_ctdb_start_as_disabled=${OCF_RESKEY_ctdb_start_as_disabled_default}} + +OCF_RESKEY_ctdb_config_dir_default="/etc/ctdb" +OCF_RESKEY_ctdb_binary_default="/usr/bin/ctdb" +OCF_RESKEY_ctdbd_binary_default="/usr/sbin/ctdbd" +OCF_RESKEY_ctdb_dbdir_default="${var_prefix}" +OCF_RESKEY_ctdb_logfile_default="/var/log/ctdb/log.ctdb" +OCF_RESKEY_ctdb_rundir_default="${run_prefix}/ctdb" +OCF_RESKEY_ctdb_timeout_default="10" + +: ${OCF_RESKEY_ctdb_config_dir=${OCF_RESKEY_ctdb_config_dir_default}} +: ${OCF_RESKEY_ctdb_binary=${OCF_RESKEY_ctdb_binary_default}} +: ${OCF_RESKEY_ctdbd_binary=${OCF_RESKEY_ctdbd_binary_default}} +: ${OCF_RESKEY_ctdb_dbdir=${OCF_RESKEY_ctdb_dbdir_default}} +: ${OCF_RESKEY_ctdb_logfile=${OCF_RESKEY_ctdb_logfile_default}} +: ${OCF_RESKEY_ctdb_rundir=${OCF_RESKEY_ctdb_rundir_default}} +: ${OCF_RESKEY_ctdb_timeout=${OCF_RESKEY_ctdb_timeout_default}} + +OCF_RESKEY_ctdb_socket_default="${OCF_RESKEY_ctdb_rundir}/ctdbd.socket" +OCF_RESKEY_ctdb_debuglevel_default="2" +OCF_RESKEY_ctdb_max_open_files_default="" + +: ${OCF_RESKEY_ctdb_socket=${OCF_RESKEY_ctdb_socket_default}} +: ${OCF_RESKEY_ctdb_debuglevel=${OCF_RESKEY_ctdb_debuglevel_default}} +: ${OCF_RESKEY_ctdb_max_open_files=${OCF_RESKEY_ctdb_max_open_files_default}} + +OCF_RESKEY_smb_conf_default="/etc/samba/smb.conf" +OCF_RESKEY_smb_private_dir_default="" +OCF_RESKEY_smb_passdb_backend_default="tdbsam" +OCF_RESKEY_smb_idmap_backend_default="tdb2" +OCF_RESKEY_smb_fileid_algorithm_default="" + +: ${OCF_RESKEY_smb_conf=${OCF_RESKEY_smb_conf_default}} +: ${OCF_RESKEY_smb_private_dir=${OCF_RESKEY_smb_private_dir_default}} +: ${OCF_RESKEY_smb_passdb_backend=${OCF_RESKEY_smb_passdb_backend_default}} +: ${OCF_RESKEY_smb_idmap_backend=${OCF_RESKEY_smb_idmap_backend_default}} +: ${OCF_RESKEY_smb_fileid_algorithm=${OCF_RESKEY_smb_fileid_algorithm_default}} + +####################################################################### + +ctdb_version() { + $OCF_RESKEY_ctdb_binary version | awk '{print $NF}' | sed "s/[-\.]\?[[:alpha:]].*//" +} + +meta_data() { + cat <<END +<?xml version="1.0"?> +<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> +<resource-agent name="CTDB" version="1.0"> +<version>1.0</version> + +<longdesc lang="en"> +This resource agent manages CTDB, allowing one to use Clustered Samba in a +Linux-HA/Pacemaker cluster. You need a shared filesystem (e.g. OCFS2 or GFS2) on +which the CTDB lock will be stored. Create /etc/ctdb/nodes containing a list +of private IP addresses of each node in the cluster, then configure this RA +as a clone. This agent expects the samba and windbind resources +to be managed outside of CTDB's control as a separate set of resources controlled +by the cluster manager. The optional support for enabling CTDB management of these +daemons will be depreciated. + +For more information see http://linux-ha.org/wiki/CTDB_(resource_agent) +</longdesc> +<shortdesc lang="en">CTDB Resource Agent</shortdesc> + +<parameters> + +<parameter name="ctdb_recovery_lock" unique="1" required="1"> +<longdesc lang="en"> +The location of a shared lock file or helper binary, common across all nodes. +See CTDB documentation for details. +</longdesc> +<shortdesc lang="en">CTDB shared lock file</shortdesc> +<content type="string" default="${OCF_RESKEY_ctdb_recovery_lock_default}" /> +</parameter> + +<parameter name="ctdb_manages_samba" unique="0" required="0"> +<longdesc lang="en"> +Should CTDB manage starting/stopping the Samba service for you? +This will be deprecated in future, in favor of configuring a +separate Samba resource. +</longdesc> +<shortdesc lang="en">Should CTDB manage Samba?</shortdesc> +<content type="boolean" default="${OCF_RESKEY_ctdb_manages_samba_default}" /> +</parameter> + +<parameter name="ctdb_manages_winbind" unique="0" required="0"> +<longdesc lang="en"> +Should CTDB manage starting/stopping the Winbind service for you? +This will be deprecated in future, in favor of configuring a +separate Winbind resource. +</longdesc> +<shortdesc lang="en">Should CTDB manage Winbind?</shortdesc> +<content type="boolean" default="${OCF_RESKEY_ctdb_manages_winbind_default}" /> +</parameter> + +<parameter name="ctdb_service_smb" unique="0" required="0"> +<longdesc lang="en"> +Name of smb init script. Only necessary if CTDB is managing +Samba directly. Will usually be auto-detected. +</longdesc> +<shortdesc lang="en">Name of smb init script</shortdesc> +<content type="string" default="${OCF_RESKEY_ctdb_service_smb_default}" /> +</parameter> + +<parameter name="ctdb_service_nmb" unique="0" required="0"> +<longdesc lang="en"> +Name of nmb init script. Only necessary if CTDB is managing +Samba directly. Will usually be auto-detected. +</longdesc> +<shortdesc lang="en">Name of nmb init script</shortdesc> +<content type="string" default="${OCF_RESKEY_ctdb_service_nmb_default}" /> +</parameter> + +<parameter name="ctdb_service_winbind" unique="0" required="0"> +<longdesc lang="en"> +Name of winbind init script. Only necessary if CTDB is managing +Winbind directly. Will usually be auto-detected. +</longdesc> +<shortdesc lang="en">Name of winbind init script</shortdesc> +<content type="string" default="${OCF_RESKEY_ctdb_service_winbind_default}" /> +</parameter> + +<parameter name="ctdb_samba_skip_share_check" unique="0" required="0"> +<longdesc lang="en"> +If there are very many shares it may not be feasible to check that all +of them are available during each monitoring interval. In that case +this check can be disabled. +</longdesc> +<shortdesc lang="en">Skip share check during monitor?</shortdesc> +<content type="boolean" default="${OCF_RESKEY_ctdb_samba_skip_share_check_default}" /> +</parameter> + +<parameter name="ctdb_monitor_free_memory" unique="0" required="0"> +<longdesc lang="en"> +If the amount of free memory drops below this value the node will +become unhealthy and ctdb and all managed services will be shutdown. +Once this occurs, the administrator needs to find the reason for the +OOM situation, rectify it and restart ctdb with "service ctdb start". +With CTDB 4.4.0 and later this parameter is ignored. +</longdesc> +<shortdesc lang="en">Minimum amount of free memory (MB)</shortdesc> +<content type="integer" default="${OCF_RESKEY_ctdb_monitor_free_memory_default}" /> +</parameter> + +<parameter name="ctdb_start_as_disabled" unique="0" required="0"> +<longdesc lang="en"> +When set to yes, the CTDB node will start in DISABLED mode and not +host any public ip addresses. +</longdesc> +<shortdesc lang="en">Start CTDB disabled?</shortdesc> +<content type="boolean" default="${OCF_RESKEY_ctdb_start_as_disabled_default}" /> +</parameter> + +<parameter name="ctdb_config_dir" unique="0" required="0"> +<longdesc lang="en"> +The directory containing various CTDB configuration files. +The "nodes" and "notify.sh" scripts are expected to be +in this directory. +</longdesc> +<shortdesc lang="en">CTDB config file directory</shortdesc> +<content type="string" default="${OCF_RESKEY_ctdb_config_dir_default}" /> +</parameter> + +<parameter name="ctdb_binary" unique="0" required="0"> +<longdesc lang="en"> +Full path to the CTDB binary. +</longdesc> +<shortdesc lang="en">CTDB binary path</shortdesc> +<content type="string" default="${OCF_RESKEY_ctdb_binary_default}" /> +</parameter> + +<parameter name="ctdbd_binary" unique="0" required="0"> +<longdesc lang="en"> +Full path to the CTDB cluster daemon binary. +</longdesc> +<shortdesc lang="en">CTDB Daemon binary path</shortdesc> +<content type="string" default="${OCF_RESKEY_ctdbd_binary_default}" /> +</parameter> + +<parameter name="ctdb_socket" unique="1" required="0"> +<longdesc lang="en"> +Full path to the domain socket that ctdbd will create, used for +local clients to attach and communicate with the ctdb daemon. +With CTDB 4.9.0 and later the socket path is hardcoded at build +time, so this parameter is ignored. +</longdesc> +<shortdesc lang="en">CTDB socket location (ignored with CTDB 4.9+)</shortdesc> +<content type="string" default="${OCF_RESKEY_ctdb_socket_default}" /> +</parameter> + +<parameter name="ctdb_dbdir" unique="1" required="0"> +<longdesc lang="en"> +The directory to put the local CTDB database files in. +Persistent database files will be put in ctdb_dbdir/persistent. +</longdesc> +<shortdesc lang="en">CTDB database directory</shortdesc> +<content type="string" default="${OCF_RESKEY_ctdb_dbdir_default}" /> +</parameter> + +<parameter name="ctdb_logfile" unique="0" required="0"> +<longdesc lang="en"> +Full path to log file. To log to syslog instead, use the +value "syslog". +</longdesc> +<shortdesc lang="en">CTDB log file location</shortdesc> +<content type="string" default="${OCF_RESKEY_ctdb_logfile_default}" /> +</parameter> + +<parameter name="ctdb_rundir" unique="0" required="0"> +<longdesc lang="en"> +Full path to ctdb runtime directory, used for storage of socket +lock state. +</longdesc> +<shortdesc lang="en">CTDB runtime directory location</shortdesc> +<content type="string" default="${OCF_RESKEY_ctdb_rundir_default}" /> +</parameter> + +<parameter name="ctdb_timeout" unique="1" required="0"> +<longdesc lang="en"> +Indicates that ctdb should wait up to TIMEOUT seconds for a response to most commands sent to the CTDB daemon. +</longdesc> +<shortdesc lang="en">CTDB timeout in seconds</shortdesc> +<content type="integer" default="${OCF_RESKEY_ctdb_timeout_default}" /> +</parameter> + +<parameter name="ctdb_debuglevel" unique="0" required="0"> +<longdesc lang="en"> +What debug level to run at (0-10). Higher means more verbose. +</longdesc> +<shortdesc lang="en">CTDB debug level</shortdesc> +<content type="integer" default="${OCF_RESKEY_ctdb_debuglevel_default}" /> +</parameter> + +<parameter name="ctdb_max_open_files" required="0"> +<longdesc lang="en"> +Maximum number of open files (for ulimit -n) +</longdesc> +<shortdesc lang="en">Max open files</shortdesc> +<content type="integer" default="${OCF_RESKEY_ctdb_max_open_files_default}" /> +</parameter> + +<parameter name="smb_conf" unique="0" required="0"> +<longdesc lang="en"> +Path to default samba config file. Only necessary if CTDB +is managing Samba. +</longdesc> +<shortdesc lang="en">Path to smb.conf</shortdesc> +<content type="string" default="${OCF_RESKEY_smb_conf_default}" /> +</parameter> + +<parameter name="smb_private_dir" unique="1" required="0"> +<longdesc lang="en"> +The directory for smbd to use for storing such files as +smbpasswd and secrets.tdb. Old versions of CTBD (prior to 1.0.50) +required this to be on shared storage. This parameter should not +be set for current versions of CTDB, and only remains in the RA +for backwards compatibility. +</longdesc> +<shortdesc lang="en">Samba private dir (deprecated)</shortdesc> +<content type="string" default="${OCF_RESKEY_smb_private_dir_default}" /> +</parameter> + +<parameter name="smb_passdb_backend" unique="0" required="0"> +<longdesc lang="en"> +Which backend to use for storing user and possibly group +information. Only necessary if CTDB is managing Samba. +</longdesc> +<shortdesc lang="en">Samba passdb backend</shortdesc> +<content type="string" default="${OCF_RESKEY_smb_passdb_backend_default}" /> +</parameter> + +<parameter name="smb_idmap_backend" unique="0" required="0"> +<longdesc lang="en"> +Which backend to use for SID/uid/gid mapping. Only necessary +if CTDB is managing Samba. +</longdesc> +<shortdesc lang="en">Samba idmap backend</shortdesc> +<content type="string" default="${OCF_RESKEY_smb_idmap_backend_default}" /> +</parameter> + +<parameter name="smb_fileid_algorithm" unique="0" required="0"> +<longdesc lang="en"> +Which fileid:algorithm to use with vfs_fileid. The correct +value depends on which clustered filesystem is in use, e.g.: +for OCFS2, this should be set to "fsid". Only necessary if +CTDB is managing Samba. +</longdesc> +<shortdesc lang="en">Samba VFS fileid algorithm</shortdesc> +<content type="string" default="${OCF_RESKEY_smb_fileid_algorithm_default}" /> +</parameter> + +</parameters> + +<actions> +<action name="start" timeout="90s" /> +<action name="stop" timeout="100s" /> +<action name="monitor" timeout="20s" interval="10s" depth="0" /> +<action name="meta-data" timeout="5s" /> +<action name="validate-all" timeout="30s" /> +</actions> +</resource-agent> +END +} + +####################################################################### + +# Figure out path to /etc/sysconfig/ctdb (same logic as +# loadconfig() from /etc/ctdb/functions +if [ -f /etc/sysconfig/ctdb ]; then + CTDB_SYSCONFIG=/etc/sysconfig/ctdb +elif [ -f /etc/default/ctdb ]; then + CTDB_SYSCONFIG=/etc/default/ctdb +elif [ -f "$OCF_RESKEY_ctdb_config_dir/ctdb" ]; then + CTDB_SYSCONFIG=$OCF_RESKEY_ctdb_config_dir/ctdb +elif [ -f "$OCF_RESKEY_ctdb_config_dir/ctdbd.conf" ]; then + CTDB_SYSCONFIG=$OCF_RESKEY_ctdb_config_dir/ctdbd.conf +fi + +# Backup paths +CTDB_SYSCONFIG_BACKUP=${CTDB_SYSCONFIG}.ctdb-ra-orig + +invoke_ctdb() { + # CTDB's defaults are: + local timelimit + timelimit=120 + # ...but we override with the timeout for the current op: + if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then + timelimit=$((OCF_RESKEY_CRM_meta_timeout/1000)) + fi + + local vers=$(ctdb_version) + ocf_version_cmp "$vers" "4.9.0" + + # if version < 4.9.0 specify '--socket' otherwise it's + # a compiled option + if [ "$?" -eq "0" ]; then + $OCF_RESKEY_ctdb_binary --socket="$OCF_RESKEY_ctdb_socket" \ + -t ${OCF_RESKEY_ctdb_timeout} -T $timelimit \ + "$@" + else + $OCF_RESKEY_ctdb_binary \ + -t ${OCF_RESKEY_ctdb_timeout} -T $timelimit \ + "$@" + fi +} + +# Enable any event scripts that are explicitly required. +# Any others will ultimately be invoked or not based on how they ship +# with CTDB, but will generally have no effect, beacuase the relevant +# CTDB_MANAGES_* options won't be set in /etc/sysconfig/ctdb. +enable_event_scripts_chmod() { + local event_dir + event_dir=$OCF_RESKEY_ctdb_config_dir/events.d + + chmod u+x "$event_dir/00.ctdb" # core database health check + + if [ -f "${OCF_RESKEY_ctdb_config_dir}/public_addresses" ]; then + chmod u+x "$event_dir/10.interface" + else + chmod a-x "$event_dir/10.interface" + fi + if [ -f "${OCF_RESKEY_ctdb_config_dir}/static-routes" ]; then + chmod u+x "$event_dir/11.routing" + else + chmod a-x "$event_dir/11.routing" + fi + if ocf_is_true "$OCF_RESKEY_ctdb_manages_samba" || \ + ocf_is_true "$OCF_RESKEY_ctdb_manages_winbind"; then + chmod u+x "$event_dir/50.samba" + else + chmod a-x "$event_dir/50.samba" + fi +} + +enable_event_scripts_symlink() { + # event scripts are symlinked once enabled, with the link source in... + mkdir -p "$OCF_RESKEY_ctdb_config_dir/events/legacy" 2>/dev/null + + invoke_ctdb event script enable legacy 00.ctdb + + if [ -f "${OCF_RESKEY_ctdb_config_dir}/public_addresses" ]; then + invoke_ctdb event script enable legacy 10.interface + else + invoke_ctdb event script disable legacy 10.interface + fi + if [ -f "${OCF_RESKEY_ctdb_config_dir}/static-routes" ]; then + invoke_ctdb event script enable legacy 11.routing + else + invoke_ctdb event script disable legacy 11.routing + fi + + if ocf_is_true "$OCF_RESKEY_ctdb_manages_winbind"; then + invoke_ctdb event script enable legacy 49.winbind + else + invoke_ctdb event script disable legacy 49.winbind + fi + + if ocf_is_true "$OCF_RESKEY_ctdb_manages_samba"; then + invoke_ctdb event script enable legacy 50.samba + else + invoke_ctdb event script disable legacy 50.samba + fi +} + +# This function has no effect (currently no way to set CTDB_SET_*) +# but remains here in case we need it in future. +set_ctdb_variables() { + rv=$OCF_SUCCESS + set | grep ^CTDB_SET_ | cut -d_ -f3- | + while read v; do + varname=$(echo "$v" | cut -d= -f1) + value=$(echo "$v" | cut -d= -f2) + invoke_ctdb setvar "$varname" "$value" || rv=$OCF_ERR_GENERIC + done || rv=$OCF_ERR_GENERIC + return $rv +} + + +# Add necessary settings to /etc/samba/smb.conf. In a perfect world, +# we'd be able to generate a new, temporary, smb.conf file somewhere, +# something like: +# include = /etc/samba/smb.conf +# [global] +# clustering = yes +# # ...etc... +# Unfortunately, we can't do this, because there's no way to tell the +# smb init script where the temporary config is, so we just edit +# the default config file. +init_smb_conf() { + # Don't screw around with the config if CTDB isn't managing Samba! + ocf_is_true "$OCF_RESKEY_ctdb_manages_samba" || return 0 + + # replace these things in smb.conf + local repl + repl='# CTDB-RA:|passdb backend|clustering|idmap backend|idmap config[[:space:]]*\*[[:space:]]*:[[:space:]]*backend|private dir|ctdbd socket' + + local private_dir + [ -n "$OCF_RESKEY_smb_private_dir" ] && private_dir="\tprivate dir = $OCF_RESKEY_smb_private_dir\n" + + local vfs_fileid + local do_vfs + do_vfs=0 + if [ -n "$OCF_RESKEY_smb_fileid_algorithm" ]; then + repl="${repl}|fileid:algorithm|fileid:mapping" + vfs_fileid="\tfileid:algorithm = $OCF_RESKEY_smb_fileid_algorithm\n" + if sed -n '/^[[:space:]]*\[global\]/,/^[[:space:]]*\[/p' $OCF_RESKEY_smb_conf | \ + grep -Eq '^[[:space:]]*vfs objects'; then + # vfs objects already specified, will append fileid to existing line + do_vfs=1 + else + vfs_fileid="$vfs_fileid\tvfs objects = fileid\n" + fi + fi + # Preserve permissions of smb.conf + local idmap_config + if grep -Eqs '^[[:space:]]*idmap backend[[:space:]]*=' $OCF_RESKEY_smb_conf; then + idmap_config=old + else + idmap_config=new + fi + cp -a "$OCF_RESKEY_smb_conf" "$OCF_RESKEY_smb_conf.$$" + awk ' + /^[[:space:]]*\[/ { global = 0 } + /^[[:space:]]*\[global\]/ { global = 1 } + { + if(global) { + if ('$do_vfs' && $0 ~ /^[[:space:]]vfs objects/ && $0 !~ /fileid/) { + print $0" fileid" + } else if ($0 !~ /^[[:space:]]*('"$repl"')/) { + print + } + } else { + print + } + }' "$OCF_RESKEY_smb_conf" | sed "/^[[:space:]]*\[global\]/ a\\ +\t# CTDB-RA: Begin auto-generated section (do not change below)\n\ +\tpassdb backend = $OCF_RESKEY_smb_passdb_backend\n\ +\tclustering = yes\n\ +\tctdbd socket = $OCF_RESKEY_ctdb_socket\n$private_dir$vfs_fileid\ +\t# CTDB-RA: End auto-generated section (do not change above)" > "$OCF_RESKEY_smb_conf.$$" + if [ "$idmap_config" = "old" ]; then + sed -i "/^[[:space:]]*clustering = yes/ a\\ +\tidmap backend = $OCF_RESKEY_smb_idmap_backend" $OCF_RESKEY_smb_conf.$$ + else + sed -i "/^[[:space:]]*clustering = yes/ a\\ +\tidmap config * : backend = $OCF_RESKEY_smb_idmap_backend" $OCF_RESKEY_smb_conf.$$ + fi + dd conv=notrunc,fsync of="$OCF_RESKEY_smb_conf.$$" if=/dev/null >/dev/null 2>&1 + mv "$OCF_RESKEY_smb_conf.$$" "$OCF_RESKEY_smb_conf" +} + + +# Get rid of that section we added +cleanup_smb_conf() { + ocf_is_true "$OCF_RESKEY_ctdb_manages_samba" || return 0 + + # preserve permissions of smb.conf + cp -a "$OCF_RESKEY_smb_conf" "$OCF_RESKEY_smb_conf.$$" + sed '/# CTDB-RA: Begin/,/# CTDB-RA: End/d' "$OCF_RESKEY_smb_conf" > "$OCF_RESKEY_smb_conf.$$" + mv "$OCF_RESKEY_smb_conf.$$" "$OCF_RESKEY_smb_conf" +} + +append_conf() { + local file_path="$1" + shift + [ -n "$2" ] && echo "$1=$2" >> "$file_path" +} + +generate_ctdb_config() { + local ctdb_config="$OCF_RESKEY_ctdb_config_dir/ctdb.conf" + + # Backup existing config if we're not already using an auto-generated one + grep -qa '# CTDB-RA: Auto-generated' $ctdb_config || cp -p $ctdb_config ${ctdb_config}.ctdb-ra-orig + if [ $? -ne 0 ]; then + ocf_log warn "Unable to backup $ctdb_config to ${ctdb_config}.ctdb-ra-orig" + fi + + local log_option="file:$OCF_RESKEY_ctdb_logfile" + if [ "$OCF_RESKEY_ctdb_logfile" = "syslog" ]; then + log_option="syslog" + fi + + local start_as_disabled="false" + ocf_is_true "$OCF_RESKEY_ctdb_start_as_disabled" && start_as_disabled="true" + + local dbdir_volatile="$OCF_RESKEY_ctdb_dbdir/volatile" + [ -d "$dbdir_volatile" ] || mkdir -p "$dbdir_volatile" 2>/dev/null + local dbdir_persistent="$OCF_RESKEY_ctdb_dbdir/persistent" + [ -d "$dbdir_persistent" ] || mkdir -p "$dbdir_persistent" 2>/dev/null + local dbdir_state="$OCF_RESKEY_ctdb_dbdir/state" + [ -d "$dbdir_state" ] || mkdir -p "$dbdir_state" 2>/dev/null + +cat >$ctdb_config <<EOF +# CTDB-RA: Auto-generated +[logging] + location = $log_option + log level = $OCF_RESKEY_ctdb_debuglevel +[cluster] + recovery lock = $OCF_RESKEY_ctdb_recovery_lock +[database] + volatile database directory = $dbdir_volatile + persistent database directory = $dbdir_persistent + state database directory = $dbdir_state +[legacy] + start as disabled = $start_as_disabled +EOF +} + +generate_event_script_options() { + local script_options="$OCF_RESKEY_ctdb_config_dir/script.options" + + # Backup existing config if we're not already using an auto-generated one + grep -qa '# CTDB-RA: Auto-generated' $script_options || cp -p $script_options ${script_options}.ctdb-ra-orig + if [ $? -ne 0 ]; then + ocf_log warn "Unable to backup $script_options to ${script_options}.ctdb-ra-orig" + fi + +cat >$script_options <<EOF +# CTDB-RA: Auto-generated +CTDB_SAMBA_SKIP_SHARE_CHECK=$(ocf_is_true "$OCF_RESKEY_ctdb_samba_skip_share_check" && echo 'yes' || echo 'no') +EOF + + append_conf "$script_options" CTDB_SERVICE_SMB $OCF_RESKEY_ctdb_service_smb + append_conf "$script_options" CTDB_SERVICE_NMB $OCF_RESKEY_ctdb_service_nmb + append_conf "$script_options" CTDB_SERVICE_WINBIND $OCF_RESKEY_ctdb_service_winbind +} + +# Generate a new, minimal CTDB config file that's just enough +# to get CTDB running as configured by the RA parameters. +generate_ctdb_sysconfig() { + # Backup existing sysconfig if we're not already using an auto-generated one + grep -qa '# CTDB-RA: Auto-generated' $CTDB_SYSCONFIG || cp -p $CTDB_SYSCONFIG $CTDB_SYSCONFIG_BACKUP + if [ $? -ne 0 ]; then + ocf_log warn "Unable to backup $CTDB_SYSCONFIG to $CTDB_SYSCONFIG_BACKUP" + fi + + ocf_log info "Generating new $CTDB_SYSCONFIG" + + # Note to maintainers and other random hackers: + # Parameters may need to be set here, for CTDB event + # scripts to pick up, or may need to be passed to ctdbd + # when starting, or both. Be careful. The CTDB source + # tree and manpages are your friends. As a concrete + # example, setting CTDB_START_AS_DISABLED here is + # completely useless, as this is actually a command line + # argument for ctdbd; it's not used anywhere else. + + cat >$CTDB_SYSCONFIG <<EOF +# CTDB-RA: Auto-generated by ${0}, backup is at $CTDB_SYSCONFIG_BACKUP +CTDB_MONITOR_FREE_MEMORY=$OCF_RESKEY_ctdb_monitor_free_memory +CTDB_SAMBA_SKIP_SHARE_CHECK=$(ocf_is_true "$OCF_RESKEY_ctdb_samba_skip_share_check" && echo 'yes' || echo 'no') +CTDB_MANAGES_SAMBA=$(ocf_is_true "$OCF_RESKEY_ctdb_manages_samba" && echo 'yes' || echo 'no') +CTDB_MANAGES_WINBIND=$(ocf_is_true "$OCF_RESKEY_ctdb_manages_winbind" && echo 'yes' || echo 'no') +EOF + append_conf "$CTDB_SYSCONFIG" CTDB_SERVICE_SMB $OCF_RESKEY_ctdb_service_smb + append_conf "$CTDB_SYSCONFIG" CTDB_SERVICE_NMB $OCF_RESKEY_ctdb_service_nmb + append_conf "$CTDB_SYSCONFIG" CTDB_SERVICE_WINBIND $OCF_RESKEY_ctdb_service_winbind +} + + +invoke_ctdbd() { + local vers="$1" + + ocf_move_to_root_cgroup_if_rt_enabled + + ocf_version_cmp "$vers" "4.9.0" + if [ "$?" -ne "0" ]; then + # With 4.9+, all ctdbd binary parameters are provided as + # config settings + $OCF_RESKEY_ctdbd_binary + return + fi + + # Use logfile by default, or syslog if asked for + local log_option + # --logging supported from v4.3.0 and --logfile / --syslog support + # has been removed from newer versions + ocf_version_cmp "$vers" "4.2.14" + if [ "$?" -eq "2" ]; then + log_option="--logging=file:$OCF_RESKEY_ctdb_logfile" + if [ "$OCF_RESKEY_ctdb_logfile" = "syslog" ]; then + log_option="--logging=syslog" + fi + else + log_option="--logfile=$OCF_RESKEY_ctdb_logfile" + if [ "$OCF_RESKEY_ctdb_logfile" = "syslog" ]; then + log_option="--syslog" + fi + fi + + # public addresses file (should not be present, but need to set for correctness if it is) + local pub_addr_option + pub_addr_option="" + [ -f "${OCF_RESKEY_ctdb_config_dir}/public_addresses" ] && \ + pub_addr_option="--public-addresses=${OCF_RESKEY_ctdb_config_dir}/public_addresses" + # start as disabled + local start_as_disabled + start_as_disabled="--start-as-disabled" + ocf_is_true "$OCF_RESKEY_ctdb_start_as_disabled" || start_as_disabled="" + + $OCF_RESKEY_ctdbd_binary \ + --reclock="$OCF_RESKEY_ctdb_recovery_lock" \ + --nlist="$OCF_RESKEY_ctdb_config_dir/nodes" \ + --socket="$OCF_RESKEY_ctdb_socket" \ + --dbdir="$OCF_RESKEY_ctdb_dbdir" \ + --dbdir-persistent="$OCF_RESKEY_ctdb_dbdir/persistent" \ + --event-script-dir="$OCF_RESKEY_ctdb_config_dir/events.d" \ + --notification-script="$OCF_RESKEY_ctdb_config_dir/notify.sh" \ + --transport=tcp \ + $start_as_disabled $log_option $pub_addr_option \ + -d "$OCF_RESKEY_ctdb_debuglevel" +} + + +ctdb_usage() { + cat <<END +usage: $0 {start|stop|monitor|validate-all|meta-data} + +Expects to have a fully populated OCF RA-compliant environment set. +END +} + + +ctdb_start() { + # Do nothing if already running + ctdb_monitor && return $OCF_SUCCESS + + # Make sure config is adequate + ctdb_validate + rv=$? + [ $rv -ne 0 ] && return $rv + + # Add necessary configuration to smb.conf + init_smb_conf + if [ $? -ne 0 ]; then + ocf_exit_reason "Failed to update $OCF_RESKEY_smb_conf." + return $OCF_ERR_GENERIC + fi + + local version=$(ctdb_version) + + ocf_version_cmp "$version" "4.9.0" + if [ "$?" -eq "0" ]; then + # prior to 4.9, ctdbd parameters are in sysconfig or passed as + # binary arguments + generate_ctdb_sysconfig + + # prior to 4.9, event script enablement without a running + # ctdbd is done by chmoding the scripts directly + enable_event_scripts_chmod + else + # 4.9+ moves all ctdbd parameters to ctdb.conf + generate_ctdb_config + + # 4.9+ event script options are in script.options + generate_event_script_options + + # 4.9+ event scripts can be enabled with ctdb directly, which + # performs a symlink + enable_event_scripts_symlink + fi + + if [ ! -d "$(dirname $OCF_RESKEY_ctdb_logfile)" ]; then + # ensure the logfile's directory exists, otherwise ctdb will fail to start + mkdir -p $(dirname $OCF_RESKEY_ctdb_logfile) + fi + + # ensure ctdb's rundir exists, otherwise it will fail to start + mkdir -p $OCF_RESKEY_ctdb_rundir 2>/dev/null + + # set nofile ulimit for ctdbd process + if [ -n "$OCF_RESKEY_ctdb_max_open_files" ]; then + ulimit -n "$OCF_RESKEY_ctdb_max_open_files" + fi + + # Start her up + invoke_ctdbd "$version" + + if [ $? -ne 0 ]; then + # cleanup smb.conf + cleanup_smb_conf + + ocf_exit_reason "Failed to execute $OCF_RESKEY_ctdbd_binary." + return $OCF_ERR_GENERIC + else + # Wait a bit for CTDB to stabilize + # (until start times out if necessary) + while true; do + # Initial sleep is intentional (ctdb init script + # has sleep after ctdbd start, but before invoking + # ctdb to talk to it) + sleep 1 + status=$(invoke_ctdb status 2>/dev/null) + if [ $? -ne 0 ]; then + # CTDB will be running, kill it before returning + ctdb_stop + ocf_exit_reason "Can't invoke $OCF_RESKEY_ctdb_binary status" + return $OCF_ERR_GENERIC + fi + if ! echo "$status" | grep -qs 'UNHEALTHY (THIS'; then + # Status does not say this node is unhealthy, + # so we're good to go. Do a bit of final + # setup and (hopefully) return success. + set_ctdb_variables + return $? + fi + done + fi + + # ctdbd will (or can) actually still be running at this point, so kill it + ctdb_stop + + ocf_exit_reason "Timeout waiting for CTDB to stabilize" + return $OCF_ERR_GENERIC +} + + +ctdb_stop() { + # Do nothing if already stopped + pkill -0 -f "$OCF_RESKEY_ctdbd_binary" || return $OCF_SUCCESS + + # Tell it to die nicely + invoke_ctdb shutdown >/dev/null 2>&1 + rv=$? + + # No more Mr. Nice Guy + count=0 + while pkill -0 -f "$OCF_RESKEY_ctdbd_binary" ; do + sleep 1 + count=$((count + 1)) + [ $count -gt 10 ] && { + ocf_log info "killing ctdbd " + pkill -9 -f "$OCF_RESKEY_ctdbd_binary" + pkill -9 -f "${OCF_RESKEY_ctdb_config_dir}/events" + } + done + + # Cleanup smb.conf + cleanup_smb_conf + + # It was a clean shutdown, return success + [ $rv -eq $OCF_SUCCESS ] && return $OCF_SUCCESS + + # Unclean shutdown, return success if there's no ctdbds left (we + # killed them forcibly, but at least they're good and dead). + pkill -0 -f "$OCF_RESKEY_ctdbd_binary" || return $OCF_SUCCESS + + # Problem: ctdb shutdown didn't work and neither did some vigorous + # kill -9ing. Only thing to do is report failure. + return $OCF_ERR_GENERIC +} + + +ctdb_monitor() { + local status + # "ctdb status" exits non-zero if CTDB isn't running. + # It can also exit non-zero if there's a timeout (ctdbd blocked, + # stalled, massive load, or otherwise wedged). If it's actually + # not running, STDERR will say "Errno:Connection refused(111)", + # whereas if it's wedged, it'll say various other unpleasant things. + status=$(invoke_ctdb status 2>&1) + if [ $? -ne 0 ]; then + if echo "$status" | grep -qs 'Connection refused'; then + return $OCF_NOT_RUNNING + elif echo "$status" | grep -qs 'No such file or directory'; then + return $OCF_NOT_RUNNING + elif echo $status | grep -qs 'connect() failed'; then + return $OCF_NOT_RUNNING + else + ocf_exit_reason "CTDB status call failed: $status" + return $OCF_ERR_GENERIC + fi + fi + if echo "$status" | grep -Eqs '(OK|DISABLED) \(THIS'; then + return $OCF_SUCCESS + fi + + ocf_exit_reason "CTDB status is bad: $status" + return $OCF_ERR_GENERIC +} + + +ctdb_validate() { + # Required binaries + for binary in pkill; do + check_binary $binary + done + + if ocf_is_true "$OCF_RESKEY_ctdb_manages_samba" && [ ! -f "$OCF_RESKEY_smb_conf" ]; then + ocf_exit_reason "Samba config file '$OCF_RESKEY_smb_conf' does not exist." + return $OCF_ERR_INSTALLED + fi + + if [ -f "${OCF_RESKEY_ctdb_config_dir}/public_addresses" ]; then + ocf_log info "CTDB file '${OCF_RESKEY_ctdb_config_dir}/public_addresses' exists - CTDB will try to manage IP failover!" + fi + + if [ ! -f "$OCF_RESKEY_ctdb_config_dir/nodes" ]; then + ocf_exit_reason "$OCF_RESKEY_ctdb_config_dir/nodes does not exist." + return $OCF_ERR_ARGS + fi + + if [ -z "$OCF_RESKEY_ctdb_recovery_lock" ]; then + ocf_exit_reason "ctdb_recovery_lock not specified." + return $OCF_ERR_CONFIGURED + fi + + if [ "${OCF_RESKEY_ctdb_recovery_lock:0:1}" == '!' ]; then + # '!' prefix means recovery lock is handled via a helper binary + binary="${OCF_RESKEY_ctdb_recovery_lock:1}" + binary="${binary%% *}" # trim any parameters + if [ -z "$binary" ]; then + ocf_exit_reason "ctdb_recovery_lock invalid helper" + return $OCF_ERR_CONFIGURED + fi + check_binary "${binary}" + else + lock_dir=$(dirname "$OCF_RESKEY_ctdb_recovery_lock") + touch "$lock_dir/$$" 2>/dev/null + if [ $? != 0 ]; then + ocf_exit_reason "Directory for lock file '$OCF_RESKEY_ctdb_recovery_lock' does not exist, or is not writable." + return $OCF_ERR_ARGS + fi + rm "$lock_dir/$$" + fi + + return $OCF_SUCCESS +} + + +case $__OCF_ACTION in +meta-data) meta_data + exit $OCF_SUCCESS + ;; +start) ctdb_start;; +stop) ctdb_stop;; +monitor) ctdb_monitor;; +validate-all) ctdb_validate;; +usage|help) ctdb_usage + exit $OCF_SUCCESS + ;; +*) ctdb_usage + exit $OCF_ERR_UNIMPLEMENTED + ;; +esac +rc=$? +ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc" +exit $rc |