openshift_ansible.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. # TODO: Temporarily disabled due to importing old code into openshift-ansible
  2. # repo. We will work on these over time.
  3. # pylint: disable=bad-continuation,missing-docstring,no-self-use,invalid-name,global-statement,global-variable-not-assigned
  4. import socket
  5. import subprocess
  6. import sys
  7. import os
  8. import yaml
  9. from ooinstall.variants import find_variant
  10. CFG = None
  11. def set_config(cfg):
  12. global CFG
  13. CFG = cfg
  14. def generate_inventory(hosts):
  15. global CFG
  16. masters = [host for host in hosts if host.master]
  17. nodes = [host for host in hosts if host.node]
  18. new_nodes = [host for host in hosts if host.node and host.new_host]
  19. proxy = determine_proxy_configuration(hosts)
  20. storage = determine_storage_configuration(hosts)
  21. multiple_masters = len(masters) > 1
  22. scaleup = len(new_nodes) > 0
  23. base_inventory_path = CFG.settings['ansible_inventory_path']
  24. base_inventory = open(base_inventory_path, 'w')
  25. write_inventory_children(base_inventory, multiple_masters, proxy, storage, scaleup)
  26. write_inventory_vars(base_inventory, multiple_masters, proxy)
  27. # Find the correct deployment type for ansible:
  28. ver = find_variant(CFG.settings['variant'],
  29. version=CFG.settings.get('variant_version', None))[1]
  30. base_inventory.write('deployment_type={}\n'.format(ver.ansible_key))
  31. if 'OO_INSTALL_ADDITIONAL_REGISTRIES' in os.environ:
  32. base_inventory.write('openshift_docker_additional_registries={}\n'
  33. .format(os.environ['OO_INSTALL_ADDITIONAL_REGISTRIES']))
  34. if 'OO_INSTALL_INSECURE_REGISTRIES' in os.environ:
  35. base_inventory.write('openshift_docker_insecure_registries={}\n'
  36. .format(os.environ['OO_INSTALL_INSECURE_REGISTRIES']))
  37. if 'OO_INSTALL_PUDDLE_REPO' in os.environ:
  38. # We have to double the '{' here for literals
  39. base_inventory.write("openshift_additional_repos=[{{'id': 'ose-devel', "
  40. "'name': 'ose-devel', "
  41. "'baseurl': '{}', "
  42. "'enabled': 1, 'gpgcheck': 0}}]\n".format(os.environ['OO_INSTALL_PUDDLE_REPO']))
  43. base_inventory.write('\n[masters]\n')
  44. for master in masters:
  45. write_host(master, base_inventory)
  46. if len(masters) > 1:
  47. base_inventory.write('\n[etcd]\n')
  48. for master in masters:
  49. write_host(master, base_inventory)
  50. base_inventory.write('\n[nodes]\n')
  51. for node in nodes:
  52. # Let the fact defaults decide if we're not a master:
  53. schedulable = None
  54. # If the node is also a master, we must explicitly set schedulablity:
  55. if node.master:
  56. schedulable = node.is_schedulable_node(hosts)
  57. write_host(node, base_inventory, schedulable)
  58. if not getattr(proxy, 'preconfigured', True):
  59. base_inventory.write('\n[lb]\n')
  60. write_host(proxy, base_inventory)
  61. if scaleup:
  62. base_inventory.write('\n[new_nodes]\n')
  63. for node in new_nodes:
  64. write_host(node, base_inventory)
  65. if storage:
  66. base_inventory.write('\n[nfs]\n')
  67. write_host(storage, base_inventory)
  68. base_inventory.close()
  69. return base_inventory_path
  70. def determine_proxy_configuration(hosts):
  71. proxy = next((host for host in hosts if host.master_lb), None)
  72. if proxy:
  73. if proxy.hostname == None:
  74. proxy.hostname = proxy.connect_to
  75. proxy.public_hostname = proxy.connect_to
  76. return proxy
  77. def determine_storage_configuration(hosts):
  78. storage = next((host for host in hosts if host.storage), None)
  79. return storage
  80. def write_inventory_children(base_inventory, multiple_masters, proxy, storage, scaleup):
  81. global CFG
  82. base_inventory.write('\n[OSEv3:children]\n')
  83. base_inventory.write('masters\n')
  84. base_inventory.write('nodes\n')
  85. if scaleup:
  86. base_inventory.write('new_nodes\n')
  87. if multiple_masters:
  88. base_inventory.write('etcd\n')
  89. if not getattr(proxy, 'preconfigured', True):
  90. base_inventory.write('lb\n')
  91. if storage:
  92. base_inventory.write('nfs\n')
  93. def write_inventory_vars(base_inventory, multiple_masters, proxy):
  94. global CFG
  95. base_inventory.write('\n[OSEv3:vars]\n')
  96. base_inventory.write('ansible_ssh_user={}\n'.format(CFG.settings['ansible_ssh_user']))
  97. if CFG.settings['ansible_ssh_user'] != 'root':
  98. base_inventory.write('ansible_become=yes\n')
  99. if multiple_masters and proxy is not None:
  100. base_inventory.write('openshift_master_cluster_method=native\n')
  101. base_inventory.write("openshift_master_cluster_hostname={}\n".format(proxy.hostname))
  102. base_inventory.write(
  103. "openshift_master_cluster_public_hostname={}\n".format(proxy.public_hostname))
  104. if CFG.settings.get('master_routingconfig_subdomain', False):
  105. base_inventory.write(
  106. "openshift_master_default_subdomain={}\n".format(
  107. CFG.settings['master_routingconfig_subdomain']))
  108. if CFG.settings.get('variant_version', None) == '3.1':
  109. #base_inventory.write('openshift_image_tag=v{}\n'.format(CFG.settings.get('variant_version')))
  110. base_inventory.write('openshift_image_tag=v{}\n'.format('3.1.1.6'))
  111. if CFG.settings.get('openshift_http_proxy', ''):
  112. base_inventory.write("openshift_http_proxy={}\n".format(
  113. CFG.settings['openshift_http_proxy']))
  114. if CFG.settings.get('openshift_https_proxy', ''):
  115. base_inventory.write("openshift_https_proxy={}\n".format(
  116. CFG.settings['openshift_https_proxy']))
  117. if CFG.settings.get('openshift_no_proxy', ''):
  118. base_inventory.write("openshift_no_proxy={}\n".format(
  119. CFG.settings['openshift_no_proxy']))
  120. def write_host(host, inventory, schedulable=None):
  121. global CFG
  122. facts = ''
  123. if host.ip:
  124. facts += ' openshift_ip={}'.format(host.ip)
  125. if host.public_ip:
  126. facts += ' openshift_public_ip={}'.format(host.public_ip)
  127. if host.hostname:
  128. facts += ' openshift_hostname={}'.format(host.hostname)
  129. if host.public_hostname:
  130. facts += ' openshift_public_hostname={}'.format(host.public_hostname)
  131. if host.containerized:
  132. facts += ' containerized={}'.format(host.containerized)
  133. # TODO: For not write_host is handles both master and nodes.
  134. # Technically only nodes will ever need this.
  135. # Distinguish between three states, no schedulability specified (use default),
  136. # explicitly set to True, or explicitly set to False:
  137. if schedulable is None:
  138. pass
  139. elif schedulable:
  140. facts += ' openshift_schedulable=True'
  141. elif not schedulable:
  142. facts += ' openshift_schedulable=False'
  143. installer_host = socket.gethostname()
  144. if installer_host in [host.connect_to, host.hostname, host.public_hostname]:
  145. facts += ' ansible_connection=local'
  146. if os.geteuid() != 0:
  147. no_pwd_sudo = subprocess.call(['sudo', '-n', 'echo', 'openshift'])
  148. if no_pwd_sudo == 1:
  149. print 'The atomic-openshift-installer requires sudo access without a password.'
  150. sys.exit(1)
  151. facts += ' ansible_become=yes'
  152. inventory.write('{} {}\n'.format(host.connect_to, facts))
  153. def load_system_facts(inventory_file, os_facts_path, env_vars, verbose=False):
  154. """
  155. Retrieves system facts from the remote systems.
  156. """
  157. FNULL = open(os.devnull, 'w')
  158. args = ['ansible-playbook', '-v'] if verbose \
  159. else ['ansible-playbook']
  160. args.extend([
  161. '--inventory-file={}'.format(inventory_file),
  162. os_facts_path])
  163. status = subprocess.call(args, env=env_vars, stdout=FNULL)
  164. if not status == 0:
  165. return [], 1
  166. with open(CFG.settings['ansible_callback_facts_yaml'], 'r') as callback_facts_file:
  167. try:
  168. callback_facts = yaml.safe_load(callback_facts_file)
  169. except yaml.YAMLError, exc:
  170. print "Error in {}".format(CFG.settings['ansible_callback_facts_yaml']), exc
  171. print "Try deleting and rerunning the atomic-openshift-installer"
  172. sys.exit(1)
  173. return callback_facts, 0
  174. def default_facts(hosts, verbose=False):
  175. global CFG
  176. inventory_file = generate_inventory(hosts)
  177. os_facts_path = '{}/playbooks/byo/openshift_facts.yml'.format(CFG.ansible_playbook_directory)
  178. facts_env = os.environ.copy()
  179. facts_env["OO_INSTALL_CALLBACK_FACTS_YAML"] = CFG.settings['ansible_callback_facts_yaml']
  180. facts_env["ANSIBLE_CALLBACK_PLUGINS"] = CFG.settings['ansible_plugins_directory']
  181. facts_env["OPENSHIFT_MASTER_CLUSTER_METHOD"] = 'native'
  182. if 'ansible_log_path' in CFG.settings:
  183. facts_env["ANSIBLE_LOG_PATH"] = CFG.settings['ansible_log_path']
  184. if 'ansible_config' in CFG.settings:
  185. facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_config']
  186. return load_system_facts(inventory_file, os_facts_path, facts_env, verbose)
  187. def run_main_playbook(inventory_file, hosts, hosts_to_run_on, verbose=False):
  188. global CFG
  189. if len(hosts_to_run_on) != len(hosts):
  190. main_playbook_path = os.path.join(CFG.ansible_playbook_directory,
  191. 'playbooks/byo/openshift-node/scaleup.yml')
  192. else:
  193. main_playbook_path = os.path.join(CFG.ansible_playbook_directory,
  194. 'playbooks/byo/openshift-cluster/config.yml')
  195. facts_env = os.environ.copy()
  196. if 'ansible_log_path' in CFG.settings:
  197. facts_env['ANSIBLE_LOG_PATH'] = CFG.settings['ansible_log_path']
  198. if 'ansible_config' in CFG.settings:
  199. facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_config']
  200. return run_ansible(main_playbook_path, inventory_file, facts_env, verbose)
  201. def run_ansible(playbook, inventory, env_vars, verbose=False):
  202. args = ['ansible-playbook', '-v'] if verbose \
  203. else ['ansible-playbook']
  204. args.extend([
  205. '--inventory-file={}'.format(inventory),
  206. playbook])
  207. return subprocess.call(args, env=env_vars)
  208. def run_uninstall_playbook(verbose=False):
  209. playbook = os.path.join(CFG.settings['ansible_playbook_directory'],
  210. 'playbooks/adhoc/uninstall.yml')
  211. inventory_file = generate_inventory(CFG.hosts)
  212. facts_env = os.environ.copy()
  213. if 'ansible_log_path' in CFG.settings:
  214. facts_env['ANSIBLE_LOG_PATH'] = CFG.settings['ansible_log_path']
  215. if 'ansible_config' in CFG.settings:
  216. facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_config']
  217. return run_ansible(playbook, inventory_file, facts_env, verbose)
  218. def run_upgrade_playbook(playbook, verbose=False):
  219. playbook = os.path.join(CFG.settings['ansible_playbook_directory'],
  220. 'playbooks/byo/openshift-cluster/upgrades/{}'.format(playbook))
  221. # TODO: Upgrade inventory for upgrade?
  222. inventory_file = generate_inventory(CFG.hosts)
  223. facts_env = os.environ.copy()
  224. if 'ansible_log_path' in CFG.settings:
  225. facts_env['ANSIBLE_LOG_PATH'] = CFG.settings['ansible_log_path']
  226. if 'ansible_config' in CFG.settings:
  227. facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_config']
  228. return run_ansible(playbook, inventory_file, facts_env, verbose)