[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-ha-dev
Subject:    [Linux-ha-dev] dovecot ocf resource agent
From:       <jeroen () intuxicated ! org>
Date:       2011-02-03 12:13:47
Message-ID: fbaddcacd36ba1ca897f2ca2fac2109a () mail ! perrit ! nl
[Download RAW message or body]

Hi,

I created a resource agent for dovecot as well, basic testing using
ocf-tester has been done. It would be great if someone could have a look.

Again, I will happily modify it if necessary to get it included.

Best regards,
Jeroen Koekkoek
["dovecot.sh" (application/x-shellscript)]

#!/bin/sh
#
# Dovecot
#
# Description:  Manages Dovecot as an OCF resource in an high-availability
#               setup.
#
# Author:       Jeroen Koekkoek
# License:      GNU General Public License (GPL)
# Copyright:    (C) 2011 Pagelink B.V.
#
#       The OCF code was inspired by the Postfix resource script written by
#       Raoul Bhatia <r.bhatia@ipax.at>.
#
# OCF parameters:
#   OCF_RESKEY_dovecot
#   OCF_RESKEY_doveconf
#   OCF_RESKEY_config_file
#
################################################################################

# Initialization:

> ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat}
. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs

> ${OCF_RESKEY_dovecot="/usr/sbin/dovecot"}
> ${OCF_RESKEY_doveconf="/usr/bin/doveconf"}
> ${OCF_RESKEY_config_file="/etc/dovecot/dovecot.conf"}
USAGE="Usage: $0 {start|stop|reload|status|monitor|validate-all|meta-data}"

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

usage()
{
  echo $USAGE >&2
}

meta_data()
{
	cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="dovecot">
<version>0.1</version>
<longdesc lang="en">
Resource script for Dovecot. It manages a Dovecot instance as an OCF resource.
</longdesc>
<shortdesc lang="en">Manages a Dovecot instance</shortdesc>

<parameters>

<parameter name="dovecot" unique="0" required="0">
<longdesc lang="en">
Full path to the dovecot binary.
For example, "/usr/sbin/dovecot".
</longdesc>
<shortdesc lang="en">Full path to dovecot binary</shortdesc>
<content type="string" default="/usr/sbin/dovecot" />
</parameter>

<parameter name="doveconf" unique="0" required="0">
<longdesc lang="en">
Full path to the doveconf binary.
For example, "/usr/bin/doveconf".
</longdesc>
<shortdesc lang="en">Full path to doveconf binary</shortdesc>
<content type="string" default="/usr/bin/doveconf" />
</parameter>

<parameter name="config_file" unique="1" required="0">
<longdesc>
Full pathname of the Dovecot configuration file.
For example, "/etc/dovecot/dovecot.conf"
</longdesc>
<shortdesc>Full pathname of configuration file</shortdesc>
<content type="string" default="/etc/dovecot/dovecot.conf" />
</parameter>

</parameters>

<actions>
<action name="start" timeout="20s" />
<action name="stop" timeout="20s" />
<action name="reload" 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
}

cmd_by_pid()
{
  local pid=$1

  if [ "$pid" = "" ]; then
    return 1 # failure
  fi

  local cmd=`ps -p $pid -o ucomm | tail -n 1`

  if [ "$cmd" = "" ]; then
    return 1 # failure
  fi

  echo "$cmd"

  return 0 # success
}

pids_by_ppid()
{
  local pids
  local proc
  local ppid=$1

  if [ "$ppid" = "" ]; then
    return 1 # failure
  fi

  for proc in `ps ax -o pid= -o ppid= | sed \
's/^[[:space:]]*\([0-9]*\)[[:space:]]*\([0-9]*\)[[:space:]]*$/\1;\2/'`; do  local \
pid=`echo $proc | cut -f 1 -d \;`  local pid_ppid=`echo $proc | cut -f 2 -d \;`

    if [ "$ppid" = "$pid_ppid" ]; then
      pids="$pids $pid"
    fi
  done

  echo "$pids"

  return 0 # success
}

terminate()
{
  local pid=$1
  local signal=$2
  local recheck=$3
  local result

  if [ -z "$recheck" ]; then
    recheck=1
  fi

  kill -$signal $pid >/dev/null 2>&1; result=$?

  if [ $result -eq 0 ] && [ $recheck -gt 0 ]; then
    # Grant some time for shutdown and recheck n times.
    local i=0

    while [ $result -eq 0 ] && [ $i -lt $recheck ]; do
      kill -0 $pid >/dev/null 2>&1; result=$?
      let "i += 1"

      if [ $result -eq 0 ]; then
        sleep 1
      fi
    done
  else
    result=1
  fi

  if [ $result -ne 0 ]; then
    return 0
  fi

  # The command name can provide valuable information to the administrator so
  # we try our best to be as complete as possible.
  local cmd=`cmd_by_pid $ppid`

  if [ $? -eq 0 ]; then
    ocf_log err "Dovecot child process '$cmd' with pid '$pid' failed to stop."
  else
    ocf_log err "Dovecot child process with pid '$pid' failed to stop."
  fi

  return 1
}

terminate_tree()
{
  local cmd
  local pid
  local ppid=$1
  local signal=$2
  local recheck=$3
  local result=0

  if [ "$ppid" = "" ]; then
    return 1 # failure
  fi

  if [ "$recheck" = "" ]; then
    recheck=0
  fi

  for pid in `pids_by_ppid $ppid`; do
    terminate_tree $pid

    if [ $? -eq 1 ]; then
      # terminate_tree failed to terminate $pid, but it might still be able to
      # terminate other child processes.
      result=1
    fi
  done

  # If we failed to terminate all child processes, the parent process will not
  # be killed, since that would leave processes floating around.

  if [ $result -eq 0 ]; then
    terminate $ppid $signal $recheck
    recheck=$?
  fi

  return $result
}

dovecot_option()
{
  local result
  local value

  if [ -z "$1" ]; then
    return $OCF_ERR_GENERIC
  fi

  value=`$doveconf -c $config_file -h $1 2>/dev/null`; result=$?

  if [ $result -ne 0 ]; then
    return $OCF_ERR_CONFIGURED
  fi

  echo "$value"

  return $OCF_SUCCESS
}

dovecot_pid()
{
  local pid

  if [ -f "$pid_file" ]; then
    pid=`head -n 1 "$pid_file" 2>/dev/null`

    if [ -n "$pid" ]; then
      echo "$pid"
      return $OCF_SUCCESS
    fi

    ocf_log err "dovecot pid file '$pid_file' empty."

    return $OCF_ERR_GENERIC
  fi

  ocf_log err "dovecot pid file '$pid_file' does not exist."

  return $OCF_NOT_RUNNING
}

dovecot_status()
{
  local pid
  local state

  pid=`dovecot_pid`; state=$?

  if [ $state -eq $OCF_SUCCESS ]; then

    if ! kill -0 $pid >/dev/null 2>&1; then
      return $OCF_NOT_RUNNING
    else
      echo "$pid"
      return $OCF_SUCCESS
    fi
  fi

  return $state
}

dovecot_start()
{
  local pid
  local result
  local state

  pid=`dovecot_status`; state=$?

  if [ $state -eq $OCF_SUCCESS ]; then
    ocf_log info "Dovecot already running."
    return $state
  elif [ $state -eq $OCF_ERR_GENERIC ]; then
    ocf_log err "Dovecot returned error."
    return $state
  fi

  $dovecot -c $config_file >/dev/null 2>&1; result=$?

  if [ $result -ne 0 ]; then
    ocf_log err "Dovecot returned error."

    return $OCF_ERR_GENERIC
  fi

  ocf_log info "Dovecot started."

  return $OCF_SUCCESS
}

dovecot_stop()
{
  local pid
  local ppid
  local result
  local state

  ppid=`dovecot_status`; state=$?

  if [ $state -eq $OCF_NOT_RUNNING ]; then
    ocf_log info "Dovecot already stopped."
    return $OCF_SUCCESS
  elif [ $state -eq $OCF_ERR_GENERIC ]; then
    ocf_log info "Dovecot returned error."
    return $OCF_ERR_GENERIC
  fi

  local kill_master=0
  local remove_pid_file=0
  local shutdown_clients=0

#  terminate $ppid 15 5; result=$?
  terminate $ppid 0 1; result=$?
  if [ $result -ne 0 ]; then
    ocf_log err "Dovecot failed to stop. Escalating to KILL."

    # Figure out if we need to shutdown all active clients as well. This
    # behaviour is controlled by the shutdown_clients option in the Dovecot
    # configuration file.

    shutdown_clients=`dovecot_option shutdown_clients`; state=$?

    if [ $state -ne $OCF_SUCCES ]; then
      return $state
    fi

    local cmd
    local anvil_pid=0
    local config_pid=0
    local log_pid=0

    if [ "$shutdown_clients" = "yes" ]; then
      result=0

      for pid in `pids_by_ppid $ppid`; do
        cmd=`cmd_by_pid $pid`

        if [ "x$cmd" = "xanvil" ]; then
          anvil_pid=$pid
        elif [ "x$cmd" = "xconfig" ]; then
          config_pid=$pid
        elif [ "x$cmd" = "xlog" ]; then
          log_pid=$pid
        else
          terminate_tree $pid 9 5 || result=1
          kill_master=1
        fi
      done

      if [ $result -eq 0 ] && [ $anvil_pid -ne 0 ]; then
        terminate $anvil_pid 9 3; result=$?
        kill_master=1
      fi

      if [ $result -eq 0 ] && [ $log_pid -ne 0 ]; then
        terminate $log_pid 9 3; result=$?
        kill_master=1
      fi

    else
      result=0

      for pid in `pids_by_ppid $ppid`; do
        cmd=`cmd_by_pid $pid`

        if [ "x$cmd" = "xconfig" ]; then
          config_pid=$pid
        fi
      done
    fi

    if [ $result -eq 0 ] && [ $config_pid -ne 0 ]; then
      terminate $config_pid 9 3; result=$?
      kill_master=1
    fi

    if [ $result -eq 0 ] && [ $kill_master -eq 1 ]; then
      terminate $ppid 9 5; result=$?
      remove_pid_file=1
    fi
  else
    remove_pid_file=1
  fi

  if [ $result -eq 0 ] && [ $remove_pid_file -eq 1 ]; then

    if [ -f $pid_file ]; then
      rm -f "$pid_file" >/dev/null 2>&1
    fi

    ocf_log info "Dovecot stopped."

    return $OCF_SUCCESS
  fi

  ocf_log err "Dovecot failed to stop."

  return $OCF_ERR_GENERIC
}

dovecot_reload()
{
  local pid
  local state
  local result

  pid=`dovecot_status`; state=$?

  if [ $result -eq $OCF_SUCCESS ]; then

    kill -1 $pid >/dev/null 2>&1; result=$?

    if [ $result -eq 0 ]; then
      state=$OCF_SUCCESS
    else
      state=$OCF_ERR_GENERIC
    fi
  fi

  if [ $state -eq $OCF_SUCCESS ]; then
    ocf_log info "Reloading Dovecot."
  elif [ $state -eq $OCF_ERR_GENERIC ]; then
    ocf_log err "Dovecot returned error."
  fi

  return $state
}

dovecot_validate_all()
{
  local x

  for x in $dovecot $doveconf; do
    if [ ! -x $x ]; then
      ocf_log err "Dovecot binary '$x' does not exist or cannot be executed."
      exit $OCF_ERR_GENERIC
    fi
  done

  if [ ! -f $OCF_RESKEY_conffile ]; then
    ocf_log err "Dovecot configuration file '$config_file' does not exist."
    exit $OCF_ERR_GENERIC
  fi

  return $OCF_SUCCESS
}

#
# Main
#

dovecot=$OCF_RESKEY_dovecot
doveconf=$OCF_RESKEY_doveconf
config_file=$OCF_RESKEY_config_file
pid_file=''

if [ -z "$config_file" ]; then
  config_file="/etc/dovecot/dovecot.conf"
fi

pid_file="`dovecot_option base_dir`/master.pid"

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

case $1 in
  meta-data)
    meta_data
    exit $OCF_SUCCESS
    ;;
  usage|help)
    usage
    exit $OCF_SUCCESS
    ;;
esac

dovecot_validate_all

[ $? -eq $OCF_SUCCESS ] || exit $?

case $1 in
  monitor|status)
    pid=`dovecot_status`; state=$?

    if [ $result -eq $OCF_SUCCESS ]; then
      ocf_log info "Dovecot is running."
    elif [ $result -eq $OCF_NOT_RUNNING ]; then
      ocf_log info "Dovecot is stopped."
    fi

    exit $state
    ;;
  start)
    dovecot_start
    exit $?
    ;;
  stop)
    dovecot_stop
    exit $?
    ;;
  reload)
    dovecot_reload
    exit $?
    ;;
  validate-all)
    exit $OCF_SUCCESS
    ;;
  *)
    usage
    exit $OCF_ERR_UNIMPLEMENTED
    ;;
esac



_______________________________________________________
Linux-HA-Dev: Linux-HA-Dev@lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic