diff options
Diffstat (limited to '')
-rwxr-xr-x | ctdb/tools/ctdb_lvs | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/ctdb/tools/ctdb_lvs b/ctdb/tools/ctdb_lvs new file mode 100755 index 0000000..d0249b9 --- /dev/null +++ b/ctdb/tools/ctdb_lvs @@ -0,0 +1,204 @@ +#!/bin/sh + +if [ -z "$CTDB_BASE" ] ; then + export CTDB_BASE="/usr/local/etc/ctdb" +fi + +. "${CTDB_BASE}/functions" + +load_script_options "failover" "91.lvs" + +# Default LVS nodes file location +[ -n "$CTDB_LVS_NODES" ] || CTDB_LVS_NODES="${CTDB_BASE}/lvs_nodes" + +if [ -z "$CTDB" ] ; then + CTDB=ctdb +fi + +############################################################ + +usage () +{ + cat <<EOF +$0 <option> + +<option> is one of: + leader Display node number of leader node + list List node number and private IP address of usable nodes in group + status Show status of all nodes in LVS 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) + case $? in + # $CTDB nodestatus returns 255 on failure + 0|255) return 0 ;; + *) return 1 ;; + esac +} + +get_lvs_nodes () +{ + # Result is cached in global variable lvs_nodes + if [ -n "$lvs_nodes" ] ; then + return + fi + + if [ ! -r "$CTDB_LVS_NODES" ] ; then + return 1 + fi + + lvs_nodes=$(cat "$CTDB_LVS_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_LVS_NODES\"" + esac + done <<EOF +$lvs_nodes +EOF + + return 0 +} + +# Print PNN and IP address of given nodes meeting the criteria for +# usable LVS nodes. That is, either those that are healthy or, if no +# healthy nodes, then nodes that are active and not-disabled. +# Return codes: 0 = nodes found, 255 = no nodes found, 10 = error. +filter_nodes () +{ + # $_ns is an @-delimited list of nodes to be considered + _ns="$1" + + get_nodestatus_X + [ -n "$nodestatus_X" ] || return 10 + + # Now filter by $_ns and by status of nodes... + + # Note that the 2 awk invocations below have "||" between + # them, so the first to succeed will print the nodes. + + # 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 ns="$_ns" ' + BEGIN { ret = 255 } + ns ~ "@" $2 "@" && $4 == 0 && $6 == 0 && $7 == 0 && $9 == 0 { + print $1, $2 ; ret=0 + } + END { exit ret } + ' <<EOF || +$nodestatus_X +EOF + # Not found? UNHEALTHY do, so node must not be INACTIVE or + # DISABLED + awk -F '|' -v ns="$_ns" ' + BEGIN { ret = 255 } + ns ~ "@" $2 "@" && $6 == 0 && $9 == 0 { + print $1, $2 ; ret=0 + } + END { exit ret } + ' <<EOF +$nodestatus_X +EOF +} + +# Print the PNN of the LVS leader node +find_leader () +{ + get_lvs_nodes || \ + die "${prog}: LVS nodes file \"$CTDB_LVS_NODES\" not found" + + # $_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 +$lvs_nodes +EOF + + _leader_candidates=$(filter_nodes "$_ms") || return $? + echo "${_leader_candidates%% *}" +} + +# List all usable nodes in the LVS group +nodes_list () +{ + get_lvs_nodes || \ + die "${prog}: LVS nodes file \"$CTDB_LVS_NODES\" not found" + + # $_ns is a @-delimited list of nodes in the LVS group + _ns="@" + while read _ip _options ; do + _ns="${_ns}${_ip}@" + done <<EOF +$lvs_nodes +EOF + + _usable_nodes=$(filter_nodes "$_ns") + case $? in + 0) : ;; + 255) exit 0 ;; # Return 0 even if no usable nodes + *) exit 10 ;; + esac + + awk '{ print $1, $2 }'<<EOF +$_usable_nodes +EOF +} + +# Print the status of all nodes in the LVS group, along with a count +nodes_status () +{ + get_lvs_nodes || \ + die "${prog}: LVS nodes file \"$CTDB_LVS_NODES\" not found" + get_nodestatus + [ -n "$nodestatus" ] || exit 10 + + # $_ns is a @-delimited list of nodes in the LVS group + _ns="@" + while read _ip _options ; do + _ns="${_ns}${_ip}@" + done <<EOF +$lvs_nodes +EOF + + # Print status of nodes in $_ns, along with node count + awk -v ns="$_ns" 'ns ~ "@" $2 "@" { print }' <<EOF +$nodestatus +EOF +} + +# For backward compatibility +prog=$(basename "$0") +cmd="$1" + +case "$cmd" in +leader) find_leader ;; +list) nodes_list ;; +status) nodes_status ;; +*) usage ;; +esac |