mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
794f125802
When a node is starting, CTDB reports remote nodes as unhealthy by default. This can be misleading. To hide this, report an "UNKNOWN" pseudo state when a remote node is not disconnected and the runstate is less than or equal to "FIRST_RECOVERY". Signed-off-by: Vinit Agnihotri <vagnihotri@ddn.com> Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com>
195 lines
4.8 KiB
Bash
Executable File
195 lines
4.8 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
if [ -z "$CTDB_BASE" ] ; then
|
|
export CTDB_BASE="/usr/local/etc/ctdb"
|
|
fi
|
|
|
|
. "${CTDB_BASE}/functions"
|
|
|
|
load_script_options "failover" "11.natgw"
|
|
|
|
# Default NAT gateway nodes file location
|
|
[ -n "$CTDB_NATGW_NODES" ] || CTDB_NATGW_NODES="${CTDB_BASE}/natgw_nodes"
|
|
|
|
if [ -z "$CTDB" ] ; then
|
|
CTDB=ctdb
|
|
fi
|
|
|
|
############################################################
|
|
|
|
usage ()
|
|
{
|
|
cat <<EOF
|
|
$0 <option>
|
|
|
|
<option> is one of:
|
|
leader Display node number and private IP address of leader node
|
|
list List private IP addresses of nodes in group, annotate leader
|
|
status Show status of nodes in NAT gateway group
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
nodestatus_X=""
|
|
# Fields are:
|
|
# Node|IP|Disconnected|Unknown|Banned|Disabled|Unhealthy|Stopped|Inactive|PartiallyOnline|ThisNode
|
|
get_nodestatus_X ()
|
|
{
|
|
# Result is cached in global variable nodestatus_X
|
|
[ -n "$nodestatus_X" ] || \
|
|
nodestatus_X=$($CTDB -X nodestatus all |
|
|
sed -e '1d' -e 's@^|@@' -e 's@|$@@')
|
|
}
|
|
|
|
get_nodestatus ()
|
|
{
|
|
# Result is cached in global variable nodestatus
|
|
[ -n "$nodestatus" ] || nodestatus=$($CTDB nodestatus all)
|
|
[ $? -ne 255 ] # ctdb nodestatus returns 255 on failure
|
|
}
|
|
|
|
get_natgw_nodes ()
|
|
{
|
|
# Result is cached in global variable natgw_nodes
|
|
if [ -n "$natgw_nodes" ] ; then
|
|
return
|
|
fi
|
|
|
|
if [ ! -r "$CTDB_NATGW_NODES" ] ; then
|
|
return 1
|
|
fi
|
|
|
|
natgw_nodes=$(cat "$CTDB_NATGW_NODES") || return 1
|
|
|
|
# Sanity check file contents here
|
|
while read _ip _options ; do
|
|
# Skip comments
|
|
case "$_ip" in
|
|
\#*) continue ;;
|
|
esac
|
|
case "$_options" in
|
|
follower-only|"") : ;;
|
|
*) die "${prog}: Invalid options \"${_options}\" in \"$CTDB_NATGW_NODES\""
|
|
esac
|
|
done <<EOF
|
|
$natgw_nodes
|
|
EOF
|
|
|
|
return 0
|
|
}
|
|
|
|
# Print the PNN and IP address of the NAT gateway leader node
|
|
find_leader ()
|
|
{
|
|
get_natgw_nodes || \
|
|
die "${prog}: NAT gateway nodes file \"$CTDB_NATGW_NODES\" not found"
|
|
get_nodestatus_X || \
|
|
die "${prog}: Unable to get status of nodes"
|
|
|
|
# $_ms is an @-delimited list of nodes that are allowed to be the leader
|
|
_ms="@"
|
|
while read _ip _options ; do
|
|
case "$_options" in
|
|
"") _ms="${_ms}${_ip}@" ;;
|
|
esac
|
|
done <<EOF
|
|
$natgw_nodes
|
|
EOF
|
|
|
|
# Now filter by $ms and by status of nodes...
|
|
|
|
# Note that the 3 awk invocations below have "||" between them, so
|
|
# the first to succeed will select the leader node.
|
|
|
|
# First try for a fully active and healthy node, so must not be
|
|
# UNKNOWN, DISABLED, UNHEALTHY or INACTIVE (last covers DISCONNECTED,
|
|
# BANNED or STOPPED)
|
|
awk -F '|' -v ms="$_ms" \
|
|
'BEGIN { ret = 2 }
|
|
ms ~ "@" $2 "@" &&
|
|
$4 == 0 && $6 == 0 && $7 == 0 && $9 == 0 { print $1, $2 ; ret=0 ; exit }
|
|
END { exit ret }' <<EOF ||
|
|
$nodestatus_X
|
|
EOF
|
|
# Not found? UNHEALTHY/BANNED will do, so node must not be
|
|
# DISCONNECTED, DISABLED or STOPPED
|
|
awk -F '|' -v ms="$_ms" \
|
|
'BEGIN { ret = 2 }
|
|
ms ~ "@" $2 "@" &&
|
|
$3 == 0 && $6 == 0 && $8 == 0 { print $1, $2 ; ret=0 ; exit }
|
|
END { exit ret }' <<EOF ||
|
|
$nodestatus_X
|
|
EOF
|
|
# Not found? STOPPED will do, so node must not be DISCONNECTED or
|
|
# DISABLED
|
|
awk -F '|' -v ms="$_ms" \
|
|
'BEGIN { ret = 2 }
|
|
ms ~ "@" $2 "@" &&
|
|
$3 == 0 && $6 == 0 { print $1, $2 ; ret=0 ; exit }
|
|
END { exit ret }' <<EOF
|
|
$nodestatus_X
|
|
EOF
|
|
}
|
|
|
|
# List all nodes in the NAT gateway group, annotating the leader node
|
|
nodes_list ()
|
|
{
|
|
get_natgw_nodes || \
|
|
die "${prog}: NAT gateway nodes file \"$CTDB_NATGW_NODES\" not found"
|
|
# Intentional word splitting here
|
|
# shellcheck disable=SC2046
|
|
set -- $(find_leader) || \
|
|
die "${prog}: Unable to determine NAT gateway leader node"
|
|
_leader_ip="$2"
|
|
|
|
# Annotate the leader node
|
|
while read _ip _options ; do
|
|
if [ "$_ip" = "$_leader_ip" ] ; then
|
|
_options="LEADER${_options:+,}${_options}"
|
|
fi
|
|
# There is no other way to do this and keep shellcheck happy.
|
|
# The tab character must be in the format string and the
|
|
# format string must contain no variables. Some shells will
|
|
# expand a tab if it is in an argument but others won't.
|
|
if [ -n "$_options" ] ; then
|
|
printf '%s\t%s\n' "$_ip" "$_options"
|
|
else
|
|
echo "$_ip"
|
|
fi
|
|
done <<EOF
|
|
$natgw_nodes
|
|
EOF
|
|
}
|
|
|
|
# Print the status of all nodes in the NAT gateway group, along with a count
|
|
nodes_status ()
|
|
{
|
|
get_natgw_nodes || \
|
|
die "${prog}: NAT gateway nodes file \"$CTDB_NATGW_NODES\" not found"
|
|
get_nodestatus || \
|
|
die "${prog}: Unable to get status of nodes"
|
|
|
|
# $_ns is a @-delimited list of nodes in the NAT gateway group
|
|
_ns="@"
|
|
while read _ip _options ; do
|
|
_ns="${_ns}${_ip}@"
|
|
done <<EOF
|
|
$natgw_nodes
|
|
EOF
|
|
|
|
# Print status of nodes in $_ns, along with node count
|
|
awk -v ns="$_ns" 'ns ~ "@" $2 "@" { print $0 }' <<EOF
|
|
$nodestatus
|
|
EOF
|
|
}
|
|
|
|
prog=$(basename "$0")
|
|
cmd="$1"
|
|
|
|
case "$cmd" in
|
|
leader) find_leader ;;
|
|
list) nodes_list ;;
|
|
status) nodes_status ;;
|
|
*) usage ;;
|
|
esac
|