origin-keepalived-ipfailover/lib/utils.sh
2019-01-21 10:43:55 +01:00

269 lines
6.1 KiB
Bash
Executable file

#!/bin/bash
# Constants.
LIB_DIR=$(dirname "${BASH_SOURCE[0]}")
VBOX_INTERFACES="enp0s3 enp0s8 eth1"
#
# Returns "scrubbed" name - removes characters that are not alphanumeric or
# underscore and replacing dashes with underscores.
#
# Examples:
# scrub "config\!@#@$%$^&*()-+=1_{}|[]\\:;'<>?,./ipfailover"
# # -> config_1_ipfailover
#
# scrub "ha-1" # -> ha_1
#
function scrub() {
local val=$(echo "$1" | tr -dc '[:alnum:]\-_')
echo "${val//-/_}"
}
#
# Tests if an IPv4 address is valid
# Echos true (0) if valid, false (1) if invalid
#
# Examples:
# validate_ipv4 192.0.2.3
# # -> 0
#
# validate_ipv4 192.0.3.4.0
# # -> 1
#
# validate_ipv4 192.0.2
# # -> 1
#
function validate_ipv4() {
local IPv4_GROUP="[0-2]?[0-9]{1,2}"
local IPv4_SHAPE="^(${IPv4_GROUP}\.){3,3}(${IPv4_GROUP})$"
local is_valid=0
local i
if [[ ${1} =~ ${IPv4_SHAPE} ]]; then
for i in $(echo ${1} | tr "." " "); do
if [ $i -gt 255 ]; then
is_valid=1
fi
done
else
is_valid=1
fi
return ${is_valid}
}
#
# Tests if an IPv6 address is valid
# Returns true (0) if valid, false (1) if invalid
#
# Examples:
# validate_ipv6 2001:DB8:1:E32:FFFF:3:19:39FB
# # -> 0
#
# validate_ipv6 2001:DB8::39FB
# # -> 0
#
# validate_ipv6 2001::DB8::39FB
# # -> 1
#
function validate_ipv6() {
local IPv6_GROUP="[[:xdigit:]]{1,4}"
local IPv6_SHAPE1="^(${IPv6_GROUP}:){7,7}(${IPv6_GROUP})$"
local IPv6_SHAPE2="^::(${IPv6_GROUP}:){0,6}(${IPv6_GROUP})$"
local IPv6_SHAPE3="^(${IPv6_GROUP}:){0,6}:(${IPv6_GROUP}:){0,6}(${IPv6_GROUP})$"
local VALID_SHAPE3="^(${IPv6_GROUP}:+){1,6}(${IPv6_GROUP})$"
local is_valid=1
if [[ ${1} =~ ${IPv6_SHAPE1} ]]; then
is_valid=0
fi
if [[ ${1} =~ ${IPv6_SHAPE2} ]]; then
is_valid=0
fi
if [[ ${1} =~ ${IPv6_SHAPE3} ]]; then
if [[ ${1} =~ ${VALID_SHAPE3} ]]; then
is_valid=0
fi
fi
return ${is_valid}
}
#
# Expands list of IPv4 addresses. List elements can be an IP address
# range or an IP address.
#
# Examples:
# expand_ipv4_range "3.3.3.3-4"
# # -> 3.3.3.3 3.3.3.4
#
# expand_ipv4_range "10.1.1.100-100"
# # -> 10.1.1.100
#
# expand_ipv4_range "10.1.1.100"
# # -> 10.1.1.100
#
function expand_ipv4_range() {
local expandedset=()
local ip1=$(echo "$1" | awk '{print $1}' FS='-')
local ip2=$(echo "$1" | awk '{print $2}' FS='-')
local n
if [ -z "$ip2" ]; then
expandedset=(${expandedset[@]} "$ip1")
else
local base=$(echo "$ip1" | cut -f 1-3 -d '.')
local start=$(echo "$ip1" | awk '{print $NF}' FS='.')
local end=$(echo "$ip2" | awk '{print $NF}' FS='.')
for n in `seq $start $end`; do
expandedset=(${expandedset[@]} "${base}.$n")
done
fi
echo "${expandedset[@]}"
}
#
# Expands list of IPv6 addresses. List elements can be an IP address
# range or an IP address.
#
# Examples:
# expand_ipv6_range "2001:DB8:1ABC::1F39-1F3B"
# # -> 2001:DB8:1ABC::1F39 2001:DB8:1ABC::1F3A 2001:DB8:1ABC::1F3B
#
function expand_ipv6_range() {
local expandedset=()
local ip1=$(echo "$1" | awk '{print $1}' FS='-')
local ip2=$(echo "$1" | awk '{print $2}' FS='-')
local n
if [ -z "$ip2" ]; then
expandedset=(${expandedset[@]} "$ip1")
else
local start=${ip1##*:}
local decstart=`echo "ibase=16; ${start}" | bc`
local base=${ip1%%${start}}
local decend=`echo "ibase=16; ${ip2}" | bc`
for n in `seq $decstart $decend`; do
end=`echo "obase=16; ${n}" | bc`
expandedset=(${expandedset[@]} "${base}${end}")
done
fi
echo "${expandedset[@]}"
}
#
# Returns the IP address family (IPv4 or IPv6)
# Returns "4" or "6" respectively
#
# Examples:
# get_address_family "192.168.3.1"
# # -> 4
#
# get_address_family "2001:DB8:1ABC::1F3A"
# # -> 6
#
function get_address_family() {
if validate_ipv4 ${1}; then
return 4
elif validate_ipv6 ${1}; then
return 6
else
return 1
fi
}
#
# Expands list of virtual IP addresses. List elements can be an IP address
# range or an IP address and elements can be space or comma separated.
#
# Examples:
# expand_ip_ranges "1.1.1.1, 2.2.2.2,3.3.3.3-4 4.4.4.4"
# # -> 1.1.1.1 2.2.2.2 3.3.3.3 3.3.3.4 4.4.4.4
#
# expand_ip_ranges "10.1.1.100-102 10.1.1.200-200 10.42.42.42"
# # -> 10.1.1.100 10.1.1.101 10.1.1.102 10.1.1.200 10.42.42.42
#
function expand_ip_ranges() {
local vips=${1:-""}
local expandedset=()
local iprange
local newip
for iprange in $(echo "$vips" | sed 's/[^0-9a-fA-F:\.,-]//g' | tr "," " "); do
local ip1=$(echo "$iprange" | awk '{print $1}' FS='-')
get_address_family ${ip1}
local family=$?
if [ ${family} == "4" ]; then
for newip in $(expand_ipv4_range ${iprange}); do
expandedset=(${expandedset[@]} ${newip})
done
elif [ ${family} == "6" ]; then
for newip in $(expand_ipv6_range ${iprange}); do
expandedset=(${expandedset[@]} ${newip})
done
fi
done
echo "${expandedset[@]}"
}
#
# Generate base name for the VRRP instance.
#
# Examples:
# vrrp_instance_basename "arp" # -> arp_VIP
#
# vrrp_instance_basename "ha-1" # -> ha_1_VIP
#
function vrrp_instance_basename() {
echo "$(scrub "$1")_VIP"
}
#
# Generate VRRP instance name.
#
# Examples:
# generate_vrrp_instance_name arp 42 # -> arp_VIP_42
#
# generate_vrrp_instance_name ha-1 # -> ha_1_VIP_0
#
function generate_vrrp_instance_name() {
local iid=${2:-0}
echo "$(vrrp_instance_basename "$1")_${iid}"
}
#
# Returns the network device name to use for VRRP.
#
# Examples:
# get_network_device
#
# get_network_device "eth0"
#
function get_network_device() {
for dev in $1 ${VBOX_INTERFACES}; do
if ip addr show dev "$dev" &> /dev/null; then
echo "$dev"
return
fi
done
ip route get 8.8.8.8 | awk '/dev/ { f=NR }; f && (NR-1 == f)' RS=" "
}
#
# Returns the IP address associated with a network device.
#
# Examples:
# get_device_ip_address
#
# get_device_ip_address "docker0"
#
function get_device_ip_address() {
local dev=${1:-"$(get_network_device)"}
ifconfig "$dev" | awk '/inet / { print $2 }'
}