Skip to content

Instantly share code, notes, and snippets.

@canozokur
Last active October 9, 2016 18:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save canozokur/d5e1e9676f05d743d338 to your computer and use it in GitHub Desktop.
Save canozokur/d5e1e9676f05d743d338 to your computer and use it in GitHub Desktop.
A pacemaker resource definition to manage Amazon EC2 Private IP's. Not much tested but it works. AWS CLI and jq packages are required.
#!/bin/bash
###############################################################################
# CONFIG
# You'll need AWS cli for this to work.
# AWS config
export AWS_ACCESS_KEY_ID="XXXXX"
export AWS_SECRET_ACCESS_KEY="XXXXXXX"
export AWS_DEFAULT_REGION="XXXXX"
# needed for moving the IP
AWS_INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) # different for each node, ex: i-xxxxxxxx - should be cached in case of network or Amazon's service failure.
PRIVATE_IP="10.10.10.10" # ex: 174.129.253.XXX
ENI_ID=$(aws ec2 describe-network-interfaces --filters "Name=attachment.instance-id,Values=${AWS_INSTANCE_ID}" --output json | jq -r '.NetworkInterfaces[0].NetworkInterfaceId')
###############################################################################
###############################################################################
# INIT
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat}
if [ -f ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs ]; then
. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs
fi
USAGE="usage: $0 {start|stop|status|meta-data}";
###############################################################################
# TODO: (enhancement) add more parameters, parameters can be configured while adding resource to the cluster.
meta_data() {
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="EC2PrivateIP">
<version>1.0</version>
<longdesc lang="en">
This script manages Amazon EC2 Private IP addresses.
</longdesc>
<shortdesc lang="en">Manages Amazon EC2 Private IP addresses</shortdesc>
<parameters></parameters>
<actions>
<action name="start" timeout="20s" />
<action name="stop" timeout="20s" />
<action name="monitor" timeout="20s" />
<action name="meta-data" timeout="5s" />
</actions>
</resource-agent>
END
}
ip_already_associated() {
if [ $(aws ec2 describe-network-interfaces --filters "Name=addresses.private-ip-address,Values=${PRIVATE_IP}" | jq -r '.NetworkInterfaces[0].Attachment.InstanceId') = "$AWS_INSTANCE_ID" ]; then
ocf_log info "Elastic IP address already associated to the node"
return $OCF_SUCCESS
else
ocf_log err "Elastic IP address not associated to the node"
return $OCF_ERR_GENERIC
fi
}
ip_start() {
ip_validate_all || exit $?
if ip_monitor; then
ocf_log info "Resource is already running"
return $OCF_SUCCESS
fi
aws ec2 assign-private-ip-addresses --network-interface-id $ENI_ID --private-ip-addresses $PRIVATE_IP --allow-reassignment #> /dev/null
if [ $? -eq 1 ]; then
ocf_log info "An error occurred when starting the resource"
return $OCF_ERR_GENERIC
fi
ip address add ${PRIVATE_IP}/32 dev eth0
if [ $? -eq 1 ]; then
ocf_log info "An error occurred when starting the resource"
return $OCF_ERR_GENERIC
fi
while ! ip_monitor; do
ocf_log debug "Resource has not started yet, waiting"
sleep 1
done
ocf_log info "Elastic IP sucessfully associated with the node"
return $OCF_SUCCESS
}
ip_stop() {
ip_validate_all || exit $?
if ip_monitor; then
ocf_log debug "Resource is currently running"
else
ocf_log info "Resource is already stopped"
return $OCF_SUCCESS
fi
aws ec2 unassign-private-ip-addresses --network-interface-id ${ENI_ID} --private-ip-addresses ${PRIVATE_IP} #> /dev/null
if [ $? -eq 0 ]; then
while ip_monitor; do
ocf_log debug "Resource has not stopped yet, waiting"
sleep 1
done
ocf_log info "Resource is stopped"
else
ocf_log info "An error occurred when stopping the resource"
exit $OCF_ERR_GENERIC
fi
ip address del ${PRIVATE_IP}/32 dev eth0
return $OCF_SUCCESS
}
ip_monitor() {
ip_validate_all || exit $?
if ip_already_associated; then
ping -c 1 $PRIVATE_IP > /dev/null
if [ $? -eq 0 ]; then
ocf_log info "Elastic IP responding to ping test, resource test sucessful"
return $OCF_SUCCESS
else
ocf_log err "Elastic IP not responding to ping test, resource test failed"
return $OCF_ERR_GENERIC
fi
else
ocf_log debug "Resource not running"
return $OCF_NOT_RUNNING
fi
return $OCF_SUCCESS
}
ip_validate_all() {
which aws > /dev/null
if [ $? -eq 1 ]; then
ocf_log info "AWS cli unavailable"
return $OCF_ERR_INSTALLED
elif [ -z "$AWS_ACCESS_KEY_ID" ]; then
ocf_log info "AWS_SECRET_KEY env variable not set"
return $OCF_ERR_CONFIGURED
elif [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
ocf_log info "AWS_ACCESS_KEY env variable not set"
return $OCF_ERR_CONFIGURED
elif [ -z "$AWS_DEFAULT_REGION" ]; then
ocf_log info "EC2_HOME env variable not set"
return $OCF_ERR_CONFIGURED
elif [ -z "$AWS_INSTANCE_ID" ]; then
ocf_log info "AWS_INSTANCE_ID env variable not set"
return $OCF_ERR_CONFIGURED
elif [ -z $PRIVATE_IP ]; then
ocf_log info "PRIVATE_IP env variable not set"
return $OCF_ERR_CONFIGURED
fi
return $OCF_SUCCESS
}
usage() {
echo $USAGE >&2
return $1
}
case $1 in
meta-data) meta_data;;
start) ip_start;;
stop) ip_stop;;
status) ip_monitor;; # Status is deprecated, monitor replaces it.
monitor) ip_monitor;;
validate-all) ip_validate_all;;
usage|help) usage $OCF_SUCCESS;;
*) usage $OCF_ERR_UNIMPLEMENTED;;
esac
exit $?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment