diff --git a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip old mode 100644 new mode 100755 index 1d469f7ff..30ea106e6 --- a/heartbeat/aws-vpc-move-ip +++ b/heartbeat/aws-vpc-move-ip @@ -1,259 +1,306 @@ -#!/bin/bash +#!/bin/sh # # # OCF resource agent to move an IP address within a VPC in the AWS # # Copyright (c) 2017 Markus Guertler (SUSE) # Based on code of Adam Gandelman (GitHub ec2-resource-agents/elasticip) # 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. # -############################################################################### -# For testing purposes delete OCF_ROOT after testing -OCF_ROOT=/usr/lib/ocf/ -# -# INIT -#: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat} -#if [ -f ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs ]; then -# . ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs -#fi - - ####################################################################### # Initialization: -: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} -. ${OCF_FUNCTIONS} -: ${__OCF_ACTION=$1} +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} +. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs + +# Defaults +OCF_RESKEY_awscli_default="/usr/bin/aws" +OCF_RESKEY_profile_default="default" +OCF_RESKEY_monapi_default="false" +: ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}} +: ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}} +: ${OCF_RESKEY_monapi=${OCF_RESKEY_monapi_default}} ####################################################################### USAGE="usage: $0 {start|stop|status|meta-data}"; ############################################################################### ############################################################################### # # Functions # ############################################################################### metadata() { cat < 2.0 Resource Agent to move IP addresses within a VPC of the Amazon Webservices EC2 by changing an entry in an specific routing table Move IP within a APC of the AWS EC2 + - + + +Path to command line tools for AWS + +Path to AWS CLI tools + + + + + +Valid AWS CLI profile name (see ~/.aws/config and 'aws configure') + +profile name + + + + VPC private IP address -vpc ip +VPC private IP + Name of the routing table, where the route for the IP address should be changed, i.e. rtb-... routing table name + -Name of the network interfacen, i.e. eth0 +Name of the network interface, i.e. eth0 network interface name - - -Valid AWS CLI profile name (see ~/.aws/config and 'aws configure') - -profile name - - - + + Enable enhanced monitoring using AWS API calls to check route table entry Enhanced Monitoring - + + END } ec2ip_validate() { - ocf_log debug "function: validate" - - # IP address - [[ -z "$OCF_RESKEY_address" ]] && ocf_log error "IP address parameter not set $OCF_RESKEY_ADDRESS!" && exit $OCF_ERR_CONFIGURED - - # Network Interface - [[ -z "$OCF_RESKEY_interface" ]] && ocf_log error "Network interface parameter not set $OCF_RESKEY_INTERFACE!" && exit $OCF_ERR_CONFIGURED - - # Routing Table - [[ -z "$OCF_RESKEY_routing_table" ]] && ocf_log error "Routing table parameter not set $OCF_RESKEY_ROUTING_TABLE!" && exit $OCF_ERR_CONFIGURED - - COMMANDS="ec2metadata aws ip" - - for i in $COMMANDS ; do - ocf_log debug "Locating command: $i" - [[ ! -x $(which $i) ]] && ocf_log error "Command $i not found or exectuable" && exit $OCF_ERR_INSTALLED - ocf_log debug "Command $i found" + for cmd in aws ip curl; do + check_binary "$cmd" done - ocf_log debug "Testing aws command" - aws --version 2>&1 - if [ "$?" -gt 0 ]; then - ocf_log error "Error while executing aws command as user root! Please check if AWS CLI tools (Python flavor) are properly installed and configured." && exit $OCF_ERR_INSTALLED + if [ -z "$OCF_RESKEY_profile" ]; then + ocf_exit_reason "profile parameter not set" + return $OCF_ERR_CONFIGURED fi - ocf_log debug "ok" - EC2_INSTANCE_ID=$(ec2metadata --instance-id) + EC2_INSTANCE_ID="$(curl -s http://169.254.169.254/latest/meta-data/instance-id)" - if [ -n "$OCF_RESKEY_profile" ]; then - AWS_PROFILE_OPT="--profile $OCF_RESKEY_profile" - else - AWS_PROFILE_OPT="--profile default" + if [ -z "${EC2_INSTANCE_ID}" ]; then + ocf_exit_reason "Instance ID not found. Is this a EC2 instance?" + return $OCF_ERR_GENERIC fi - AWS_MONAPI="${OCF_RESKEY_monapi:-false}" - return $OCF_SUCCESS } ec2ip_monitor() { - ec2ip_validate - if ocf_is_true ${AWS_MONAPI} || [ -n "$STARTING_AWS_IP" ]; then - ocf_log info "function: ec2ip_monitor: check routing table (API call)" - cmd="aws $AWS_PROFILE_OPT ec2 describe-route-tables --route-table-ids $OCF_RESKEY_routing_table" + if ocf_is_true ${OCF_RESKEY_monapi} || [ "$__OCF_ACTION" = "start" ]; then + ocf_log info "monitor: check routing table (API call)" + cmd="$OCF_RESKEY_awscli --profile $OCF_RESKEY_profile --output text ec2 describe-route-tables --route-table-ids $OCF_RESKEY_routing_table" ocf_log debug "executing command: $cmd" - ROUTE_TO_INSTANCE="$($cmd |grep $OCF_RESKEY_address | awk '{ print $3 }')" + ROUTE_TO_INSTANCE="$($cmd | grep $OCF_RESKEY_ip | awk '{ print $3 }')" if [ -z "$ROUTE_TO_INSTANCE" ]; then ROUTE_TO_INSTANCE="" fi - [[ "$EC2_INSTANCE_ID" != "$ROUTE_TO_INSTANCE" ]] && ocf_log warn "not routed to this instance ($EC2_INSTANCE_ID) but to instance $ROUTE_TO_INSTANCE" && return $OCF_NOT_RUNNING + if [ "$EC2_INSTANCE_ID" != "$ROUTE_TO_INSTANCE" ];then + ocf_log warn "not routed to this instance ($EC2_INSTANCE_ID) but to instance $ROUTE_TO_INSTANCE" + return $OCF_NOT_RUNNING + fi else - ocf_log info "function: ec2ip_monitor: Enhanced Monitoring disabled - omitting API call" + ocf_log debug "monitor: Enhanced Monitoring disabled - omitting API call" fi - cmd="ping -W 1 -c 1 $OCF_RESKEY_address" + + cmd="ping -W 1 -c 1 $OCF_RESKEY_ip" ocf_log debug "executing command: $cmd" $cmd > /dev/null - [[ $? -gt 0 ]] && ocf_log warn "IP $OCF_RESKEY_address not locally reachable via ping on this system" && return $OCF_NOT_RUNNING - ocf_log debug "routed in VPC and locally reachable" + if [ "$?" -gt 0 ]; then + ocf_log warn "IP $OCF_RESKEY_ip not locally reachable via ping on this system" + return $OCF_NOT_RUNNING + fi + + ocf_log debug "route in VPC and locally reachable" return $OCF_SUCCESS } ec2ip_drop() { - ocf_log info "function: ec2ip_drop" - cmd="ip addr delete ${OCF_RESKEY_address}/32 dev $OCF_RESKEY_interface" + cmd="ip addr delete ${OCF_RESKEY_ip}/32 dev $OCF_RESKEY_interface" ocf_log debug "executing command: $cmd" $cmd rc=$? - [[ $rc -gt 0 ]] && ocf_log warn "command failed, rc $rc" && return $OCF_ERR_GENERIC - ocf_log debug "command succeeded" + if [ "$rc" -gt 0 ]; then + ocf_log warn "command failed, rc $rc" + return $OCF_ERR_GENERIC + fi + return $OCF_SUCCESS } ec2ip_get_and_configure() { - ocf_log info "function: ec2ip_get_and_configure" # Adjusting the routing table - cmd="aws $AWS_PROFILE_OPT ec2 replace-route --route-table-id $OCF_RESKEY_routing_table --destination-cidr-block ${OCF_RESKEY_address}/32 --instance-id $EC2_INSTANCE_ID" + cmd="$OCF_RESKEY_awscli --profile $OCF_RESKEY_profile ec2 replace-route --route-table-id $OCF_RESKEY_routing_table --destination-cidr-block ${OCF_RESKEY_ip}/32 --instance-id $EC2_INSTANCE_ID" ocf_log debug "executing command: $cmd" $cmd rc=$? - [[ $rc != 0 ]] && ocf_log warn "command failed, rc: $rc" && return $OCF_ERR_GENERIC + if [ "$rc" != 0 ]; then + ocf_log warn "command failed, rc: $rc" + return $OCF_ERR_GENERIC + fi + # Reconfigure the local ip address ec2ip_drop - ip addr add "${OCF_RESKEY_address}/32" dev $OCF_RESKEY_interface + ip addr add "${OCF_RESKEY_ip}/32" dev $OCF_RESKEY_interface rc=$? - [[ $rc != 0 ]] && ocf_log warn "command failed, rc: $rc" && return $OCF_ERR_GENERIC - ocf_log debug "command executed successfully" + if [ $rc != 0 ]; then + ocf_log warn "command failed, rc: $rc" + return $OCF_ERR_GENERIC + fi + return $OCF_SUCCESS } ec2ip_stop() { - ocf_log info "EC2: Bringing down IP address $OCF_RESKEY_address" - ec2ip_validate + ocf_log info "EC2: Bringing down IP address $OCF_RESKEY_ip" + ec2ip_monitor - [[ $? == $OCF_NOT_RUNNING ]] && ocf_log info "EC2: Address $OCF_RESKEY_address already down" && return $OCF_SUCCESS + if [ $? = $OCF_NOT_RUNNING ]; then + ocf_log info "EC2: Address $OCF_RESKEY_ip already down" + return $OCF_SUCCESS + fi + ec2ip_drop - [[ $? != $OCF_SUCCESS ]] && return $OCF_ERR_GENERIC + if [ $? != $OCF_SUCCESS ]; then + return $OCF_ERR_GENERIC + fi + ec2ip_monitor - [[ $? == $OCF_NOT_RUNNING ]] && ocf_log info "EC2: Successfully brought down $OCF_RESKEY_address" && return $OCF_SUCCESS - ocf_log error "EC2: Couldn't bring down IP address $OCF_RESKEY_address on interface $OCF_RESKEY_interface." - return $OCF_ERR_GENERIC + if [ $? != $OCF_NOT_RUNNING ]; then + ocf_log error "EC2: Couldn't bring down IP address $OCF_RESKEY_ip on interface $OCF_RESKEY_interface." + return $OCF_ERR_GENERIC + fi + + ocf_log info "EC2: Successfully brought down $OCF_RESKEY_ip" + return $OCF_SUCCESS } ec2ip_start() { - ocf_log info "EC2: Moving IP address $OCF_RESKEY_address to this host by adjusting routing table $OCF_RESKEY_routing_table" - STARTING_AWS_IP="true" - ec2ip_validate + ocf_log info "EC2: Moving IP address $OCF_RESKEY_ip to this host by adjusting routing table $OCF_RESKEY_routing_table" + ec2ip_monitor - [[ $? == $OCF_SUCCESS ]] && ocf_log info "EC2: $OCF_RESKEY_address already started" && return $OCF_SUCCESS + if [ $? = $OCF_SUCCESS ]; then + ocf_log info "EC2: $OCF_RESKEY_ip already started" + return $OCF_SUCCESS + fi + ocf_log info "EC2: Adjusting routing table and locally configuring IP address" ec2ip_get_and_configure - [[ $? != 0 ]] && ocf_log error "Received $? from 'aws'" && return $OCF_ERR_GENERIC + rc=$? + if [ $rc != $OCF_SUCCESS ]; then + ocf_log error "Received $rc from 'aws'" + return $OCF_ERR_GENERIC + fi + ec2ip_monitor - [[ $? == $OCF_SUCCESS ]] && return $? - ocf_log error "EC2: IP address couldn't be configured on this host (IP: $OCF_RESKEY_address, Interface: $OCF_RESKEY_interface)" - return $OCF_ERR_GENERIC + if [ $? != $OCF_SUCCESS ]; then + ocf_log error "EC2: IP address couldn't be configured on this host (IP: $OCF_RESKEY_ip, Interface: $OCF_RESKEY_interface)" + return $OCF_ERR_GENERIC + fi + + return $OCF_SUCCESS } ############################################################################### # # MAIN # ############################################################################### case $__OCF_ACTION in - meta-data) metadata - exit $OCF_SUCCESS;; - monitor) - ec2ip_monitor;; - stop) - ec2ip_stop;; - validate-all) ec2ip_validate;; + meta-data) + metadata + exit $OCF_SUCCESS + ;; + usage|help) + echo $USAGE + exit $OCF_SUCCESS + ;; +esac + +if ! ocf_is_root; then + ocf_log err "You must be root for $__OCF_ACTION operation." + exit $OCF_ERR_PERM +fi + +ec2ip_validate + +case $__OCF_ACTION in start) ec2ip_start;; - *) exit $OCF_ERR_UNIMPLEMENTED;; + stop) + ec2ip_stop;; + monitor) + ec2ip_monitor;; + validate-all) + exit $?;; + *) + echo $USAGE + exit $OCF_ERR_UNIMPLEMENTED + ;; esac