#!/bin/sh # # Description: Manages a named (Bind) server as an OCF High-Availability # resource # # Authors: Serge Dubrouski (sergeyfd@gmail.com) # # Copyright: 2011 Serge Dubrouski # # 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 < 1.0 Resource script for named (Bind) server. It manages named as an HA resource. Manages a named server Path to the named command. named Path to the rndc command. rndc Path to the host command. host User that should own named process. named_user Configuration file for named. named_config PIDFILE file for named. named_pidfile Directory that named should use for chroot if any. named_rootdir Options for named process if any. named_options named service keytab file (for GSS-TSIG). named_keytab_file Options for rndc process if any. rndc_options Options for host process if any. host_options Request that shall be sent to named for monitoring. Usually an A record in DNS. monitor_request Expected response from named server. monitor_response IP Address where named listens. monitor_ip EOF } # # methods: What methods/operations do we support? # named_methods() { cat </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: