diff --git a/heartbeat/awseip b/heartbeat/awseip index fc2d61a6b..445a03666 100755 --- a/heartbeat/awseip +++ b/heartbeat/awseip @@ -1,285 +1,286 @@ #!/bin/sh # # # Manage Elastic IP with Pacemaker # # # Copyright 2016-2018 guessi <guessi@gmail.com> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # # # Prerequisites: # # - preconfigured AWS CLI running environment (AccessKey, SecretAccessKey, etc.) -# - a reserved secondary private IP address for EC2 instances high availablity +# - a reserved secondary private IP address for EC2 instances high availability # - IAM user role with the following permissions: # * DescribeInstances # * AssociateAddress +# * DescribeAddresses # * DisassociateAddress # ####################################################################### # Initialization: : ${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_api_delay_default="3" : ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}} : ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}} : ${OCF_RESKEY_api_delay=${OCF_RESKEY_api_delay_default}} meta_data() { cat <<END <?xml version="1.0"?> <!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> <resource-agent name="awseip"> <version>1.0</version> <longdesc lang="en"> Resource Agent for Amazon AWS Elastic IP Addresses. It manages AWS Elastic IP Addresses with awscli. Credentials needs to be setup by running "aws configure". See https://aws.amazon.com/cli/ for more information about awscli. </longdesc> <shortdesc lang="en">Amazon AWS Elastic IP Address Resource Agent</shortdesc> <parameters> <parameter name="awscli" unique="0"> <longdesc lang="en"> command line tools for aws services </longdesc> <shortdesc lang="en">aws cli tools</shortdesc> <content type="string" default="${OCF_RESKEY_awscli_default}" /> </parameter> <parameter name="profile"> <longdesc lang="en"> Valid AWS CLI profile name (see ~/.aws/config and 'aws configure') </longdesc> <shortdesc lang="en">profile name</shortdesc> <content type="string" default="${OCF_RESKEY_profile_default}" /> </parameter> <parameter name="elastic_ip" unique="1" required="1"> <longdesc lang="en"> reserved elastic ip for ec2 instance </longdesc> <shortdesc lang="en">reserved elastic ip for ec2 instance</shortdesc> <content type="string" default="" /> </parameter> <parameter name="allocation_id" unique="1" required="1"> <longdesc lang="en"> reserved allocation id for ec2 instance </longdesc> <shortdesc lang="en">reserved allocation id for ec2 instance</shortdesc> <content type="string" default="" /> </parameter> <parameter name="private_ip_address" unique="1" required="0"> <longdesc lang="en"> predefined private ip address for ec2 instance </longdesc> <shortdesc lang="en">predefined private ip address for ec2 instance</shortdesc> <content type="string" default="" /> </parameter> <parameter name="api_delay" unique="0"> <longdesc lang="en"> a short delay between API calls, to avoid sending API too quick </longdesc> <shortdesc lang="en">a short delay between API calls</shortdesc> <content type="integer" default="${OCF_RESKEY_api_delay_default}" /> </parameter> </parameters> <actions> <action name="start" timeout="30s" /> <action name="stop" timeout="30s" /> <action name="monitor" timeout="30s" interval="20s" depth="0" /> <action name="migrate_to" timeout="30s" /> <action name="migrate_from" timeout="30s" /> <action name="meta-data" timeout="5s" /> <action name="validate" timeout="10s" /> <action name="validate-all" timeout="10s" /> </actions> </resource-agent> END } ####################################################################### awseip_usage() { cat <<END usage: $0 {start|stop|monitor|migrate_to|migrate_from|validate|validate-all|meta-data} Expects to have a fully populated OCF RA-compliant environment set. END } awseip_start() { awseip_monitor && return $OCF_SUCCESS if [ -n "${PRIVATE_IP_ADDRESS}" ]; then NETWORK_INTERFACES_MACS="$(curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/)" for MAC in ${NETWORK_INTERFACES_MACS}; do curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC}/local-ipv4s | grep -q "^${PRIVATE_IP_ADDRESS}$" if [ $? -eq 0 ]; then NETWORK_ID="$(curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC}/interface-id)" fi done $AWSCLI --profile $OCF_RESKEY_profile ec2 associate-address \ --network-interface-id ${NETWORK_ID} \ --allocation-id ${ALLOCATION_ID} \ --private-ip-address ${PRIVATE_IP_ADDRESS} RET=$? else $AWSCLI --profile $OCF_RESKEY_profile ec2 associate-address \ --instance-id ${INSTANCE_ID} \ --allocation-id ${ALLOCATION_ID} RET=$? fi # delay to avoid sending request too fast sleep ${OCF_RESKEY_api_delay} if [ $RET -ne 0 ]; then return $OCF_NOT_RUNNING fi ocf_log info "elastic_ip has been successfully brought up (${ELASTIC_IP})" return $OCF_SUCCESS } awseip_stop() { awseip_monitor || return $OCF_SUCCESS ASSOCIATION_ID=$($AWSCLI --profile $OCF_RESKEY_profile --output json ec2 describe-addresses \ --allocation-id ${ALLOCATION_ID} | grep -m 1 "AssociationId" | awk -F'"' '{print$4}') if [ -z "${ASSOCIATION_ID}" ]; then ocf_log info "ASSOCIATION_ID not found while stopping AWS Elastic IP" return $OCF_NOT_RUNNING fi $AWSCLI --profile ${OCF_RESKEY_profile} \ ec2 disassociate-address \ --association-id ${ASSOCIATION_ID} RET=$? # delay to avoid sending request too fast sleep ${OCF_RESKEY_api_delay} if [ $RET -ne 0 ]; then return $OCF_NOT_RUNNING fi ocf_log info "elastic_ip has been successfully brought down (${ELASTIC_IP})" return $OCF_SUCCESS } awseip_monitor() { $AWSCLI --profile $OCF_RESKEY_profile ec2 describe-instances --instance-id "${INSTANCE_ID}" | grep -q "${ELASTIC_IP}" RET=$? if [ $RET -ne 0 ]; then return $OCF_NOT_RUNNING fi return $OCF_SUCCESS } awseip_validate() { check_binary ${AWSCLI} if [ -z "$OCF_RESKEY_profile" ]; then ocf_exit_reason "profile parameter not set" return $OCF_ERR_CONFIGURED fi if [ -z "${INSTANCE_ID}" ]; then ocf_exit_reason "instance_id not found. Is this a EC2 instance?" return $OCF_ERR_GENERIC fi return $OCF_SUCCESS } case $__OCF_ACTION in meta-data) meta_data exit $OCF_SUCCESS ;; esac AWSCLI="${OCF_RESKEY_awscli}" ELASTIC_IP="${OCF_RESKEY_elastic_ip}" ALLOCATION_ID="${OCF_RESKEY_allocation_id}" PRIVATE_IP_ADDRESS="${OCF_RESKEY_private_ip_address}" INSTANCE_ID="$(curl -s http://169.254.169.254/latest/meta-data/instance-id)" case $__OCF_ACTION in start) awseip_validate awseip_start ;; stop) awseip_stop ;; monitor) awseip_monitor ;; migrate_to) ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} to ${OCF_RESKEY_CRM_meta_migrate_target}." awseip_stop ;; migrate_from) ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} from ${OCF_RESKEY_CRM_meta_migrate_source}." awseip_start ;; reload) ocf_log info "Reloading ${OCF_RESOURCE_INSTANCE} ..." ;; validate|validate-all) awseip_validate ;; usage|help) awseip_usage exit $OCF_SUCCESS ;; *) awseip_usage exit $OCF_ERR_UNIMPLEMENTED ;; esac rc=$? ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc" exit $rc