#!/bin/bash
#
# Resource script for dnsmasq daemon with namespace support
#
# Description:  Manages dnsmasq daemon as an OCF resource in
#               an High Availability setup inside a namespace
#
# dnsmasq OCF script's Author: Mirantis
# License: GNU General Public License (GPL)
#
#  usage: $0 {start|stop|restart|status|monitor|validate-all|meta-data}
#
#  The "start" arg starts dnsmasq.
#
#  The "stop" arg stops it.
#
# OCF parameters:
# OCF_RESKEY_ns
# OCF_RESKEY_conffile
# OCF_RESKEY_pidfile
# OCF_RESKEY_binpath
# OCF_RESKEY_extraconf
#
# Note: This RA requires that the dnsmasq config files has a "pidfile"
# entry so that it is able to act on the correct process
##########################################################################
# Initialization:

OCF_ROOT_default="/usr/lib/ocf"

OCF_RESKEY_ns_default="haproxy"
OCF_RESKEY_conffile_default="/etc/dnsmasq.d/dns.conf"
OCF_RESKEY_pidfile_default="/var/run/dnsmasq.pid"
OCF_RESKEY_binpath_default="/usr/sbin/dnsmasq"
OCF_RESKEY_extraconf_default=""

: ${OCF_ROOT=${OCF_ROOT_default}}
: ${HA_LOGTAG="ocf-ns_dns"}
: ${HA_LOGFACILITY="daemon"}

: ${OCF_RESKEY_ns=${OCF_RESKEY_ns_default}}
: ${OCF_RESKEY_conffile=${OCF_RESKEY_conffile_default}}
: ${OCF_RESKEY_pidfile=${OCF_RESKEY_pidfile_default}}
: ${OCF_RESKEY_binpath=${OCF_RESKEY_binpath_default}}
: ${OCF_RESKEY_extraconf=${OCF_RESKEY_extraconf_default}}

: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat}
. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs
: ${OCF_FUEL_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/fuel}
. ${OCF_FUEL_FUNCTIONS_DIR}/ocf-fuel-funcs

USAGE="Usage: $0 {start|stop|restart|status|monitor|validate-all|meta-data}";

RUN_IN_NS="ip netns exec $OCF_RESKEY_ns "
if [ -z $OCF_RESKEY_ns ] ; then
  RUN=''
else
  RUN="$RUN_IN_NS "
fi

##########################################################################

usage()
{
  echo $USAGE >&2
}

meta_data()
{
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="dnsmasq">
<version>1.0</version>
<longdesc lang="en">
This script manages dnsmasq daemon with namespace support
</longdesc>
<shortdesc lang="en">Manages an dnsmasq daemon inside a namespace</shortdesc>

<parameters>

<parameter name="ns">
<longdesc lang="en">
Name of network namespace.
Should be present.
</longdesc>
<shortdesc lang="en">Name of network namespace.</shortdesc>
<content type="string" default="${OCF_RESKEY_ns_default}"/>
</parameter>

<parameter name="conffile">
<longdesc lang="en">
The dnsmasq daemon configuration file name with full path.
For example, "/etc/dnsmasq/dnsmasq.cfg"
</longdesc>
<shortdesc lang="en">Configuration file name with full path</shortdesc>
<content type="string" default="${OCF_RESKEY_conffile_default}" />
</parameter>

<parameter name="pidfile">
<longdesc lang="en">
The dnsmasq pid file path.
For example, "/var/run/dnsmasq.pid"
</longdesc>
<shortdesc lang="en">Full path to the dnsmasq pid file</shortdesc>
<content type="string" default="${OCF_RESKEY_pidfile_default}"/>
</parameter>

<parameter name="binpath">
<longdesc lang="en">
The dnsmasq binary path.
For example, "/usr/sbin/dnsmasq"
</longdesc>
<shortdesc lang="en">Full path to the dnsmasq binary</shortdesc>
<content type="string" default="${OCF_RESKEY_binpath_default}"/>
</parameter>

<parameter name="extraconf">
<longdesc lang="en">
Extra command line arguments to pass to dnsmasq.
For example, "-f /etc/dnsmasq/shared.cfg"
</longdesc>
<shortdesc lang="en">Extra command line arguments for dnsmasq</shortdesc>
<content type="string" default="${OCF_RESKEY_extraconf_default}" />
</parameter>

</parameters>

<actions>
<action name="start" timeout="20s"/>
<action name="stop" timeout="20s"/>
<action name="monitor" depth="0" timeout="20s" interval="60s" />
<action name="validate-all" timeout="20s"/>
<action name="meta-data"  timeout="5s"/>
</actions>
</resource-agent>
END
exit $OCF_SUCCESS
}

check_ns() {
  local ns=`ip netns list | grep "$OCF_RESKEY_ns"`
  [ $ns != $OCF_RESKEY_ns ] && return $OCF_ERR_GENERIC
  return $OCF_SUCCESS
}

get_ns() {
  local rc
  check_ns && return $OCF_SUCCESS

  ocf_run ip netns add $OCF_RESKEY_ns
  rc=$?
  ocf_run $RUN_IN_NS ip link set up dev lo

  return $rc
}

get_variables() {
        get_ns
  CONF_FILE="${OCF_RESKEY_conffile}"
  COMMAND="$RUN ${OCF_RESKEY_binpath}"
  PIDFILE="${OCF_RESKEY_pidfile}"
}

dnsmasq_status() {
  get_variables
  if [ -n "${PIDFILE}" -a -f "${PIDFILE}" ]; then
    # dnsmasq is probably running
    # get pid from pidfile
    PID="`cat ${PIDFILE}`"
    if [ -n "${PID}" ]; then
      # check if process exists
      if $RUN ps -p "${PID}" | grep -q dnsmasq; then
        ocf_log info "dnsmasq daemon running"
        return $OCF_SUCCESS
      else
        ocf_log info "dnsmasq daemon is not running but pid file exists"
        return $OCF_NOT_RUNNING
      fi
    else
      ocf_log err "PID file empty!"
      return $OCF_ERR_GENERIC
    fi
  fi
  # dnsmasq is not running
  ocf_log info "dnsmasq daemon is not running"
  return $OCF_NOT_RUNNING
}

dnsmasq_start()
{
  get_variables
  # if dnsmasq is running return success
  dnsmasq_status
  retVal=$?
  if [ $retVal -eq $OCF_SUCCESS ]; then
    return $OCF_SUCCESS
  elif [ $retVal -ne $OCF_NOT_RUNNING ]; then
    ocf_log err "Error. Unknown status."
    return $OCF_ERR_GENERIC
  fi

  # run the dnsmasq binary
  ocf_run_as_root ${COMMAND} ${OCF_RESKEY_extraconf} --conf-file=${CONF_FILE} --pid-file="${PIDFILE}"
  if [ $? -ne 0 ]; then
    ocf_log err "Error. dnsmasq daemon returned error $?."
    return $OCF_ERR_GENERIC
  fi

  ocf_log info "Started dnsmasq daemon."
  return $OCF_SUCCESS
}

dnsmasq_stop()
{
    local rc
    local LH="${LL} dnsmasq_stop():"
    local shutdown_timeout=15
    if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
        shutdown_timeout=$(( ($OCF_RESKEY_CRM_meta_timeout/1000) ))
    fi

    get_variables
    dnsmasq_status
    rc="${?}"
    if [ "${rc}" -eq "${OCF_NOT_RUNNING}" ]; then
        ocf_log info "${LH} dnsmasq already stopped"
        return "${OCF_SUCCESS}"
    fi

    proc_stop "${PIDFILE}" "${OCF_RESKEY_binpath}" $shutdown_timeout
    return "${?}"
}

dnsmasq_monitor()
{
  dnsmasq_status
}

dnsmasq_validate_all()
{
  get_variables
  if [ -n "$OCF_RESKEY_binpath" -a ! -x "$OCF_RESKEY_binpath" ]; then
    ocf_log err "Binary path $OCF_RESKEY_binpath does not exist."
    return $OCF_ERR_ARGS
  fi
  if [ -n "$OCF_RESKEY_conffile" -a ! -f "$OCF_RESKEY_conffile" ]; then
    ocf_log err "Config file $OCF_RESKEY_conffile does not exist."
    return $OCF_ERR_ARGS
  fi

  if  grep -v "^#" "$CONF_FILE" | grep "pidfile" > /dev/null ; then
    :
  else
    ocf_log err "Error. \"pidfile\" entry required in the dnsmasq config file by dnsmasq OCF RA."
    return $OCF_ERR_GENERIC
  fi

  return $OCF_SUCCESS
}

dnsmasq_restart()
{
  dnsmasq_stop
  dnsmasq_start
}

#
# Main
#

if [ $# -ne 1 ]; then
  usage
  exit $OCF_ERR_ARGS
fi

export LL="${OCF_RESOURCE_INSTANCE}:"

case $1 in
  start) dnsmasq_start
  ;;

  stop) dnsmasq_stop
  ;;

  restart) dnsmasq_restart
  ;;

  status)  dnsmasq_status
  ;;

  monitor) dnsmasq_monitor
  ;;

  validate-all) dnsmasq_validate_all
  ;;

  meta-data) meta_data
  ;;

  usage) usage; exit $OCF_SUCCESS
  ;;

  *) usage; exit $OCF_ERR_UNIMPLEMENTED
  ;;
esac
