diff --git a/doc/Makefile.am b/doc/Makefile.am index f6437bf0d..3801a16e3 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,161 +1,162 @@ # # doc: Linux-HA resource agents # # Copyright (C) 2009 Florian Haas # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = $(doc_DATA) $(REFENTRY_STYLESHEET) \ mkappendix.sh ralist.sh CLEANFILES = $(man_MANS) $(xmlfiles) metadata-*.xml doc_DATA = README.webapps STYLESHEET_PREFIX ?= http://docbook.sourceforge.net/release/xsl/current MANPAGES_STYLESHEET ?= $(STYLESHEET_PREFIX)/manpages/docbook.xsl HTML_STYLESHEET ?= $(STYLESHEET_PREFIX)/xhtml/docbook.xsl FO_STYLESHEET ?= $(STYLESHEET_PREFIX)/fo/docbook.xsl REFENTRY_STYLESHEET ?= ra2refentry.xsl XSLTPROC_OPTIONS ?= --xinclude XSLTPROC_MANPAGES_OPTIONS ?= $(XSLTPROC_OPTIONS) XSLTPROC_HTML_OPTIONS ?= $(XSLTPROC_OPTIONS) XSLTPROC_FO_OPTIONS ?= $(XSLTPROC_OPTIONS) radir = $(top_srcdir)/heartbeat # OCF_ROOT=. is necessary due to a sanity check in ocf-shellfuncs # (which tests whether $OCF_ROOT points to a directory metadata-%.xml: $(radir)/% OCF_ROOT=. OCF_FUNCTIONS_DIR=$(radir) $< meta-data > $@ metadata-IPv6addr.xml: ../heartbeat/IPv6addr OCF_ROOT=. OCF_FUNCTIONS_DIR=$(radir) $< meta-data > $@ # Please note: we can't name the man pages # ocf:heartbeat:. Believe me, I've tried. It looks like it # works, but then it doesn't. While make can deal correctly with # colons in target names (when properly escaped), it royally messes up # when it is deals with _dependencies_ that contain colons. See Bug # 12126 on savannah.gnu.org. But, maybe it gets fixed soon, it was # first reported in 1995 and added to Savannah in in 2005... if BUILD_DOC man_MANS = ocf_heartbeat_AoEtarget.7 \ ocf_heartbeat_AudibleAlarm.7 \ ocf_heartbeat_ClusterMon.7 \ ocf_heartbeat_CTDB.7 \ ocf_heartbeat_Delay.7 \ ocf_heartbeat_Dummy.7 \ ocf_heartbeat_EvmsSCC.7 \ ocf_heartbeat_Evmsd.7 \ ocf_heartbeat_Filesystem.7 \ ocf_heartbeat_ICP.7 \ ocf_heartbeat_IPaddr.7 \ ocf_heartbeat_IPaddr2.7 \ ocf_heartbeat_IPsrcaddr.7 \ ocf_heartbeat_LVM.7 \ ocf_heartbeat_LinuxSCSI.7 \ ocf_heartbeat_MailTo.7 \ ocf_heartbeat_ManageRAID.7 \ ocf_heartbeat_ManageVE.7 \ ocf_heartbeat_Pure-FTPd.7 \ ocf_heartbeat_Raid1.7 \ ocf_heartbeat_Route.7 \ ocf_heartbeat_SAPDatabase.7 \ ocf_heartbeat_SAPInstance.7 \ ocf_heartbeat_SendArp.7 \ ocf_heartbeat_ServeRAID.7 \ ocf_heartbeat_SphinxSearchDaemon.7 \ ocf_heartbeat_Squid.7 \ ocf_heartbeat_Stateful.7 \ ocf_heartbeat_SysInfo.7 \ ocf_heartbeat_VIPArip.7 \ ocf_heartbeat_VirtualDomain.7 \ ocf_heartbeat_WAS.7 \ ocf_heartbeat_WAS6.7 \ ocf_heartbeat_WinPopup.7 \ ocf_heartbeat_Xen.7 \ ocf_heartbeat_Xinetd.7 \ ocf_heartbeat_anything.7 \ ocf_heartbeat_apache.7 \ + ocf_heartbeat_asterisk.7 \ ocf_heartbeat_conntrackd.7 \ ocf_heartbeat_db2.7 \ ocf_heartbeat_drbd.7 \ ocf_heartbeat_eDir88.7 \ ocf_heartbeat_ethmonitor.7 \ ocf_heartbeat_exportfs.7 \ ocf_heartbeat_fio.7 \ ocf_heartbeat_iSCSILogicalUnit.7 \ ocf_heartbeat_iSCSITarget.7 \ ocf_heartbeat_ids.7 \ ocf_heartbeat_iscsi.7 \ ocf_heartbeat_jboss.7 \ ocf_heartbeat_lxc.7 \ ocf_heartbeat_mysql.7 \ ocf_heartbeat_mysql-proxy.7 \ ocf_heartbeat_named.7 \ ocf_heartbeat_nfsserver.7 \ ocf_heartbeat_nginx.7 \ ocf_heartbeat_oracle.7 \ ocf_heartbeat_oralsnr.7 \ ocf_heartbeat_pgsql.7 \ ocf_heartbeat_pingd.7 \ ocf_heartbeat_portblock.7 \ ocf_heartbeat_postfix.7 \ ocf_heartbeat_proftpd.7 \ ocf_heartbeat_rsyncd.7 \ ocf_heartbeat_rsyslog.7 \ ocf_heartbeat_scsi2reservation.7 \ ocf_heartbeat_sfex.7 \ ocf_heartbeat_slapd.7 \ ocf_heartbeat_symlink.7 \ ocf_heartbeat_syslog-ng.7 \ ocf_heartbeat_tomcat.7 \ ocf_heartbeat_vmware.7 if USE_IPV6ADDR man_MANS += ocf_heartbeat_IPv6addr.7 endif xmlfiles = $(man_MANS:.7=.xml) %.1 %.5 %.7 %.8: %.xml $(XSLTPROC) \ $(XSLTPROC_MANPAGES_OPTIONS) \ $(MANPAGES_STYLESHEET) $< ocf_heartbeat_%.xml: metadata-%.xml $(srcdir)/$(REFENTRY_STYLESHEET) $(XSLTPROC) --novalid \ --stringparam package $(PACKAGE_NAME) \ --stringparam version $(VERSION) \ --output $@ \ $(srcdir)/$(REFENTRY_STYLESHEET) $< ocf_resource_agents.xml: $(xmlfiles) mkappendix.sh ./mkappendix.sh $(xmlfiles) > $@ %.html: %.xml $(XSLTPROC) \ $(XSLTPROC_HTML_OPTIONS) \ --output $@ \ $(HTML_STYLESHEET) $< xml: ocf_resource_agents.xml endif diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am index 9a91de51d..b32b241c1 100644 --- a/heartbeat/Makefile.am +++ b/heartbeat/Makefile.am @@ -1,126 +1,127 @@ # Makefile.am for OCF RAs # # Author: Sun Jing Dong # Copyright (C) 2004 IBM # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = $(ocf_SCRIPTS) $(ocfcommon_DATA) \ $(common_DATA) $(hb_DATA) $(dtd_DATA) \ README INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/linux-ha ocfdir = $(OCF_RA_DIR_PREFIX)/heartbeat dtddir = $(datadir)/$(PACKAGE_NAME) dtd_DATA = ra-api-1.dtd if USE_IPV6ADDR ocf_PROGRAMS = IPv6addr else ocf_PROGRAMS = endif IPv6addr_SOURCES = IPv6addr.c IPv6addr_LDADD = -lplumb $(LIBNETLIBS) ocf_SCRIPTS = ClusterMon \ CTDB \ Dummy \ IPaddr \ IPaddr2 \ drbd \ anything \ AoEtarget \ apache \ + asterisk \ nginx \ AudibleAlarm \ conntrackd \ db2 \ Delay \ eDir88 \ EvmsSCC \ Evmsd \ ethmonitor \ exportfs \ Filesystem \ fio \ ids \ iscsi \ ICP \ IPsrcaddr \ iSCSITarget \ iSCSILogicalUnit \ jboss \ LinuxSCSI \ LVM \ lxc \ MailTo \ ManageRAID \ ManageVE \ mysql \ mysql-proxy \ named \ nfsserver \ oracle \ oralsnr \ pingd \ portblock \ postfix \ pgsql \ proftpd \ Pure-FTPd \ Raid1 \ Route \ rsyncd \ rsyslog \ SAPDatabase \ SAPInstance \ SendArp \ ServeRAID \ slapd \ SphinxSearchDaemon \ Squid \ Stateful \ SysInfo \ scsi2reservation \ sfex \ symlink \ syslog-ng \ tomcat \ VIPArip \ VirtualDomain \ vmware \ WAS \ WAS6 \ WinPopup \ Xen \ Xinetd ocfcommondir = $(OCF_LIB_DIR_PREFIX)/heartbeat ocfcommon_DATA = ocf-shellfuncs \ ocf-binaries \ ocf-directories \ ocf-returncodes \ apache-conf.sh \ http-mon.sh # Legacy locations hbdir = $(sysconfdir)/ha.d hb_DATA = shellfuncs diff --git a/heartbeat/asterisk b/heartbeat/asterisk new file mode 100755 index 000000000..9b91c8b76 --- /dev/null +++ b/heartbeat/asterisk @@ -0,0 +1,485 @@ +#!/bin/sh +# +# +# Asterisk +# +# Description: Manages an Asterisk PBX as an HA resource +# +# Authors: Martin Gerhard Loschwitz +# Florian Haas +# +# Support: linux-ha@lists.linux-ha.org +# License: GNU General Public License (GPL) +# +# (c) 2011 hastexo Professional Services GmbH +# +# This resource agent is losely derived from the MySQL resource +# agent, which itself is made available to the public under the +# following copyright: +# +# (c) 2002-2005 International Business Machines, Inc. +# 2005-2010 Linux-HA contributors +# +# See usage() function below for more details ... +# +# OCF instance parameters: +# OCF_RESKEY_binary +# OCF_RESKEY_canary_binary +# OCF_RESKEY_config +# OCF_RESKEY_user +# OCF_RESKEY_group +# OCF_RESKEY_additional_parameters +# OCF_RESKEY_realtime +# OCF_RESKEY_maxfiles +####################################################################### +# Initialization: + +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} +. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs + +####################################################################### + +# Fill in some defaults if no values are specified +HOSTOS=`uname` +if [ "X${HOSTOS}" = "XOpenBSD" ]; then + OCF_RESKEY_user_default="_asterisk" + OCF_RESKEY_group_default="_asterisk" +else + OCF_RESKEY_user_default="asterisk" + OCF_RESKEY_group_default="asterisk" +fi +OCF_RESKEY_binary_default="asterisk" +OCF_RESKEY_canary_binary_default="astcanary" +OCF_RESKEY_config_default="/etc/asterisk/asterisk.conf" +OCF_RESKEY_additional_parameters_default="-g -vvv" +OCF_RESKEY_realtime_default="false" +OCF_RESKEY_maxfiles_default="8192" + +: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}} +: ${OCF_RESKEY_canary_binary=${OCF_RESKEY_canary_binary_default}} +: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}} +: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}} +: ${OCF_RESKEY_group=${OCF_RESKEY_group_default}} +: ${OCF_RESKEY_additional_parameters=${OCF_RESKEY_additional_parameters_default}} +: ${OCF_RESKEY_realtime=${OCF_RESKEY_realtime_default}} +: ${OCF_RESKEY_maxfiles=${OCF_RESKEY_maxfiles_default}} + +####################################################################### + +usage() { + cat < + + +1.0 + + +Resource agent for the Asterisk PBX. +May manage an Asterisk PBX telephony system or a clone set that +forms an Asterisk distributed device setup. + +Manages an Asterisk PBX + + + + +Location of the Asterisk PBX server binary + +Asterisk PBX server binary + + + + + +Location of the Asterisk PBX Canary server binary + +Asterisk PBX Canary server binary + + + + + +The Asterisk PBX configuration file + +Asterisk PBX config + + + + + +User running Asterisk PBX daemon + +Asterisk PBX user + + + + + +Group running Asterisk PBX daemon (for logfile and directory permissions) + +Asterisk PBX group + + + + + +Additional parameters which are passed to the Asterisk PBX on +startup (e.g. -L <load> or -M <value>). + +Additional parameters to pass to the Asterisk PBX + + + + + +Determines whether the Asterisk PBX daemon will be run with +realtime priority or not. + +Asterisk PBX realtime priority + + + + + +Determines how many files the Asterisk PBX is allowed to open at +a time. Helps to fix the 'Too many open files' error message. + +Asterisk PBX allowed MAXFILES + + + + + +A SIP URI to check when monitoring. During monitor, the agent will +attempt to do a SIP OPTIONS request against this URI. +Requires the sipsak utility to be present and executable. +If unset, the agent does no SIP URI monitoring. + +SIP URI to check when monitoring + + + + + + + + + + + + + + +END +} + +####################################################################### +# Convenience functions + +asterisk_rx() { + # if $HOME is set, asterisk -rx writes a .asterisk_history there + ( + unset HOME + ocf_run $OCF_RESKEY_binary -r -s $ASTRUNDIR/asterisk.ctl -x "$1" + ) +} + +####################################################################### +# Functions invoked by resource manager actions + +asterisk_validate() { + local rc + + check_binary $OCF_RESKEY_binary + check_binary pgrep + + if [ -n "$OCF_RESKEY_monitor_sipuri" ]; then + check_binary sipsak + fi + + if [ ! -f $OCF_RESKEY_config ]; then + ocf_log err "Config $OCF_RESKEY_config doesn't exist" + return $OCF_ERR_INSTALLED + fi + + getent passwd $OCF_RESKEY_user >/dev/null 2>&1 + rc=$? + if [ $rc -ne 0 ]; then + ocf_log err "User $OCF_RESKEY_user doesn't exist" + return $OCF_ERR_INSTALLED + fi + + getent group $OCF_RESKEY_group >/dev/null 2>&1 + rc=$? + if [ $rc -ne 0 ]; then + ocf_log err "Group $OCF_RESKEY_group doesn't exist" + return $OCF_ERR_INSTALLED + fi + + true +} + +asterisk_status() { + local pid + local rc + + if [ ! -f $ASTRUNDIR/asterisk.pid ]; then + ocf_log info "Asterisk PBX is not running" + return $OCF_NOT_RUNNING + fi + + pid=`cat $ASTRUNDIR/asterisk.pid` + ocf_run kill -s 0 $pid + rc=$? + + if [ $rc -eq 0 ]; then + if ocf_is_true "$OCF_RESKEY_realtime"; then + astcanary_pid=`pgrep -d " " -f "astcanary $ASTRUNDIR/alt.asterisk.canary.tweet.tweet.tweet"` + if [ ! "$astcanary_pid" ]; then + ocf_log err "Asterisk PBX is running but astcanary is not although it should" + return $OCF_ERR_GENERIC + fi + else + return $OCF_SUCCESS + fi + else + ocf_log info "Asterisk PBX not running: removing old PID file" + rm -f $ASTRUNDIR/asterisk.pid + return $OCF_NOT_RUNNING + fi +} + +asterisk_monitor() { + local rc + + asterisk_status + rc=$? + + # If status returned an error, return that immediately + if [ $rc -ne $OCF_SUCCESS ]; then + return $rc + fi + + # Check whether connecting to asterisk is possible + asterisk_rx 'core show channels count' + rc=$? + + if [ $rc -ne 0 ]; then + ocf_log err "Failed to connect to the Asterisk PBX" + return $OCF_ERR_GENERIC + fi + + # Optionally check the monitor URI with sipsak + # The return values: + # 0 means that a 200 was received. + # 1 means something else then 1xx or 2xx was received. + # 2 will be returned on local errors like non resolvable names + # or wrong options combination. + # 3 will be returned on remote errors like socket errors + # (e.g. icmp error), redirects without a contact header or + # simply no answer (timeout). + # This can also happen if sipsak is run too early after asterisk + # start. + if [ -n "$OCF_RESKEY_monitor_sipuri" ]; then + ocf_run sipsak -s "$OCF_RESKEY_monitor_sipuri" + rc=$? + case "$rc" in + 1|2) return $OCF_ERR_GENERIC;; + 3) return $OCF_NOT_RUNNING;; + esac + fi + + ocf_log debug "Asterisk PBX monitor succeeded" + return $OCF_SUCCESS +} + +asterisk_start() { + local asterisk_extra_params + local dir + local rc + + asterisk_status + rc=$? + if [ $rc -eq $OCF_SUCCESS ]; then + ocf_log info "Asterisk PBX already running" + return $OCF_SUCCESS + fi + + # If Asterisk is not already running, make sure there is no + # old astcanary instance when the new asterisk starts. To + # achieve this, kill old astcanary instances belonging to + # this $ASTRUNDIR. + + # Find out PIDs of running astcanaries + astcanary_pid=`pgrep -d " " -f "astcanary $ASTRUNDIR/alt.asterisk.canary.tweet.tweet.tweet"` + + # If there are astcanaries running that belong to $ASTRUNDIR, + # kill them. + if [ "$astcanary_pid" ]; then + for i in $astcanary_pid; do ocf_run kill -s KILL $astcanary_pid; done + fi + + for dir in $ASTRUNDIR $ASTLOGDIR $ASTLOGDIR/cdr-csv $ASTLOGDIR/cdr-custom; do + if [ ! -d "$dir" ]; then + ocf_run install -d -o $OCF_RESKEY_user -g $OCF_RESKEY_group $dir \ + || exit $OCF_ERR_GENERIC + fi + # Regardless of whether we just created the directory or it + # already existed, check whether it is writable by the configured + # user + if ! su -s /bin/sh - $OCF_RESKEY_user -c "test -w $dir"; then + ocf_log err "Directory $dir is not writable by $OCF_RESKEY_user" + exit $OCF_ERR_PERM + fi + done + + # set MAXFILES + ulimit -n $OCF_RESKEY_maxfiles + + # Determine whether Asterisk PBX is supposed to run in Realtime mode + # or not and make asterisk daemonize automatically + if ocf_is_true "$OCF_RESKEY_realtime"; then + asterisk_extra_params="-F -p" + else + asterisk_extra_params="-F" + fi + + ocf_run ${OCF_RESKEY_binary} -G $OCF_RESKEY_group -U $OCF_RESKEY_user \ + -C $OCF_RESKEY_config \ + $OCF_RESKEY_additional_parameters \ + $asterisk_extra_params + rc=$? + if [ $rc -ne 0 ]; then + ocf_log err "Asterisk PBX start command failed: $rc" + exit $OCF_ERR_GENERIC + fi + + # Spin waiting for the server to come up. + # Let the CRM/LRM time us out if required + while true; do + asterisk_monitor + rc=$? + [ $rc -eq $OCF_SUCCESS ] && break + if [ $rc -ne $OCF_NOT_RUNNING ]; then + ocf_log err "Asterisk PBX start failed" + exit $OCF_ERR_GENERIC + fi + sleep 2 + done + + ocf_log info "Asterisk PBX started" + return $OCF_SUCCESS +} + +asterisk_stop() { + local pid + local astcanary_pid + local rc + + asterisk_status + rc=$? + if [ $rc -eq $OCF_NOT_RUNNING ]; then + ocf_log info "Asterisk PBX already stopped" + return $OCF_SUCCESS + fi + + # do a "soft shutdown" via the asterisk command line first + asterisk_rx 'core stop now' + + asterisk_status + rc=$? + if [ $rc -eq $OCF_NOT_RUNNING ]; then + ocf_log info "Asterisk PBX stopped" + return $OCF_SUCCESS + fi + + # If "core stop now" didn't succeed, try SIGTERM + pid=`cat $ASTRUNDIR/asterisk.pid` + ocf_run kill -s TERM $pid + rc=$? + if [ $rc -ne 0 ]; then + ocf_log err "Asterisk PBX couldn't be stopped" + exit $OCF_ERR_GENERIC + fi + + # stop waiting + shutdown_timeout=15 + if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then + shutdown_timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000)-5)) + fi + count=0 + while [ $count -lt $shutdown_timeout ]; do + asterisk_status + rc=$? + if [ $rc -eq $OCF_NOT_RUNNING ]; then + break + fi + count=`expr $count + 1` + sleep 1 + ocf_log debug "Asterisk PBX still hasn't stopped yet. Waiting ..." + done + + asterisk_status + rc=$? + if [ $rc -ne $OCF_NOT_RUNNING ]; then + # SIGTERM didn't help either, try SIGKILL + ocf_log info "Asterisk PBX failed to stop after ${shutdown_timeout}s using SIGTERM. Trying SIGKILL ..." + ocf_run kill -s KILL $pid + fi + + # After killing asterisk, stop astcanary + if ocf_is_true "$OCF_RESKEY_realtime"; then + astcanary_pid=`pgrep -d " " -f "astcanary $ASTRUNDIR/alt.asterisk.canary.tweet.tweet.tweet"` + if [ "$astcanary_pid" ]; then + for i in $astcanary_pid; do ocf_run kill -s KILL $astcanary_pid; done + fi + fi + + ocf_log info "Asterisk PBX stopped" + return $OCF_SUCCESS +} + +####################################################################### + +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 +asterisk_validate || exit $? + +# Now that validate has passed and we can be sure to be able to read +# the config file, set convenience variables +ASTRUNDIR=`grep astrundir $OCF_RESKEY_config | awk '/^astrundir/ {print $3}'` +ASTLOGDIR=`grep astlogdir $OCF_RESKEY_config | awk '/^astlogdir/ {print $3}'` + +# What kind of method was invoked? +case "$1" in + start) asterisk_start;; + stop) asterisk_stop;; + status) asterisk_status;; + monitor) asterisk_monitor;; + validate-all) ;; + *) usage + exit $OCF_ERR_UNIMPLEMENTED;; +esac