Revert scheduling back to use real-time processes
[sahlberg/ctdb.git] / tools / onnode
index e00cd2b1d917feedc4ca2f46214d90df3a0e4349..fa61b47e5bd6f50c7a0f55bd142ebf3aacd917bc 100755 (executable)
@@ -34,11 +34,14 @@ Usage: onnode [OPTION] ... <NODES> <COMMAND> ...
     -o <prefix> Save standard output from each node to file <prefix>.<ip>
     -p          Run command in parallel on specified nodes.
     -q          Do not print node addresses (overrides -v).
+    -n          Allow nodes to be specified by name.
+    -f          Specify nodes file, overrides CTDB_NODES_FILE.
     -v          Print node address even for a single node.
-  <NODES>       "all", "ok" (or "healthy"), "con" (or "connected"),
+  <NODES>       "all", "any", "ok" (or "healthy"), "con" (or "connected"),
                 "rm" (or "recmaster"), "lvs" (or "lvsmaster"),
-                "natgw" (or "natgwlist");
-                or a node number (0 base); or
+                "natgw" (or "natgwlist"); or
+                a node number (0 base); or
+                a hostname (if -n is specified); or
                 list (comma separated) of <NODES>; or
                 range (hyphen separated) of node numbers.
 EOF
@@ -58,13 +61,16 @@ parallel=false
 verbose=false
 quiet=false
 prefix=""
+names_ok=false
+
+ctdb_base="${CTDB_BASE:-/etc/ctdb}"
 
 parse_options ()
 {
     # $POSIXLY_CORRECT means that the command passed to onnode can
     # take options and getopt won't reorder things to make them
     # options ot onnode.
-    local temp=$(POSIXLY_CORRECT=1 getopt -n "$prog" -o "cho:pqv" -l help -- "$@")
+    local temp=$(POSIXLY_CORRECT=1 getopt -n "$prog" -o "cf:hno:pqv" -l help -- "$@")
 
     [ $? != 0 ] && usage
 
@@ -73,6 +79,8 @@ parse_options ()
     while true ; do
        case "$1" in
            -c) current=true ; shift ;;
+           -f) CTDB_NODES_FILE="$2" ; shift 2 ;;
+           -n) names_ok=true ; shift ;;
            -o) prefix="$2" ; shift 2 ;;
            -p) parallel=true ; shift ;;
            -q) quiet=true ; shift ;;
@@ -112,10 +120,10 @@ parse_nodespec ()
            case "$i" in
                *-*) seq "${i%-*}" "${i#*-}" 2>/dev/null || invalid_nodespec ;;
                # Separate lines for readability.
-               all|ok|healthy|con|connected) echo "$i" ;;
+               all|any|ok|healthy|con|connected) echo "$i" ;;
                rm|recmaster|lvs|lvsmaster|natgw|natgwlist) echo "$i" ;;
                *)
-                   [ $i -gt -1 ] 2>/dev/null || invalid_nodespec
+                   [ $i -gt -1 ] 2>/dev/null || $names_ok || invalid_nodespec
                    echo $i
            esac
        done
@@ -159,7 +167,7 @@ get_nodes_with_status ()
            # Succeeded.  Get address.  NOTE: this is an optimisation.
            # It might be better to get the node number and then get
            # the nth node to get the address.  This would make things
-           # more consistent if /etc/ctdb/nodes actually contained
+           # more consistent if $ctdb_base/nodes actually contained
            # hostnames.
            nodes="${nodes} ${t##*:}"
        fi
@@ -198,6 +206,24 @@ get_node_with_property ()
     fi
 }
 
+get_any_available_node ()
+{
+    local all_nodes="$1"
+
+    # We do a recursive onnode to find which nodes are up and running.
+    local out=$($0 -pq all ctdb pnn 2>&1)
+    local line
+    while read line ; do 
+       local pnn="${line#PNN:}"
+       if [ "$pnn" != "$line" ] ; then
+           echo_nth "$pnn" $all_nodes
+           return 0
+       fi
+       # Else must be an error message from a down node.
+    done <<<"$out"
+    return 1
+}
+
 get_nodes ()
 {
     local all_nodes
@@ -205,8 +231,21 @@ get_nodes ()
     if [ -n "$CTDB_NODES_SOCKETS" ] ; then 
        all_nodes="$CTDB_NODES_SOCKETS"
     else
-       [ -f "$CTDB_NODES_FILE" ] || CTDB_NODES_FILE=/etc/ctdb/nodes
-       all_nodes=$(sed -e 's@#.*@@g' -e 's@ *@@g' -e 's@^$@#DEAD@' $CTDB_NODES_FILE)
+       local f="${ctdb_base}/nodes"
+       if [ -n "$CTDB_NODES_FILE" ] ; then
+           f="$CTDB_NODES_FILE"
+           if [ ! -e "$f" -a "${f#/}" = "$f" ] ; then
+               # $f is relative, try in $ctdb_base
+               f="${ctdb_base}/${f}"
+           fi
+       fi
+
+       if [ ! -r "$f" ] ; then
+           echo "${prog}: unable to open nodes file  \"${f}\"" >&2
+           exit 1
+       fi
+
+       all_nodes=$(sed -e 's@#.*@@g' -e 's@ *@@g' -e 's@^$@#DEAD@' "$f")
     fi
 
     local nodes=""
@@ -217,6 +256,9 @@ get_nodes ()
            all)
                echo "${all_nodes//#DEAD/}"
                ;;
+           any)
+               get_any_available_node "$all_nodes" || exit 1
+               ;;
            ok|healthy) 
                get_nodes_with_status "$all_nodes" "healthy" || exit 1
                ;;
@@ -232,10 +274,13 @@ get_nodes ()
            natgw|natgwlist)
                get_node_with_property "$all_nodes" "natgwlist" || exit 1
                ;;
-           *)
+           [0-9]|[0-9][0-9]|[0-9][0-9][0-9])
                echo_nth $n $all_nodes
+               ;;
+           *)
+               $names_ok || invalid_nodespec
+               echo $n
        esac
-       
     done
 }
 
@@ -275,7 +320,7 @@ if [ -n "$CTDB_NODES_SOCKETS" ] ; then
     SSH=fakessh
 else 
     # Could "2>/dev/null || true" but want to see errors from typos in file.
-    [ -r /etc/ctdb/onnode.conf ] && . /etc/ctdb/onnode.conf
+    [ -r "${ctdb_base}/onnode.conf" ] && . "${ctdb_base}/onnode.conf"
     [ -n "$SSH" ] || SSH=ssh
     if [ "$SSH" = "ssh" ] ; then
        ssh_opts="-n"