Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e946fe8df5 |
10 changed files with 1041 additions and 0 deletions
32
Dockerfile
Normal file
32
Dockerfile
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#
|
||||||
|
# VIP failover monitoring container for OpenShift.
|
||||||
|
#
|
||||||
|
# ImageName: openshift/origin-keepalived-ipfailover
|
||||||
|
#
|
||||||
|
FROM registry.fedoraproject.org/f29/origin-base:latest
|
||||||
|
|
||||||
|
ENV NAME=origin-keepalived-ipfailover \
|
||||||
|
VERSION=3.11 \
|
||||||
|
ARCH=x86_64
|
||||||
|
|
||||||
|
RUN INSTALL_PKGS="kmod keepalived iproute psmisc nmap-ncat net-tools ipset ipset-libs" && \
|
||||||
|
dnf install -y $INSTALL_PKGS && \
|
||||||
|
rpm -V $INSTALL_PKGS && \
|
||||||
|
dnf clean all
|
||||||
|
COPY . /var/lib/ipfailover/keepalived/
|
||||||
|
|
||||||
|
LABEL io.k8s.display-name="OpenShift IP Failover" \
|
||||||
|
io.k8s.description="This is a component of OpenShift and runs a clustered keepalived instance across multiple hosts to allow highly available IP addresses." \
|
||||||
|
io.openshift.tags="openshift,ha,ip,failover" \
|
||||||
|
summary="This is the base image from which all OpenShift Origin images inherit." \
|
||||||
|
maintainer="Jakub Cajka <jcajka@fedoraproject.org>" \
|
||||||
|
License="GPLv2+" \
|
||||||
|
name="$FGC/$NAME" \
|
||||||
|
com.redhat.component="$NAME" \
|
||||||
|
version="$VERSION" \
|
||||||
|
architecture="$ARCH" \
|
||||||
|
usage="This is the base image from which all OpenShift Origin images inherit."
|
||||||
|
|
||||||
|
EXPOSE 1985
|
||||||
|
WORKDIR /var/lib/ipfailover
|
||||||
|
ENTRYPOINT ["/var/lib/ipfailover/keepalived/monitor.sh"]
|
||||||
101
conf/hello-openshift-template.json
Normal file
101
conf/hello-openshift-template.json
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
{
|
||||||
|
"kind": "Config",
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"metadata": {},
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"kind": "Service",
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"metadata": {
|
||||||
|
"name": "hello-openshift-service",
|
||||||
|
"creationTimestamp": null
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"ports": [
|
||||||
|
{
|
||||||
|
"protocol": "TCP",
|
||||||
|
"port": 8080,
|
||||||
|
"targetPort": 0,
|
||||||
|
"nodePort": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"selector": {
|
||||||
|
"name": "hello-openshift-label"
|
||||||
|
},
|
||||||
|
"type": "ClusterIP",
|
||||||
|
"sessionAffinity": "None"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"loadBalancer": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "ReplicationController",
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"metadata": {
|
||||||
|
"name": "hello-openshift",
|
||||||
|
"creationTimestamp": null,
|
||||||
|
"labels": {
|
||||||
|
"name": "hello-openshift-label"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"replicas": 1,
|
||||||
|
"selector": {
|
||||||
|
"name": "hello-openshift-label"
|
||||||
|
},
|
||||||
|
"template": {
|
||||||
|
"metadata": {
|
||||||
|
"creationTimestamp": null,
|
||||||
|
"labels": {
|
||||||
|
"name": "hello-openshift-label"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"containers": [
|
||||||
|
{
|
||||||
|
"name": "hello-openshift-container",
|
||||||
|
"image": "openshift/hello-openshift",
|
||||||
|
"ports": [
|
||||||
|
{
|
||||||
|
"containerPort": 8080,
|
||||||
|
"protocol": "TCP"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resources": {},
|
||||||
|
"terminationMessagePath": "/dev/termination-log",
|
||||||
|
"imagePullPolicy": "IfNotPresent",
|
||||||
|
"capabilities": {},
|
||||||
|
"securityContext": {
|
||||||
|
"capabilities": {},
|
||||||
|
"privileged": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"restartPolicy": "Always",
|
||||||
|
"dnsPolicy": "ClusterFirst"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"replicas": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Route",
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"metadata": {
|
||||||
|
"name": "hello-openshift-route",
|
||||||
|
"creationTimestamp": null
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"host": "hello.openshift.test",
|
||||||
|
"to": {
|
||||||
|
"kind": "Service",
|
||||||
|
"name": "hello-openshift-service"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
111
conf/settings.sh
Executable file
111
conf/settings.sh
Executable file
|
|
@ -0,0 +1,111 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# Settings passed by the failover coordinator on OpenShift Origin.
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
# Name of this IP Failover config instance.
|
||||||
|
HA_CONFIG_NAME="${OPENSHIFT_HA_CONFIG_NAME:-"OpenShift-IPFailover"}"
|
||||||
|
|
||||||
|
# IP Failover config selector.
|
||||||
|
HA_SELECTOR="${OPENSHIFT_HA_SELECTOR:-""}"
|
||||||
|
|
||||||
|
|
||||||
|
# List of virtual IP addresses.
|
||||||
|
#
|
||||||
|
# The value entries are comma-separated entries of the form:
|
||||||
|
# <ipaddress-range|ipaddress>
|
||||||
|
#
|
||||||
|
# where: ipaddress-range = <start-ipaddress>-<endip>
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# OPENSHIFT_HA_VIRTUAL_IPS="10.42.42.42,10.100.1.20-24"
|
||||||
|
#
|
||||||
|
HA_VIPS="${OPENSHIFT_HA_VIRTUAL_IPS:-""}"
|
||||||
|
HA_VIP_GROUPS="${OPENSHIFT_HA_VIP_GROUPS:-""}"
|
||||||
|
|
||||||
|
# Interface (ethernet) to use - bound by vrrp.
|
||||||
|
NETWORK_INTERFACE="${OPENSHIFT_HA_NETWORK_INTERFACE:-""}" # "enp0s8"
|
||||||
|
|
||||||
|
|
||||||
|
# Service port to monitor for failover.
|
||||||
|
HA_MONITOR_PORT="${OPENSHIFT_HA_MONITOR_PORT:-"80"}"
|
||||||
|
|
||||||
|
# Number of initial replicas.
|
||||||
|
HA_REPLICA_COUNT="${OPENSHIFT_HA_REPLICA_COUNT:-"1"}"
|
||||||
|
|
||||||
|
|
||||||
|
# Offset value to use to set the virtual router ids. Using different offset
|
||||||
|
# values allows multiple ipfailover configurations to exist within the
|
||||||
|
# same cluster. Range 1..255
|
||||||
|
# HA_VRRP_ID_OFFSET=30
|
||||||
|
#
|
||||||
|
HA_VRRP_ID_OFFSET="${OPENSHIFT_HA_VRRP_ID_OFFSET:-"0"}"
|
||||||
|
|
||||||
|
# When the DC supplies an (non null) iptables chain
|
||||||
|
# (OPENSHIFT_HA_IPTABLES_CHAIN) make sure the rule to pass keepalived
|
||||||
|
# multicast (224.0.0.18) traffic is in the table.
|
||||||
|
HA_IPTABLES_CHAIN="${OPENSHIFT_HA_IPTABLES_CHAIN:-""}"
|
||||||
|
|
||||||
|
# Optional external check script that is run every HA_CHECK_INTERVAL seconds
|
||||||
|
# The script can test whatever is needed to verify the application is running.
|
||||||
|
# Must return 0 -- OK, or 1 -- fail
|
||||||
|
# This script is in addition to the default check that the port is listening.
|
||||||
|
# The script must be accessible from inside the keepalived pod
|
||||||
|
HA_CHECK_SCRIPT="${OPENSHIFT_HA_CHECK_SCRIPT:-""}"
|
||||||
|
|
||||||
|
# Optional notify script is called when a state transition occurs
|
||||||
|
# Transition to MASTER, or to BACKUP, or to FAULT
|
||||||
|
# The parameters to the script are passed in by keepalived:
|
||||||
|
# $1 - "GROUP"|"INSTANCE"
|
||||||
|
# $2 - name of group or instance
|
||||||
|
# $3 - target state of transition ("MASTER"|"BACKUP"|"FAULT")
|
||||||
|
# The script must be accessible from inside the keepalived pod
|
||||||
|
HA_NOTIFY_SCRIPT="${OPENSHIFT_HA_NOTIFY_SCRIPT:-""}"
|
||||||
|
|
||||||
|
# The check script is run every HA_CHECK_INTERVAL seconds.
|
||||||
|
# Default is 2
|
||||||
|
HA_CHECK_INTERVAL="${OPENSHIFT_HA_CHECK_INTERVAL:-"2"}"
|
||||||
|
|
||||||
|
# VRRP will preempt a lower priority machine when a higher priority one
|
||||||
|
# comes back online. You can change the preemption strategy to either:
|
||||||
|
# "nopreempt" - which allows the lower priority machine to maintain its
|
||||||
|
# 'MASTER' status.
|
||||||
|
# OR
|
||||||
|
# "preempt_delay 300" - waits 5 mins (in seconds) after startup to
|
||||||
|
# preempt lower priority MASTERs.
|
||||||
|
PREEMPTION="${OPENSHIFT_HA_PREEMPTION:-"preempt_delay 300"}"
|
||||||
|
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# Default settings - not currently exposed or overridden on OpenShift.
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
# If your environment doesn't support multicast, you can send VRRP adverts
|
||||||
|
# to a list of IPv{4,6} addresses using unicast.
|
||||||
|
# Example:
|
||||||
|
# UNICAST_PEERS="5.6.7.8,9.10.11.12,13.14.15.16"
|
||||||
|
UNICAST_PEERS="${OPENSHIFT_HA_UNICAST_PEERS:-""}"
|
||||||
|
|
||||||
|
|
||||||
|
# List of emails to send admin messages to. If the list of email ids is
|
||||||
|
# too long, you can use a DL (distribution list) ala:
|
||||||
|
# ADMIN_EMAILS=("ramr@redhat.com" "cops@acme.org")
|
||||||
|
ADMIN_EMAILS=(${OPENSHIFT_HA_ADMIN_EMAILS:-"root@localhost"})
|
||||||
|
|
||||||
|
# Email sender - the from address in the email headers.
|
||||||
|
EMAIL_FROM="ipfailover@openshift.local"
|
||||||
|
|
||||||
|
# IP address of the SMTP server.
|
||||||
|
SMTP_SERVER="${OPENSHIFT_HA_SMTP_SERVER:-"127.0.0.1"}"
|
||||||
|
|
||||||
|
# SMTP connect timeout (in seconds).
|
||||||
|
SMTP_CONNECT_TIMEOUT=30
|
||||||
|
|
||||||
|
# By default, the IP for binding vrrpd is the primary IP on the above
|
||||||
|
# specified interface. If you want to hide the location of vrrpd, you can
|
||||||
|
# specify a src_addr for multicast/unicast vrrp packets.
|
||||||
|
# MULTICAST_SOURCE_IPADDRESS="1.2.3.4"
|
||||||
|
# UNICAST_SOURCE_IPADDRESS="1.2.3.4"
|
||||||
|
|
||||||
297
lib/config-generators.sh
Executable file
297
lib/config-generators.sh
Executable file
|
|
@ -0,0 +1,297 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# TODO: This follows the initial demo pieces and uses a bash script to
|
||||||
|
# generate the keepalived config - rework this into a template
|
||||||
|
# similar to how it is done for the haproxy configuration.
|
||||||
|
|
||||||
|
# Includes.
|
||||||
|
source "$(dirname "${BASH_SOURCE[0]}")/utils.sh"
|
||||||
|
|
||||||
|
|
||||||
|
# Constants.
|
||||||
|
readonly CHECK_SCRIPT_NAME="chk_${HA_CONFIG_NAME//-/_}"
|
||||||
|
readonly CHECK_INTERVAL_SECS="${HA_CHECK_INTERVAL}"
|
||||||
|
readonly VRRP_SLAVE_PRIORITY=42
|
||||||
|
|
||||||
|
readonly DEFAULT_PREEMPTION_STRATEGY="preempt_delay 300"
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate global config section.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# generate_global_config arparp
|
||||||
|
#
|
||||||
|
function generate_global_config() {
|
||||||
|
local routername ; routername=$(scrub "$1")
|
||||||
|
|
||||||
|
echo "global_defs {"
|
||||||
|
echo " notification_email {"
|
||||||
|
|
||||||
|
for email in ${ADMIN_EMAILS[@]}; do
|
||||||
|
echo " $email"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo " }"
|
||||||
|
echo ""
|
||||||
|
echo " notification_email_from ${EMAIL_FROM:-"ipfailover@openshift.local"}"
|
||||||
|
echo " smtp_server ${SMTP_SERVER:-"127.0.0.1"}"
|
||||||
|
echo " smtp_connect_timeout ${SMTP_CONNECT_TIMEOUT:-"30"}"
|
||||||
|
echo " router_id ${routername}"
|
||||||
|
echo "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate VRRP checker script configuration section.
|
||||||
|
# When a check script is provided use it instead of default script
|
||||||
|
# The default script is suppressed When port is 0
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# generate_script_config
|
||||||
|
# generate_script_config "10.1.2.3" 8080
|
||||||
|
#
|
||||||
|
function generate_script_config() {
|
||||||
|
local serviceip ; serviceip=${1:-"127.0.0.1"}
|
||||||
|
local port=${2:-80}
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "vrrp_script ${CHECK_SCRIPT_NAME} {"
|
||||||
|
|
||||||
|
if [[ -n "${HA_CHECK_SCRIPT}" ]]; then
|
||||||
|
echo " script \"${HA_CHECK_SCRIPT}\""
|
||||||
|
else
|
||||||
|
if [[ "${port}" == "0" ]]; then
|
||||||
|
echo " script \"true\""
|
||||||
|
else
|
||||||
|
echo " script \"/bin/bash -c '</dev/tcp/${serviceip}/${port}'\""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " interval ${CHECK_INTERVAL_SECS}"
|
||||||
|
echo "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate authentication information section.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# generate_authentication_info
|
||||||
|
#
|
||||||
|
function generate_authentication_info() {
|
||||||
|
local creds=${1:-"R0ut3r"}
|
||||||
|
echo ""
|
||||||
|
echo " authentication {"
|
||||||
|
echo " auth_type PASS"
|
||||||
|
echo " auth_pass ${creds}"
|
||||||
|
echo " }"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate track script section.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# generate_track_script
|
||||||
|
#
|
||||||
|
function generate_track_script() {
|
||||||
|
echo ""
|
||||||
|
echo " track_script {"
|
||||||
|
echo " ${CHECK_SCRIPT_NAME}"
|
||||||
|
echo " }"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate multicast + unicast options section based on the values of the
|
||||||
|
# MULTICAST_SOURCE_IPADDRESS, UNICAST_SOURCE_IPADDRESS and UNICAST_PEERS
|
||||||
|
# environment variables.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# generate_mucast_options
|
||||||
|
#
|
||||||
|
# UNICAST_SOURCE_IPADDRESS=10.1.1.1 UNICAST_PEERS="10.1.1.2,10.1.1.3" \
|
||||||
|
# generate_mucast_options
|
||||||
|
#
|
||||||
|
function generate_mucast_options() {
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ -n "${MULTICAST_SOURCE_IPADDRESS}" ]]; then
|
||||||
|
echo " mcast_src_ip ${MULTICAST_SOURCE_IPADDRESS}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "${UNICAST_SOURCE_IPADDRESS}" ]]; then
|
||||||
|
echo " unicast_src_ip ${UNICAST_SOURCE_IPADDRESS}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "${UNICAST_PEERS}" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo " unicast_peer {"
|
||||||
|
|
||||||
|
OLD_IFS=$IFS
|
||||||
|
IFS=","
|
||||||
|
for ip in ${UNICAST_PEERS}; do
|
||||||
|
echo " ${ip}"
|
||||||
|
done
|
||||||
|
IFS=$OLD_IFS
|
||||||
|
|
||||||
|
echo " }"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate virtual ip address section.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# generate_vip_section "10.245.2.3" "enp0s8"
|
||||||
|
#
|
||||||
|
# generate_vip_section "10.1.1.1 10.1.2.2" "enp0s8"
|
||||||
|
#
|
||||||
|
# generate_vip_section "10.42.42.42-45, 10.9.1.1"
|
||||||
|
#
|
||||||
|
function generate_vip_section() {
|
||||||
|
local interface ; interface=${2:-"$(get_network_device)"}
|
||||||
|
echo ""
|
||||||
|
echo " virtual_ipaddress {"
|
||||||
|
|
||||||
|
for ip in ${1}; do
|
||||||
|
echo " ${ip} dev ${interface}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo " }"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate vrrpd instance configuration section.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# generate_vrrpd_instance_config arp 1 "10.1.2.3" enp0s8 "252" "master"
|
||||||
|
#
|
||||||
|
# generate_vrrpd_instance_config arp 1 "10.1.2.3" enp0s8 "3" "slave"
|
||||||
|
#
|
||||||
|
# generate_vrrpd_instance_config ipf-1 4 "10.1.2.3-4" enp0s8 "7"
|
||||||
|
#
|
||||||
|
function generate_vrrpd_instance_config() {
|
||||||
|
local servicename=$1
|
||||||
|
local iid=${2:-"1"}
|
||||||
|
local vips=$3
|
||||||
|
local interface=$4
|
||||||
|
local priority=${5:-"10"}
|
||||||
|
local instancetype=${6:-"slave"}
|
||||||
|
|
||||||
|
local vipname ; vipname=$(scrub "$1")
|
||||||
|
local initialstate=""
|
||||||
|
local preempt=${PREEMPTION:-"${DEFAULT_PREEMPTION_STRATEGY}"}
|
||||||
|
local vrrpidoffset=${HA_VRRP_ID_OFFSET:-0}
|
||||||
|
|
||||||
|
[ "${instancetype}" = "master" ] && initialstate="state MASTER"
|
||||||
|
|
||||||
|
local instance_name ; instance_name=$(generate_vrrp_instance_name "${servicename}" "${iid}")
|
||||||
|
|
||||||
|
local auth_section ; auth_section=$(generate_authentication_info "${servicename}")
|
||||||
|
local vip_section ; vip_section=$(generate_vip_section "${vips}" "${interface}")
|
||||||
|
# Emit instance
|
||||||
|
echo "
|
||||||
|
vrrp_instance ${instance_name} {
|
||||||
|
interface ${interface}
|
||||||
|
${initialstate}
|
||||||
|
virtual_router_id $((vrrpidoffset + iid))
|
||||||
|
priority ${priority}
|
||||||
|
${preempt}
|
||||||
|
${auth_section}
|
||||||
|
$(generate_track_script)
|
||||||
|
"
|
||||||
|
if [[ -n $HA_NOTIFY_SCRIPT ]]; then
|
||||||
|
echo " notify \"${HA_NOTIFY_SCRIPT}\""
|
||||||
|
fi
|
||||||
|
echo " $(generate_mucast_options)
|
||||||
|
${vip_section}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate failover configuration.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# generate_failover_configuration
|
||||||
|
#
|
||||||
|
function generate_failover_config() {
|
||||||
|
local vips ; vips=$(expand_ip_ranges "${HA_VIPS}")
|
||||||
|
local vip_groups ; vip_groups="${HA_VIP_GROUPS}"
|
||||||
|
local interface ; interface=$(get_network_device "${NETWORK_INTERFACE}")
|
||||||
|
local ipaddr ; ipaddr=$(get_device_ip_address "${interface}")
|
||||||
|
local port="${HA_MONITOR_PORT//[^0-9]/}"
|
||||||
|
|
||||||
|
echo "! Configuration File for keepalived
|
||||||
|
|
||||||
|
$(generate_global_config "${HA_CONFIG_NAME}")
|
||||||
|
$(generate_script_config "${ipaddr}" "${port}")
|
||||||
|
"
|
||||||
|
|
||||||
|
local ipkey ; ipkey=$(echo "${ipaddr}" | cut -f 4 -d '.')
|
||||||
|
local ipslot=$((ipkey % 128))
|
||||||
|
|
||||||
|
local nodecount
|
||||||
|
if [[ "${HA_REPLICA_COUNT}" -gt 0 ]]; then
|
||||||
|
nodecount="${HA_REPLICA_COUNT}"
|
||||||
|
else
|
||||||
|
nodecount="1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local idx=$((ipslot % nodecount))
|
||||||
|
idx=$((idx + 1))
|
||||||
|
|
||||||
|
local counter=1
|
||||||
|
local previous="none"
|
||||||
|
local vip_counter=0
|
||||||
|
local total_vips=( $vips )
|
||||||
|
local vips_per_group=1
|
||||||
|
local vips_mod=0
|
||||||
|
|
||||||
|
if [[ $vip_groups -gt 0 ]]; then
|
||||||
|
vips_per_group=$((${#total_vips[@]} / vip_groups))
|
||||||
|
vips_mod=$((${#total_vips[@]} % vip_groups))
|
||||||
|
fi
|
||||||
|
|
||||||
|
while [[ "${vip_counter}" -lt "${#total_vips[@]}" ]]; do
|
||||||
|
local cur_vip_count=vips_per_group
|
||||||
|
|
||||||
|
if [[ ${vips_mod} -gt 0 ]]; then
|
||||||
|
((cur_vip_count++))
|
||||||
|
((vips_mod--))
|
||||||
|
fi
|
||||||
|
|
||||||
|
vip_group=("${total_vips[@]:vip_counter:cur_vip_count}")
|
||||||
|
vip_counter=$((vip_counter + cur_vip_count))
|
||||||
|
|
||||||
|
local offset=$((RANDOM % 32))
|
||||||
|
local priority=$((ipslot % 64 + offset))
|
||||||
|
local instancetype="slave"
|
||||||
|
local n=$((counter % idx))
|
||||||
|
|
||||||
|
if [[ ${n} -eq 0 ]]; then
|
||||||
|
instancetype="master"
|
||||||
|
if [[ "${previous}" == "master" ]]; then
|
||||||
|
# Inverse priority + reset, so that we can flip-flop priorities.
|
||||||
|
priority=$((ipslot + 1))
|
||||||
|
previous="flip-flop"
|
||||||
|
else
|
||||||
|
priority=$((255 - ipslot))
|
||||||
|
previous=${instancetype}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
generate_vrrpd_instance_config "${HA_CONFIG_NAME}" "${counter}" "${vip_group[*]}" \
|
||||||
|
"${interface}" "${priority}" "${instancetype}"
|
||||||
|
((counter++))
|
||||||
|
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
79
lib/failover-functions.sh
Executable file
79
lib/failover-functions.sh
Executable file
|
|
@ -0,0 +1,79 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
# Includes.
|
||||||
|
mydir=$(dirname "${BASH_SOURCE[0]}")
|
||||||
|
source "$mydir/../conf/settings.sh"
|
||||||
|
source "$mydir/utils.sh"
|
||||||
|
source "$mydir/config-generators.sh"
|
||||||
|
|
||||||
|
# Constants.
|
||||||
|
readonly KEEPALIVED_CONFIG=${KEEPALIVED_CONFIG:-"/etc/keepalived/keepalived.conf"}
|
||||||
|
readonly KEEPALIVED_DEFAULTS="/etc/sysconfig/keepalived"
|
||||||
|
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
echo " - Cleaning up ... "
|
||||||
|
[ -n "$1" ] && kill -TERM $1
|
||||||
|
|
||||||
|
local interface=$(get_network_device "$NETWORK_INTERFACE")
|
||||||
|
local vips=$(expand_ip_ranges "$HA_VIPS")
|
||||||
|
echo " - Releasing VIPs ${vips} (interface ${interface}) ... "
|
||||||
|
|
||||||
|
local regex='^.*?/[0-9]+$'
|
||||||
|
|
||||||
|
for vip in ${vips}; do
|
||||||
|
echo " - Releasing VIP ${vip} ... "
|
||||||
|
if [[ ${vip} =~ ${regex} ]] ; then
|
||||||
|
ip addr del ${vip} dev ${interface} || :
|
||||||
|
else
|
||||||
|
ip addr del ${vip}/32 dev ${interface} || :
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function setup_failover() {
|
||||||
|
echo " - Loading ip_vs module ..."
|
||||||
|
modprobe ip_vs
|
||||||
|
|
||||||
|
echo " - Checking if ip_vs module is available ..."
|
||||||
|
if lsmod | grep '^ip_vs'; then
|
||||||
|
echo " - Module ip_vs is loaded."
|
||||||
|
else
|
||||||
|
echo "ERROR: Module ip_vs is NOT available."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# When the DC supplies an (non null) iptables chain
|
||||||
|
# (OPENSHIFT_HA_IPTABLES_CHAIN) make sure the rule to pass keepalived
|
||||||
|
# multicast (224.0.0.18) traffic is in the table.
|
||||||
|
chain="${HA_IPTABLES_CHAIN:-""}"
|
||||||
|
if [[ -n ${chain} ]]; then
|
||||||
|
echo " - check for iptables rule for keepalived multicast (224.0.0.18) ..."
|
||||||
|
if ! iptables -S | grep 224.0.0.18 > /dev/null 2>&1 ; then
|
||||||
|
# Add the rule to the beginning of the chain.
|
||||||
|
echo " - adding iptables rule to $chain to access 224.0.0.18."
|
||||||
|
iptables -I ${chain} 1 -d 224.0.0.18/32 -j ACCEPT
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " - Generating and writing config to $KEEPALIVED_CONFIG"
|
||||||
|
generate_failover_config > "$KEEPALIVED_CONFIG"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function start_failover_services() {
|
||||||
|
echo " - Starting failover services ..."
|
||||||
|
|
||||||
|
[ -f "$KEEPALIVED_DEFAULTS" ] && source "$KEEPALIVED_DEFAULTS"
|
||||||
|
|
||||||
|
killall -9 /usr/sbin/keepalived &> /dev/null || :
|
||||||
|
/usr/sbin/keepalived $KEEPALIVED_OPTIONS -n --log-console &
|
||||||
|
local pid=$!
|
||||||
|
|
||||||
|
trap "cleanup ${pid}" SIGHUP SIGINT SIGTERM
|
||||||
|
wait ${pid}
|
||||||
|
}
|
||||||
|
|
||||||
269
lib/utils.sh
Executable file
269
lib/utils.sh
Executable file
|
|
@ -0,0 +1,269 @@
|
||||||
|
#!/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 }'
|
||||||
|
}
|
||||||
11
makefile.test
Normal file
11
makefile.test
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
IMAGE_NAME="openshift/origin-keepalived-ipfailover"
|
||||||
|
|
||||||
|
|
||||||
|
all: image
|
||||||
|
|
||||||
|
test: image
|
||||||
|
(cd tests && ./verify_failover_image.sh)
|
||||||
|
|
||||||
|
image:
|
||||||
|
docker build -t $(IMAGE_NAME) .
|
||||||
15
monitor.sh
Executable file
15
monitor.sh
Executable file
|
|
@ -0,0 +1,15 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Includes.
|
||||||
|
source "$(dirname "${BASH_SOURCE[0]}")/lib/failover-functions.sh"
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# main():
|
||||||
|
#
|
||||||
|
setup_failover
|
||||||
|
|
||||||
|
start_failover_services
|
||||||
|
|
||||||
|
echo "`basename $0`: OpenShift IP Failover service terminated."
|
||||||
|
|
||||||
36
tests/echoserver.py
Normal file
36
tests/echoserver.py
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
""" Echo server - reply back with the received message. """
|
||||||
|
|
||||||
|
import os
|
||||||
|
import signal
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def sigusr1_handler(signum, frame):
|
||||||
|
print 'signal %s received, exiting ...' % signum
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def setup():
|
||||||
|
signal.signal(signal.SIGUSR1, sigusr1_handler)
|
||||||
|
|
||||||
|
|
||||||
|
def runserver():
|
||||||
|
sock = socket.socket()
|
||||||
|
sock.bind(('0.0.0.0', int(os.environ.get('PORT', '12345'))))
|
||||||
|
sock.listen(10)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
c, raddr = sock.accept()
|
||||||
|
try:
|
||||||
|
d = c.recv(4096)
|
||||||
|
c.send(d if d else '')
|
||||||
|
finally:
|
||||||
|
c.close()
|
||||||
|
|
||||||
|
|
||||||
|
if "__main__" == __name__:
|
||||||
|
setup()
|
||||||
|
runserver()
|
||||||
90
tests/verify_failover_image.sh
Executable file
90
tests/verify_failover_image.sh
Executable file
|
|
@ -0,0 +1,90 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
# Constants.
|
||||||
|
readonly TEST_DIR=$(dirname "${BASH_SOURCE[0]}")
|
||||||
|
readonly FAILOVER_IMAGE="openshift/origin-keepalived-ipfailover"
|
||||||
|
readonly TEST_VIPS="10.0.2.100-102,2001:DB8:1ABC::1F39-1F3B"
|
||||||
|
readonly MONITOR_PORT="12345"
|
||||||
|
|
||||||
|
|
||||||
|
function stop_echo_server() {
|
||||||
|
local pid=$1
|
||||||
|
if [ -z "$pid" ]; then
|
||||||
|
pid=$(ps -e -opid,args | grep echoserver.py | grep -v grep | awk '{print $1}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Send SIGUSR1 to the echo server to terminate it.
|
||||||
|
[ -n "$pid" ] && kill -s USR1 $pid
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function start_echo_server() {
|
||||||
|
stop_echo_server
|
||||||
|
|
||||||
|
export PORT=${MONITOR_PORT}
|
||||||
|
nohup python ${TEST_DIR}/echoserver.py &> /dev/null &
|
||||||
|
echo $!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function start_failover_container() {
|
||||||
|
local cfg="-e OPENSHIFT_HA_CONFIG_NAME="roto-r00ter""
|
||||||
|
local vips="-e OPENSHIFT_HA_VIRTUAL_IPS="${TEST_VIPS}""
|
||||||
|
local netif="-e OPENSHIFT_HA_NETWORK_INTERFACE="enp0s3""
|
||||||
|
local port="-e OPENSHIFT_HA_MONITOR_PORT="${MONITOR_PORT}""
|
||||||
|
# local unicast="-e export OPENSHIFT_HA_USE_UNICAST="true""
|
||||||
|
# local unicastpeers="-e OPENSHIFT_HA_UNICAST_PEERS="127.0.0.1""
|
||||||
|
local selector="-e OPENSHIFT_HA_SELECTOR="""
|
||||||
|
local envopts="$cfg $vips $netif $port $unicast $unicastpeers $selector"
|
||||||
|
|
||||||
|
docker run -dit --net=host --privileged=true \
|
||||||
|
-v /lib/modules:/lib/modules $envopts $FAILOVER_IMAGE &
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function run_image_verification_test() {
|
||||||
|
echo " - starting echo server ..."
|
||||||
|
local pid=$(start_echo_server)
|
||||||
|
echo " - started echo server pid=$pid ..."
|
||||||
|
|
||||||
|
# On interrupt, cleanup - stop echo server.
|
||||||
|
trap "stop_echo_server $pid" INT
|
||||||
|
|
||||||
|
local cname=$(start_failover_container)
|
||||||
|
echo " - started docker container $cname ..."
|
||||||
|
|
||||||
|
# Wait a bit for all the services to startup.
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# Check container is up and has keepalived processes.
|
||||||
|
local cmd="ps -ef | grep '/usr/sbin/keepalived' | grep -v grep | wc -l"
|
||||||
|
local numprocs=$(echo "$cmd" | docker exec -i $cname /bin/bash)
|
||||||
|
|
||||||
|
# Stop echo server.
|
||||||
|
stop_echo_server $pid
|
||||||
|
|
||||||
|
if [[ -n "$numprocs" && $numprocs -gt 0 ]]; then
|
||||||
|
# Success - print info and kill the container.
|
||||||
|
echo " - There are $numprocs keepalived processes running"
|
||||||
|
echo " - Cleaning up docker containers ..."
|
||||||
|
docker rm -f $cname
|
||||||
|
echo " - All tests PASSED."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Failure - print info and dump logs (keep the docker container around
|
||||||
|
# for debugging).
|
||||||
|
echo " - There are $numprocs keepalived processes running"
|
||||||
|
echo " - logs from container $cname:"
|
||||||
|
docker logs $cname || :
|
||||||
|
echo " - Test FAILED."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# main():
|
||||||
|
#
|
||||||
|
run_image_verification_test
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue