b5979: Setup the new structure for AZ comparison.

This commit is contained in:
Thomas Stokes
2024-03-15 13:24:32 +01:00
parent b12748629e
commit 75ce00af9a
@@ -5,7 +5,7 @@
outputMessage() {
# parameter 1: the message to display on the site
echo "Content-type: text/html"
echo "Content-type: text/html"
echo ""
echo $1
}
@@ -14,12 +14,6 @@ status() {
# parameter 1: status code and messages
echo "Status: $1"
}
convert_ip_to_num() {
# $1: Ip4 address in 4 octets form, separated by 3 dots.
IFS=. read -r a b c d <<< "$1"
echo "$(( ( $a << 24 ) + ( $b << 16 ) + ($c << 8 ) + ($d) ))"
}
# The names of the variables in the macros file.
ARCHIVE_IP_NAME="ARCHIVE_IP"
ARCHIVE_FAILOVER_IP_NAME="ARCHIVE_FAILOVER_IP"
@@ -29,46 +23,53 @@ MACROS_PATH="/etc/httpd/conf.d/000-macros.conf"
IP_REGEX="[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$"
# Extracts which IP is in production.
PRODUCTION_IP=$(sed -n -e "s/^Define ${PRODUCTION_IP_NAME}\> \(.*\)$/\1/p" ${MACROS_PATH})
SUBNET_MASK_SIZE_VAR_LOCATION="/var/cache/httpd/subnetMaskSize"
SELF_IP=$( ec2-metadata --local-ipv4 | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\>")
# Cache locations
CACHE_LOCATION="/var/cache/httpd/healthcheck" # Folder storing all the cached info, which the Apache user can access.
ID_TO_AZ_FILENAME="${CACHE_LOCATION}/id_to_az"
ARCHIVE_IP_FILENAME="${CACHE_LOCATION}/archive_ip"
ARCHIVE_AZ_FILENAME="${CACHE_LOCATION}/archive_az"
mkdir --parents ${CACHE_LOCATION}
# IPs and AZs of instance
MY_IP=$( ec2-metadata --local-ipv4 | grep -o "${IP_REGEX}")
MY_AZ=$( ec2-metadata --availability-zone | grep -o "${IP_REGEX}")
ARCHIVE_IP=$(grep -m 1 "^Define ${ARCHIVE_IP_NAME}\> .*" ${MACROS_PATH} | grep -o "${IP_REGEX}")
ARCHIVE_TAG_KEY="temp-key"
ARCHIVE_TAG_VALUE="ARCHIVE"
if [[ "$1" == "cleanup" ]]; then
rm -f ${SUBNET_MASK_SIZE_VAR_LOCATION}
rm -rf ${CACHE_LOCATION}
status "200"
outputMessage "cleanup complete"
exit 0
fi
curl --silent --location --fail "http://${SELF_IP}/internal-server-status" >/dev/null
curl --silent --location --fail "http://${MY_IP}/internal-server-status" >/dev/null
if [[ "$?" -ne 0 ]]; then
status "500 Reverse proxy itself is unhealthy"
outputMessage "Reverse proxy is unhealthy"
exit 0
fi
if [[ ! -e "$SUBNET_MASK_SIZE_VAR_LOCATION" ]]; then
# Get subnet mask size
MY_AZ=$( ec2-metadata --availability-zone | grep -o "[a-zA-Z]\+-[a-zA-Z]\+-[0-9a-z]\+\>")
aws ec2 describe-subnets | jq -r '.Subnets[] | select( .AvailabilityZone =="'"$MY_AZ"'") | select (.Tags ==null or (.Tags | any(.Key == "noInstanceDeployment") | not )) | .CidrBlock | split("/") | .[1]' > $SUBNET_MASK_SIZE_VAR_LOCATION
if [[ ! -e "$ID_TO_AZ_FILENAME" || ! -e "$ARCHIVE_AZ_FILENAME" || "$(cat ${ARCHIVE_IP_FILENAME})" != "${ARCHIVE_IP}" ]]; then
# Cache instance IDs, archive AZ and the archive IP (as a sort of cache invalidator).
instances=$(aws ec2 describe-instances)
echo "$instances" | jq -r ".Reservations | .[] | .Instances | .[]" | jq -r '"\(.InstanceId) \(.Placement.AvailabilityZone)"' > ${ID_TO_AZ_FILENAME}
tmp_az=$(echo "$instances" | jq -r '.Reservations | .[] | .Instances | .[] | select(.Tags | any(.Key=="'${ARCHIVE_TAG_KEY}'" and .Value=="'${ARCHIVE_TAG_VALUE}'")) | "\(.Placement.AvailabilityZone)"')
if [[ -z "$tmp_az" ]]; then
status "500 Unable to retrieve archive AZ"
outputMessage "Cannot retrieve archive AZ, ensure the correct tags are in place"
exit 1
fi
echo "$tmp_az" > ${ARCHIVE_AZ_FILENAME}
echo "$ARCHIVE_IP" > $ARCHIVE_IP_FILENAME
fi
if [[ "$PRODUCTION_IP" == "\${${ARCHIVE_IP_NAME}}" ]]
then
# Check if main archive is in the same az by comparing the network portion of the archive and this instance's IP, with the same bitmask.
MY_IP=$( ec2-metadata --local-ipv4 | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\>")
MY_IP_VALUE="$(convert_ip_to_num "$MY_IP")"
MY_AZ_MASK_SIZE=$(cat $SUBNET_MASK_SIZE_VAR_LOCATION)
# convert the value after the CIDR slash into a bitmask
BITMASK_VALUE=0
for i in $(seq $((31 - $MY_AZ_MASK_SIZE + 1)) 31); do
BITMASK_VALUE=$(($BITMASK_VALUE | (1 << i ) ))
done
MY_SUBNET_VALUE=$(($BITMASK_VALUE & $MY_IP_VALUE))
# Extract the actual IP of the archive
ARCHIVE_IP=$(grep -m 1 "^Define ${ARCHIVE_IP_NAME}\> .*" ${MACROS_PATH} | grep -o "${IP_REGEX}")
ARCHIVE_IP_VALUE=$(convert_ip_to_num "$ARCHIVE_IP")
ARCHIVE_SUBNET_VALUE=$(($BITMASK_VALUE & $ARCHIVE_IP_VALUE )) #Apply the mask to the archive IP value.
if [[ "$ARCHIVE_SUBNET_VALUE" -eq "$MY_SUBNET_VALUE" ]]; then
# Check if main archive is in the same AZ as the archive.
archive_az=$(cat ${ARCHIVE_AZ_FILENAME})
if [[ "$archive_az" == "$MY_AZ" ]]; then
status "200"
outputMessage "Healthy: in the same az as the archive"
else
else
# TODO: Perform check to see if there is anything healthy in the same AZ as the archive. Force healthy if no.
aws elbv2 describe-target-health --target-group-arn ${QUERY_STRING//arn=/} >/dev/null
status "503 Not in the same az"
outputMessage "Unhealthy: Not in the same az as the archive"
fi