Hi Dejan,

After a long long time... You find the new script in the attachment.

Dejan Muhamedagic wrote:
Hi Achim,

On Thu, Nov 20, 2008 at 01:32:06PM +0100, Achim Stumpf wrote:
Hi,

I am still waiting for further advice to finish the commit
process to your repository. ;o)

I'd have a few suggestions as well:

1. You could drop both connect_timeout and max_time parameters.
It is advisable to have the upper layer decide when an operation
should timeout (by setting the operation's "timeout" attribute).

done


2. kill -0 "$1"

returns success with zombie processes too.


I have checked the other scripts, some of them check /proc/pid. But with a 
zombie it's the same as with kill -0. What do you suggest?

3. Poftpd: a typo in a message.


done

4. In proftpd_start()

     # check that the proftpd binary exists
    if [ ! -x "$OCF_RESKEY_binary" ]; then
                ocf_log err "Proftpd binary $OCF_RESKEY_binary does not exist"
                exit $OCF_ERR_CONFIGURED

This belongs to validate. Should also be OCF_ERR_INSTALLED.


moved to validate

5. In proftpd_stop()
...
                TRIES=0
                while isRunning "$PID" && [ $TRIES -lt 5 ]
                do
                    sleep 1
                    kill $PID > /dev/null 2>&1
                    ocf_log info "Killing Proftpd PID $PID"
                    TRIES=`expr $TRIES + 1`
                done

Move the kill command in front of the loop: it's enough to send a
signal once. The same for the latter 'kill -9'. You can also try
other signals, such as HUP (see, perhaps, the proftpd docs).
Also, could it be that 5 seconds is a bit too short to let the
ftpd exit?

As in 1. above, it's better to leave the timeout handling to
lrmd. You can just do an infinite look here:

                while isRunning "$PID"; do
                                        sleep 1
                                        ...
                                done


Before it wasn't only 5 seconds. It was five seconds for kill, and then you got 
another loop with kill -9. for kill it is 30 second's
now. And an infinite loop with kill -9. The kill and kill -9 is in front of the 
loop and only sleep and logging is left inside the loop.

6. In proftpd_monitor()

            ocf_log err "Proftpd monitor on PID $PID failed"

It may or may not be an error if proftpd is not running. Better
to keep silent.


changed to debug

            ocf_log err "$OCF_RESKEY_curl_binary does not exist"
            return $OCF_ERR_CONFIGURED

This belongs to the validate action. The error should be
OCF_ERR_INSTALLED.

See the validate action in other OCF agents. Note that a failure
to validate the environment and parameters shouldn't influence
the meta-data operation.


I have checked other scripts. Most of them return just ocf_success. What I have to check in validate all?
I have made just a test with a wrong path to the curl binary. heartbeat does 
not do a validate all or? In the logs I see only that monitoring fails. For 
whom is that validate all???

And... very sorry for taking this long.


Never mind...


Cheers

Achim

Cheers,

Dejan


Achim


Achim Stumpf wrote:
Hi,

What's about the proftpd script? Maybe we could finish that one... ;o)


Thanks,

Achim



Achim Stumpf wrote:
Hi,

Lars Marowsky-Bree wrote:
"start_delay" should not be necessary, unless your start operation is
broken.

I have removed the start_delay.

You also need to do a check_binary on the proftpd binary somewhere prior
to calling this command.

All config files and binaries get checked now.

proftpd_stop()
{
    if proftpd_status ; then
        PID=`head -n 1 $OCF_RESKEY_pidfile`
        if [ ! -z $PID ] ; then
            kill $PID
            if [ $? -ne 0 ]; then
                ocf_log err "Proftpd couldn't be stopped"
                return $OCF_ERR_GENERIC
            fi
        fi
    fi
You need to check afterwards that the process is really gone. kill is
not sufficient; it might send the signal, but if the process is stuck on
IO, it might not stop. I'd also recommend kill -9.

I have adapted some code of the apache ocf script:

proftpd_stop()
{
   if proftpd_status ; then
       PID=`head -n 1 $OCF_RESKEY_pidfile`
       if [ ! -z "$PID" ]; then
           kill $PID > /dev/null 2>&1            if [ $? -eq 0 ]; then
               TRIES=0
while isRunning "$PID" && [ $TRIES -lt 5 ] do
                   sleep 1
                   kill $PID > /dev/null 2>&1
                   ocf_log info "Killing Proftpd PID $PID"
                   TRIES=`expr $TRIES + 1`
               done
               TRIES=0
while isRunning "$PID" && [ $TRIES -lt 3 ] do
                   sleep 1
                   kill -9 $PID > /dev/null 2>&1
                   ocf_log info "Killing Proftpd PID $PID with SIGKILL"
                   TRIES=`expr $TRIES + 1`
               done
               if isRunning "$PID" ; then
                   ocf_log err "Killing Proftpd PID $PID FAILED"
                   exit $OCF_ERR_GENERIC
               fi
           else
               ocf_log err "Killing Proftpd PID $PID FAILED"
               exit $OCF_ERR_GENERIC
           fi
       fi
   fi    exit $OCF_SUCCESS
}

1. kill -15 2. if it is still running try max. 5 times to kill again with kill -15
3. after that if it is still running try 3 times with kill -9

Hope that it meets your needs ;o)

And actually I got the idea to send in the while loop with kill -9 a kill -9 signal to all the child processes as returned by:

ps --no-headers -o pid --ppid $PID

If you like the above code and the idea with kill -9 to the child processes, I will implement that too.

proftpd_monitor()
{
if [ $OCF_CHECK_LEVEL -eq 0 ]; then if proftpd_status ; then
            ocf_log debug "Proftpd monitor succeded"
            return $OCF_SUCCESS
        fi
    else
${OCF_RESKEY_curl_binary} -sS --connect-timeout ${OCF_RESKEY_connect_timeout} --max-time ${OCF_RESKEY_max_time} -u "${OCF_RESKEY_test_user}:${OCF_RESKEY_test_pass}" ftp://localhost/ > /dev/null 2>&1
The curl_binary also needs to be "check_binary"ed somewhere.

done

And you might be managing several proftpd instances, none of which might
bind to "localhost"; I think the URL needs to be configurable.
done


Thanks for your advice. Let's see what is wrong now... ;o)


Achim



_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/
_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/
#!/bin/sh
#
# Resource script for Proftpd
#
# Description:  Manages Proftpd as an OCF resource in 
#               an Active-Passive High Availability setup.
#
# Author:       Rajat Upadhyaya <[email protected]> : Pure-FTPd script 
# Author:       Achim Stumpf <[email protected]> : Rewrite as Proftpd
# License:      GNU General Public License (GPL) 
#
#
#       usage: $0 {start|stop|status|monitor|validate-all|meta-data}
#
#       The "start" arg starts Proftpd.
#
#       The "stop" arg stops it.
#
# OCF parameters:
#  OCF_RESKEY_binary
#  OCF_RESKEY_conffile
#  OCF_RESKEY_pidfile
#  OCF_RESKEY_curl_binary
#  OCF_RESKEY_curl_url
#  OCF_RESKEY_test_user
#  OCF_RESKEY_test_pass
#
##########################################################################
# Initialization:

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

: ${OCF_RESKEY_binary="/usr/sbin/proftpd"}
: ${OCF_RESKEY_conffile="/etc/proftpd.conf"}
: ${OCF_RESKEY_pidfile="/var/run/proftpd.pid"}
: ${OCF_RESKEY_curl_binary="/usr/bin/curl"}
: ${OCF_RESKEY_curl_url="ftp://localhost/"}
: ${OCF_RESKEY_test_user="test"}
: ${OCF_RESKEY_test_pass=""}

USAGE="Usage: $0 {start|stop|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="proftpd">
<version>1.0</version>
<longdesc lang="en">
This script manages Proftpd in an Active-Passive setup
</longdesc>
<shortdesc lang="en">OCF Resource Agent compliant FTP script.</shortdesc>

<parameters>

<parameter name="binary" unique="0" required="0">
<longdesc lang="en">The Proftpd binary</longdesc>
<shortdesc lang="en">The Proftpd binary</shortdesc>
<content type="string" default="/usr/sbin/proftpd" />
</parameter>

<parameter name="conffile" unique="0" required="0">
<longdesc lang="en">
The Proftpd configuration file name with full path. 
For example, "/etc/proftpd.conf"
</longdesc>
<shortdesc lang="en">Configuration file name with full path</shortdesc>
<content type="string" default="/etc/proftpd.conf" />
</parameter>

<parameter name="pidfile" unique="0" required="0">
<longdesc lang="en">The Proftpd PID file. The location of the PID file is 
configured in the Proftpd configuration file.</longdesc>
<shortdesc lang="en">PID file</shortdesc>
<content type="string" default="/var/run/proftpd.pid" />
</parameter>

<parameter name="curl_binary" unique="0" required="0">
<longdesc lang="en">The absolut path to the curl binary for monitoring with 
OCF_CHECK_LEVEL greater zero.</longdesc>
<shortdesc lang="en">The absolut path to the curl binary</shortdesc>
<content type="string" default="/usr/bin/curl" />
</parameter>

<parameter name="curl_url" unique="0" required="0">
<longdesc lang="en">The URL which is checked by curl with OCF_CHECK_LEVEL 
greater zero.</longdesc>
<shortdesc lang="en">The URL which is checked by curl</shortdesc>
<content type="string" default="ftp://localhost/"; />
</parameter>

<parameter name="test_user" unique="0" required="0">
<longdesc lang="en">The name of the ftp user for monitoring with 
OCF_CHECK_LEVEL greater zero.</longdesc>
<shortdesc lang="en">The name of the ftp user</shortdesc>
<content type="string" default="test" />
</parameter>

<parameter name="test_pass" unique="0" required="0">
<longdesc lang="en">The password of the ftp user for monitoring with 
OCF_CHECK_LEVEL greater zero.</longdesc>
<shortdesc lang="en">The password of the ftp user</shortdesc>
<content type="string" default="" />
</parameter>

</parameters>

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

isRunning()
{
        kill -0 "$1" > /dev/null 2>&1
}

proftpd_status()
{
        if [ -f "$OCF_RESKEY_pidfile" ]
        then
        # Proftpd is probably running
                PID=`head -n 1 $OCF_RESKEY_pidfile`
                if [ ! -z "$PID" ] ; then
                        isRunning "$PID" && `ps -p $PID | grep proftpd > 
/dev/null 2>&1`
                        return $?
                fi
        fi
        
        # Proftpd is not running
        return $OCF_NOT_RUNNING;
}

proftpd_start()
{
        # make a few checks and start Proftpd
        if ocf_is_root ; then : ; else
                ocf_log err "You must be root"
                exit $OCF_ERR_PERM
        fi
        
        # if Proftpd is running return success
        if proftpd_status ; then
                ocf_log info "Proftpd is running already"
                exit $OCF_SUCCESS
        fi

        # check that the Proftpd config file exist
        if [ ! -f "$OCF_RESKEY_conffile" ]; then
                ocf_log err "Proftpd config file $OCF_RESKEY_conffile does not 
exist"
                exit $OCF_ERR_CONFIGURED
        fi

        # starting Proftpd
        ${OCF_RESKEY_binary} --config ${OCF_RESKEY_conffile} 2>/dev/null

        if [ "$?" -ne 0 ]; then
                ocf_log err "Proftpd returned error" $?
                exit $OCF_ERR_GENERIC
        fi

        exit $OCF_SUCCESS
}


proftpd_stop()
{
        if proftpd_status ; then
                PID=`head -n 1 $OCF_RESKEY_pidfile`
                if [ ! -z "$PID" ]; then
                        ocf_log info "Killing Proftpd PID $PID"
                        kill $PID > /dev/null 2>&1 
                        if [ "$?" -eq 0 ]; then
                                TRIES=0
                                while isRunning "$PID" && [ "$TRIES" -lt 30 ]
                                do
                                        sleep 1
                                        ocf_log info "Proftpd PID $PID is still 
running"
                                        TRIES=`expr $TRIES + 1`
                                done
                                isRunning "$PID"
                                RET=$?
                                if [ "$RET" -eq 0 ]; then
                                        ocf_log info "Killing Proftpd PID $PID 
with SIGKILL"
                                        kill -9 $PID > /dev/null 2>&1
                                        while isRunning "$PID" 
                                        do
                                                sleep 1
                                                ocf_log info "Proftpd PID $PID 
is still running"
                                        done
                                fi
                        else
                                ocf_log err "Killing Proftpd PID $PID FAILED"
                                exit $OCF_ERR_GENERIC
                        fi      
                fi
        fi

        exit $OCF_SUCCESS
}

proftpd_monitor()
{
        proftpd_status
        RET=$?

        if [ "$RET" -ne 0 -o "$OCF_CHECK_LEVEL" -eq 0 ]; then   
                if [ "$RET" -eq 0 ]; then
                        PID=`head -n 1 $OCF_RESKEY_pidfile`
                        ocf_log debug "Proftpd monitor on PID $PID succeeded"
                        return $OCF_SUCCESS
                else
                        ocf_log debug "Proftpd monitor on PID $PID failed"
                        return $OCF_NOT_RUNNING
                fi
        else
                ${OCF_RESKEY_curl_binary} -sS -u 
"${OCF_RESKEY_test_user}:${OCF_RESKEY_test_pass}" ${OCF_RESKEY_curl_url} > 
/dev/null 2>&1
                if [ "$?" -eq 0 ]; then
                        ocf_log debug "Proftpd monitor with curl on URL 
$OCF_RESKEY_curl_url succeeded"
                        return $OCF_SUCCESS
                else
                        ocf_log err "Proftpd monitor with curl on URL 
$OCF_RESKEY_curl_url failed"
                        return $OCF_NOT_RUNNING
                fi
        fi
}

proftpd_validate_all()
{

        # check that the proftpd binary exists
        if [ ! -x "$OCF_RESKEY_binary" ]; then
                ocf_log err "Proftpd binary $OCF_RESKEY_binary does not exist"
                exit $OCF_ERR_INSTALLED
        fi      

        # check that the curl binary exists
        if [ ! -x "$OCF_RESKEY_curl_binary" ]; then
                ocf_log err "$OCF_RESKEY_curl_binary does not exist"
                return $OCF_ERR_CONFIGURED
        fi

        return $OCF_SUCCESS
}

#
# Main
#

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

case $1 in
    start)      proftpd_start
                ;;
        
    stop)       proftpd_stop
                ;;
                
    status)     if proftpd_status
                then
                        ocf_log info "Proftpd is running"
                        exit $OCF_SUCCESS
                else
                        ocf_log info "Proftpd is stopped"
                        exit $OCF_NOT_RUNNING
                fi
                ;;
                
    monitor)    proftpd_monitor
                exit $?
                ;;
                
    validate-all)       proftpd_validate_all
                        exit $?
                        ;;
                        
    meta-data)  meta_data
                ;;
                
    usage)      usage
                exit $OCF_SUCCESS
                ;;
                
    *)          usage
                exit $OCF_ERR_UNIMPLEMENTED
                ;;
esac

_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/

Reply via email to