From 734c853474b18564c7252d22314fc729db6207bb Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Sat, 2 May 2015 01:24:36 -0400 Subject: changed opssh to a bash script using ohi to make it easier to maintain, and to expose all of the pssh features directly. --- bin/opscp | 151 ++++++++++++++++++---------------- bin/opssh | 277 ++++++++++++++++++++++++++++++-------------------------------- 2 files changed, 215 insertions(+), 213 deletions(-) (limited to 'bin') diff --git a/bin/opscp b/bin/opscp index d76480253..32fd341b9 100755 --- a/bin/opscp +++ b/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[@]}" diff --git a/bin/opssh b/bin/opssh index a4fceb6a8..130549506 100755 --- a/bin/opssh +++ b/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[@]}" -- cgit v1.2.1