diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am index a82c926a2..152e8dd50 100644 --- a/heartbeat/Makefile.am +++ b/heartbeat/Makefile.am @@ -1,149 +1,150 @@ # 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 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/linux-ha halibdir = $(libexecdir)/heartbeat ocfdir = $(OCF_RA_DIR_PREFIX)/heartbeat dtddir = $(datadir)/$(PACKAGE_NAME) dtd_DATA = ra-api-1.dtd if USE_IPV6ADDR_AGENT ocf_PROGRAMS = IPv6addr else ocf_PROGRAMS = endif if IPV6ADDR_COMPATIBLE halib_PROGRAMS = send_ua else halib_PROGRAMS = endif IPv6addr_SOURCES = IPv6addr.c IPv6addr_utils.c send_ua_SOURCES = send_ua.c IPv6addr_utils.c IPv6addr_LDADD = -lplumb $(LIBNETLIBS) send_ua_LDADD = $(LIBNETLIBS) ocf_SCRIPTS = ClusterMon \ CTDB \ Dummy \ IPaddr \ IPaddr2 \ anything \ AoEtarget \ apache \ asterisk \ nginx \ AudibleAlarm \ clvm \ conntrackd \ db2 \ dhcpd \ Delay \ + dnsupdate \ eDir88 \ EvmsSCC \ Evmsd \ ethmonitor \ exportfs \ Filesystem \ fio \ ids \ iscsi \ ICP \ IPsrcaddr \ iSCSITarget \ iSCSILogicalUnit \ iface-bridge \ iface-vlan \ jboss \ kamailio \ LinuxSCSI \ LVM \ lxc \ MailTo \ ManageRAID \ ManageVE \ mysql \ mysql-proxy \ named \ nfsserver \ oracle \ oralsnr \ pingd \ portblock \ postfix \ pound \ 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 \ varnish \ vmware \ WAS \ WAS6 \ WinPopup \ Xen \ Xinetd \ zabbixserver ocfcommondir = $(OCF_LIB_DIR_PREFIX)/heartbeat ocfcommon_DATA = ocf-shellfuncs \ ocf-binaries \ ocf-directories \ ocf-returncodes \ ocf-rarun \ apache-conf.sh \ http-mon.sh \ sapdb-nosha.sh \ sapdb.sh \ ora-common.sh \ findif.sh # Legacy locations hbdir = $(sysconfdir)/ha.d hb_DATA = shellfuncs diff --git a/heartbeat/dnsupdate b/heartbeat/dnsupdate new file mode 100755 index 000000000..50ed8ec7a --- /dev/null +++ b/heartbeat/dnsupdate @@ -0,0 +1,272 @@ +#!/bin/bash +# +# +# Support: linux-ha@lists.linux-ha.org +# License: GNU General Public License v2 +# +# Copyright (c) 2014 SUSE Linux Products GmbH, Lars Marowsky-Brée +# All Rights Reserved. +# +####################################################################### +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} +. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs +####################################################################### + +# TODO: +# - Should setting CNAMEs be supported? +# - Should multiple A records be supported? + +usage() { + cat <<-! + usage: $0 {start|stop|status|monitor|meta-data|validate-all} + ! +} + +meta_data() { + cat < + + +1.0 + + +This resource agent manages IP take-over via dynamic DNS updates. + +IP take-over via dynamic DNS update + + + + + +The hostname whose IP address will need to be updated. + +Hostname to update + + + + + +IP address to set. + +IP address to set + + + + + +Time to live, in seconds, for the DNS record. This +affects how soon DNS updates propagate. It should be +a reasonable compromise between update speed and DNS +server load. + +If using booth, the ticket timeout is a good start. + +TTL for the DNS record + + + + + +The file containing the shared secret needed to update +the DNS record. Please see the nsupdate man page for +the exact syntax. + +nsupdate key file + + + + + +Which DNS server to send these updates for. When no +server is provided, this defaults to the master server +for the correct zone. + +DNS server to contact + + + + + +Port number on the DNS server. + +Note: due to a limitation in the nsupdate command, this option will only +take effect if you also specify the DNS server! + +Port number on the DNS server + + + + + +Additional options to be passed to nsupdate. + +Additional nsupdate options + + + + + +Whether or not to actively remove records on stop. This is not needed +for normal operation, since the site taking over the IP address will +delete all previous records. + +Remove A record on stop + + + + + + + + + + + + + + +END +} + +dnsupdate_status() { + # The resource is considered active if the current IP + # address is returned as the only response. + local record=$(dig ${dig_opts} ${hostname}. A +short 2>/dev/null) + if [ "$record" = "$ip" ]; then + return $OCF_SUCCESS + fi + return $OCF_NOT_RUNNING +} + +dnsupdate_monitor() { + if ocf_is_probe ; then + # + return $OCF_NOT_RUNNING + fi + dnsupdate_status +} + +dnsupdate_start() { + if dnsupdate_status ; then + ocf_log info "$hostname already resolves to $ip" + return $OCF_SUCCESS + fi + + ocf_log info "Updating DNS records for $hostname" + + ( + if [ -n "$dns_server" ]; then + echo "server ${dns_server} ${dns_serverport}" + fi + echo "update delete $hostname A" + echo "update add $hostname ${OCF_RESKEY_ttl} A $ip" + echo "send" + ) | nsupdate ${nsupdate_opts} + + dnsupdate_monitor + + return $? +} + +dnsupdate_stop() { + if ocf_is_true "${OCF_RESKEY_unregister_on_stop}" && dnsupdate_status ; then + ocf_log info "Unregistering $hostname with $ip from DNS server" + ( + if [ -n "$dns_server" ]; then + echo "server ${dns_server} ${dns_serverport}" + fi + echo "update delete $hostname A $ip" + echo "send" + ) | nsupdate ${nsupdate_opts} + + dnsupdate_monitor + if [ $? -ne $OCF_NOT_RUNNING ]; then + ocf_log warn "Unregistering failed!" + # There's no point in invoking a stop failure + # here. If another site takes over the record, + # it'll delete all previous entries anyway. + fi + fi + return $OCF_SUCCESS +} + +dnsupdate_validate() { + hostname=${OCF_RESKEY_hostname} + ip=${OCF_RESKEY_ip} + dig_opts="" + dns_server=${OCF_RESKEY_server} + : ${OCF_RESKEY_serverport:="53"} + dns_serverport=${OCF_RESKEY_serverport} + : ${OCF_RESKEY_ttl:="300"} + nsupdate_opts=${OCF_RESKEY_opts} + + if [ -z "$hostname" ]; then + ocf_log err "No hostname specified." + exit $OCF_ERR_CONFIGURED + fi + if [ -z "$ip" ]; then + ocf_log err "No IP specified." + exit $OCF_ERR_CONFIGURED + fi + if ! ocf_is_decimal $OCF_RESKEY_ttl ; then + ocf_log err "ttl $OCF_RESKEY_ttl is not valid" + exit $OCF_ERR_CONFIGURED + fi + + if ! ocf_is_decimal $dns_serverport ; then + ocf_log err "serverport $dns_serverport is not valid" + exit $OCF_ERR_CONFIGURED + fi + dig_opts+=" -p ${dns_serverport}" + + if [ -n "$dns_server" ]; then + dig_opts+=" @${dns_server}" + fi + + if [ -n "$OCF_RESKEY_keyfile" ]; then + if [ ! -f ${OCF_RESKEY_keyfile} ]; then + ocf_log err "keyfile $OCF_RESKEY_keyfile does not exist" + exit $OCF_ERR_CONFIGURED + fi + nsupdate_opts+=" -k $OCF_RESKEY_keyfile" + fi +} + +if [ $# -ne 1 ]; then + usage + exit $OCF_ERR_ARGS +fi + +case $1 in +meta-data) meta_data + exit $OCF_SUCCESS + ;; +usage) usage + exit $OCF_SUCCESS + ;; +esac + +check_binary dig +check_binary nsupdate + +dnsupdate_validate + +case $1 in +start) dnsupdate_start + ;; +stop) dnsupdate_stop + ;; +monitor) dnsupdate_monitor + ;; +status) dnsupdate_status + ;; +validate-all) # We've already run this + exit $OCF_SUCCESS + ;; +*) usage + exit $OCF_ERR_UNIMPLEMENTED + ;; +esac +exit $? + +