diff options
Diffstat (limited to 'utils/src')
-rw-r--r-- | utils/src/ooinstall/cli_installer.py | 160 |
1 files changed, 90 insertions, 70 deletions
diff --git a/utils/src/ooinstall/cli_installer.py b/utils/src/ooinstall/cli_installer.py index 230891e7f..67f3659ff 100644 --- a/utils/src/ooinstall/cli_installer.py +++ b/utils/src/ooinstall/cli_installer.py @@ -28,25 +28,26 @@ DEFAULT_ANSIBLE_CONFIG = '/usr/share/atomic-openshift-utils/ansible.cfg' DEFAULT_PLAYBOOK_DIR = '/usr/share/ansible/openshift-ansible/' UPGRADE_MAPPINGS = { - '3.0':{ - 'minor_version' :'3.0', - 'minor_playbook':'v3_0_minor/upgrade.yml', - 'major_version' :'3.1', - 'major_playbook':'v3_0_to_v3_1/upgrade.yml', - }, - '3.1':{ - 'minor_version' :'3.1', - 'minor_playbook':'v3_1_minor/upgrade.yml', - 'major_playbook':'v3_1_to_v3_2/upgrade.yml', - 'major_version' :'3.2', - }, - '3.2':{ - 'minor_version' :'3.2', - 'minor_playbook':'v3_2/upgrade.yml', - 'major_playbook':'v3_2/upgrade.yml', - 'major_version' :'3.3', - } - } + '3.0': { + 'minor_version': '3.0', + 'minor_playbook': 'v3_0_minor/upgrade.yml', + 'major_version': '3.1', + 'major_playbook': 'v3_0_to_v3_1/upgrade.yml', + }, + '3.1': { + 'minor_version': '3.1', + 'minor_playbook': 'v3_1_minor/upgrade.yml', + 'major_playbook': 'v3_1_to_v3_2/upgrade.yml', + 'major_version': '3.2', + }, + '3.2': { + 'minor_version': '3.2', + 'minor_playbook': 'v3_2/upgrade.yml', + 'major_playbook': 'v3_2/upgrade.yml', + 'major_version': '3.3', + } +} + def validate_ansible_dir(path): if not path: @@ -55,6 +56,7 @@ def validate_ansible_dir(path): # if not os.path.exists(path)): # raise click.BadParameter("Path \"{}\" doesn't exist".format(path)) + def is_valid_hostname(hostname): if not hostname or len(hostname) > 255: return False @@ -63,11 +65,13 @@ def is_valid_hostname(hostname): allowed = re.compile(r"(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE) return all(allowed.match(x) for x in hostname.split(".")) + def validate_prompt_hostname(hostname): if hostname == '' or is_valid_hostname(hostname): return hostname raise click.BadParameter('Invalid hostname. Please double-check this value and re-enter it.') + def get_ansible_ssh_user(): click.clear() message = """ @@ -78,6 +82,7 @@ passwordless sudo access. click.echo(message) return click.prompt('User for ssh access', default='root') + def get_master_routingconfig_subdomain(): click.clear() message = """ @@ -86,15 +91,17 @@ You might want to override the default subdomain used for exposed routes. If you click.echo(message) return click.prompt('New default subdomain (ENTER for none)', default='') + def list_hosts(hosts): hosts_idx = range(len(hosts)) for idx in hosts_idx: click.echo(' {}: {}'.format(idx, hosts[idx])) + def delete_hosts(hosts): while True: list_hosts(hosts) - del_idx = click.prompt('Select host to delete, y/Y to confirm, ' \ + del_idx = click.prompt('Select host to delete, y/Y to confirm, ' 'or n/N to add more hosts', default='n') try: del_idx = int(del_idx) @@ -111,6 +118,7 @@ def delete_hosts(hosts): click.echo("\"{}\" doesn't correspond to any valid input.".format(del_idx)) return hosts, None + def collect_hosts(oo_cfg, existing_env=False, masters_set=False, print_summary=True): """ Collect host information from user. This will later be filled in using @@ -186,7 +194,6 @@ http://docs.openshift.com/enterprise/latest/architecture/infrastructure_componen hosts.append(host) - if print_summary: print_installation_summary(hosts, oo_cfg.settings['variant_version']) @@ -329,6 +336,7 @@ hostname. master_lb = Host(**host_props) hosts.append(master_lb) + def collect_storage_host(hosts): """ Get a valid host for storage from the user and append it to the list of @@ -346,8 +354,8 @@ Note: Containerized storage hosts are not currently supported. first_master = next(host for host in hosts if host.is_master()) hostname_or_ip = click.prompt('Enter hostname or IP address', - value_proc=validate_prompt_hostname, - default=first_master.connect_to) + value_proc=validate_prompt_hostname, + default=first_master.connect_to) existing, existing_host = is_host_already_node_or_master(hostname_or_ip, hosts) if existing and existing_host.is_node(): existing_host.roles.append('storage') @@ -358,6 +366,7 @@ Note: Containerized storage hosts are not currently supported. storage = Host(**host_props) hosts.append(storage) + def is_host_already_node_or_master(hostname, hosts): is_existing = False existing_host = None @@ -369,6 +378,7 @@ def is_host_already_node_or_master(hostname, hosts): return is_existing, existing_host + def confirm_hosts_facts(oo_cfg, callback_facts): hosts = oo_cfg.deployment.hosts click.clear() @@ -443,7 +453,6 @@ Edit %s with the desired values and run `atomic-openshift-installer --unattended return default_facts - def check_hosts_config(oo_cfg, unattended): click.clear() masters = [host for host in oo_cfg.deployment.hosts if host.is_master()] @@ -460,7 +469,7 @@ def check_hosts_config(oo_cfg, unattended): sys.exit(1) elif len(master_lb) == 1: if master_lb[0].is_master() or master_lb[0].is_node(): - click.echo('ERROR: The master load balancer is configured as a master or node. ' \ + click.echo('ERROR: The master load balancer is configured as a master or node. ' 'Please correct this.') sys.exit(1) else: @@ -473,8 +482,8 @@ https://docs.openshift.org/latest/install_config/install/advanced_install.html#m click.echo(message) sys.exit(1) - dedicated_nodes = [host for host in oo_cfg.deployment.hosts \ - if host.is_node() and not host.is_master()] + dedicated_nodes = [host for host in oo_cfg.deployment.hosts + if host.is_node() and not host.is_master()] if len(dedicated_nodes) == 0: message = """ WARNING: No dedicated nodes specified. By default, colocated masters have @@ -488,6 +497,7 @@ as schedulable. return + def get_variant_and_version(multi_master=False): message = "\nWhich variant would you like to install?\n\n" @@ -495,7 +505,7 @@ def get_variant_and_version(multi_master=False): combos = get_variant_version_combos() for (variant, version) in combos: message = "%s\n(%s) %s %s" % (message, i, variant.description, - version.name) + version.name) i = i + 1 message = "%s\n" % message @@ -507,12 +517,14 @@ def get_variant_and_version(multi_master=False): return product, version + def confirm_continue(message): if message: click.echo(message) click.confirm("Are you ready to continue?", default=False, abort=True) return + def error_if_missing_info(oo_cfg): missing_info = False if not oo_cfg.deployment.hosts: @@ -552,6 +564,7 @@ def error_if_missing_info(oo_cfg): if missing_info: sys.exit(1) + def get_host_roles_set(oo_cfg): roles_set = set() for host in oo_cfg.deployment.hosts: @@ -560,6 +573,7 @@ def get_host_roles_set(oo_cfg): return roles_set + def get_proxy_hostnames_and_excludes(): message = """ If a proxy is needed to reach HTTP and HTTPS traffic, please enter the name below. @@ -588,6 +602,7 @@ Please provide any additional hosts to be added to NO_PROXY. (ENTER for none) return http_proxy_hostname, https_proxy_hostname, proxy_excludes + def get_missing_info_from_user(oo_cfg): """ Prompts the user for any information missing from the given configuration. """ click.clear() @@ -633,9 +648,8 @@ https://docs.openshift.com/enterprise/latest/admin_guide/install/prerequisites.h oo_cfg.deployment.roles[role] = Role(name=role, variables={}) click.clear() - if not 'master_routingconfig_subdomain' in oo_cfg.deployment.variables: - oo_cfg.deployment.variables['master_routingconfig_subdomain'] = \ - get_master_routingconfig_subdomain() + if 'master_routingconfig_subdomain' not in oo_cfg.deployment.variables: + oo_cfg.deployment.variables['master_routingconfig_subdomain'] = get_master_routingconfig_subdomain() click.clear() if not oo_cfg.settings.get('openshift_http_proxy', None) and \ @@ -657,10 +671,12 @@ def get_role_variable(oo_cfg, role_name, variable_name): except (StopIteration, KeyError): return None + def set_role_variable(oo_cfg, role_name, variable_name, variable_value): target_role = next(role for role in oo_cfg.deployment.roles if role.name is role_name) target_role[variable_name] = variable_value + def collect_new_nodes(oo_cfg): click.clear() click.echo('*** New Node Configuration ***') @@ -671,6 +687,7 @@ Add new nodes here new_nodes, _ = collect_hosts(oo_cfg, existing_env=True, masters_set=True, print_summary=False) return new_nodes + def get_installed_hosts(hosts, callback_facts): installed_hosts = [] uninstalled_hosts = [] @@ -682,13 +699,15 @@ def get_installed_hosts(hosts, callback_facts): uninstalled_hosts.append(host) return installed_hosts, uninstalled_hosts + def is_installed_host(host, callback_facts): version_found = 'common' in callback_facts[host.connect_to].keys() and \ - callback_facts[host.connect_to]['common'].get('version', '') and \ - callback_facts[host.connect_to]['common'].get('version', '') != 'None' + callback_facts[host.connect_to]['common'].get('version', '') and \ + callback_facts[host.connect_to]['common'].get('version', '') != 'None' return version_found + # pylint: disable=too-many-branches # This pylint error will be corrected shortly in separate PR. def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force, verbose): @@ -703,10 +722,10 @@ def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force, verbose): # This check has to happen before we start removing hosts later in this method if not force: if not unattended: - click.echo('By default the installer only adds new nodes ' \ + click.echo('By default the installer only adds new nodes ' 'to an installed environment.') - response = click.prompt('Do you want to (1) only add additional nodes or ' \ - '(2) reinstall the existing hosts ' \ + response = click.prompt('Do you want to (1) only add additional nodes or ' + '(2) reinstall the existing hosts ' 'potentially erasing any custom changes?', type=int) # TODO: this should be reworked with error handling. @@ -735,16 +754,16 @@ def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force, verbose): for uninstalled_host in uninstalled_hosts: click.echo("{} is currently uninstalled".format(uninstalled_host)) # Fall through - click.echo('\nUninstalled hosts have been detected in your environment. ' \ - 'Please make sure your environment was installed successfully ' \ - 'before adding new nodes. If you want a fresh install, use ' \ + click.echo('\nUninstalled hosts have been detected in your environment. ' + 'Please make sure your environment was installed successfully ' + 'before adding new nodes. If you want a fresh install, use ' '`atomic-openshift-installer install --force`') sys.exit(1) else: if unattended: if not force: - click.echo('Installed environment detected and no additional ' \ - 'nodes specified: aborting. If you want a fresh install, use ' \ + click.echo('Installed environment detected and no additional ' + 'nodes specified: aborting. If you want a fresh install, use ' '`atomic-openshift-installer install --force`') sys.exit(1) else: @@ -758,14 +777,15 @@ def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force, verbose): click.echo('Gathering information from hosts...') callback_facts, error = openshift_ansible.default_facts(oo_cfg.deployment.hosts, verbose) if error or callback_facts is None: - click.echo("There was a problem fetching the required information. See " \ + click.echo("There was a problem fetching the required information. See " "{} for details.".format(oo_cfg.settings['ansible_log_path'])) sys.exit(1) else: - pass # proceeding as normal should do a clean install + pass # proceeding as normal should do a clean install return hosts_to_run_on, callback_facts + def set_infra_nodes(hosts): if all(host.is_master() for host in hosts): infra_list = hosts @@ -781,11 +801,11 @@ def set_infra_nodes(hosts): @click.pass_context @click.option('--unattended', '-u', is_flag=True, default=False) @click.option('--configuration', '-c', - type=click.Path(file_okay=True, - dir_okay=False, - writable=True, - readable=True), - default=None) + type=click.Path(file_okay=True, + dir_okay=False, + writable=True, + readable=True), + default=None) @click.option('--ansible-playbook-directory', '-a', type=click.Path(exists=True, @@ -796,25 +816,25 @@ def set_infra_nodes(hosts): default=DEFAULT_PLAYBOOK_DIR, envvar='OO_ANSIBLE_PLAYBOOK_DIRECTORY') @click.option('--ansible-config', - type=click.Path(file_okay=True, - dir_okay=False, - writable=True, - readable=True), - default=None) + type=click.Path(file_okay=True, + dir_okay=False, + writable=True, + readable=True), + default=None) @click.option('--ansible-log-path', - type=click.Path(file_okay=True, - dir_okay=False, - writable=True, - readable=True), - default="/tmp/ansible.log") + type=click.Path(file_okay=True, + dir_okay=False, + writable=True, + readable=True), + default="/tmp/ansible.log") @click.option('-v', '--verbose', - is_flag=True, default=False) + is_flag=True, default=False) @click.option('-d', '--debug', - help="Enable installer debugging (/tmp/installer.log)", - is_flag=True, default=False) + help="Enable installer debugging (/tmp/installer.log)", + is_flag=True, default=False) @click.help_option('--help', '-h') -#pylint: disable=too-many-arguments -#pylint: disable=line-too-long +# pylint: disable=too-many-arguments +# pylint: disable=line-too-long # Main CLI entrypoint, not much we can do about too many arguments. def cli(ctx, unattended, configuration, ansible_playbook_directory, ansible_config, ansible_log_path, verbose, debug): """ @@ -859,7 +879,7 @@ def cli(ctx, unattended, configuration, ansible_playbook_directory, ansible_conf if ctx.obj['ansible_config']: oo_cfg.settings['ansible_config'] = ctx.obj['ansible_config'] elif 'ansible_config' not in oo_cfg.settings and \ - os.path.exists(DEFAULT_ANSIBLE_CONFIG): + os.path.exists(DEFAULT_ANSIBLE_CONFIG): # If we're installed by RPM this file should exist and we can use it as our default: oo_cfg.settings['ansible_config'] = DEFAULT_ANSIBLE_CONFIG @@ -900,7 +920,7 @@ def uninstall(ctx): @click.option('--latest-minor', '-l', is_flag=True, default=False) @click.option('--next-major', '-n', is_flag=True, default=False) @click.pass_context -#pylint: disable=bad-builtin,too-many-statements +# pylint: disable=bad-builtin,too-many-statements def upgrade(ctx, latest_minor, next_major): oo_cfg = ctx.obj['oo_cfg'] @@ -943,7 +963,7 @@ def upgrade(ctx, latest_minor, next_major): if next_major: if 'major_playbook' not in mapping: - click.echo("No major upgrade supported for %s %s with this version "\ + click.echo("No major upgrade supported for %s %s with this version " "of atomic-openshift-utils." % (variant, old_version)) sys.exit(0) playbook = mapping['major_playbook'] @@ -956,7 +976,7 @@ def upgrade(ctx, latest_minor, next_major): if latest_minor: if 'minor_playbook' not in mapping: - click.echo("No minor upgrade supported for %s %s with this version "\ + click.echo("No minor upgrade supported for %s %s with this version " "of atomic-openshift-utils." % (variant, old_version)) sys.exit(0) playbook = mapping['minor_playbook'] @@ -978,7 +998,7 @@ def upgrade(ctx, latest_minor, next_major): ctx.obj['verbose']) if retcode > 0: click.echo("Errors encountered during upgrade, please check %s." % - oo_cfg.settings['ansible_log_path']) + oo_cfg.settings['ansible_log_path']) else: oo_cfg.save_to_disk() click.echo("Upgrade completed! Rebooting all hosts is recommended.") @@ -1003,10 +1023,10 @@ def install(ctx, force, gen_inventory): print_installation_summary(oo_cfg.deployment.hosts, oo_cfg.settings.get('variant_version', None)) click.echo('Gathering information from hosts...') callback_facts, error = openshift_ansible.default_facts(oo_cfg.deployment.hosts, - verbose) + verbose) if error or callback_facts is None: - click.echo("There was a problem fetching the required information. " \ + click.echo("There was a problem fetching the required information. " "Please see {} for details.".format(oo_cfg.settings['ansible_log_path'])) sys.exit(1) |