pyldb: avoid segfault when adding an element with no name
[vlendec/samba-autobuild/.git] / ctdb / tools / ctdb_lvs
1 #!/bin/sh
2
3 if [ -z "$CTDB_BASE" ] ; then
4         export CTDB_BASE="/usr/local/etc/ctdb"
5 fi
6
7 . "${CTDB_BASE}/functions"
8
9 load_script_options "failover" "91.lvs"
10
11 # Default LVS nodes file location
12 [ -n "$CTDB_LVS_NODES" ] || CTDB_LVS_NODES="${CTDB_BASE}/lvs_nodes"
13
14 if [ -z "$CTDB" ] ; then
15         CTDB=ctdb
16 fi
17
18 ############################################################
19
20 usage ()
21 {
22         cat <<EOF
23 $0 <option>
24
25 <option> is one of:
26   master     Display node number of master node
27   list       List node number and private IP address of usable nodes in group
28   status     Show status of all nodes in LVS group
29 EOF
30     exit 1
31 }
32
33 nodestatus_X=""
34 # Fields are:
35 # Node|IP|Disconnected|Banned|Disabled|Unhealthy|Stopped|Inactive|PartiallyOnline|ThisNode
36 get_nodestatus_X ()
37 {
38         # Result is cached in global variable nodestatus_X
39         [ -n "$nodestatus_X" ] || \
40                 nodestatus_X=$($CTDB -X nodestatus all |
41                                sed -e '1d' -e 's@^|@@' -e 's@|$@@')
42 }
43
44 get_nodestatus ()
45 {
46         # Result is cached in global variable nodestatus
47         [ -n "$nodestatus" ] || nodestatus=$($CTDB nodestatus all)
48         case $? in
49         # $CTDB nodestatus returns 255 on failure
50         0|255) return 0 ;;
51         *)     return 1 ;;
52         esac
53 }
54
55 get_lvs_nodes ()
56 {
57         # Result is cached in global variable lvs_nodes
58         if [ -n "$lvs_nodes" ] ; then
59                 return
60         fi
61
62         if [ ! -r "$CTDB_LVS_NODES" ] ; then
63                 return 1
64         fi
65
66         lvs_nodes=$(cat "$CTDB_LVS_NODES") || return 1
67
68         # Sanity check file contents here
69         while read _ip _options ; do
70                 # Skip comments
71                 case "$_ip" in
72                 \#*) continue ;;
73                 esac
74                 case "$_options" in
75                 slave-only|"") : ;;
76                 *) die "${prog}: Invalid options \"${_options}\" in  \"$CTDB_LVS_NODES\""
77                 esac
78         done <<EOF
79 $lvs_nodes
80 EOF
81
82         return 0
83 }
84
85 # Print PNN and IP address of given nodes meeting the criteria for
86 # usable LVS nodes.  That is, either those that are healthy or, if no
87 # healthy nodes, then nodes that are active and not-disabled.
88 # Return codes: 0 = nodes found, 255 = no nodes found, 10 = error.
89 filter_nodes ()
90 {
91         # $_ns is an @-delimited list of nodes to be considered
92         _ns="$1"
93
94         get_nodestatus_X
95         [ -n "$nodestatus_X" ] || return 10
96
97         # Now filter by $_ns and by status of nodes...
98
99         # Note that the 2 awk invocations below have "||" between
100         # them, so the first to succeed will print the nodes.
101
102         # First try for a fully active and healthy node, so must not
103         # be DISABLED, UNHEALTHY or INACTIVE (last covers
104         # DISCONNECTED, BANNED or STOPPED)
105         awk -F '|' -v ns="$_ns" '
106                 BEGIN { ret = 255 }
107                 ns ~ "@" $2 "@" && $5 == 0 && $6 == 0 && $8 == 0 {
108                         print $1, $2 ; ret=0
109                 }
110                 END { exit ret }
111                 ' <<EOF ||
112 $nodestatus_X
113 EOF
114         # Not found?  UNHEALTHY do, so node must not be INACTIVE or
115         # DISABLED
116         awk -F '|' -v ns="$_ns" '
117                 BEGIN { ret = 255 }
118                 ns ~ "@" $2 "@" && $5 == 0 && $8 == 0 {
119                         print $1, $2 ; ret=0
120                 }
121                 END { exit ret }
122                 ' <<EOF
123 $nodestatus_X
124 EOF
125 }
126
127 # Print the PNN of the LVS master node
128 find_master ()
129 {
130         get_lvs_nodes || \
131                 die "${prog}: LVS nodes file \"$CTDB_LVS_NODES\" not found"
132
133         # $_ms is an @-delimited list of nodes that are allowed to be the master
134         _ms="@"
135         while read _ip _options ; do
136                 case "$_options" in
137                 "") _ms="${_ms}${_ip}@" ;;
138                 esac
139         done <<EOF
140 $lvs_nodes
141 EOF
142
143         _master_candidates=$(filter_nodes "$_ms") || return $?
144         echo "${_master_candidates%% *}"
145 }
146
147 # List all usable nodes in the LVS group
148 nodes_list ()
149 {
150         get_lvs_nodes || \
151                 die "${prog}: LVS nodes file \"$CTDB_LVS_NODES\" not found"
152
153         # $_ns is a @-delimited list of nodes in the LVS  group
154         _ns="@"
155         while read _ip _options ; do
156                 _ns="${_ns}${_ip}@"
157         done <<EOF
158 $lvs_nodes
159 EOF
160
161         _usable_nodes=$(filter_nodes "$_ns")
162         case $? in
163         0)   : ;;
164         255) exit 0 ;; # Return 0 even if no usable nodes
165         *)   exit 10 ;;
166         esac
167
168         awk '{ print $1, $2 }'<<EOF
169 $_usable_nodes
170 EOF
171 }
172
173 # Print the status of all nodes in the LVS group, along with a count
174 nodes_status ()
175 {
176         get_lvs_nodes || \
177                 die "${prog}: LVS nodes file \"$CTDB_LVS_NODES\" not found"
178         get_nodestatus
179         [ -n "$nodestatus" ] || exit 10
180
181         # $_ns is a @-delimited list of nodes in the LVS  group
182         _ns="@"
183         while read _ip _options ; do
184                 _ns="${_ns}${_ip}@"
185         done <<EOF
186 $lvs_nodes
187 EOF
188
189         # Print status of nodes in $_ns, along with node count
190         awk -v ns="$_ns" 'ns ~ "@" $2 "@" { print }' <<EOF
191 $nodestatus
192 EOF
193 }
194
195 # For backward compatibility
196 prog=$(basename "$0")
197 cmd="$1"
198
199 case "$cmd" in
200 master) find_master ;;
201 list)   nodes_list ;;
202 status) nodes_status ;;
203 *)      usage ;;
204 esac