opssh 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #!/usr/bin/env python
  2. # vim: expandtab:tabstop=4:shiftwidth=4
  3. import argparse
  4. import awsutil
  5. import traceback
  6. import sys
  7. import os
  8. import re
  9. import tempfile
  10. import time
  11. import subprocess
  12. import ConfigParser
  13. DEFAULT_PSSH_PAR = 200
  14. PSSH = '/usr/bin/pssh'
  15. CONFIG_MAIN_SECTION = 'main'
  16. CONFIG_HOST_TYPE_ALIAS_SECTION = 'host_type_aliases'
  17. CONFIG_INVENTORY_OPTION = 'inventory'
  18. class Opssh(object):
  19. def __init__(self):
  20. self.inventory = None
  21. self.host_type_aliases = {}
  22. self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)))
  23. # Default the config path to /etc
  24. self.config_path = os.path.join(os.path.sep, 'etc', \
  25. 'openshift_ansible', \
  26. 'openshift_ansible.conf')
  27. self.parse_cli_args()
  28. self.parse_config_file()
  29. self.aws = awsutil.AwsUtil(self.inventory, self.host_type_aliases)
  30. if self.args.list_host_types:
  31. self.aws.print_host_types()
  32. return
  33. if self.args.env and \
  34. self.args.host_type and \
  35. self.args.command:
  36. retval = self.run_pssh()
  37. if retval != 0:
  38. raise ValueError("pssh run failed")
  39. return
  40. # If it makes it here, we weren't able to determine what they wanted to do
  41. raise ValueError("Invalid combination of arguments")
  42. def run_pssh(self):
  43. """Actually run the pssh command based off of the supplied options
  44. """
  45. # Default set of options
  46. pssh_args = [PSSH, '-i', '-t', '0', '-p', str(self.args.par), '--user', self.args.user]
  47. if self.args.outdir:
  48. pssh_args.append("--outdir='%s'" % self.args.outdir)
  49. if self.args.errdir:
  50. pssh_args.append("--errdir='%s'" % self.args.errdir)
  51. hosts = self.aws.get_host_list(self.args.host_type, self.args.env)
  52. with tempfile.NamedTemporaryFile(prefix='opssh-', delete=True) as f:
  53. for h in hosts:
  54. f.write(h + os.linesep)
  55. f.flush()
  56. pssh_args.extend(["-h", "%s" % f.name])
  57. pssh_args.append("%s" % self.args.command)
  58. print
  59. print "Running: %s" % ' '.join(pssh_args)
  60. print
  61. return subprocess.call(pssh_args)
  62. return None
  63. def parse_config_file(self):
  64. if os.path.isfile(self.config_path):
  65. config = ConfigParser.ConfigParser()
  66. config.read(self.config_path)
  67. if config.has_section(CONFIG_MAIN_SECTION) and \
  68. config.has_option(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION):
  69. self.inventory = config.get(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION)
  70. self.host_type_aliases = {}
  71. if config.has_section(CONFIG_HOST_TYPE_ALIAS_SECTION):
  72. for alias in config.options(CONFIG_HOST_TYPE_ALIAS_SECTION):
  73. value = config.get(CONFIG_HOST_TYPE_ALIAS_SECTION, alias).split(',')
  74. self.host_type_aliases[alias] = value
  75. def parse_cli_args(self):
  76. """Setup the command line parser with the options we want
  77. """
  78. parser = argparse.ArgumentParser(description='Openshift Online PSSH Tool.')
  79. parser.add_argument('--list-host-types', default=False, action='store_true',
  80. help='List all of the host types')
  81. parser.add_argument('-e', '--env', action="store",
  82. help="Which environment to use")
  83. parser.add_argument('-t', '--host-type', action="store",
  84. help="Which host type to use")
  85. parser.add_argument('-c', '--command', action='store',
  86. help='Command to run on remote host(s)')
  87. parser.add_argument('--user', action='store', default='root',
  88. help='username')
  89. parser.add_argument('-p', '--par', action='store', default=DEFAULT_PSSH_PAR,
  90. help=('max number of parallel threads (default %s)' % DEFAULT_PSSH_PAR))
  91. parser.add_argument('--outdir', action='store',
  92. help='output directory for stdout files')
  93. parser.add_argument('--errdir', action='store',
  94. help='output directory for stderr files')
  95. self.args = parser.parse_args()
  96. if __name__ == '__main__':
  97. if len(sys.argv) == 1:
  98. print "\nError: No options given. Use --help to see the available options\n"
  99. sys.exit(0)
  100. try:
  101. opssh = Opssh()
  102. except ValueError as e:
  103. print "\nError: %s\n" % e.message