File 0015-High-aws-vpc-route53-Add-agent-for-AWS-Route-53-fate.patch of Package resource-agents.11561
From 8b5f5607cd01cf80ae646086c39d162c1bc32959 Mon Sep 17 00:00:00 2001
From: scalingbits <scalingbits@users.noreply.github.com>
Date: Wed, 28 Jun 2017 18:01:13 +0200
Subject: [PATCH 15/17] High: aws-vpc-route53: Add agent for AWS Route 53
(fate#322781)
This agent changes a private zone Route 53 agent to
the appropriate IP address. This agent has been
developed in collaboration of SUSE and Amazon/AWS.
---
heartbeat/Makefile.am | 1 +
heartbeat/aws-vpc-route53 | 334 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 335 insertions(+)
create mode 100755 heartbeat/aws-vpc-route53
diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am
index 3b26f656..071c54c6 100644
--- a/heartbeat/Makefile.am
+++ b/heartbeat/Makefile.am
@@ -59,6 +59,7 @@ ocf_SCRIPTS = ClusterMon \
AoEtarget \
apache \
asterisk \
+ aws-vpc-route53 \
awseip \
awsvip \
nginx \
diff --git a/heartbeat/aws-vpc-route53 b/heartbeat/aws-vpc-route53
new file mode 100755
index 00000000..a6e7218a
--- /dev/null
+++ b/heartbeat/aws-vpc-route53
@@ -0,0 +1,334 @@
+#!/bin/bash
+#
+# Copyright 2017 Amazon.com, Inc. and its affiliates. All Rights Reserved.
+# Licensed under the MIT License.
+#
+# Copyright 2017 Amazon.com, Inc. and its affiliates
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy of
+# this software and associated documentation files (the "Software"), to deal in
+# the Software without restriction, including without limitation the rights to
+# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is furnished to do
+# so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+#
+#
+#
+# OCF resource agent to move an IP address within a VPC in the AWS
+# Written by Stefan Schneider , Martin Tegmeier (AWS)
+# Based on code of Markus Guertler#
+#
+#
+# OCF resource agent to move an IP address within a VPC in the AWS
+# Written by Stefan Schneider (AWS) , Martin Tegmeier (AWS)
+# Based on code of Markus Guertler (SUSE)
+#
+# Mar. 15, 2017, vers 1.0.2
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+OCF_RESKEY_ttl_default=10
+
+: ${OCF_RESKEY_ttl:=${OCF_RESKEY_ttl_default}}
+
+#######################################################################
+
+usage() {
+ cat <<-EOT
+ usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+ EOT
+}
+
+metadata() {
+cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="aws-vpc-route53">
+<version>1.0</version>
+<longdesc lang="en">
+Update Route53 record of Amazon Webservices EC2 by updating an entry in a
+hosted zone ID table.
+
+AWS instances will require policies which allow them to update Route53 ARecords:
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Sid": "Stmt1471878724000",
+ "Effect": "Allow",
+ "Action": [
+ "route53:ChangeResourceRecordSets",
+ "route53:GetChange",
+ "route53:ListResourceRecordSets",
+ ],
+ "Resource": [
+ "*"
+ ]
+ }
+ ]
+}
+
+Example Cluster Configuration:
+
+Use a configuration in "crm configure edit" which looks as follows. Replace
+hostedzoneid, fullname and profile with the appropriate values:
+
+primitive res_route53 ocf:heartbeat:aws-vpc-route53 \
+ params hostedzoneid=Z22XDORCGO4P3T fullname=suse-service5.awslab.cloud.sap.corp. profile=cluster \
+ op start interval=0 timeout=180 \
+ op stop interval=0 timeout=180 \
+ op monitor interval=300 timeout=180 \
+ meta target-role=Started
+</longdesc>
+<shortdesc lang="en">Update Route53 VPC record for AWS EC2</shortdesc>
+<parameters>
+<parameter name="hostedzoneid" required="1">
+<longdesc lang="en">
+Hosted zone ID of Route 53. This is the table of
+the Route 53 record.
+</longdesc>
+<shortdesc lang="en">AWS hosted zone ID</shortdesc>
+<content type="string" default="" />
+</parameter>
+<parameter name="fullname" required="1">
+<longdesc lang="en">
+The full name of the service which will host the IP address.
+Example: suse-service5.awslab.cloud.sap.corp.
+Note: The trailing dot is important to Route53!
+</longdesc>
+<shortdesc lang="en">Full service name</shortdesc>
+<content type="string" default="" />
+</parameter>
+<parameter name="ttl" required="0">
+<longdesc lang="en">
+Time to live for Route53 ARECORD
+</longdesc>
+<shortdesc lang="en">ARECORD TTL</shortdesc>
+<content type="string" default="${OCF_RESKEY_ttl_default}" />
+</parameter>
+<parameter name="profile" required="1">
+<longdesc lang="en">
+The name of the AWS CLI profile of the root account. This
+profile will have to use the "text" format for CLI output.
+The file /root/.aws/config should have an entry which looks
+like:
+
+ [profile cluster]
+ region = us-east-1
+ output = text
+
+"cluster" is the name which has to be used in the cluster
+configuration. The region has to be the current one. The
+output has to be "text".
+</longdesc>
+<shortdesc lang="en">AWS Profile Name</shortdesc>
+<content type="string" default="" />
+</parameter>
+</parameters>
+<actions>
+<action name="start" timeout="180" />
+<action name="stop" timeout="180" />
+<action name="monitor" depth="0" timeout="180" interval="300" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+debugger() {
+ ocf_log debug "DEBUG: $1"
+}
+
+ec2ip_validate() {
+ debugger "function: validate"
+
+ # Full name
+ [[ -z "$OCF_RESKEY_fullname" ]] && ocf_log error "Full name parameter not set $OCF_RESKEY_fullname!" && exit $OCF_ERR_CONFIGURED
+
+ # Hosted Zone ID
+ [[ -z "$OCF_RESKEY_hostedzoneid" ]] && ocf_log error "Hosted Zone ID parameter not set $OCF_RESKEY_hostedzoneid!" && exit $OCF_ERR_CONFIGURED
+
+ # profile
+ [[ -z "$OCF_RESKEY_profile" ]] && ocf_log error "AWS CLI profile not set $OCF_RESKEY_profile!" && exit $OCF_ERR_CONFIGURED
+
+ # TTL
+ [[ -z "$OCF_RESKEY_ttl" ]] && ocf_log error "TTL not set $OCF_RESKEY_ttl!" && exit $OCF_ERR_CONFIGURED
+
+ debugger "Testing aws command"
+ aws --version 2>&1
+ if [ "$?" -gt 0 ]; then
+ 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
+ fi
+ debugger "ok"
+
+ if [ -n "$OCF_RESKEY_profile" ]; then
+ AWS_PROFILE_OPT="--profile $OCF_RESKEY_profile"
+ else
+ AWS_PROFILE_OPT="--profile default"
+ fi
+
+ return $OCF_SUCCESS
+}
+
+ec2ip_monitor() {
+ ec2ip_validate
+ debugger "function: ec2ip_monitor: check Route53 record "
+ IPADDRESS="$(ec2metadata aws ip | grep local-ipv4 | /usr/bin/awk '{ print $2 }')"
+ ARECORD="$(aws $AWS_PROFILE_OPT route53 list-resource-record-sets --hosted-zone-id $OCF_RESKEY_hostedzoneid --query "ResourceRecordSets[?Name=='$OCF_RESKEY_fullname']" | grep RESOURCERECORDS | /usr/bin/awk '{ print $2 }' )"
+ debugger "function: ec2ip_monitor: found IP address: $ARECORD ."
+ if [ "${ARECORD}" == "${IPADDRESS}" ]; then
+ debugger "function: ec2ip_monitor: ARECORD $ARECORD found"
+ return $OCF_SUCCESS
+ else
+ debugger "function: ec2ip_monitor: no ARECORD found"
+ return $OCF_NOT_RUNNING
+ fi
+
+ return $OCF_SUCCESS
+}
+
+ec2ip_stop() {
+ ocf_log info "EC2: Bringing down Route53 agent. (Will remove ARECORD)"
+ IPADDRESS="$(ec2metadata aws ip | grep local-ipv4 | /usr/bin/awk '{ print $2 }')"
+ ARECORD="$(aws $AWS_PROFILE_OPT route53 list-resource-record-sets --hosted-zone-id $OCF_RESKEY_hostedzoneid --query "ResourceRecordSets[?Name=='$OCF_RESKEY_fullname']" | grep RESOURCERECORDS | /usr/bin/awk '{ print $2 }' )"
+ debugger "function: ec2ip_monitor: found IP address: $ARECORD ."
+ if [ ${ARECORD} != ${IPADDRESS} ]; then
+ debugger "function: ec2ip_monitor: no ARECORD found"
+ return $OCF_SUCCESS
+ else
+ debugger "function: ec2ip_monitor: ARECORD $ARECORD found"
+ # determine IP address
+ IPADDRESS="$(ec2metadata aws ip | grep local-ipv4 | /usr/bin/awk '{ print $2 }')"
+ # Patch file
+ debugger "function ec2ip_stop: will delete IP address to ${IPADDRESS}"
+ ocf_log info "EC2: Updating Route53 $OCF_RESKEY_hostedzoneid with $IPADDRESS for $OCF_RESKEY_fullname"
+ ROUTE53RECORD="/var/tmp/route53-${OCF_RESKEY_hostedzoneid}-${IPADDRESS}.json"
+ echo "{ " > ${ROUTE53RECORD}
+ echo " \"Comment\": \"Update record to reflect new IP address for a system \", " >> ${ROUTE53RECORD}
+ echo " \"Changes\": [ " >> ${ROUTE53RECORD}
+ echo " { " >> ${ROUTE53RECORD}
+ echo " \"Action\": \"DELETE\", " >> ${ROUTE53RECORD}
+ echo " \"ResourceRecordSet\": { " >> ${ROUTE53RECORD}
+ echo " \"Name\": \"${OCF_RESKEY_fullname}\", " >> ${ROUTE53RECORD}
+ echo " \"Type\": \"A\", " >> ${ROUTE53RECORD}
+ echo " \"TTL\": ${OCF_RESKEY_ttl}, " >> ${ROUTE53RECORD}
+ echo " \"ResourceRecords\": [ " >> ${ROUTE53RECORD}
+ echo " { " >> ${ROUTE53RECORD}
+ echo " \"Value\": \"${IPADDRESS}\" " >> ${ROUTE53RECORD}
+ echo " } " >> ${ROUTE53RECORD}
+ echo " ] " >> ${ROUTE53RECORD}
+ echo " } " >> ${ROUTE53RECORD}
+ echo " } " >> ${ROUTE53RECORD}
+ echo " ] " >> ${ROUTE53RECORD}
+ echo "}" >> ${ROUTE53RECORD}
+ cmd="aws --profile ${OCF_RESKEY_profile} route53 change-resource-record-sets --hosted-zone-id ${OCF_RESKEY_hostedzoneid} \
+ --change-batch file://${ROUTE53RECORD} "
+ debugger "function ec2ip_start: executing command: $cmd"
+ CHANGEID=$($cmd | grep CHANGEINFO | /usr/bin/awk -F'\t' '{ print $3 }' )
+ debugger "Change id: ${CHANGEID}"
+ rm ${ROUTE53RECORD}
+ CHANGEID=$(echo $CHANGEID |cut -d'/' -f 3 |cut -d'"' -f 1 )
+ debugger "Change id: ${CHANGEID}"
+ STATUS="PENDING"
+ MYSECONDS=2
+ while [ "$STATUS" = 'PENDING' ]; do
+ sleep ${MYSECONDS}
+ STATUS="$(aws --profile ${OCF_RESKEY_profile} route53 get-change --id $CHANGEID | grep CHANGEINFO | /usr/bin/awk -F'\t' '{ print $4 }' |cut -d'"' -f 2 )"
+ debugger "Waited for ${MYSECONDS} seconds and checked execution of Route 53 update status: ${STATUS} "
+ done
+
+ return $OCF_SUCCESS
+ fi
+
+ return $OCF_SUCCESS
+}
+
+ec2ip_start() {
+ # determine IP address
+ IPADDRESS="$(ec2metadata aws ip | grep local-ipv4 | /usr/bin/awk '{ print $2 }')"
+ # Patch file
+ debugger "function ec2ip_start: will update IP address to ${IPADDRESS}"
+ ocf_log info "EC2: Updating Route53 $OCF_RESKEY_hostedzoneid with $IPADDRESS for $OCF_RESKEY_fullname"
+ ROUTE53RECORD="/var/tmp/route53-${OCF_RESKEY_hostedzoneid}-${IPADDRESS}.json"
+ echo "{ " > ${ROUTE53RECORD}
+ echo " \"Comment\": \"Update record to reflect new IP address for a system \", " >> ${ROUTE53RECORD}
+ echo " \"Changes\": [ " >> ${ROUTE53RECORD}
+ echo " { " >> ${ROUTE53RECORD}
+ echo " \"Action\": \"UPSERT\", " >> ${ROUTE53RECORD}
+ echo " \"ResourceRecordSet\": { " >> ${ROUTE53RECORD}
+ echo " \"Name\": \"${OCF_RESKEY_fullname}\", " >> ${ROUTE53RECORD}
+ echo " \"Type\": \"A\", " >> ${ROUTE53RECORD}
+ echo " \"TTL\": ${OCF_RESKEY_ttl} , " >> ${ROUTE53RECORD}
+ echo " \"ResourceRecords\": [ " >> ${ROUTE53RECORD}
+ echo " { " >> ${ROUTE53RECORD}
+ echo " \"Value\": \"${IPADDRESS}\" " >> ${ROUTE53RECORD}
+ echo " } " >> ${ROUTE53RECORD}
+ echo " ] " >> ${ROUTE53RECORD}
+ echo " } " >> ${ROUTE53RECORD}
+ echo " } " >> ${ROUTE53RECORD}
+ echo " ] " >> ${ROUTE53RECORD}
+ echo "}" >> ${ROUTE53RECORD}
+ cmd="aws --profile ${OCF_RESKEY_profile} route53 change-resource-record-sets --hosted-zone-id ${OCF_RESKEY_hostedzoneid} \
+ --change-batch file://${ROUTE53RECORD} "
+ debugger "function ec2ip_start: executing command: $cmd"
+ CHANGEID=$($cmd | grep CHANGEINFO | /usr/bin/awk -F'\t' '{ print $3 }' )
+ debugger "Change id: ${CHANGEID}"
+ rm ${ROUTE53RECORD}
+ CHANGEID=$(echo $CHANGEID |cut -d'/' -f 3 |cut -d'"' -f 1 )
+ debugger "Change id: ${CHANGEID}"
+ STATUS="PENDING"
+ MYSECONDS=2
+ while [ "$STATUS" = 'PENDING' ]; do
+ sleep ${MYSECONDS}
+ STATUS="$(aws --profile ${OCF_RESKEY_profile} route53 get-change --id $CHANGEID | grep CHANGEINFO | /usr/bin/awk -F'\t' '{ print $4 }' |cut -d'"' -f 2 )"
+ debugger "Waited for ${MYSECONDS} seconds and checked execution of Route 53 update status: ${STATUS} "
+ done
+
+ return $OCF_SUCCESS
+}
+
+###############################################################################
+
+case $__OCF_ACTION in
+ usage|help)
+ usage
+ exit $OCF_SUCCESS
+ ;;
+ meta-data)
+ metadata
+ exit $OCF_SUCCESS
+ ;;
+ monitor)
+ ec2ip_monitor
+ ;;
+ stop)
+ ec2ip_stop
+ ;;
+ validate-all)
+ ec2ip_validate
+ ;;
+ start)
+ ec2ip_start
+ ;;
+ *)
+ usage
+ exit $OCF_ERR_UNIMPLEMENTED
+ ;;
+esac
--
2.13.1