269 lines
6.1 KiB
Bash
Executable file
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 }'
|
|
}
|