oscp 7.4 KB

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