diff options
Diffstat (limited to 'bin/oscp')
-rwxr-xr-x | bin/oscp | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/bin/oscp b/bin/oscp new file mode 100755 index 000000000..a139ef38e --- /dev/null +++ b/bin/oscp @@ -0,0 +1,220 @@ +#!/usr/bin/env python +# vim: expandtab:tabstop=4:shiftwidth=4 + +import argparse +import ansibleutil +import traceback +import sys +import os +import re + +class Oscp(object): + def __init__(self): + self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__))) + self.parse_cli_args() + + # parse host and user + self.process_host() + + self.ansible = ansibleutil.AnsibleUtil() + + # get a dict of host inventory + if self.args.list: + self.get_hosts() + else: + self.get_hosts(True) + + if (self.args.src == '' or self.args.dest == '') and not self.args.list: + self.parser.print_help() + return + + if self.args.debug: + print self.host + print self.args + + # perform the scp + if self.args.list: + self.list_hosts() + else: + self.scp() + + def parse_cli_args(self): + parser = argparse.ArgumentParser(description='Openshift Online SSH Tool.') + parser.add_argument('-e', '--env', + action="store", help="Environment where this server exists.") + parser.add_argument('-d', '--debug', default=False, + action="store_true", help="debug mode") + parser.add_argument('-v', '--verbose', default=False, + action="store_true", help="Verbose?") + parser.add_argument('--list', default=False, + action="store_true", help="list out hosts") + parser.add_argument('-r', '--recurse', action='store_true', default=False, + help='Recursively copy files to or from destination.') + parser.add_argument('-o', '--ssh_opts', action='store', + help='options to pass to SSH.\n \ + "-oPort=22,TCPKeepAlive=yes"') + + parser.add_argument('src', nargs='?', default='') + parser.add_argument('dest',nargs='?', default='') + + self.args = parser.parse_args() + self.parser = parser + + + def process_host(self): + '''Determine host name and user name for SSH. + ''' + self.user = '' + + # is the first param passed a valid file? + if os.path.isfile(self.args.src) or os.path.isdir(self.args.src): + self.local_src = True + self.host = self.args.dest + else: + self.local_src = False + self.host = self.args.src + + if '@' in self.host: + re_host = re.compile("(.*@)(.*)(:.*$)") + else: + re_host = re.compile("(.*)(:.*$)") + + search = re_host.search(self.host) + + if search: + if len(search.groups()) > 2: + self.user = search.groups()[0] + self.host = search.groups()[1] + self.path = search.groups()[2] + else: + self.host = search.groups()[0] + self.path = search.groups()[1] + + if self.args.env: + self.env = self.args.env + elif "." in self.host: + self.host, self.env = self.host.split(".") + else: + self.env = None + + def get_hosts(self, cache_only=False): + '''Query our host inventory and return a dict where the format + equals: + + dict['environment'] = [{'servername' : {}}, ] + ''' + if cache_only: + self.host_inventory = self.ansible.build_host_dict_by_env(['--cache-only']) + else: + self.host_inventory = self.ansible.build_host_dict_by_env() + + def select_host(self): + '''select host attempts to match the host specified + on the command line with a list of hosts. + ''' + results = [] + for env in self.host_inventory.keys(): + for hostname, server_info in self.host_inventory[env].items(): + if hostname.split(':')[0] == self.host: + results.append((hostname, server_info)) + + # attempt to select the correct environment if specified + if self.env: + results = filter(lambda result: result[1]['ec2_tag_environment'] == self.env, results) + + if results: + return results + else: + print "Could not find specified host: %s." % self.host + + # default - no results found. + return None + + def list_hosts(self, limit=None): + '''Function to print out the host inventory. + + Takes a single parameter to limit the number of hosts printed. + ''' + + if self.env: + results = self.select_host() + if len(results) == 1: + hostname, server_info = results[0] + sorted_keys = server_info.keys() + sorted_keys.sort() + for key in sorted_keys: + print '{0:<35} {1}'.format(key, server_info[key]) + else: + for host_id, server_info in results[:limit]: + name = server_info['ec2_tag_Name'] + ec2_id = server_info['ec2_id'] + ip = server_info['ec2_ip_address'] + print '{ec2_tag_Name:<35} {ec2_tag_environment:<8} {ec2_id:<15} {ec2_ip_address}'.format(**server_info) + + if limit: + print + print 'Showing only the first %d results...' % limit + print + + else: + for env, host_ids in self.host_inventory.items(): + for host_id, server_info in host_ids.items(): + name = server_info['ec2_tag_Name'] + ec2_id = server_info['ec2_id'] + ip = server_info['ec2_ip_address'] + print '{ec2_tag_Name:<35} {ec2_tag_environment:<5} {ec2_id:<15} {ec2_ip_address}'.format(**server_info) + + def scp(self): + '''scp files to or from a specified host + ''' + try: + # shell args start with the program name in position 1 + scp_args = ['/usr/bin/scp'] + + if self.args.verbose: + scp_args.append('-v') + + if self.args.recurse: + scp_args.append('-r') + + if self.args.ssh_opts: + for arg in self.args.ssh_opts.split(","): + scp_args.append("-o%s" % arg) + + results = self.select_host() + + if self.args.debug: print results + + if not results: + return # early exit, no results + + if len(results) > 1: + print "Multiple results found for %s." % self.host + for result in results: + print "{ec2_tag_Name:<35} {ec2_tag_environment:<5} {ec2_id:<10}".format(**result[1]) + return # early exit, too many results + + # Assume we have one and only one. + hostname, server_info = results[0] + dns = server_info['ec2_public_dns_name'] + + host_str = "%s%s%s" % (self.user, dns, self.path) + + if self.local_src: + scp_args.append(self.args.src) + scp_args.append(host_str) + else: + scp_args.append(host_str) + scp_args.append(self.args.dest) + + print "Running: %s\n" % ' '.join(scp_args) + + os.execve('/usr/bin/scp', scp_args, os.environ) + except: + print traceback.print_exc() + print sys.exc_info() + + +if __name__ == '__main__': + oscp = Oscp() + |