#!/bin/sh
# Update a virtual cluster built by autocluster, with IPv6 addresses
# Copyright (C) Martin Schwenke 2019, 2020
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
# Add IPv6 addresses on interfaces eth1, eth2, eth3. The IPv6
# addresses are calculated from the IPv4 addresses. The CTDB nodes
# and public_addresses files are updated to contain only the IPv6
# addresses.
# This nasty hack is requird because vagrant-libvirt does not properly
# support IPv6 addresses.
set -eu
if [ $# -ne 1 ] ; then
echo "usage: ${0} "
exit 1
fi
cluster="$1"
hosts=".autocluster/${cluster}/hosts"
if [ ! -r "$hosts" ] ; then
echo "error: no file \"${hosts}\""
exit 1
fi
nodes=".autocluster/${cluster}/nodes"
: >"$nodes"
public_addresses=".autocluster/${cluster}/public_addresses"
: >"$public_addresses"
hosts_ipv6=".autocluster/${cluster}/hosts.ipv6"
echo '# autocluster m1' >"$hosts_ipv6"
maybe_add_ip ()
{
_host="$1"
_addr="$2"
_iface="$3"
printf ' %s@%s: ' "$_addr" "$_iface"
_t=$(ssh -n "$_host" ip -o addr show to "${_addr%/*}" | \
awk '{print $2}')
if [ -z "$_t" ] ; then
ssh -n "$_host" ip addr add "$_addr" dev "$_iface"
echo '+'
else
echo '.'
fi
}
echo "Confirming IPv6 addresses:"
sort -n "$hosts" |
while read -r ipv4 fqdn host ; do
case "$ipv4" in
\#*) continue ;;
esac
ipv4_rest="$ipv4"
a="${ipv4_rest%%.*}"
ipv4_rest="${ipv4_rest#*.}"
b="${ipv4_rest%%.*}"
ipv4_rest="${ipv4_rest#*.}"
c="${ipv4_rest%%.*}"
ipv4_rest="${ipv4_rest#*.}"
d="${ipv4_rest%%.*}"
echo "${host}:"
ssh -n "$host" sysctl -q net.ipv6.conf.all.disable_ipv6=0
#
# eth1
#
eth1_ipv6=$(printf 'fd00:%x:%x:%x::%x/64' "$a" "$b" "$c" "$d")
case "$host" in
${cluster}n[0-9]*)
echo "${eth1_ipv6%/*}" >>"$nodes"
;;
esac
echo "${eth1_ipv6%/*} ${fqdn} ${host}" >>"$hosts_ipv6"
maybe_add_ip "$host" "$eth1_ipv6" "eth1"
#
# eth2
#
eth2_c=$((c + 1))
eth2_ipv6=$(printf 'fd00:%x:%x:%x::%x/64' "$a" "$b" "$eth2_c" "$d")
case "$host" in
${cluster}n[0-9]*)
p_d=$((d + 100))
p=$(printf 'fd00:%x:%x:%x::%x/64' "$a" "$b" "$eth2_c" "$p_d")
printf '%s\t%s\n' "$p" "eth2" >>"$public_addresses"
;;
esac
maybe_add_ip "$host" "$eth2_ipv6" "eth2"
#
# eth3
#
eth3_c=$((c + 2))
eth3_ipv6=$(printf 'fd00:%x:%x:%x::%x/64' "$a" "$b" "$eth3_c" "$d")
case "$host" in
${cluster}n[0-9]*)
p_d=$((d + 100))
p=$(printf 'fd00:%x:%x:%x::%x/64' "$a" "$b" "$eth3_c" "$p_d")
printf '%s\t%s\n' "$p" "eth3" >>"$public_addresses"
;;
esac
maybe_add_ip "$host" "$eth3_ipv6" "eth3"
done
echo
echo "${nodes}:"
cat "$nodes"
echo
echo "${public_addresses}:"
cat "$public_addresses"
echo
echo "${hosts_ipv6}:"
cat "$hosts_ipv6"
echo
echo "Stopping ctdb:"
sort -n "$hosts" |
while read -r ipv4 _ host ; do
case "$ipv4" in
\#*) continue ;;
esac
case "$host" in
${cluster}n[0-9]*)
echo "${host}"
ssh -n "$host" systemctl stop ctdb
;;
esac
done
echo
echo "Determining CTDB configuration directory"
conf=".autocluster/${cluster}/config.yml"
if grep -Fxq 'tarball: null' "$conf" ; then
# Default
ctdb_config_dir="/etc/ctdb"
else
prefix=$(sed -n -e 's|^tarball_install_prefix: *||p' "$conf")
ctdb_config_dir="${prefix}/etc/ctdb"
fi
echo "$ctdb_config_dir"
echo
echo "Copying configuration files:"
sort -n "$hosts" |
while read -r ipv4 _ host ; do
case "$ipv4" in
\#*) continue ;;
esac
case "$host" in
${cluster}n[0-9]*|${cluster}test[0-9]*)
dst="${host}:${ctdb_config_dir}/nodes"
echo "$dst"
scp -q "$nodes" "$dst"
;;
esac
case "$host" in
${cluster}n[0-9]*)
dst="${host}:${ctdb_config_dir}/public_addresses"
echo "$dst"
scp -q "$public_addresses" "$dst"
;;
esac
done
echo
echo "Starting ctdb:"
sort -n "$hosts" |
while read -r ipv4 _ host ; do
case "$ipv4" in
\#*) continue ;;
esac
case "$host" in
${cluster}n[0-9]*)
echo "${host}"
ssh -n "$host" systemctl start ctdb
;;
esac
done
echo
echo "Waiting until healthy:"
sort -n "$hosts" |
while read -r ipv4 _ host ; do
case "$ipv4" in
\#*) continue ;;
esac
if [ "$host" != "${cluster}n1" ] ; then
continue
fi
timeout=120
printf '|<%d|' $timeout
for n in $(seq 1 $timeout) ; do
if ssh -n "$host" ctdb nodestatus all >/dev/null ; then
break
fi
printf '.'
sleep 1
done
out=$(ssh -n "$host" ctdb nodestatus all 2>&1)
# shellcheck disable=SC2181
if [ $? -eq 0 ] ; then
printf '|%d|\n' "$n"
else
printf 'TIMEOUT!\n'
fi
echo
echo "$out"
done