oscp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #!/usr/bin/env python2
  2. # vim: expandtab:tabstop=4:shiftwidth=4
  3. import argparse
  4. import traceback
  5. import sys
  6. import os
  7. import re
  8. import ConfigParser
  9. from openshift_ansible import awsutil
  10. CONFIG_MAIN_SECTION = 'main'
  11. CONFIG_INVENTORY_OPTION = 'inventory'
  12. class Oscp(object):
  13. def __init__(self):
  14. self.inventory = None
  15. self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)))
  16. # Default the config path to /etc
  17. self.config_path = os.path.join(os.path.sep, 'etc', \
  18. 'openshift_ansible', \
  19. 'openshift_ansible.conf')
  20. self.parse_cli_args()
  21. self.parse_config_file()
  22. # parse host and user
  23. self.process_host()
  24. self.aws = awsutil.AwsUtil(self.inventory)
  25. # get a dict of host inventory
  26. if self.args.refresh_cache:
  27. self.get_hosts(True)
  28. else:
  29. self.get_hosts()
  30. if (self.args.src == '' or self.args.dest == '') and not self.args.list:
  31. self.parser.print_help()
  32. return
  33. if self.args.debug:
  34. print self.host
  35. print self.args
  36. # perform the scp
  37. if self.args.list:
  38. self.list_hosts()
  39. else:
  40. self.scp()
  41. def parse_config_file(self):
  42. if os.path.isfile(self.config_path):
  43. config = ConfigParser.ConfigParser()
  44. config.read(self.config_path)
  45. if config.has_section(CONFIG_MAIN_SECTION) and \
  46. config.has_option(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION):
  47. self.inventory = config.get(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION)
  48. def parse_cli_args(self):
  49. parser = argparse.ArgumentParser(description='Openshift Online SSH Tool.')
  50. parser.add_argument('-e', '--env',
  51. action="store", help="Environment where this server exists.")
  52. parser.add_argument('-d', '--debug', default=False,
  53. action="store_true", help="debug mode")
  54. parser.add_argument('-v', '--verbose', default=False,
  55. action="store_true", help="Verbose?")
  56. parser.add_argument('--refresh-cache', default=False,
  57. action="store_true", help="Force a refresh on the host cache.")
  58. parser.add_argument('--list', default=False,
  59. action="store_true", help="list out hosts")
  60. parser.add_argument('-r', '--recurse', action='store_true', default=False,
  61. help='Recursively copy files to or from destination.')
  62. parser.add_argument('-o', '--ssh_opts', action='store',
  63. help='options to pass to SSH.\n \
  64. "-oPort=22,TCPKeepAlive=yes"')
  65. parser.add_argument('src', nargs='?', default='')
  66. parser.add_argument('dest',nargs='?', default='')
  67. self.args = parser.parse_args()
  68. self.parser = parser
  69. def process_host(self):
  70. '''Determine host name and user name for SSH.
  71. '''
  72. self.user = ''
  73. # is the first param passed a valid file?
  74. if os.path.isfile(self.args.src) or os.path.isdir(self.args.src):
  75. self.local_src = True
  76. self.host = self.args.dest
  77. else:
  78. self.local_src = False
  79. self.host = self.args.src
  80. if '@' in self.host:
  81. re_host = re.compile("(.*@)(.*)(:.*$)")
  82. else:
  83. re_host = re.compile("(.*)(:.*$)")
  84. search = re_host.search(self.host)
  85. if search:
  86. if len(search.groups()) > 2:
  87. self.user = search.groups()[0]
  88. self.host = search.groups()[1]
  89. self.path = search.groups()[2]
  90. else:
  91. self.host = search.groups()[0]
  92. self.path = search.groups()[1]
  93. if self.args.env:
  94. self.env = self.args.env
  95. elif "." in self.host:
  96. self.host, self.env = self.host.split(".")
  97. else:
  98. self.env = None
  99. def get_hosts(self, refresh_cache=False):
  100. '''Query our host inventory and return a dict where the format
  101. equals:
  102. dict['environment'] = [{'servername' : {}}, ]
  103. '''
  104. if refresh_cache:
  105. self.host_inventory = self.aws.build_host_dict_by_env(['--refresh-cache'])
  106. else:
  107. self.host_inventory = self.aws.build_host_dict_by_env()
  108. def select_host(self):
  109. '''select host attempts to match the host specified
  110. on the command line with a list of hosts.
  111. '''
  112. results = []
  113. for env in self.host_inventory.keys():
  114. for hostname, server_info in self.host_inventory[env].items():
  115. if hostname.split(':')[0] == self.host:
  116. results.append((hostname, server_info))
  117. # attempt to select the correct environment if specified
  118. if self.env:
  119. results = filter(lambda result: result[1]['ec2_tag_environment'] == self.env, results)
  120. if results:
  121. return results
  122. else:
  123. print "Could not find specified host: %s." % self.host
  124. # default - no results found.
  125. return None
  126. def list_hosts(self, limit=None):
  127. '''Function to print out the host inventory.
  128. Takes a single parameter to limit the number of hosts printed.
  129. '''
  130. if self.env:
  131. results = self.select_host()
  132. if len(results) == 1:
  133. hostname, server_info = results[0]
  134. sorted_keys = server_info.keys()
  135. sorted_keys.sort()
  136. for key in sorted_keys:
  137. print '{0:<35} {1}'.format(key, server_info[key])
  138. else:
  139. for host_id, server_info in results[:limit]:
  140. name = server_info['ec2_tag_Name']
  141. ec2_id = server_info['ec2_id']
  142. ip = server_info['ec2_ip_address']
  143. print '{ec2_tag_Name:<35} {ec2_tag_environment:<8} {ec2_id:<15} {ec2_ip_address}'.format(**server_info)
  144. if limit:
  145. print
  146. print 'Showing only the first %d results...' % limit
  147. print
  148. else:
  149. for env, host_ids in self.host_inventory.items():
  150. for host_id, server_info in host_ids.items():
  151. name = server_info['ec2_tag_Name']
  152. ec2_id = server_info['ec2_id']
  153. ip = server_info['ec2_ip_address']
  154. print '{ec2_tag_Name:<35} {ec2_tag_environment:<5} {ec2_id:<15} {ec2_ip_address}'.format(**server_info)
  155. def scp(self):
  156. '''scp files to or from a specified host
  157. '''
  158. try:
  159. # shell args start with the program name in position 1
  160. scp_args = ['/usr/bin/scp']
  161. if self.args.verbose:
  162. scp_args.append('-v')
  163. if self.args.recurse:
  164. scp_args.append('-r')
  165. if self.args.ssh_opts:
  166. for arg in self.args.ssh_opts.split(","):
  167. scp_args.append("-o%s" % arg)
  168. results = self.select_host()
  169. if self.args.debug: print results
  170. if not results:
  171. return # early exit, no results
  172. if len(results) > 1:
  173. print "Multiple results found for %s." % self.host
  174. for result in results:
  175. print "{ec2_tag_Name:<35} {ec2_tag_environment:<5} {ec2_id:<10}".format(**result[1])
  176. return # early exit, too many results
  177. # Assume we have one and only one.
  178. hostname, server_info = results[0]
  179. dns = server_info['ec2_public_dns_name']
  180. host_str = "%s%s%s" % (self.user, dns, self.path)
  181. if self.local_src:
  182. scp_args.append(self.args.src)
  183. scp_args.append(host_str)
  184. else:
  185. scp_args.append(host_str)
  186. scp_args.append(self.args.dest)
  187. print "Running: %s\n" % ' '.join(scp_args)
  188. os.execve('/usr/bin/scp', scp_args, os.environ)
  189. except:
  190. print traceback.print_exc()
  191. print sys.exc_info()
  192. if __name__ == '__main__':
  193. oscp = Oscp()