diff options
| author | Samuel Munilla <smunilla@redhat.com> | 2015-11-18 10:59:04 -0500 | 
|---|---|---|
| committer | Samuel Munilla <smunilla@redhat.com> | 2015-11-23 18:05:26 -0500 | 
| commit | 0ee19018001ed6a0a578aa5b7b75e096d6c014d6 (patch) | |
| tree | 147bcea2f07a8d495621c0177a3e1a4221fbf408 /utils/src | |
| parent | cb3da200563684c15d3a65cb2bf3958b9a34b249 (diff) | |
| download | openshift-0ee19018001ed6a0a578aa5b7b75e096d6c014d6.tar.gz openshift-0ee19018001ed6a0a578aa5b7b75e096d6c014d6.tar.bz2 openshift-0ee19018001ed6a0a578aa5b7b75e096d6c014d6.tar.xz openshift-0ee19018001ed6a0a578aa5b7b75e096d6c014d6.zip  | |
atomic-openshift-installer: HA for quick installer
This adds the ability to quickly set up a multi-master environment.
Diffstat (limited to 'utils/src')
| -rw-r--r-- | utils/src/ooinstall/cli_installer.py | 82 | ||||
| -rw-r--r-- | utils/src/ooinstall/oo_config.py | 9 | ||||
| -rw-r--r-- | utils/src/ooinstall/openshift_ansible.py | 36 | 
3 files changed, 110 insertions, 17 deletions
diff --git a/utils/src/ooinstall/cli_installer.py b/utils/src/ooinstall/cli_installer.py index 0b3af8829..1b4a67259 100644 --- a/utils/src/ooinstall/cli_installer.py +++ b/utils/src/ooinstall/cli_installer.py @@ -72,7 +72,7 @@ def delete_hosts(hosts):                  click.echo("\"{}\" doesn't coorespond to any valid input.".format(del_idx))      return hosts, None -def collect_hosts(master_set=False): +def collect_hosts(masters_set=False):      """          Collect host information from user. This will later be filled in using          ansible. @@ -102,17 +102,20 @@ http://docs.openshift.com/enterprise/latest/architecture/infrastructure_componen      hosts = []      more_hosts = True +    num_masters = 0      while more_hosts:          host_props = {} -        hostname_or_ip = click.prompt('Enter hostname or IP address:', -                                      default='', -                                      value_proc=validate_prompt_hostname) - -        host_props['connect_to'] = hostname_or_ip -        if not master_set: -            is_master = click.confirm('Will this host be an OpenShift Master?') -            host_props['master'] = is_master -            master_set = is_master +        host_props['connect_to'] = click.prompt('Enter hostname or IP address:', +                                                default='', +                                                value_proc=validate_prompt_hostname) + +        if not masters_set: +            if click.confirm('Will this host be an OpenShift Master?'): +                host_props['master'] = True +                num_masters += 1 +                if num_masters >= 3: +                    masters_set = True +                    hosts.append(collect_ha_proxy())          host_props['node'] = True          #TODO: Reenable this option once container installs are out of tech preview @@ -132,6 +135,29 @@ http://docs.openshift.com/enterprise/latest/architecture/infrastructure_componen          more_hosts = click.confirm('Do you want to add additional hosts?')      return hosts +def collect_ha_proxy(): +    """ +    Get an HA proxy from the user +    """ +    message = """ +Setting up High Availability Masters requires a load balancing solution. +Please provide a host that will be configured as a proxy. This can either be +an existing load balancer configured to balance all masters on port 8443 or a +new host that will have HAProxy installed on it. +""" +    click.echo(message) +    host_props = {} +    host_props['connect_to'] = click.prompt('Enter hostname or IP address:', +                                            default='', +                                            value_proc=validate_prompt_hostname) +    host_props['run_on'] = click.confirm('Is this a clean host you want to install HAProxy on?') +    host_props['master'] = False +    host_props['node'] = False +    host_props['ha_proxy'] = True +    ha_proxy = Host(**host_props) + +    return ha_proxy +  def confirm_hosts_facts(oo_cfg, callback_facts):      hosts = oo_cfg.hosts      click.clear() @@ -199,6 +225,40 @@ Edit %s with the desired values and run `atomic-openshift-installer --unattended          sys.exit(0)      return default_facts + + +def check_hosts_config(oo_cfg): +    click.clear() +    masters = [host for host in oo_cfg.hosts if host.master] +    if len(masters) > 1: +        ha_proxy = [host for host in oo_cfg.hosts if host.ha_proxy] +        click.echo(ha_proxy) +        if len(ha_proxy) > 1: +            click.echo('More than one HAProxy specified. Only one proxy is allowed.') +            sys.exit(0) +        elif len(ha_proxy) == 1: +            if ha_proxy[0].master or ha_proxy[0].node: +                click.echo('HAProxy is configured as a master or node. Please correct this.') +                sys.exit(0) +        else: +            message = """ +No HAProxy given in config. Either specify one or provide a load balancing solution +of your choice to balance the master API (port 8443) on all master hosts. + +https://docs.openshift.org/latest/install_config/install/advanced_install.html#multiple-masters +""" +            confirm_continue(message) + +    nodes = [host.node for host in oo_cfg.hosts] +    if len(masters) == len(nodes): +        message = """ +No dedicated Nodes specified. By default, colocated Masters have their Nodes set to unscheduleable. +Would you like to label the colocated masters as scheduleable? +""" +        confirm_continue(message) + +    return +  def get_variant_and_version():      message = "\nWhich variant would you like to install?\n\n" @@ -555,6 +615,8 @@ def install(ctx, force):      else:          oo_cfg = get_missing_info_from_user(oo_cfg) +    check_hosts_config(oo_cfg) +      click.echo('Gathering information from hosts...')      callback_facts, error = openshift_ansible.default_facts(oo_cfg.hosts,          verbose) diff --git a/utils/src/ooinstall/oo_config.py b/utils/src/ooinstall/oo_config.py index 9c97e6e93..6b4f36204 100644 --- a/utils/src/ooinstall/oo_config.py +++ b/utils/src/ooinstall/oo_config.py @@ -36,19 +36,24 @@ class Host(object):          self.public_ip = kwargs.get('public_ip', None)          self.public_hostname = kwargs.get('public_hostname', None)          self.connect_to = kwargs.get('connect_to', None) +        self.run_on = kwargs.get('run_on', None)          # Should this host run as an OpenShift master:          self.master = kwargs.get('master', False)          # Should this host run as an OpenShift node:          self.node = kwargs.get('node', False) + +        # Should this host run as an HAProxy: +        self.ha_proxy = kwargs.get('ha_proxy', False) +          self.containerized = kwargs.get('containerized', False)          if self.connect_to is None:              raise OOConfigInvalidHostError("You must specify either and 'ip' " \                                             "or 'hostname' to connect to.") -        if self.master is False and self.node is False: +        if self.master is False and self.node is False and self.ha_proxy is False:              raise OOConfigInvalidHostError(                  "You must specify each host as either a master or a node.") @@ -62,7 +67,7 @@ class Host(object):          """ Used when exporting to yaml. """          d = {}          for prop in ['ip', 'hostname', 'public_ip', 'public_hostname', -                     'master', 'node', 'containerized', 'connect_to']: +                     'master', 'node', 'ha_proxy', 'containerized', 'connect_to', 'run_on']:              # If the property is defined (not None or False), export it:              if getattr(self, prop):                  d[prop] = getattr(self, prop) diff --git a/utils/src/ooinstall/openshift_ansible.py b/utils/src/ooinstall/openshift_ansible.py index 372f27bda..ec97c4144 100644 --- a/utils/src/ooinstall/openshift_ansible.py +++ b/utils/src/ooinstall/openshift_ansible.py @@ -17,14 +17,31 @@ def set_config(cfg):  def generate_inventory(hosts):      global CFG +    masters = [host for host in hosts if host.master] +    nodes = [host for host in hosts if host.node] +    proxy = next((host for host in hosts if host.ha_proxy), None) +    multiple_masters = len(masters) > 1      base_inventory_path = CFG.settings['ansible_inventory_path']      base_inventory = open(base_inventory_path, 'w') -    base_inventory.write('\n[OSEv3:children]\nmasters\nnodes\n') + +    base_inventory.write('\n[OSEv3:children]\n') +    base_inventory.write('masters\n') +    base_inventory.write('nodes\n') +    if multiple_masters: +        base_inventory.write('etcd\n') +    if getattr(proxy, 'run_on', False): +        base_inventory.write('lb\n') +      base_inventory.write('\n[OSEv3:vars]\n')      base_inventory.write('ansible_ssh_user={}\n'.format(CFG.settings['ansible_ssh_user']))      if CFG.settings['ansible_ssh_user'] != 'root':          base_inventory.write('ansible_become=true\n') +    if multiple_masters: +        base_inventory.write('openshift_master_cluster_method=native\n') +        base_inventory.write("openshift_master_cluster_hostname={}\n".format(proxy.hostname)) +        base_inventory.write("openshift_master_cluster_public_hostname={}\n".format(proxy.public_hostname)) +      # Find the correct deployment type for ansible:      ver = find_variant(CFG.settings['variant'], @@ -45,19 +62,28 @@ def generate_inventory(hosts):              "'enabled': 1, 'gpgcheck': 0}}]\n".format(os.environ['OO_INSTALL_PUDDLE_REPO']))      base_inventory.write('\n[masters]\n') -    masters = (host for host in hosts if host.master)      for master in masters:          write_host(master, base_inventory) + +    if len(masters) > 1: +        base_inventory.write('\n[etcd]\n') +        for master in masters: +            write_host(master, base_inventory) +      base_inventory.write('\n[nodes]\n') -    nodes = (host for host in hosts if host.node)      for node in nodes:          # TODO: Until the Master can run the SDN itself we have to configure the Masters          # as Nodes too.          scheduleable = True          # If there's only one Node and it's also a Master we want it to be scheduleable: -        if node in masters and len(masters) != 1: +        if node in masters and len(masters) != len(nodes):              scheduleable = False          write_host(node, base_inventory, scheduleable) + +    if getattr(proxy, 'run_on', False): +        base_inventory.write('\n[lb]\n') +        write_host(proxy, base_inventory) +      base_inventory.close()      return base_inventory_path @@ -118,6 +144,7 @@ def default_facts(hosts, verbose=False):      facts_env = os.environ.copy()      facts_env["OO_INSTALL_CALLBACK_FACTS_YAML"] = CFG.settings['ansible_callback_facts_yaml']      facts_env["ANSIBLE_CALLBACK_PLUGINS"] = CFG.settings['ansible_plugins_directory'] +    facts_env["OPENSHIFT_MASTER_CLUSTER_METHOD"] = 'native'      if 'ansible_log_path' in CFG.settings:          facts_env["ANSIBLE_LOG_PATH"] = CFG.settings['ansible_log_path']      if 'ansible_config' in CFG.settings: @@ -176,4 +203,3 @@ def run_upgrade_playbook(verbose=False):      if 'ansible_config' in CFG.settings:          facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_config']      return run_ansible(playbook, inventory_file, facts_env, verbose) -  | 
