You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
868 lines
25 KiB
868 lines
25 KiB
7 years ago
|
diff -uNr a/doc/man/Makefile.am b/doc/man/Makefile.am
|
||
|
--- a/doc/man/Makefile.am 2018-02-21 13:07:56.172091057 +0100
|
||
|
+++ b/doc/man/Makefile.am 2018-02-21 13:05:37.589245986 +0100
|
||
|
@@ -99,6 +99,9 @@
|
||
|
ocf_heartbeat_anything.7 \
|
||
|
ocf_heartbeat_apache.7 \
|
||
|
ocf_heartbeat_asterisk.7 \
|
||
|
+ ocf_heartbeat_aws-vpc-move-ip.7 \
|
||
|
+ ocf_heartbeat_awseip.7 \
|
||
|
+ ocf_heartbeat_awsvip.7 \
|
||
|
ocf_heartbeat_clvm.7 \
|
||
|
ocf_heartbeat_conntrackd.7 \
|
||
|
ocf_heartbeat_db2.7 \
|
||
|
diff -uNr a/heartbeat/awseip b/heartbeat/awseip
|
||
|
--- a/heartbeat/awseip 1970-01-01 01:00:00.000000000 +0100
|
||
|
+++ b/heartbeat/awseip 2018-02-21 13:08:21.112887254 +0100
|
||
|
@@ -0,0 +1,278 @@
|
||
|
+#!/bin/sh
|
||
|
+#
|
||
|
+#
|
||
|
+# Manage Elastic IP with Pacemaker
|
||
|
+#
|
||
|
+#
|
||
|
+# Copyright 2016 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
|
||
|
+# - IAM user role with the following permissions:
|
||
|
+# * DescribeInstances
|
||
|
+# * AssociateAddress
|
||
|
+# * 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="30" />
|
||
|
+<action name="stop" timeout="30" />
|
||
|
+<action name="monitor" timeout="30" interval="20" depth="0" />
|
||
|
+<action name="migrate_to" timeout="30" />
|
||
|
+<action name="migrate_from" timeout="30" />
|
||
|
+<action name="meta-data" timeout="5" />
|
||
|
+<action name="validate" timeout="10" />
|
||
|
+<action name="validate-all" timeout="10" />
|
||
|
+</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}')
|
||
|
+ $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
|
||
|
diff -uNr a/heartbeat/awsvip b/heartbeat/awsvip
|
||
|
--- a/heartbeat/awsvip 1970-01-01 01:00:00.000000000 +0100
|
||
|
+++ b/heartbeat/awsvip 2018-02-21 13:08:21.112887254 +0100
|
||
|
@@ -0,0 +1,245 @@
|
||
|
+#!/bin/sh
|
||
|
+#
|
||
|
+#
|
||
|
+# Manage Secondary Private IP with Pacemaker
|
||
|
+#
|
||
|
+#
|
||
|
+# Copyright 2016 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
|
||
|
+# - IAM user role with the following permissions:
|
||
|
+# * DescribeInstances
|
||
|
+# * AssignPrivateIpAddresses
|
||
|
+# * UnassignPrivateIpAddresses
|
||
|
+#
|
||
|
+
|
||
|
+#######################################################################
|
||
|
+# 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="awsvip">
|
||
|
+<version>1.0</version>
|
||
|
+
|
||
|
+<longdesc lang="en">
|
||
|
+Resource Agent for Amazon AWS Secondary Private IP Addresses.
|
||
|
+
|
||
|
+It manages AWS Secondary Private 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 Secondary Private 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="secondary_private_ip" unique="1" required="1">
|
||
|
+<longdesc lang="en">
|
||
|
+reserved secondary private ip for ec2 instance
|
||
|
+</longdesc>
|
||
|
+<shortdesc lang="en">reserved secondary private ip 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="30" />
|
||
|
+<action name="stop" timeout="30" />
|
||
|
+<action name="monitor" timeout="30" interval="20" depth="0" />
|
||
|
+<action name="migrate_to" timeout="30" />
|
||
|
+<action name="migrate_from" timeout="30" />
|
||
|
+<action name="meta-data" timeout="5" />
|
||
|
+<action name="validate" timeout="10" />
|
||
|
+<action name="validate-all" timeout="10" />
|
||
|
+</actions>
|
||
|
+</resource-agent>
|
||
|
+END
|
||
|
+}
|
||
|
+
|
||
|
+#######################################################################
|
||
|
+
|
||
|
+awsvip_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
|
||
|
+}
|
||
|
+
|
||
|
+awsvip_start() {
|
||
|
+ awsvip_monitor && return $OCF_SUCCESS
|
||
|
+
|
||
|
+ $AWSCLI --profile $OCF_RESKEY_profile ec2 assign-private-ip-addresses \
|
||
|
+ --network-interface-id ${NETWORK_ID} \
|
||
|
+ --private-ip-addresses ${SECONDARY_PRIVATE_IP} \
|
||
|
+ --allow-reassignment
|
||
|
+ 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 "secondary_private_ip has been successfully brought up (${SECONDARY_PRIVATE_IP})"
|
||
|
+ return $OCF_SUCCESS
|
||
|
+}
|
||
|
+
|
||
|
+awsvip_stop() {
|
||
|
+ awsvip_monitor || return $OCF_SUCCESS
|
||
|
+
|
||
|
+ $AWSCLI --profile $OCF_RESKEY_profile ec2 unassign-private-ip-addresses \
|
||
|
+ --network-interface-id ${NETWORK_ID} \
|
||
|
+ --private-ip-addresses ${SECONDARY_PRIVATE_IP}
|
||
|
+ 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 "secondary_private_ip has been successfully brought down (${SECONDARY_PRIVATE_IP})"
|
||
|
+ return $OCF_SUCCESS
|
||
|
+}
|
||
|
+
|
||
|
+awsvip_monitor() {
|
||
|
+ $AWSCLI --profile $OCF_RESKEY_profile ec2 describe-instances --instance-id "${INSTANCE_ID}" | grep -q "${SECONDARY_PRIVATE_IP}"
|
||
|
+ RET=$?
|
||
|
+
|
||
|
+ if [ $RET -ne 0 ]; then
|
||
|
+ return $OCF_NOT_RUNNING
|
||
|
+ fi
|
||
|
+ return $OCF_SUCCESS
|
||
|
+}
|
||
|
+
|
||
|
+awsvip_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}"
|
||
|
+SECONDARY_PRIVATE_IP="${OCF_RESKEY_secondary_private_ip}"
|
||
|
+INSTANCE_ID="$(curl -s http://169.254.169.254/latest/meta-data/instance-id)"
|
||
|
+NETWORK_ID="$($AWSCLI --profile $OCF_RESKEY_profile --output json ec2 describe-instances --instance-id ${INSTANCE_ID} | grep -m 1 'eni' | awk -F'"' '{print$4}')"
|
||
|
+
|
||
|
+case $__OCF_ACTION in
|
||
|
+ start)
|
||
|
+ awsvip_validate
|
||
|
+ awsvip_start
|
||
|
+ ;;
|
||
|
+ stop)
|
||
|
+ awsvip_stop
|
||
|
+ ;;
|
||
|
+ monitor)
|
||
|
+ awsvip_monitor
|
||
|
+ ;;
|
||
|
+ migrate_to)
|
||
|
+ ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} to ${OCF_RESKEY_CRM_meta_migrate_target}."
|
||
|
+ awsvip_stop
|
||
|
+ ;;
|
||
|
+ migrate_from)
|
||
|
+ ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} from ${OCF_RESKEY_CRM_meta_migrate_source}."
|
||
|
+ awsvip_start
|
||
|
+ ;;
|
||
|
+ reload)
|
||
|
+ ocf_log info "Reloading ${OCF_RESOURCE_INSTANCE} ..."
|
||
|
+ ;;
|
||
|
+ validate|validate-all)
|
||
|
+ awsvip_validate
|
||
|
+ ;;
|
||
|
+ usage|help)
|
||
|
+ awsvip_usage
|
||
|
+ exit $OCF_SUCCESS
|
||
|
+ ;;
|
||
|
+ *)
|
||
|
+ awsvip_usage
|
||
|
+ exit $OCF_ERR_UNIMPLEMENTED
|
||
|
+ ;;
|
||
|
+esac
|
||
|
+
|
||
|
+rc=$?
|
||
|
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
|
||
|
+exit $rc
|
||
|
diff -uNr a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip
|
||
|
--- a/heartbeat/aws-vpc-move-ip 1970-01-01 01:00:00.000000000 +0100
|
||
|
+++ b/heartbeat/aws-vpc-move-ip 2018-02-21 13:05:37.580246065 +0100
|
||
|
@@ -0,0 +1,306 @@
|
||
|
+#!/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.
|
||
|
+#
|
||
|
+
|
||
|
+
|
||
|
+#######################################################################
|
||
|
+# 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_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 <<END
|
||
|
+<?xml version="1.0"?>
|
||
|
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||
|
+<resource-agent name="aws-vpc-move-ip">
|
||
|
+<version>2.0</version>
|
||
|
+<longdesc lang="en">
|
||
|
+Resource Agent to move IP addresses within a VPC of the Amazon Webservices EC2
|
||
|
+by changing an entry in an specific routing table
|
||
|
+</longdesc>
|
||
|
+<shortdesc lang="en">Move IP within a APC of the AWS EC2</shortdesc>
|
||
|
+
|
||
|
+<parameters>
|
||
|
+<parameter name="awscli">
|
||
|
+<longdesc lang="en">
|
||
|
+Path to command line tools for AWS
|
||
|
+</longdesc>
|
||
|
+<shortdesc lang="en">Path to 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="ip" required="1">
|
||
|
+<longdesc lang="en">
|
||
|
+VPC private IP address
|
||
|
+</longdesc>
|
||
|
+<shortdesc lang="en">VPC private IP</shortdesc>
|
||
|
+<content type="string" default="" />
|
||
|
+</parameter>
|
||
|
+
|
||
|
+<parameter name="routing_table" required="1">
|
||
|
+<longdesc lang="en">
|
||
|
+Name of the routing table, where the route for the IP address should be changed, i.e. rtb-...
|
||
|
+</longdesc>
|
||
|
+<shortdesc lang="en">routing table name</shortdesc>
|
||
|
+<content type="string" default="" />
|
||
|
+</parameter>
|
||
|
+
|
||
|
+<parameter name="interface" required="1">
|
||
|
+<longdesc lang="en">
|
||
|
+Name of the network interface, i.e. eth0
|
||
|
+</longdesc>
|
||
|
+<shortdesc lang="en">network interface name</shortdesc>
|
||
|
+<content type="string" default="eth0" />
|
||
|
+</parameter>
|
||
|
+
|
||
|
+<parameter name="monapi">
|
||
|
+<longdesc lang="en">
|
||
|
+Enable enhanced monitoring using AWS API calls to check route table entry
|
||
|
+</longdesc>
|
||
|
+<shortdesc lang="en">Enhanced Monitoring</shortdesc>
|
||
|
+<content type="boolean" default="${OCF_RESKEY_monapi_default}" />
|
||
|
+</parameter>
|
||
|
+</parameters>
|
||
|
+
|
||
|
+<actions>
|
||
|
+<action name="start" timeout="180" />
|
||
|
+<action name="stop" timeout="180" />
|
||
|
+<action name="monitor" depth="0" timeout="30" interval="60" />
|
||
|
+<action name="validate-all" timeout="5" />
|
||
|
+<action name="meta-data" timeout="5" />
|
||
|
+</actions>
|
||
|
+</resource-agent>
|
||
|
+END
|
||
|
+}
|
||
|
+
|
||
|
+ec2ip_validate() {
|
||
|
+ for cmd in aws ip curl; do
|
||
|
+ check_binary "$cmd"
|
||
|
+ done
|
||
|
+
|
||
|
+ if [ -z "$OCF_RESKEY_profile" ]; then
|
||
|
+ ocf_exit_reason "profile parameter not set"
|
||
|
+ return $OCF_ERR_CONFIGURED
|
||
|
+ fi
|
||
|
+
|
||
|
+ EC2_INSTANCE_ID="$(curl -s http://169.254.169.254/latest/meta-data/instance-id)"
|
||
|
+
|
||
|
+ if [ -z "${EC2_INSTANCE_ID}" ]; then
|
||
|
+ ocf_exit_reason "Instance ID not found. Is this a EC2 instance?"
|
||
|
+ return $OCF_ERR_GENERIC
|
||
|
+ fi
|
||
|
+
|
||
|
+ return $OCF_SUCCESS
|
||
|
+}
|
||
|
+
|
||
|
+ec2ip_monitor() {
|
||
|
+ 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_ip | awk '{ print $3 }')"
|
||
|
+ if [ -z "$ROUTE_TO_INSTANCE" ]; then
|
||
|
+ ROUTE_TO_INSTANCE="<unknown>"
|
||
|
+ fi
|
||
|
+
|
||
|
+ 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 debug "monitor: Enhanced Monitoring disabled - omitting API call"
|
||
|
+ fi
|
||
|
+
|
||
|
+ cmd="ping -W 1 -c 1 $OCF_RESKEY_ip"
|
||
|
+ ocf_log debug "executing command: $cmd"
|
||
|
+ $cmd > /dev/null
|
||
|
+ 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() {
|
||
|
+ cmd="ip addr delete ${OCF_RESKEY_ip}/32 dev $OCF_RESKEY_interface"
|
||
|
+ ocf_log debug "executing command: $cmd"
|
||
|
+ $cmd
|
||
|
+ rc=$?
|
||
|
+ if [ "$rc" -gt 0 ]; then
|
||
|
+ ocf_log warn "command failed, rc $rc"
|
||
|
+ return $OCF_ERR_GENERIC
|
||
|
+ fi
|
||
|
+
|
||
|
+ return $OCF_SUCCESS
|
||
|
+}
|
||
|
+
|
||
|
+ec2ip_get_and_configure() {
|
||
|
+ # Adjusting the routing table
|
||
|
+ 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=$?
|
||
|
+ 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_ip}/32" dev $OCF_RESKEY_interface
|
||
|
+ rc=$?
|
||
|
+ 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_ip"
|
||
|
+
|
||
|
+ ec2ip_monitor
|
||
|
+ if [ $? = $OCF_NOT_RUNNING ]; then
|
||
|
+ ocf_log info "EC2: Address $OCF_RESKEY_ip already down"
|
||
|
+ return $OCF_SUCCESS
|
||
|
+ fi
|
||
|
+
|
||
|
+ ec2ip_drop
|
||
|
+ if [ $? != $OCF_SUCCESS ]; then
|
||
|
+ return $OCF_ERR_GENERIC
|
||
|
+ fi
|
||
|
+
|
||
|
+ ec2ip_monitor
|
||
|
+ 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_ip to this host by adjusting routing table $OCF_RESKEY_routing_table"
|
||
|
+
|
||
|
+ ec2ip_monitor
|
||
|
+ 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
|
||
|
+ rc=$?
|
||
|
+ if [ $rc != $OCF_SUCCESS ]; then
|
||
|
+ ocf_log error "Received $rc from 'aws'"
|
||
|
+ return $OCF_ERR_GENERIC
|
||
|
+ fi
|
||
|
+
|
||
|
+ ec2ip_monitor
|
||
|
+ 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
|
||
|
+ ;;
|
||
|
+ 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;;
|
||
|
+ stop)
|
||
|
+ ec2ip_stop;;
|
||
|
+ monitor)
|
||
|
+ ec2ip_monitor;;
|
||
|
+ validate-all)
|
||
|
+ exit $?;;
|
||
|
+ *)
|
||
|
+ echo $USAGE
|
||
|
+ exit $OCF_ERR_UNIMPLEMENTED
|
||
|
+ ;;
|
||
|
+esac
|
||
|
diff -uNr a/heartbeat/Makefile.am b/heartbeat/Makefile.am
|
||
|
--- a/heartbeat/Makefile.am 2018-02-21 13:07:45.862175305 +0100
|
||
|
+++ b/heartbeat/Makefile.am 2018-02-21 13:05:37.589245986 +0100
|
||
|
@@ -64,6 +64,9 @@
|
||
|
AoEtarget \
|
||
|
apache \
|
||
|
asterisk \
|
||
|
+ aws-vpc-move-ip \
|
||
|
+ awseip \
|
||
|
+ awsvip \
|
||
|
nginx \
|
||
|
AudibleAlarm \
|
||
|
clvm \
|