Last active
October 9, 2016 18:37
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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