diff --git a/heartbeat/aliyun-vpc-move-ip b/heartbeat/aliyun-vpc-move-ip index 3091a6d96..a57bbfe34 100755 --- a/heartbeat/aliyun-vpc-move-ip +++ b/heartbeat/aliyun-vpc-move-ip @@ -1,298 +1,311 @@ #!/bin/sh # # OCF resource agent to move an IP address within a VPC in the Aliyun # Based on code of Markus Guertler (GitHub AWS-VPC-move-IP) # Based on code of Adam Gandelman (GitHub ec2-resource-agents/elasticip) # ####################################################################### # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs + +# Parameter defaults + +OCF_RESKEY_address_default="" +OCF_RESKEY_routing_table_default="" +OCF_RESKEY_interface_default="eth0" +OCF_RESKEY_profile_default="default" + +: ${OCF_RESKEY_address=${OCF_RESKEY_address_default}} +: ${OCF_RESKEY_routing_table=${OCF_RESKEY_routing_table_default}} +: ${OCF_RESKEY_interface=${OCF_RESKEY_interface_default}} +: ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}} + ####################################################################### # aliyuncli doesnt work without HOME parameter export HOME="/root" USAGE="usage: $0 {start|stop|status|meta-data}"; ############################################################################### ############################################################################### # # Functions # ############################################################################### ip_get_and_configure() { ocf_log debug "function: ip_get_and_configure" ROUTE_TO_INSTANCE="$($cmd |grep $OCF_RESKEY_address | awk '{ print $3 }')" if [ "$ECS_INSTANCE_ID" != "$ROUTE_TO_INSTANCE" ]; then if [ -n "$ROUTE_TO_INSTANCE" ]; then ip_drop fi cmd="aliyuncli vpc CreateRouteEntry --RouteTableId $OCF_RESKEY_routing_table --DestinationCidrBlock ${OCF_RESKEY_address}/32 --NextHopId $ECS_INSTANCE_ID --NextHopType Instance --output text" ocf_log debug "executing command: $cmd" $cmd rc=$? while [ $rc -ne 0 ]; do sleep 1 cmd="aliyuncli vpc CreateRouteEntry --RouteTableId $OCF_RESKEY_routing_table --DestinationCidrBlock ${OCF_RESKEY_address}/32 --NextHopId $ECS_INSTANCE_ID --NextHopType Instance --output text" ocf_log debug "executing command: $cmd" $cmd rc=$? done wait_for_started fi # Reconfigure the local ip address ip addr add "${OCF_RESKEY_address}/32" dev $OCF_RESKEY_interface rc=$? if [ $rc -ne 0 ]; then ocf_log err "command failed, rc: $rc" return $OCF_ERR_GENERIC fi ocf_log debug "IP added" return $OCF_SUCCESS } ip_drop() { ocf_log debug "function: ip_drop" cmd="ip addr delete ${OCF_RESKEY_address}/32 dev $OCF_RESKEY_interface" ocf_log debug "executing command: $cmd" $cmd rc=$? if [ $rc -ne 0 ] && [ $rc -ne 2 ]; then ocf_log err "command failed, rc $rc" return $OCF_ERR_GENERIC fi cmd="aliyuncli vpc DeleteRouteEntry --RouteTableId $OCF_RESKEY_routing_table --DestinationCidrBlock ${OCF_RESKEY_address}/32 --NextHopId $ROUTE_TO_INSTANCE --output text" ocf_log debug "executing command: $cmd" $cmd if [ $? -ne 0 ]; then ocf_log err "command failed, rc: $rc" return $OCF_ERR_GENERIC fi wait_for_deleted ocf_log debug "IP dropped" return $OCF_SUCCESS } wait_for_started() { cmd="aliyuncli vpc DescribeRouteTables --RouteTableId $OCF_RESKEY_routing_table --output text" ocf_log debug "executing command: $cmd" ROUTE_TO_INSTANCE="$($cmd | grep $OCF_RESKEY_address | awk '{ print $3 }')" while [ "$ECS_INSTANCE_ID" != "$ROUTE_TO_INSTANCE" ]; do sleep 3 cmd="aliyuncli vpc DescribeRouteTables --RouteTableId $OCF_RESKEY_routing_table --output text" ocf_log debug "executing command: $cmd" ROUTE_TO_INSTANCE="$($cmd | grep $OCF_RESKEY_address | awk '{ print $3 }')" done } wait_for_deleted() { ROUTE_TO_INSTANCE="$($cmd |grep $OCF_RESKEY_address | awk '{ print $3 }')" while [ ! -z "$ROUTE_TO_INSTANCE" ]; do sleep 1 cmd="aliyuncli vpc DescribeRouteTables --RouteTableId $OCF_RESKEY_routing_table --output text" ocf_log debug "executing command: $cmd" ROUTE_TO_INSTANCE="$($cmd |grep $OCF_RESKEY_address | awk '{ print $3 }')" done } ecs_ip_metadata() { cat < 2.0 Resource Agent to move IP addresses within a VPC of the Aliyun Webservices ECS by changing an entry in an specific routing table Move IP within a VPC of the Aliyun ECS VPC private IP address vpc ip - + Name of the routing table, where the route for the IP address should be changed, i.e. vtb-... routing table name - + Name of the network interface, i.e. eth0 network interface name - + Valid Aliyun CLI profile name (see 'aliyuncli configure'). See https://www.alibabacloud.com/help/doc-detail/43039.htm?spm=a2c63.p38356.b99.16.38a914abRZtOU3 for more information about aliyuncli. profile name - + END } ecs_ip_validate() { ocf_log debug "function: validate" # IP address if [ -z "$OCF_RESKEY_address" ]; then ocf_log err "IP address parameter not set $OCF_RESKEY_ADDRESS!" exit $OCF_ERR_CONFIGURED fi # Network Interface if [ -z "$OCF_RESKEY_interface" ]; then ocf_log err "Network interface parameter not set $OCF_RESKEY_INTERFACE!" exit $OCF_ERR_CONFIGURED fi # Routing Table if [ -z "$OCF_RESKEY_routing_table" ]; then ocf_log err "Routing table parameter not set $OCF_RESKEY_ROUTING_TABLE!" exit $OCF_ERR_CONFIGURED fi if [ -z "${ECS_INSTANCE_ID}" ]; then ocf_exit_reason "Instance ID not found. Is this a ECS instance?" return $OCF_ERR_GENERIC fi return $OCF_SUCCESS } ecs_ip_start() { ocf_log info "ECS: Moving IP address $OCF_RESKEY_address to this host by adjusting routing table $OCF_RESKEY_routing_table" ecs_ip_monitor if [ $? = $OCF_SUCCESS ]; then ocf_log info "ECS: $OCF_RESKEY_address already started" return $OCF_SUCCESS fi ocf_log info "ECS: Adjusting routing table and locally configuring IP address" ip_get_and_configure rc=$? if [ $rc -ne 0 ]; then ocf_log err "Received $rc from 'aliyun cli'" return $OCF_ERR_GENERIC fi ecs_ip_monitor rc=$? if [ $rc -ne $OCF_SUCCESS ]; then ocf_log err "IP address couldn't be configured on this host (IP: $OCF_RESKEY_address, Interface: $OCF_RESKEY_interface)" return $rc fi return $OCF_SUCCESS } ecs_ip_stop() { ocf_log info "ECS: Bringing down IP address $OCF_RESKEY_address" ecs_ip_monitor if [ $? = $OCF_NOT_RUNNING ]; then ocf_log info "ECS: Address $OCF_RESKEY_address already down" return $OCF_SUCCESS fi ip_drop if [ $? -ne $OCF_SUCCESS ]; then ocf_log err "ECS: Couldn't drop IP address $OCF_RESKEY_address on interface $OCF_RESKEY_interface." return $OCF_ERR_GENERIC fi ecs_ip_monitor if [ $? = $OCF_NOT_RUNNING ]; then ocf_log info "ECS: Successfully brought down $OCF_RESKEY_address" return $OCF_SUCCESS fi ocf_log err "ECS: Couldn't bring down IP address $OCF_RESKEY_address on interface $OCF_RESKEY_interface." return $OCF_ERR_GENERIC } ecs_ip_monitor() { ocf_log debug "function: ecsip_monitor: check routing table" cmd="aliyuncli vpc DescribeRouteTables --RouteTableId $OCF_RESKEY_routing_table --output text" ocf_log debug "executing command: $cmd" ROUTE_TO_INSTANCE="$($cmd |grep $OCF_RESKEY_address | awk '{ print $3 }')" if [ "$ECS_INSTANCE_ID" != "$ROUTE_TO_INSTANCE" ]; then ocf_log debug "not routed to this instance ($ECS_INSTANCE_ID) but to instance $ROUTE_TO_INSTANCE" return $OCF_NOT_RUNNING fi cmd="ping -W 1 -c 1 $OCF_RESKEY_address" ocf_log debug "executing command: $cmd" $cmd > /dev/null if [ $? -ne 0 ]; then ocf_log debug "IP $OCF_RESKEY_address not locally reachable via ping on this system" return $OCF_NOT_RUNNING fi ocf_log debug "routed in VPC and locally reachable" return $OCF_SUCCESS } ############################################################################### # # MAIN # ############################################################################### case $__OCF_ACTION in meta-data) ecs_ip_metadata exit $OCF_SUCCESS;; validate-all) ecs_ip_validate;; esac ECS_INSTANCE_ID="$(curl -s http://100.100.100.200/latest/meta-data/instance-id)" case $__OCF_ACTION in start) ecs_ip_validate ecs_ip_start;; stop) ecs_ip_stop;; monitor) ecs_ip_monitor;; *) exit $OCF_ERR_UNIMPLEMENTED;; esac diff --git a/heartbeat/anything b/heartbeat/anything index d8f4d2dd6..a20c42fa1 100755 --- a/heartbeat/anything +++ b/heartbeat/anything @@ -1,328 +1,344 @@ #!/bin/sh # # OCF Resource Agent compliant resource script. # # Copyright (c) 2009 IN-telegence GmbH & Co. KG, Dominik Klein # 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. # OCF instance parameters # OCF_RESKEY_binfile # OCF_RESKEY_cmdline_options # OCF_RESKEY_workdir # OCF_RESKEY_pidfile # OCF_RESKEY_logfile # OCF_RESKEY_errlogfile # OCF_RESKEY_user # OCF_RESKEY_monitor_hook # OCF_RESKEY_stop_timeout # # This RA starts $binfile with $cmdline_options as $user in $workdir and writes a $pidfile from that. # If you want it to, it logs: # - stdout to $logfile, stderr to $errlogfile or # - stdout and stderr to $logfile # - or to will be captured by lrmd if these options are omitted. # Monitoring is done through $pidfile or your custom $monitor_hook script. # The RA expects the program to keep running "daemon-like" and # not just quit and exit. So this is NOT (yet - feel free to # enhance) a way to just run a single one-shot command which just # does something and then exits. # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs +# Parameter defaults + +OCF_RESKEY_binfile_default="" +OCF_RESKEY_workdir_default="" +OCF_RESKEY_pidfile_default="${HA_VARRUN}/anything_${OCF_RESOURCE_INSTANCE}.pid" +OCF_RESKEY_logfile_default="/dev/null" +OCF_RESKEY_user_default="root" +OCF_RESKEY_stop_timeout_default="" + +: ${OCF_RESKEY_binfile=${OCF_RESKEY_binfile_default}} +: ${OCF_RESKEY_workdir=${OCF_RESKEY_workdir_default}} +: ${OCF_RESKEY_pidfile=${OCF_RESKEY_pidfile_default}} +: ${OCF_RESKEY_logfile=${OCF_RESKEY_logfile_default}} +: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}} +: ${OCF_RESKEY_stop_timeout=${OCF_RESKEY_stop_timeout_default}} + getpid() { grep -o '[0-9]*' $1 } anything_status() { if test -f "$pidfile" then if pid=`getpid $pidfile` && [ "$pid" ] && kill -s 0 $pid then return $OCF_SUCCESS else # pidfile w/o process means the process died return $OCF_ERR_GENERIC fi else return $OCF_NOT_RUNNING fi } anything_start() { if ! anything_status then #Make sure that PID Directory exists and is writable by proper user piddir=`dirname $pidfile` if ! su -s /bin/sh - $user -c "test -w $piddir"; then #PID Directory is not writeable by user ocf_log warn "Directory $piddir is not writable by $user, attempting to fix." ocf_log info "Creating directory $piddir" mkdir -p $piddir ocf_log info "Changing permissions for $piddir for user $user" chown $user: $piddir else ocf_log debug "Directory $piddir exists, and is writeable by $user. All fine" fi if [ -n "$logfile" -a -n "$errlogfile" ] then # We have logfile and errlogfile, so redirect STDOUT und STDERR to different files cmd="su - $user -c \"cd $workdir; nohup $binfile $cmdline_options >> $logfile 2>> $errlogfile & \"'echo \$!' " else # We only have logfile so redirect STDOUT and STDERR to the same file cmd="su - $user -c \"cd $workdir; nohup $binfile $cmdline_options >> $logfile 2>&1 & \"'echo \$!' " fi ocf_log debug "Starting $process: $cmd" # Execute the command as created above eval $cmd > $pidfile if anything_status then ocf_log debug "$process: $cmd started successfully, calling monitor" anything_monitor myres=$? return $myres else ocf_log err "$process: $cmd could not be started" return $OCF_ERR_GENERIC fi else # If already running, consider start successful ocf_log debug "$process: $cmd is already running" return $OCF_SUCCESS fi } anything_stop() { local rc=$OCF_SUCCESS if [ -n "$OCF_RESKEY_stop_timeout" ] then stop_timeout=$OCF_RESKEY_stop_timeout elif [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then # Allow 2/3 of the action timeout for the orderly shutdown # (The origin unit is ms, hence the conversion) stop_timeout=$((OCF_RESKEY_CRM_meta_timeout/1500)) else stop_timeout=10 fi if anything_status then pid=`getpid $pidfile` kill $pid i=0 while [ $i -lt $stop_timeout ] do if ! anything_status then rm -f $pidfile return $OCF_SUCCESS fi sleep 1 i=$((i+1)) done ocf_log warn "Stop with SIGTERM failed/timed out, now sending SIGKILL." kill -s 9 $pid while : do if ! anything_status then ocf_log warn "SIGKILL did the job." rc=$OCF_SUCCESS break fi ocf_log info "The job still hasn't stopped yet. Waiting..." sleep 1 done fi rm -f $pidfile return $rc } anything_monitor() { anything_status ret=$? if [ $ret -eq $OCF_SUCCESS ] then if [ -n "$OCF_RESKEY_monitor_hook" ]; then eval "$OCF_RESKEY_monitor_hook" if [ $? -ne $OCF_SUCCESS ]; then return ${OCF_ERR_GENERIC} fi return $OCF_SUCCESS else true fi else return $ret fi } # FIXME: Attributes special meaning to the resource id process="$OCF_RESOURCE_INSTANCE" binfile="$OCF_RESKEY_binfile" cmdline_options="$OCF_RESKEY_cmdline_options" workdir="$OCF_RESKEY_workdir" pidfile="$OCF_RESKEY_pidfile" [ -z "$pidfile" ] && pidfile=${HA_VARRUN}/anything_${process}.pid logfile="${OCF_RESKEY_logfile:-/dev/null}" errlogfile="$OCF_RESKEY_errlogfile" user="$OCF_RESKEY_user" [ -z "$user" ] && user=root anything_validate() { if ! su - $user -c "test -x $binfile" then ocf_log err "binfile $binfile does not exist or is not executable by $user." exit $OCF_ERR_INSTALLED fi if ! getent passwd $user >/dev/null 2>&1 then ocf_log err "user $user does not exist." exit $OCF_ERR_INSTALLED fi for logfilename in "$logfile" "$errlogfile" do if [ -n "$logfilename" ]; then mkdir -p `dirname $logfilename` || { ocf_log err "cannot create $(dirname $logfilename)" exit $OCF_ERR_INSTALLED } fi done [ "x$workdir" != x -a ! -d "$workdir" ] && { ocf_log err "working directory $workdir doesn't exist" exit $OCF_ERR_INSTALLED } return $OCF_SUCCESS } anything_meta() { cat < 1.0 This is a generic OCF RA to manage almost anything. Manages an arbitrary service The full name of the binary to be executed. This is expected to keep running with the same pid and not just do something and exit. Full path name of the binary to be executed - + Command line options to pass to the binary Command line options The path from where the binfile will be executed. Full path name of the work directory - + File to read/write the PID from/to. File to write STDOUT to - + File to write STDOUT to File to write STDOUT to - + File to write STDERR to File to write STDERR to User to run the command as User to run the command as - + Command to run in monitor operation Command to run in monitor operation In the stop operation: Seconds to wait for kill -TERM to succeed before sending kill -SIGKILL. Defaults to 2/3 of the stop operation timeout. Seconds to wait after having sent SIGTERM before sending SIGKILL in stop operation - + END exit 0 } case "$1" in meta-data|metadata|meta_data) anything_meta ;; start) anything_start ;; stop) anything_stop ;; monitor) anything_monitor ;; validate-all) anything_validate ;; *) ocf_log err "$0 was called with unsupported arguments: $*" exit $OCF_ERR_UNIMPLEMENTED ;; esac