awsutil.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. # vim: expandtab:tabstop=4:shiftwidth=4
  2. """This module comprises Aws specific utility functions."""
  3. import subprocess
  4. import os
  5. import json
  6. import re
  7. class ArgumentError(Exception):
  8. """This class is raised when improper arguments are passed."""
  9. def __init__(self, message):
  10. """Initialize an ArgumentError.
  11. Keyword arguments:
  12. message -- the exact error message being raised
  13. """
  14. super(ArgumentError, self).__init__()
  15. self.message = message
  16. class AwsUtil(object):
  17. """This class contains the AWS utility functions."""
  18. def __init__(self, inventory_path=None, host_type_aliases=None):
  19. """Initialize the AWS utility class.
  20. Keyword arguments:
  21. inventory_path -- the path to find the inventory script
  22. host_type_aliases -- a list of aliases to common host-types (e.g. ex-node)
  23. """
  24. host_type_aliases = host_type_aliases or {}
  25. self.host_type_aliases = host_type_aliases
  26. self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)))
  27. if inventory_path is None:
  28. inventory_path = os.path.realpath(os.path.join(self.file_path, \
  29. '..', '..', 'inventory', \
  30. 'multi_ec2.py'))
  31. if not os.path.isfile(inventory_path):
  32. raise Exception("Inventory file not found [%s]" % inventory_path)
  33. self.inventory_path = inventory_path
  34. self.setup_host_type_alias_lookup()
  35. def setup_host_type_alias_lookup(self):
  36. """Sets up the alias to host-type lookup table."""
  37. self.alias_lookup = {}
  38. for key, values in self.host_type_aliases.iteritems():
  39. for value in values:
  40. self.alias_lookup[value] = key
  41. def get_inventory(self, args=None):
  42. """Calls the inventory script and returns a dictionary containing the inventory."
  43. Keyword arguments:
  44. args -- optional arguments to pass to the inventory script
  45. """
  46. args = args or []
  47. cmd = [self.inventory_path]
  48. if args:
  49. cmd.extend(args)
  50. env = os.environ
  51. proc = subprocess.Popen(cmd, stderr=subprocess.PIPE,
  52. stdout=subprocess.PIPE, env=env)
  53. out, err = proc.communicate()
  54. if proc.returncode != 0:
  55. raise RuntimeError(err)
  56. return json.loads(out.strip())
  57. def get_environments(self):
  58. """Searches for env tags in the inventory and returns all of the envs found."""
  59. pattern = re.compile(r'^tag_environment_(.*)')
  60. envs = []
  61. inv = self.get_inventory()
  62. for key in inv.keys():
  63. matched = pattern.match(key)
  64. if matched:
  65. envs.append(matched.group(1))
  66. envs.sort()
  67. return envs
  68. def get_host_types(self):
  69. """Searches for host-type tags in the inventory and returns all host-types found."""
  70. pattern = re.compile(r'^tag_host-type_(.*)')
  71. host_types = []
  72. inv = self.get_inventory()
  73. for key in inv.keys():
  74. matched = pattern.match(key)
  75. if matched:
  76. host_types.append(matched.group(1))
  77. host_types.sort()
  78. return host_types
  79. def get_security_groups(self):
  80. """Searches for security_groups in the inventory and returns all SGs found."""
  81. pattern = re.compile(r'^security_group_(.*)')
  82. groups = []
  83. inv = self.get_inventory()
  84. for key in inv.keys():
  85. matched = pattern.match(key)
  86. if matched:
  87. groups.append(matched.group(1))
  88. groups.sort()
  89. return groups
  90. def build_host_dict_by_env(self, args=None):
  91. """Searches the inventory for hosts in an env and returns their hostvars."""
  92. args = args or []
  93. inv = self.get_inventory(args)
  94. inst_by_env = {}
  95. for _, host in inv['_meta']['hostvars'].items():
  96. # If you don't have an environment tag, we're going to ignore you
  97. if 'ec2_tag_environment' not in host:
  98. continue
  99. if host['ec2_tag_environment'] not in inst_by_env:
  100. inst_by_env[host['ec2_tag_environment']] = {}
  101. host_id = "%s:%s" % (host['ec2_tag_Name'], host['ec2_id'])
  102. inst_by_env[host['ec2_tag_environment']][host_id] = host
  103. return inst_by_env
  104. def print_host_types(self):
  105. """Gets the list of host types and aliases and outputs them in columns."""
  106. host_types = self.get_host_types()
  107. ht_format_str = "%35s"
  108. alias_format_str = "%-20s"
  109. combined_format_str = ht_format_str + " " + alias_format_str
  110. print
  111. print combined_format_str % ('Host Types', 'Aliases')
  112. print combined_format_str % ('----------', '-------')
  113. for host_type in host_types:
  114. aliases = []
  115. if host_type in self.host_type_aliases:
  116. aliases = self.host_type_aliases[host_type]
  117. print combined_format_str % (host_type, ", ".join(aliases))
  118. else:
  119. print ht_format_str % host_type
  120. print
  121. def resolve_host_type(self, host_type):
  122. """Converts a host-type alias into a host-type.
  123. Keyword arguments:
  124. host_type -- The alias or host_type to look up.
  125. Example (depends on aliases defined in config file):
  126. host_type = ex-node
  127. returns: openshift-node
  128. """
  129. if self.alias_lookup.has_key(host_type):
  130. return self.alias_lookup[host_type]
  131. return host_type
  132. @staticmethod
  133. def gen_env_tag(env):
  134. """Generate the environment tag
  135. """
  136. return "tag_environment_%s" % env
  137. def gen_host_type_tag(self, host_type):
  138. """Generate the host type tag
  139. """
  140. host_type = self.resolve_host_type(host_type)
  141. return "tag_host-type_%s" % host_type
  142. def gen_env_host_type_tag(self, host_type, env):
  143. """Generate the environment host type tag
  144. """
  145. host_type = self.resolve_host_type(host_type)
  146. return "tag_env-host-type_%s-%s" % (env, host_type)
  147. def get_host_list(self, host_type=None, envs=None):
  148. """Get the list of hosts from the inventory using host-type and environment
  149. """
  150. envs = envs or []
  151. inv = self.get_inventory()
  152. # We prefer to deal with a list of environments
  153. if issubclass(type(envs), basestring):
  154. if envs == 'all':
  155. envs = self.get_environments()
  156. else:
  157. envs = [envs]
  158. if host_type and envs:
  159. # Both host type and environment were specified
  160. retval = []
  161. for env in envs:
  162. env_host_type_tag = self.gen_env_host_type_tag(host_type, env)
  163. if env_host_type_tag in inv.keys():
  164. retval += inv[env_host_type_tag]
  165. return set(retval)
  166. if envs and not host_type:
  167. # Just environment was specified
  168. retval = []
  169. for env in envs:
  170. env_tag = AwsUtil.gen_env_tag(env)
  171. if env_tag in inv.keys():
  172. retval += inv[env_tag]
  173. return set(retval)
  174. if host_type and not envs:
  175. # Just host-type was specified
  176. retval = []
  177. host_type_tag = self.gen_host_type_tag(host_type)
  178. if host_type_tag in inv.keys():
  179. retval = inv[host_type_tag]
  180. return set(retval)
  181. # We should never reach here!
  182. raise ArgumentError("Invalid combination of parameters")