Dear Markus,

I was also thinking the same thing.
So, Already I've created a new one.

[ChangeSet]
- An API to be used was changed from "Amazon EC2 CLI" to "AWS CLI".
  -- "AWS CLI" is based Python. So, CPU load might be reduced.

- The "--private-key" and "--cert" options are deprecated in AWS CLI.
  So, I add a new option "--profile". Use a specific profile from that 
credential file.
  default is ""


[How to use]
- Plaese install the "AWS CLI".
  http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html

- Please copy the fence_ec2 in /usr/lib64/stonith/plugins/external/.
  And , Please set the permissions to 755.

- Please set crm settings as in this example.
  - The instance that have been set as "node01" in the "Name" tag are fence.
  ------
  primitive prmStonith1-2 stonith:external/fence_ec2 \          
        params \        
                pcmk_off_timeout="300s" \
                port="node01" \
                tag="Name" \
        op start interval="0s" timeout="60s" \      
        op monitor interval="3600s" timeout="60s" \ 
        op stop interval="0s" timeout="60s" 
  ------


Regards,
Kazuhiko Higashi

On 2015/02/25 7:22, Markus Guertler wrote:
Dear list,
I was just trying to configure the fence_ec2 stonith agent from 2012, written 
by Andrew Beekhof. It looks like, that this one not working anymore with newer 
stonith / cluster versions. Is there any other EC2 agent, that is still 
maintained?

If not, I'll write one myself. However, I'd like to check all options first.

Cheers,
Markus

_______________________________________________
Linux-HA mailing list
Linux-HA@lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems



#!/bin/bash

description="
fence_ec2 is an I/O Fencing agent which can be used with Amazon EC2 instances.

API functions used by this agent:
- aws ec2 describe-tags
- aws ec2 describe-instances
- aws ec2 stop-instances
- aws ec2 start-instances
- aws ec2 reboot-instances

If the uname used by the cluster node is any of:
 - Public DNS name (or part there of),
 - Private DNS name (or part there of),
 - Instance ID (eg. i-4f15a839)
 - Contents of tag associated with the instance
then the agent should be able to automatically discover the instances it can 
control.

If the tag containing the uname is not [Name], then it will need to be 
specified using the [tag] option.
"

#
# Copyright (c) 2011-2013 Andrew Beekhof
# Copyright (c) 2014 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
#                    All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it would be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Further, this software is distributed without any warranty that it is
# free of the rightful claim of any third person regarding infringement
# or the like.  Any license provided herein, whether implied or
# otherwise, applies only to this software file.  Patent licenses, if
# any, provided herein do not apply to combinations of this program with
# other software, or any other product whatsoever.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
#
#######################################################################

quiet=0
port_default=""

instance_not_found=0
unknown_are_stopped=0

action_default="reset"         # Default fence action
ec2_tag_default="Name"         # EC2 Tag containing the instance's uname

sleep_time="1"

ec2_tag=${tag}

: ${ec2_tag=${ec2_tag_default}}
: ${port=${port_default}}

function usage()
{
cat <<EOF
`basename $0` - A fencing agent for Amazon EC2 instances
 
$description
 
Usage: `basename $0` -o|--action [-n|--port] [options]
Options:
 -h, --help             This text
 -V, --version          Version information
 -q, --quiet            Reduced output mode
 
Commands:
 -o, --action           Action to perform: on|off|reboot|status|monitor
 -n, --port             The name of a machine/instance to control/check

Additional Options:
 -p, --profile          Use a specific profile from your credential file.
 -t, --tag              Name of the tag containing the instance's uname

Dangerous options:
 -U, --unknown-are-stopped      Assume any unknown instance is safely stopped

EOF
    exit 0;
}

function getinfo-xml()
{
        cat <<EOF
<parameters>
        <parameter name="port" unique="1" required="1">
                <content type="string" />
                <shortdesc lang="en">The name/id/tag of a instance to 
control/check</shortdesc>
        </parameter>
        <parameter name="profile" unique="0" required="0">
                <content type="string" default="default" />
                <shortdesc lang="en">Use a specific profile from your 
credential file.</shortdesc>
        </parameter>
        <parameter name="tag" unique="0" required="1">
                <content type="string" default="Name" />
                <shortdesc lang="en">Name of the tag containing the instances 
uname</shortdesc>
        </parameter>
        <parameter name="unknown_are_stopped" unique="0" required="0">
                <content type="string" default="false" />
                <shortdesc lang="en">DANGER: Assume any unknown instance is 
safely stopped</shortdesc>
        </parameter>
</parameters>
EOF
        exit 0;
}

function metadata()
{
        cat <<EOF
<?xml version="1.0" ?>
<resource-agent name="fence_ec2" shortdesc="Fencing agent for Amazon EC2 
instances" >
        <longdesc>
$description
        </longdesc>
        <parameters>
        <parameter name="action" unique="0" required="1">
                <getopt mixed="-o, --action=[action]" />
                <content type="string" default="reboot" />
                <shortdesc lang="en">Fencing Action</shortdesc>
        </parameter>
        <parameter name="port" unique="1" required="1">
                <getopt mixed="-n, --port=[port]" />
                <content type="string" />
                <shortdesc lang="en">The name/id/tag of a instance to 
control/check</shortdesc>
        </parameter>
        <parameter name="profile" unique="0" required="0">
                <getopt mixed="-p, --profile=[profile]" />
                <content type="string" default="default" />
                <shortdesc lang="en">Use a specific profile from your 
credential file.</shortdesc>
        </parameter>
        <parameter name="tag" unique="0" required="1">
                <getopt mixed="-t, --tag=[tag]" />
                <content type="string" default="Name" />
                <shortdesc lang="en">Name of the tag containing the instances 
uname</shortdesc>
        </parameter>
        <parameter name="unknown-are-stopped" unique="0" required="0">
                <getopt mixed="-U, --unknown-are-stopped" />
                <content type="string" default="false" />
                <shortdesc lang="en">DANGER: Assume any unknown instance is 
safely stopped</shortdesc>
        </parameter>
        </parameters>
        <actions>
        <action name="on" />
        <action name="off" />
        <action name="reboot" />
        <action name="status" />
        <action name="list" />
        <action name="monitor" />
        <action name="metadata" />
        </actions>
</resource-agent>
EOF
        exit 0;
}

function instance_for_port()
{
        local port=$1
        local instance=""

        # Look for port name -n in the INSTANCE data
        instance=`aws ec2 describe-instances $options | grep 
"^INSTANCES[[:space:]].*[[:space:]]$port[[:space:]]" | awk '{print $8}'`
        if [ -z $instance ]; then
                # Look for port name -n in the Name TAG
                instance=`aws ec2 describe-tags $options | grep 
"^TAGS[[:space:]]$ec2_tag[[:space:]].*[[:space:]]instance[[:space:]]$port$" | 
awk '{print $3}'`
        fi

        if [ -z $instance ]; then
                instance_not_found=1
                instance=$port
        fi

        echo $instance
}

function instance_on()
{
        aws ec2 start-instances $options --instance-ids $instance
}

function instance_off()
{
        if [ $unknown_are_stopped = 1 -a $instance_not_found ]; then
                : nothing to do
                ha_log.sh info "Assuming unknown instance $instance is already 
off"
        else
                aws ec2 stop-instances $options --instance-ids $instance --force
        fi
}

function instance_status()
{
        local instance=$1
        local status="unknown"
        local rc=1

        # List of instances and their current status
        if [ $unknown_are_stopped = 1 -a $instance_not_found ]; then
                ha_log.sh info "$instance stopped (unknown)"
        else
                status=`aws ec2 describe-instances $options --instance-ids 
$instance | awk '{ 
                        if (/^STATE\t/) { printf "%s", $3 }
                        }'`
                rc=$?
        fi
        ha_log.sh info "status check for $instance is $status"
        echo $status
        return $rc
}


TEMP=`getopt -o qVho:e:p:n:t:U --long 
version,help,action:,port:,option:,profile:,tag:,quiet,unknown-are-stopped \
     -n 'fence_ec2' -- "$@"`

if [ $? != 0 ];then 
    usage
    exit 1
fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

if [ -z $1 ]; then
        # If there are no command line args, look for options from stdin
        while read line; do
                case $line in 
                        option=*|action=*) action=`echo $line | sed s/.*=//`;;
                        port=*)        port=`echo $line | sed s/.*=//`;;
                        profile=*)     ec2_profile=`echo $line | sed s/.*=//`;;
                        tag=*)         ec2_tag=`echo $line | sed s/.*=//`;;
                        quiet*)        quiet=1;;
                        unknown-are-stopped*) unknown_are_stopped=1;;
                        --);;
                        *) ha_log.sh err "Invalid command: $line";;
                esac
        done
fi

while true ; do
        case "$1" in
                -o|--action|--option) action=$2;   shift; shift;;
                -n|--port)            port=$2;     shift; shift;;
                -p|--profile)         ec2_profile=$2; shift; shift;;
                -t|--tag)             ec2_tag=$2; shift; shift;;
                -U|--unknown-are-stopped) unknown_are_stopped=1; shift;;
                -q|--quiet) quiet=1; shift;;
                -V|--version) echo "1.0.0"; exit 0;;
                --help|-h) 
                        usage;
                        exit 0;;
                --) shift ; break ;;
                *) ha_log.sh err "Unknown option: $1. See --help for details."; 
exit 1;;
        esac
done

[ -n "$1" ] && action=$1

if [ -z "$ec2_profile"]; then
        options="--output text --profile default"
else
        options="--output text --profile $ec2_profile "
fi

action=`echo $action | tr 'A-Z' 'a-z'`

case $action in 
        metadata)
                metadata
        ;;
        getinfo-xml)
                getinfo-xml
        ;;
        getconfignames)
                for i in profile port tag
                do
                        echo $i
                done
                exit 0
        ;;
        getinfo-devid)
                echo "EC2 STONITH device"
                exit 0
        ;;
        getinfo-devname)
                echo "EC2 STONITH external device"
                exit 0
        ;;
        getinfo-devdescr)
                echo "fence_ec2 is an I/O Fencing agent which can be used with 
Amazon EC2 instances."
                exit 0
        ;;
        getinfo-devurl)
                echo ""
                exit 0
        ;;
esac

# get my instance id
myinstance=`curl http://169.254.169.254/latest/meta-data/instance-id`

# check my status.
# When the EC2 instance be stopped by the "aws ec2 stop-instances" , the stop 
processing of the OS is executed.
# While the OS stop processing, Pacemaker can execute the STONITH processing.
# So, If my status is not "running", it determined that I was already fenced. 
And to prevent fencing each other
# in split-brain, I don't fence other node.
if [ -z "$myinstance" ]; then
        ha_log.sh err "Failed to get My Instance ID. so can not check my 
status."
        exit 1
fi
mystatus=`instance_status $myinstance`
if [ "$mystatus" != "running" ]; then #do not fence
        ha_log.sh warn "I was already fenced (My instance status=$mystatus). I 
don't fence other node."
        exit 1
fi

# get target's instance id
instance=""
if [ ! -z "$port" ]; then
        instance=`instance_for_port $port $options`
fi

case $action in 
        reboot|reset)
                status=`instance_status $instance`
                if [ "$status" != "stopped" ]; then
                        instance_off
                fi
                while true;
                do
                        status=`instance_status $instance`
                        if [ "$status" = "stopped" ]; then
                                break
                        fi
                        sleep $sleep_time
                done
                instance_on
                while true;
                do
                        status=`instance_status $instance`
                        if [ "$status" = "running" ]; then
                                break
                        fi
                        sleep $sleep_time
                done
        ;;
        poweron|on)
                instance_on
                while true;
                do
                        status=`instance_status $instance`
                        if [ "$status" = "running" ]; then
                                break
                        fi
                done
        ;;
        poweroff|off)
                instance_off
                while true;
                do
                        status=`instance_status $instance`
                        if [ "$status" = "stopped" ]; then
                                break
                        fi
                        sleep $sleep_time
                done
        ;;
        monitor)
                # Is the device ok?
                aws ec2 describe-instances $options | grep INSTANCES &> 
/dev/null
        ;;
        gethosts|hostlist|list)
                # List of names we know about
                a=`aws ec2 describe-instances $options | awk -v 
tag_pat="^TAGS\t$ec2_tag\t" -F '\t' '{ 
                        if (/^INSTANCES/) { printf "%s\n", $8 }
                        else if ( $1"\t"$2"\t" ~ tag_pat ) { printf "%s\n", $3 }
                        }' | sort -u`
                echo $a
        ;;
        stat|status)
                instance_status $instance > /dev/null
        ;;
        *) ha_log.sh err "Unknown action: $action"; exit 1;;
esac

status=$?

if [ $quiet -eq 1 ]; then
        : nothing
elif [ $status -eq 0 ]; then
        ha_log.sh info "Operation $action passed"
else
        ha_log.sh err "Operation $action failed: $status"
fi
exit $status
_______________________________________________
Linux-HA mailing list
Linux-HA@lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems

Reply via email to