Browse Source

Merge pull request #202 from twiest/pr

changed opssh to a bash script using ohi to make it easier to maintain, and to expose all of the pssh features directly. Also made spacing consistent in opscp.
Thomas Wiest 10 years ago
parent
commit
a3624d731a
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[@]}"