diff options
Diffstat (limited to 'heartbeat/named')
-rwxr-xr-x | heartbeat/named | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/heartbeat/named b/heartbeat/named new file mode 100755 index 0000000..f3a17e9 --- /dev/null +++ b/heartbeat/named @@ -0,0 +1,514 @@ +#!/bin/sh +# +# Description: Manages a named (Bind) server as an OCF High-Availability +# resource +# +# Authors: Serge Dubrouski (sergeyfd@gmail.com) +# +# Copyright: 2011 Serge Dubrouski <sergeyfd@gmail.com> +# +# License: GNU General Public License (GPL) +# +############################################################################### +# Initialization: + +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} +. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs + +#Defaults +OCF_RESKEY_named_default="/usr/sbin/named" +OCF_RESKEY_rndc_default="/usr/sbin/rndc" +OCF_RESKEY_host_default="/usr/bin/host" +OCF_RESKEY_named_user_default=named +OCF_RESKEY_named_config_default="" +OCF_RESKEY_named_pidfile_default="/var/run/named/named.pid" +OCF_RESKEY_named_rootdir_default="" +OCF_RESKEY_named_options_default="" +OCF_RESKEY_named_keytab_file_default="" +OCF_RESKEY_rndc_options_default="" +OCF_RESKEY_host_options_default="" +OCF_RESKEY_monitor_request_default="localhost" +OCF_RESKEY_monitor_response_default="127.0.0.1" +OCF_RESKEY_monitor_ip_default="127.0.0.1" + +: ${OCF_RESKEY_named=${OCF_RESKEY_named_default}} +: ${OCF_RESKEY_rndc=${OCF_RESKEY_rndc_default}} +: ${OCF_RESKEY_host=${OCF_RESKEY_host_default}} +: ${OCF_RESKEY_named_user=${OCF_RESKEY_named_user_default}} +: ${OCF_RESKEY_named_config=${OCF_RESKEY_named_config_default}} +: ${OCF_RESKEY_named_pidfile=${OCF_RESKEY_named_pidfile_default}} +: ${OCF_RESKEY_named_rootdir=${OCF_RESKEY_named_rootdir_default}} +: ${OCF_RESKEY_named_options=${OCF_RESKEY_named_options_default}} +: ${OCF_RESKEY_named_keytab_file=${OCF_RESKEY_named_keytab_file_default}} +: ${OCF_RESKEY_rndc_options=${OCF_RESKEY_rndc_options_default}} +: ${OCF_RESKEY_host_options=${OCF_RESKEY_host_options_default}} +: ${OCF_RESKEY_monitor_request=${OCF_RESKEY_monitor_request_default}} +: ${OCF_RESKEY_monitor_response=${OCF_RESKEY_monitor_response_default}} +: ${OCF_RESKEY_monitor_ip=${OCF_RESKEY_monitor_ip_default}} + +usage() { + cat <<EOF + usage: $0 start|stop|reload|status|monitor|meta-data|validate-all|methods + + $0 manages named (Bind) server as an HA resource. + + The 'start' operation starts named server. + The 'stop' operation stops named server. + The 'reload' operation reload named configuration. + The 'status' operation reports whether named is up. + The 'monitor' operation reports whether named is running. + The 'validate-all' operation reports whether parameters are valid. + The 'methods' operation reports on the methods $0 supports. +EOF + return $OCF_ERR_ARGS +} + +named_meta_data() { + cat <<EOF +<?xml version="1.0"?> +<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> +<resource-agent name="named" version="1.0"> +<version>1.0</version> + +<longdesc lang="en"> +Resource script for named (Bind) server. It manages named as an HA resource. +</longdesc> +<shortdesc lang="en">Manages a named server</shortdesc> + +<parameters> +<parameter name="named" unique="0" required="0"> +<longdesc lang="en"> +Path to the named command. +</longdesc> +<shortdesc lang="en">named</shortdesc> +<content type="string" default="${OCF_RESKEY_named_default}" /> +</parameter> + +<parameter name="rndc" unique="0" required="0"> +<longdesc lang="en"> +Path to the rndc command. +</longdesc> +<shortdesc lang="en">rndc</shortdesc> +<content type="string" default="${OCF_RESKEY_rndc_default}" /> +</parameter> + +<parameter name="host" unique="0" required="0"> +<longdesc lang="en"> +Path to the host command. +</longdesc> +<shortdesc lang="en">host</shortdesc> +<content type="string" default="${OCF_RESKEY_host_default}" /> +</parameter> + +<parameter name="named_user" unique="0" required="0"> +<longdesc lang="en"> +User that should own named process. +</longdesc> +<shortdesc lang="en">named_user</shortdesc> +<content type="string" default="${OCF_RESKEY_named_user_default}" /> +</parameter> + +<parameter name="named_config" unique="1" required="0"> +<longdesc lang="en"> +Configuration file for named. +</longdesc> +<shortdesc lang="en">named_config</shortdesc> +<content type="string" default="${OCF_RESKEY_named_config_default}" /> +</parameter> + +<parameter name="named_pidfile" unique="1" required="0"> +<longdesc lang="en"> +PIDFILE file for named. +</longdesc> +<shortdesc lang="en">named_pidfile</shortdesc> +<content type="string" default="${OCF_RESKEY_named_pidfile_default}" /> +</parameter> + +<parameter name="named_rootdir" unique="1" required="0"> +<longdesc lang="en"> +Directory that named should use for chroot if any. +</longdesc> +<shortdesc lang="en">named_rootdir</shortdesc> +<content type="string" default="${OCF_RESKEY_named_rootdir_default}" /> +</parameter> + +<parameter name="named_options" unique="0" required="0"> +<longdesc lang="en"> +Options for named process if any. +</longdesc> +<shortdesc lang="en">named_options</shortdesc> +<content type="string" default="${OCF_RESKEY_named_options_default}" /> +</parameter> + +<parameter name="named_keytab_file" unique="0" required="0"> +<longdesc lang="en"> +named service keytab file (for GSS-TSIG). +</longdesc> +<shortdesc lang="en">named_keytab_file</shortdesc> +<content type="string" default="${OCF_RESKEY_named_keytab_file_default}" /> +</parameter> + +<parameter name="rndc_options" unique="0" required="0"> +<longdesc lang="en"> +Options for rndc process if any. +</longdesc> +<shortdesc lang="en">rndc_options</shortdesc> +<content type="string" default="${OCF_RESKEY_rndc_options_default}" /> +</parameter> + +<parameter name="host_options" unique="0" required="0"> +<longdesc lang="en"> +Options for host process if any. +</longdesc> +<shortdesc lang="en">host_options</shortdesc> +<content type="string" default="${OCF_RESKEY_host_options_default}" /> +</parameter> + +<parameter name="monitor_request" unique="0" required="0"> +<longdesc lang="en"> +Request that shall be sent to named for monitoring. Usually an A record in DNS. +</longdesc> +<shortdesc lang="en">monitor_request</shortdesc> +<content type="string" default="${OCF_RESKEY_monitor_request_default}" /> +</parameter> + +<parameter name="monitor_response" unique="0" required="0"> +<longdesc lang="en"> +Expected response from named server. +</longdesc> +<shortdesc lang="en">monitor_response</shortdesc> +<content type="string" default="${OCF_RESKEY_monitor_response_default}" /> +</parameter> + +<parameter name="monitor_ip" unique="0" required="0"> +<longdesc lang="en"> +IP Address where named listens. +</longdesc> +<shortdesc lang="en">monitor_ip</shortdesc> +<content type="string" default="${OCF_RESKEY_monitor_ip_default}" /> +</parameter> +</parameters> + +<actions> +<action name="start" timeout="60s" /> +<action name="stop" timeout="60s" /> +<action name="reload" timeout="60s" /> +<action name="status" timeout="10s" /> +<action name="monitor" depth="0" timeout="30s" interval="30s"/> +<action name="meta-data" timeout="5s" /> +<action name="validate-all" timeout="5s" /> +<action name="methods" timeout="5s" /> +</actions> +</resource-agent> + +EOF +} + +# +# methods: What methods/operations do we support? +# + +named_methods() { + cat <<EOF + start + stop + status + monitor + methods + meta-data + validate-all +EOF +} + +# Validate most critical parameters +named_validate_all() { + check_binary $OCF_RESKEY_named + check_binary $OCF_RESKEY_rndc + check_binary $OCF_RESKEY_host + + if [ -n "$OCF_RESKEY_named_config" -a \ + ! -r "${OCF_RESKEY_named_rootdir}/${OCF_RESKEY_named_config}" ]; then + if ocf_is_probe; then + ocf_log info "Configuration file ${OCF_RESKEY_named_rootdir}/${OCF_RESKEY_named_config} not readable during probe." + else + ocf_exit_reason "Configuration file ${OCF_RESKEY_named_rootdir}/${OCF_RESKEY_named_config} doesn't exist" + return $OCF_ERR_INSTALLED + fi + fi + + getent passwd $OCF_RESKEY_named_user >/dev/null 2>&1 + if [ ! $? -eq 0 ]; then + ocf_exit_reason "User $OCF_RESKEY_named_user doesn't exist"; + return $OCF_ERR_INSTALLED; + fi + + if [ -z "$OCF_RESKEY_monitor_request" -o \ + -z "$OCF_RESKEY_monitor_response" -o \ + -z "$OCF_RESKEY_monitor_ip" ]; then + ocf_exit_reason "None of monitor_request, monitor_response, and monitor_ip can be empty" + return $OCF_ERR_CONFIGURED + fi + + # make sure that the pidfile directory exists + ocf_mkstatedir $OCF_RESKEY_named_user 755 `dirname $OCF_RESKEY_named_pidfile` || return $OCF_ERR_INSTALLED + + return $OCF_SUCCESS +} + +## +# Attempt to generate a /etc/rndc.key if one is not present +## +rndc_key_generator() +{ + local rndc_options="-a -r /dev/urandom -u $OCF_RESKEY_named_user" + + if [ -s /etc/rndc.key ]; then + # file already exists + return + fi + + if ! have_binary "rndc-confgen"; then + # can't autogen key... Report this, but not as a warning or error. + # It is possible that the user configured the key in named.conf + ocf_log info "rndc-confgen tool not present, unable to autogen /etc/rndc.key." + return + fi + + if [ -n "$OCF_RESKEY_rootdir" ]; then + rndc_options="$rndc_options -t $OCF_RESKEY_rootdir" + fi + + rndc-confgen $rndc_options > /dev/null 2>&1; + if [ $? -eq 0 ]; then + if have_binary "restorecon"; then + restorecon /etc/rndc.key + fi + else + ocf_log info "failed to auto-generate /etc/rndc.key file." + fi +} + +# +# named_getpid. Get pid of named process with a given parameters. +# + +named_getpid () { + local pattern="$OCF_RESKEY_named" + + if [ -n "$OCF_RESKEY_named_rootdir" -a "x${OCF_RESKEY_named_rootdir}" != "x/" ]; then + pattern="$pattern.*-t $OCF_RESKEY_named_rootdir" + fi + + if [ -n "$OCF_RESKEY_named_config" ]; then + pattern="$pattern.*-c $OCF_RESKEY_named_config" + fi + + pid=`pgrep -f "$pattern"` + echo $pid +} + +# +# named_status. Simple check of the status of named process by pidfile. +# + +named_status () { + ocf_pidfile_status ${OCF_RESKEY_named_pidfile} >/dev/null 2>&1 +} + +# +# named_monitor. Send a request to named and check response. +# + +named_monitor() { + local output + + if ! named_status + then + ocf_log info "named is down" + return $OCF_NOT_RUNNING + fi + + output=`$OCF_RESKEY_host $OCF_RESKEY_host_options $OCF_RESKEY_monitor_request $OCF_RESKEY_monitor_ip` + + if [ $? -ne 0 ] || ! echo $output | grep -q '.* has .*address '"$OCF_RESKEY_monitor_response" + then + ocf_exit_reason "named didn't answer properly for $OCF_RESKEY_monitor_request." + ocf_log err "Expected: $OCF_RESKEY_monitor_response." + ocf_log err "Got: $output" + return $OCF_ERR_GENERIC + fi + + return $OCF_SUCCESS +} + +# +# Reload +# + +named_reload() { + $OCF_RESKEY_rndc $OCF_RESKEY_rndc_options reload >/dev/null || return $OCF_ERR_GENERIC + + return $OCF_SUCCESS +} + +# +# Start +# + +named_start() { + local root_dir_opt + local pid + + root_dir_opt="" + named_status && return $OCF_SUCCESS + + # Remove pidfile if exists + rm -f ${OCF_RESKEY_named_pidfile} + + if [ -n "${OCF_RESKEY_named_rootdir}" -a "x${OCF_RESKEY_named_rootdir}" != "x/" ] + then + root_dir_opt="-t ${OCF_RESKEY_named_rootdir}" + [ -s /etc/localtime ] && cp -fp /etc/localtime ${OCF_RESKEY_named_rootdir}/etc/localtime + fi + + if [ -n "$OCF_RESKEY_named_config" ]; then + OCF_RESKEY_named_options="-c $OCF_RESKEY_named_config $OCF_RESKEY_named_options" + fi + + rndc_key_generator + + if ! ${OCF_RESKEY_named} -u ${OCF_RESKEY_named_user} $root_dir_opt ${OCF_RESKEY_named_options} + then + ocf_exit_reason "named failed to start." + return $OCF_ERR_GENERIC + fi + + + pid=`named_getpid` + + if [ -n "$pid" ]; then + if [ ! -e ${OCF_RESKEY_named_pidfile} ]; then + echo $pid > ${OCF_RESKEY_named_pidfile} + fi + else + ocf_exit_reason "named failed to start. Probably error in configuration." + return $OCF_ERR_GENERIC + fi + + while : + do + named_monitor && break + sleep 1 + ocf_log debug "named hasn't started yet." + done + ocf_log info "named has started." + + return $OCF_SUCCESS +} + +# +# Stop +# + +named_stop () { + local timeout + local timewait + + named_status || return $OCF_SUCCESS + + $OCF_RESKEY_rndc $OCF_RESKEY_rndc_options stop >/dev/null + if [ $? -ne 0 ]; then + ocf_log info "rndc stop failed. Killing named." + kill `cat ${OCF_RESKEY_named_pidfile}` + fi + + if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then + # Allow 2/3 of the action timeout for the orderly shutdown + # (The origin unit is ms, hence the conversion) + timewait=$((OCF_RESKEY_CRM_meta_timeout/1500)) + else + timewait=20 + fi + + sleep 1; timeout=0 # Sleep here for 1 sec to let rndc finish. + while named_status ; do + if [ $timeout -ge $timewait ]; then + break + else + sleep 1 + timeout=`expr $timeout + 1` + ocf_log debug "named appears to hung, waiting ..." + fi + done + + #If still up + if named_status 2>&1; then + ocf_exit_reason "named is still up! Killing" + kill -9 `cat ${OCF_RESKEY_named_pidfile}` + fi + + rm -f ${OCF_RESKEY_named_pidfile} + return $OCF_SUCCESS +} + + +# Main part + +if [ $# -ne 1 ]; then + usage + exit $OCF_ERR_GENERIC +fi + +case "$1" in + methods) named_methods + exit $?;; + + meta-data) named_meta_data + exit $OCF_SUCCESS;; +esac + +named_validate_all +rc=$? + +[ "$1" = "validate-all" ] && exit $rc + +if [ $rc -ne 0 ] +then + case "$1" in + stop) exit $OCF_SUCCESS;; + monitor) exit $OCF_NOT_RUNNING;; + status) exit $OCF_NOT_RUNNING;; + *) exit $rc;; + esac +fi + +if [ `id -u` -ne 0 ]; then + ocf_exit_reason "$0 must be run as root" + exit $OCF_ERR_GENERIC +fi + +case "$1" in + status) if named_status + then + ocf_log info "named is up" + exit $OCF_SUCCESS + else + ocf_log info "named is down" + exit $OCF_NOT_RUNNING + fi;; + + monitor) named_monitor + exit $?;; + + start) named_start + exit $?;; + + stop) named_stop + exit $?;; + reload) named_reload + exit $?;; + *) + exit $OCF_ERR_UNIMPLEMENTED;; +esac + +# vim:ts=4:sw=4:et: |