Browse Source

changed opssh to a bash script using ohi to make it easier to maintain, and to expose all of the pssh features directly.

Thomas Wiest 10 years ago
parent
commit
734c853474
2 changed files with 215 additions and 213 deletions
  1. 81 70
      bin/opscp
  2. 134 143
      bin/opssh

+ 81 - 70
bin/opscp

@@ -1,8 +1,9 @@
 #!/bin/bash
+# vim: expandtab:tabstop=4:shiftwidth=4
 
 
 function usage() {
-  cat << EOF
+    cat << EOF
 Usage: opscp [OPTIONS] local remote
 
 Options:
@@ -10,12 +11,13 @@ Options:
   --help                show this help message and exit
   -l USER, --user=USER  username (OPTIONAL)
   -p PAR, --par=PAR     max number of parallel threads (OPTIONAL)
-  --errdir=ERRDIR       output directory for stderr files (OPTIONAL)
   --outdir=OUTDIR       output directory for stdout files (OPTIONAL)
-  -e ENV, --env ENV     Which environment to use
+  --errdir=ERRDIR       output directory for stderr files (OPTIONAL)
+  -e ENV, --env ENV     which environment to use
   -t HOST_TYPE, --host-type HOST_TYPE
-                        Which host type to use
-  --list-host-types     List all of the host types
+                        which host type to use
+  --list-host-types     list all of the host types
+  --timeout=TIMEOUT     timeout (secs) (0 = no timeout) per host (OPTIONAL)
   -O OPTION, --option=OPTION
                         SSH option (OPTIONAL)
   -v, --verbose         turn on warning and diagnostic messages (OPTIONAL)
@@ -34,89 +36,98 @@ EOF
 
 if [ $# -eq 0 ] || [ "$1" == "--help" ]
 then
-  usage
-  exit 1
+    usage
+    exit 1
+fi
+
+# See if ohi is installed
+if ! which ohi &>/dev/null ; then
+    echo "ERROR: can't find ohi (OpenShift Host Inventory) on your system, please either install the openshift-ansible-bin package, or add openshift-ansible/bin to your path."
+
+    exit 10
 fi
 
-PSCP_PAR=200
+PAR=200
 USER=root
-PSCP_OPTIONS=""
+TIMEOUT=0
 ENV=""
 HOST_TYPE=""
+
 while [ $# -gt 0 ] ; do
-  if [ "$1" == "-t" -o "$1" == "--host-type" ] ; then
-    shift # get past the option
-    HOST_TYPE=$1
-    shift # get past the value of the option
-
-  elif [ "$1" == "-e" ] ; then
-    shift # get past the option
-    ENV=$1
-    shift # get past the value of the option
-
-  elif [ "$1" == "-p" -o "$1" == "--par" ] ; then
-    shift # get past the option
-    PSCP_PAR=$1
-    shift # get past the value of the option
-
-  elif [ "$1" == "-l" -o "$1" == "--user" ] ; then
-    shift # get past the option
-    USER=$1
-    shift # get past the value of the option
-
-  elif [ "$1" == "--list-host-types" ] ; then
-    ohi --list-host-types
-    exit 0
-
-  elif [ "$1" == "-h" -o "$1" == "--hosts" -o "$1" == "-H" -o "$1" == "--host" ] ||
-       [ "$1" == "-o" ] ; then
-    echo "ERROR: unknown option $1"
-    exit 20
-
-  else
-    if [ "${1:0:1}" == "-" ] ; then
-      # It's an option, don't quote
-      PSCP_OPTIONS="$PSCP_OPTIONS $1"
-    else
-      PSCP_OPTIONS="$PSCP_OPTIONS '$1'"
-    fi
-    shift # Get past this option
-  fi
+    case $1 in
+        -t|--host-type)
+            shift # get past the option
+            HOST_TYPE=$1
+            shift # get past the value of the option
+            ;;
+
+        -e)
+            shift # get past the option
+            ENV=$1
+            shift # get past the value of the option
+            ;;
+
+        --timeout)
+            shift # get past the option
+            TIMEOUT=$1
+            shift # get past the value of the option
+            ;;
+
+        -p|--par)
+            shift # get past the option
+            PAR=$1
+            shift # get past the value of the option
+            ;;
+
+        -l|--user)
+            shift # get past the option
+            USER=$1
+            shift # get past the value of the option
+            ;;
+
+        --list-host-types)
+            ohi --list-host-types
+            exit 0
+            ;;
+
+        -h|--hosts|-H|--host|-o)
+            echo "ERROR: unknown option $1"
+            exit 20
+            ;;
+
+        *)
+            args+=("$1")
+            shift
+            ;;
+    esac
 done
 
 if [ -z "$ENV" ]
 then
-  echo
-  echo "-e is a required paramemeter"
-  echo
-  exit 10
+    echo
+    echo "-e is a required paramemeter"
+    echo
+    exit 10
 fi
 
 if [ -z "$HOST_TYPE" ]
 then
-  echo
-  echo "-t is a required paramemeter"
-  echo
-  exit 15
+    echo
+    echo "-t is a required paramemeter"
+    echo
+    exit 15
 fi
 
-PSCP_OPTIONS="-t 0 -p $PSCP_PAR -l $USER -h <(ohi -t $HOST_TYPE -e $ENV 2>/dev/null) $PSCP_OPTIONS"
-
-
 # See if the ohi options are valid
-ohi -t $HOST_TYPE -e $ENV &> /dev/null
+HOSTS="$(ohi -t "$HOST_TYPE" -e "$ENV" 2>/dev/null)"
 ECODE=$?
 if [ $ECODE -ne 0 ] ; then
-  echo
-  echo "ERROR: ohi failed with exit code $ECODE"
-  echo
-  echo "This is usually caused by a bad value passed for host-type or environment."
-  echo
-  exit 25
+    echo
+    echo "ERROR: ohi failed with exit code $ECODE"
+    echo
+    echo "This is usually caused by a bad value passed for host-type or environment."
+    echo
+    exit 25
 fi
 
-echo
-echo "Running: pscp.pssh $PSCP_OPTIONS"
-echo
-
-eval pscp.pssh $PSCP_OPTIONS
+exec pscp.pssh -t $TIMEOUT -p $PAR -l $USER -h <(echo "$HOSTS") "${args[@]}"

+ 134 - 143
bin/opssh

@@ -1,146 +1,137 @@
-#!/usr/bin/env python
+#!/bin/bash
 # vim: expandtab:tabstop=4:shiftwidth=4
 
-import argparse
-import traceback
-import sys
-import os
-import re
-import tempfile
-import time
-import subprocess
-import ConfigParser
 
-from openshift_ansible import awsutil
-from openshift_ansible.awsutil import ArgumentError
-
-DEFAULT_PSSH_PAR = 200
-PSSH = '/usr/bin/pssh'
-CONFIG_MAIN_SECTION = 'main'
-CONFIG_HOST_TYPE_ALIAS_SECTION = 'host_type_aliases'
-CONFIG_INVENTORY_OPTION = 'inventory'
-
-class Opssh(object):
-    def __init__(self):
-        self.inventory = None
-        self.host_type_aliases = {}
-        self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)))
-
-        # Default the config path to /etc
-        self.config_path = os.path.join(os.path.sep, 'etc',  \
-                                        'openshift_ansible', \
-                                        'openshift_ansible.conf')
-
-        self.parse_cli_args()
-        self.parse_config_file()
-
-        self.aws = awsutil.AwsUtil(self.inventory, self.host_type_aliases)
-
-    def run(self):
-        if self.args.list_host_types:
-            self.aws.print_host_types()
-            return 0
-
-        if self.args.host_type is not None or \
-           self.args.env is not None:
-            return self.run_pssh()
-
-        # We weren't able to determine what they wanted to do
-        raise ArgumentError("Invalid combination of arguments")
-
-    def run_pssh(self):
-        """Actually run the pssh command based off of the supplied options
-        """
-
-        # Default set of options
-        pssh_args = [PSSH, '-t', '0', '-p', str(self.args.par), '--user', self.args.user]
-
-        if self.args.inline:
-            pssh_args.append("--inline")
-
-        if self.args.outdir:
-            pssh_args.extend(["--outdir", self.args.outdir])
-
-        if self.args.errdir:
-            pssh_args.extend(["--errdir", self.args.errdir])
-
-        hosts = self.aws.get_host_list(host_type=self.args.host_type,
-                                       env=self.args.env)
-
-        with tempfile.NamedTemporaryFile(prefix='opssh-', delete=True) as f:
-            for h in hosts:
-                f.write(h + os.linesep)
-            f.flush()
-
-            pssh_args.extend(["-h", f.name])
-            pssh_args.append(self.args.command)
-
-            print
-            print "Running: %s" % ' '.join(pssh_args)
-            print
-            return subprocess.call(pssh_args)
-
-        return None
-
-    def parse_config_file(self):
-        if os.path.isfile(self.config_path):
-            config = ConfigParser.ConfigParser()
-            config.read(self.config_path)
-
-            if config.has_section(CONFIG_MAIN_SECTION) and \
-               config.has_option(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION):
-                self.inventory = config.get(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION)
-
-            self.host_type_aliases = {}
-            if config.has_section(CONFIG_HOST_TYPE_ALIAS_SECTION):
-                for alias in config.options(CONFIG_HOST_TYPE_ALIAS_SECTION):
-                    value = config.get(CONFIG_HOST_TYPE_ALIAS_SECTION, alias).split(',')
-                    self.host_type_aliases[alias] = value
-
-    def parse_cli_args(self):
-        """Setup the command line parser with the options we want
-        """
-
-        parser = argparse.ArgumentParser(description='Openshift Online PSSH Tool.')
-
-        parser.add_argument('--list-host-types', default=False, action='store_true',
-                       help='List all of the host types')
-
-        parser.add_argument('-e', '--env', action="store",
-                       help="Which environment to use")
-
-        parser.add_argument('-t', '--host-type', action="store", default=None,
-                       help="Which host type to use")
-
-        parser.add_argument('-c', '--command', action='store',
-                       help='Command to run on remote host(s)')
-
-        parser.add_argument('--user', action='store', default='root',
-                       help='username')
-
-        parser.add_argument('-i', '--inline', default=False, action='store_true',
-                       help='inline aggregated output and error for each server')
-
-        parser.add_argument('-p', '--par', action='store', default=DEFAULT_PSSH_PAR,
-                       help=('max number of parallel threads (default %s)' % DEFAULT_PSSH_PAR))
-
-        parser.add_argument('--outdir', action='store',
-                       help='output directory for stdout files')
-
-        parser.add_argument('--errdir', action='store',
-                       help='output directory for stderr files')
-
-        self.args = parser.parse_args()
-
-
-if __name__ == '__main__':
-    if len(sys.argv) == 1:
-        print "\nError: No options given. Use --help to see the available options\n"
-        sys.exit(0)
-
-    try:
-        opssh = Opssh()
-        exitcode = opssh.run()
-        sys.exit(exitcode)
-    except ArgumentError as e:
-        print "\nError: %s\n" % e.message
+function usage() {
+    cat << EOF
+Usage: opssh [OPTIONS] command [...]
+
+Options:
+  --version             show program's version number and exit
+  --help                show this help message and exit
+  -l USER, --user=USER  username (OPTIONAL)
+  -p PAR, --par=PAR     max number of parallel threads (OPTIONAL)
+  --outdir=OUTDIR       output directory for stdout files (OPTIONAL)
+  --errdir=ERRDIR       output directory for stderr files (OPTIONAL)
+  -e ENV, --env ENV     which environment to use
+  -t HOST_TYPE, --host-type HOST_TYPE
+                        which host type to use
+  --list-host-types     list all of the host types
+  --timeout=TIMEOUT     timeout (secs) (0 = no timeout) per host (OPTIONAL)
+  -O OPTION, --option=OPTION
+                        SSH option (OPTIONAL)
+  -v, --verbose         turn on warning and diagnostic messages (OPTIONAL)
+  -A, --askpass         Ask for a password (OPTIONAL)
+  -x ARGS, --extra-args=ARGS
+                        Extra command-line arguments, with processing for
+                        spaces, quotes, and backslashes
+  -X ARG, --extra-arg=ARG
+                        Extra command-line argument
+  -i, --inline          inline aggregated output and error for each server
+  --inline-stdout       inline standard output for each server
+  -I, --send-input      read from standard input and send as input to ssh
+  -P, --print           print output as we get it
+
+Example: opssh -t ex-srv -e stg -l irb2 --outdir /tmp/foo uptime
+
+EOF
+}
+
+if [ $# -eq 0 ] || [ "$1" == "--help" ]
+then
+    usage
+    exit 1
+fi
+
+# See if ohi is installed
+if ! which ohi &>/dev/null ; then
+    echo "ERROR: can't find ohi (OpenShift Host Inventory) on your system, please either install the openshift-ansible-bin package, or add openshift-ansible/bin to your path."
+
+    exit 10
+fi
+
+PAR=200
+USER=root
+TIMEOUT=0
+ARGS=()
+ENV=""
+HOST_TYPE=""
+while [ $# -gt 0 ] ; do
+    case $1 in
+        -t|--host-type)
+            shift # get past the option
+            HOST_TYPE=$1
+            shift # get past the value of the option
+            ;;
+
+        -e)
+            shift # get past the option
+            ENV=$1
+            shift # get past the value of the option
+            ;;
+
+        --timeout)
+            shift # get past the option
+            TIMEOUT=$1
+            shift # get past the value of the option
+            ;;
+
+        -p|--par)
+            shift # get past the option
+            PAR=$1
+            shift # get past the value of the option
+            ;;
+
+        -l|--user)
+            shift # get past the option
+            USER=$1
+            shift # get past the value of the option
+            ;;
+
+        --list-host-types)
+            ohi --list-host-types
+            exit 0
+            ;;
+
+        -h|--hosts|-H|--host|-o)
+            echo "ERROR: unknown option $1"
+            exit 20
+            ;;
+
+        *)
+            args+=("$1")
+            shift
+            ;;
+    esac
+done
+
+if [ -z "$ENV" ]
+then
+    echo
+    echo "-e is a required paramemeter"
+    echo
+    exit 10
+fi
+
+if [ -z "$HOST_TYPE" ]
+then
+    echo
+    echo "-t is a required paramemeter"
+    echo
+    exit 15
+fi
+
+# See if the ohi options are valid
+HOSTS="$(ohi -t "$HOST_TYPE" -e "$ENV" 2>/dev/null)"
+ECODE=$?
+
+if [ $ECODE -ne 0 ] ; then
+    echo
+    echo "ERROR: ohi failed with exit code $ECODE"
+    echo
+    echo "This is usually caused by a bad value passed for host-type or environment."
+    echo
+    exit 25
+fi
+
+exec pssh -t $TIMEOUT -p $PAR -l $USER -h <(echo "$HOSTS") "${args[@]}"