summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/Makefile12
-rw-r--r--utils/docs/man/man1/atomic-openshift-installer.118
-rw-r--r--utils/docs/man/man1/atomic-openshift-installer.1.asciidoc.in6
-rw-r--r--utils/setup.py5
-rwxr-xr-xutils/site_assets/oo-install-bootstrap.sh2
-rw-r--r--utils/src/data/data_file1
-rw-r--r--utils/src/ooinstall/cli_installer.py516
-rw-r--r--utils/src/ooinstall/oo_config.py12
-rw-r--r--utils/src/ooinstall/openshift_ansible.py17
-rw-r--r--utils/src/ooinstall/utils.py11
-rw-r--r--utils/src/ooinstall/variants.py7
-rw-r--r--utils/test-requirements.txt1
-rw-r--r--utils/test/cli_installer_tests.py59
-rw-r--r--utils/test/fixture.py17
-rw-r--r--utils/test/test_utils.py100
-rw-r--r--utils/workflows/enterprise_deploy/openshift.sh2
16 files changed, 512 insertions, 274 deletions
diff --git a/utils/Makefile b/utils/Makefile
index 59aff92fd..62f08f74b 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -31,6 +31,8 @@ ASCII2MAN = a2x -D $(dir $@) -d manpage -f manpage $<
MANPAGES := docs/man/man1/atomic-openshift-installer.1
VERSION := 1.3
+PEPEXCLUDES := E501,E121,E124
+
sdist: clean
python setup.py sdist
rm -fR $(SHORTNAME).egg-info
@@ -80,7 +82,7 @@ ci-pylint:
@echo "#############################################"
@echo "# Running PyLint Tests in virtualenv"
@echo "#############################################"
- . $(NAME)env/bin/activate && python -m pylint --rcfile ../git/.pylintrc src/ooinstall/cli_installer.py src/ooinstall/oo_config.py src/ooinstall/openshift_ansible.py src/ooinstall/variants.py ../callback_plugins/openshift_quick_installer.py
+ . $(NAME)env/bin/activate && python -m pylint --rcfile ../git/.pylintrc src/ooinstall/cli_installer.py src/ooinstall/oo_config.py src/ooinstall/openshift_ansible.py src/ooinstall/variants.py ../callback_plugins/openshift_quick_installer.py ../roles/openshift_certificate_expiry/library/openshift_cert_expiry.py
ci-list-deps:
@echo "#############################################"
@@ -94,13 +96,17 @@ ci-pyflakes:
@echo "#################################################"
. $(NAME)env/bin/activate && pyflakes src/ooinstall/*.py
. $(NAME)env/bin/activate && pyflakes ../callback_plugins/openshift_quick_installer.py
+ . $(NAME)env/bin/activate && pyflakes ../roles/openshift_certificate_expiry/library/openshift_cert_expiry.py
ci-pep8:
@echo "#############################################"
@echo "# Running PEP8 Compliance Tests in virtualenv"
@echo "#############################################"
- . $(NAME)env/bin/activate && pep8 --ignore=E501,E121,E124 src/$(SHORTNAME)/
- . $(NAME)env/bin/activate && pep8 --ignore=E501,E121,E124 ../callback_plugins/openshift_quick_installer.py
+ . $(NAME)env/bin/activate && pep8 --ignore=$(PEPEXCLUDES) src/$(SHORTNAME)/
+ . $(NAME)env/bin/activate && pep8 --ignore=$(PEPEXCLUDES) ../callback_plugins/openshift_quick_installer.py
+# This one excludes E402 because it is an ansible module and the
+# boilerplate import statement is expected to be at the bottom
+ . $(NAME)env/bin/activate && pep8 --ignore=$(PEPEXCLUDES),E402 ../roles/openshift_certificate_expiry/library/openshift_cert_expiry.py
ci: clean virtualenv ci-list-deps ci-pep8 ci-pylint ci-pyflakes ci-unittests
:
diff --git a/utils/docs/man/man1/atomic-openshift-installer.1 b/utils/docs/man/man1/atomic-openshift-installer.1
index 4da82191b..072833ce8 100644
--- a/utils/docs/man/man1/atomic-openshift-installer.1
+++ b/utils/docs/man/man1/atomic-openshift-installer.1
@@ -2,12 +2,12 @@
.\" Title: atomic-openshift-installer
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 09/28/2016
+.\" Date: 10/20/2016
.\" Manual: atomic-openshift-installer
.\" Source: atomic-openshift-utils 1.3
.\" Language: English
.\"
-.TH "ATOMIC\-OPENSHIFT\-I" "1" "09/28/2016" "atomic\-openshift\-utils 1\&.3" "atomic\-openshift\-installer"
+.TH "ATOMIC\-OPENSHIFT\-I" "1" "10/20/2016" "atomic\-openshift\-utils 1\&.3" "atomic\-openshift\-installer"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -121,6 +121,17 @@ Show the usage help and exit\&.
\fBupgrade\fR
.RE
.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+\fBscaleup\fR
+.RE
+.sp
The options specific to each command are described in the following sections\&.
.SH "INSTALL"
.sp
@@ -158,6 +169,9 @@ Upgrade to the latest major version\&. For example, if you are running version
then this could upgrade you to
\fB3\&.3\fR\&.
.RE
+.SH "SCALEUP"
+.sp
+The \fBscaleup\fR command is used to add new nodes to an existing cluster\&. This command has no additional options\&.
.SH "FILES"
.sp
\fB~/\&.config/openshift/installer\&.cfg\&.yml\fR \(em Installer configuration file\&. Can be used to generate an inventory later or start an unattended installation\&.
diff --git a/utils/docs/man/man1/atomic-openshift-installer.1.asciidoc.in b/utils/docs/man/man1/atomic-openshift-installer.1.asciidoc.in
index 64e5d14a3..9b02c4d14 100644
--- a/utils/docs/man/man1/atomic-openshift-installer.1.asciidoc.in
+++ b/utils/docs/man/man1/atomic-openshift-installer.1.asciidoc.in
@@ -73,6 +73,7 @@ COMMANDS
* **install**
* **uninstall**
* **upgrade**
+* **scaleup**
The options specific to each command are described in the following
sections.
@@ -122,6 +123,11 @@ Upgrade to the latest major version. For example, if you are running
version **3.2** then this could upgrade you to **3.3**.
+SCALEUP
+-------
+
+The **scaleup** command is used to add new nodes to an existing cluster.
+This command has no additional options.
FILES
-----
diff --git a/utils/setup.py b/utils/setup.py
index 563897bb1..7909321c9 100644
--- a/utils/setup.py
+++ b/utils/setup.py
@@ -65,11 +65,6 @@ setup(
'ooinstall': ['ansible.cfg', 'ansible-quiet.cfg', 'ansible_plugins/*'],
},
- # Although 'package_data' is the preferred approach, in some case you may
- # need to place data files outside of your packages. See:
- # http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files # noqa
- # In this case, 'data_file' will be installed into '<sys.prefix>/my_data'
- #data_files=[('my_data', ['data/data_file'])],
tests_require=['nose'],
test_suite='nose.collector',
diff --git a/utils/site_assets/oo-install-bootstrap.sh b/utils/site_assets/oo-install-bootstrap.sh
index 3847c029a..3c5614d39 100755
--- a/utils/site_assets/oo-install-bootstrap.sh
+++ b/utils/site_assets/oo-install-bootstrap.sh
@@ -67,7 +67,7 @@ pip install --no-index -f file:///$(readlink -f deps) ansible 2>&1 >> $OO_INSTAL
# TODO: these deps should technically be handled as part of installing ooinstall
pip install --no-index -f file:///$(readlink -f deps) click 2>&1 >> $OO_INSTALL_LOG
pip install --no-index ./src/ 2>&1 >> $OO_INSTALL_LOG
-echo "Installation preperation done!" 2>&1 >> $OO_INSTALL_LOG
+echo "Installation preparation done!" 2>&1 >> $OO_INSTALL_LOG
echo "Using `ansible --version`" 2>&1 >> $OO_INSTALL_LOG
diff --git a/utils/src/data/data_file b/utils/src/data/data_file
deleted file mode 100644
index 7c0646bfd..000000000
--- a/utils/src/data/data_file
+++ /dev/null
@@ -1 +0,0 @@
-some data \ No newline at end of file
diff --git a/utils/src/ooinstall/cli_installer.py b/utils/src/ooinstall/cli_installer.py
index 85f18d5d3..7e5ad4144 100644
--- a/utils/src/ooinstall/cli_installer.py
+++ b/utils/src/ooinstall/cli_installer.py
@@ -1,28 +1,24 @@
-# TODO: Temporarily disabled due to importing old code into openshift-ansible
-# repo. We will work on these over time.
-# pylint: disable=bad-continuation,missing-docstring,no-self-use,invalid-name,no-value-for-parameter,too-many-lines
+# pylint: disable=missing-docstring,no-self-use,no-value-for-parameter,too-many-lines
+import logging
import os
-import re
import sys
-import logging
+
import click
from pkg_resources import parse_version
-from ooinstall import openshift_ansible
-from ooinstall.oo_config import OOConfig
-from ooinstall.oo_config import OOConfigInvalidHostError
-from ooinstall.oo_config import Host, Role
+from ooinstall import openshift_ansible, utils
+from ooinstall.oo_config import Host, OOConfig, OOConfigInvalidHostError, Role
from ooinstall.variants import find_variant, get_variant_version_combos
-installer_log = logging.getLogger('installer')
-installer_log.setLevel(logging.CRITICAL)
-installer_file_handler = logging.FileHandler('/tmp/installer.txt')
-installer_file_handler.setFormatter(
+INSTALLER_LOG = logging.getLogger('installer')
+INSTALLER_LOG.setLevel(logging.CRITICAL)
+INSTALLER_FILE_HANDLER = logging.FileHandler('/tmp/installer.txt')
+INSTALLER_FILE_HANDLER.setFormatter(
logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
# Example output:
# 2016-08-23 07:34:58,480 - installer - DEBUG - Going to 'load_system_facts'
-installer_file_handler.setLevel(logging.DEBUG)
-installer_log.addHandler(installer_file_handler)
+INSTALLER_FILE_HANDLER.setLevel(logging.DEBUG)
+INSTALLER_LOG.addHandler(INSTALLER_FILE_HANDLER)
DEFAULT_ANSIBLE_CONFIG = '/usr/share/atomic-openshift-utils/ansible.cfg'
QUIET_ANSIBLE_CONFIG = '/usr/share/atomic-openshift-utils/ansible-quiet.cfg'
@@ -47,6 +43,16 @@ UPGRADE_MAPPINGS = {
'major_playbook': 'v3_3/upgrade.yml',
'major_version': '3.3',
},
+ '3.3': {
+ 'minor_version': '3.3',
+ 'minor_playbook': 'v3_3/upgrade.yml',
+ 'major_playbook': 'v3_4/upgrade.yml',
+ 'major_version': '3.4',
+ },
+ '3.4': {
+ 'minor_version': '3.4',
+ 'minor_playbook': 'v3_4/upgrade.yml',
+ },
}
@@ -58,17 +64,8 @@ def validate_ansible_dir(path):
# raise click.BadParameter("Path \"{}\" doesn't exist".format(path))
-def is_valid_hostname(hostname):
- if not hostname or len(hostname) > 255:
- return False
- if hostname[-1] == ".":
- hostname = hostname[:-1] # strip exactly one dot from the right, if present
- 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):
+ if hostname == '' or utils.is_valid_hostname(hostname):
return hostname
raise click.BadParameter('Invalid hostname. Please double-check this value and re-enter it.')
@@ -84,7 +81,7 @@ passwordless sudo access.
return click.prompt('User for ssh access', default='root')
-def get_master_routingconfig_subdomain():
+def get_routingconfig_subdomain():
click.clear()
message = """
You might want to override the default subdomain used for exposed routes. If you don't know what this is, use the default value.
@@ -121,11 +118,6 @@ a high-availability (HA) deployment. If you choose an HA deployment, then you
are prompted to identify a *separate* system to act as the load balancer for
your cluster once you define all masters and nodes.
-If only one master is specified, an etcd instance is embedded within the
-OpenShift master service to use as the datastore. This can be later replaced
-with a separate etcd instance, if required. If multiple masters are specified,
-then a separate etcd cluster is configured with each master serving as a member.
-
Any masters configured as part of this installation process are also
configured as nodes. This enables the master to proxy to pods
from the API. By default, this node is unschedulable, but this can be changed
@@ -183,9 +175,13 @@ http://docs.openshift.com/enterprise/latest/architecture/infrastructure_componen
if masters_set or num_masters != 2:
more_hosts = click.confirm('Do you want to add additional hosts?')
- if num_masters >= 3:
- collect_master_lb(hosts)
- roles.add('master_lb')
+ if num_masters > 2:
+ master_lb = collect_master_lb(hosts)
+ if master_lb:
+ hosts.append(master_lb)
+ roles.add('master_lb')
+ else:
+ set_cluster_hostname(oo_cfg)
if not existing_env:
collect_storage_host(hosts)
@@ -193,7 +189,8 @@ http://docs.openshift.com/enterprise/latest/architecture/infrastructure_componen
return hosts, roles
-def print_installation_summary(hosts, version=None):
+# pylint: disable=too-many-branches
+def print_installation_summary(hosts, version=None, verbose=True):
"""
Displays a summary of all hosts configured thus far, and what role each
will play.
@@ -214,35 +211,36 @@ def print_installation_summary(hosts, version=None):
click.echo('Total OpenShift masters: %s' % len(masters))
click.echo('Total OpenShift nodes: %s' % len(nodes))
- if len(masters) == 1 and version != '3.0':
- ha_hint_message = """
+ if verbose:
+ if len(masters) == 1 and version != '3.0':
+ ha_hint_message = """
NOTE: Add a total of 3 or more masters to perform an HA installation."""
- click.echo(ha_hint_message)
- elif len(masters) == 2:
- min_masters_message = """
+ click.echo(ha_hint_message)
+ elif len(masters) == 2:
+ min_masters_message = """
WARNING: A minimum of 3 masters are required to perform an HA installation.
Please add one more to proceed."""
- click.echo(min_masters_message)
- elif len(masters) >= 3:
- ha_message = """
+ click.echo(min_masters_message)
+ elif len(masters) >= 3:
+ ha_message = """
NOTE: Multiple masters specified, this will be an HA deployment with a separate
etcd cluster. You will be prompted to provide the FQDN of a load balancer and
a host for storage once finished entering hosts.
-"""
- click.echo(ha_message)
+ """
+ click.echo(ha_message)
- dedicated_nodes_message = """
+ dedicated_nodes_message = """
WARNING: Dedicated nodes are recommended for an HA deployment. If no dedicated
nodes are specified, each configured master will be marked as a schedulable
node."""
- min_ha_nodes_message = """
+ min_ha_nodes_message = """
WARNING: A minimum of 3 dedicated nodes are recommended for an HA
deployment."""
- if len(dedicated_nodes) == 0:
- click.echo(dedicated_nodes_message)
- elif len(dedicated_nodes) < 3:
- click.echo(min_ha_nodes_message)
+ if len(dedicated_nodes) == 0:
+ click.echo(dedicated_nodes_message)
+ elif len(dedicated_nodes) < 3:
+ click.echo(min_ha_nodes_message)
click.echo('')
@@ -263,13 +261,12 @@ def print_host_summary(all_hosts, host):
click.echo(" - Load Balancer (Preconfigured)")
else:
click.echo(" - Load Balancer (HAProxy)")
- if host.is_master():
- if host.is_etcd_member(all_hosts):
- click.echo(" - Etcd Member")
- else:
- click.echo(" - Etcd (Embedded)")
+ if host.is_etcd():
+ click.echo(" - Etcd")
if host.is_storage():
click.echo(" - Storage")
+ if host.new_host:
+ click.echo(" - NEW")
def collect_master_lb(hosts):
@@ -307,14 +304,35 @@ hostname.
'please specify a separate host' % hostname)
return hostname
- host_props['connect_to'] = click.prompt('Enter hostname or IP address',
- value_proc=validate_prompt_lb)
- install_haproxy = \
- click.confirm('Should the reference HAProxy load balancer be installed on this host?')
- host_props['preconfigured'] = not install_haproxy
- host_props['roles'] = ['master_lb']
- master_lb = Host(**host_props)
- hosts.append(master_lb)
+ lb_hostname = click.prompt('Enter hostname or IP address',
+ value_proc=validate_prompt_lb)
+ if lb_hostname:
+ host_props['connect_to'] = lb_hostname
+ install_haproxy = \
+ click.confirm('Should the reference HAProxy load balancer be installed on this host?')
+ host_props['preconfigured'] = not install_haproxy
+ host_props['roles'] = ['master_lb']
+ return Host(**host_props)
+ else:
+ return None
+
+
+def set_cluster_hostname(oo_cfg):
+ first_master = next((host for host in oo_cfg.deployment.hosts if host.is_master()), None)
+ message = """
+You have chosen to install a single master cluster (non-HA).
+
+In a single master cluster, the cluster host name (Ansible variable openshift_master_cluster_public_hostname) is set by default to the host name of the single master. In a multiple master (HA) cluster, the FQDN of a host must be provided that will be configured as a proxy. This could be either an existing load balancer configured to balance all masters on
+port 8443 or a new host that would have HAProxy installed on it.
+
+(Optional)
+If you want to override the cluster host name now to something other than the default (the host name of the single master), or if you think you might add masters later to become an HA cluster and want to future proof your cluster host name choice, please provide a FQDN. Otherwise, press ENTER to continue and accept the default.
+"""
+ click.echo(message)
+ cluster_hostname = click.prompt('Enter hostname or IP address',
+ default=str(first_master))
+ oo_cfg.deployment.variables['openshift_master_cluster_hostname'] = cluster_hostname
+ oo_cfg.deployment.variables['openshift_master_cluster_public_hostname'] = cluster_hostname
def collect_storage_host(hosts):
@@ -395,29 +413,29 @@ Notes:
default_facts_lines = []
default_facts = {}
- for h in hosts:
- if h.preconfigured:
+ for host in hosts:
+ if host.preconfigured:
continue
try:
- default_facts[h.connect_to] = {}
- h.ip = callback_facts[h.connect_to]["common"]["ip"]
- h.public_ip = callback_facts[h.connect_to]["common"]["public_ip"]
- h.hostname = callback_facts[h.connect_to]["common"]["hostname"]
- h.public_hostname = callback_facts[h.connect_to]["common"]["public_hostname"]
+ default_facts[host.connect_to] = {}
+ host.ip = callback_facts[host.connect_to]["common"]["ip"]
+ host.public_ip = callback_facts[host.connect_to]["common"]["public_ip"]
+ host.hostname = callback_facts[host.connect_to]["common"]["hostname"]
+ host.public_hostname = callback_facts[host.connect_to]["common"]["public_hostname"]
except KeyError:
- click.echo("Problem fetching facts from {}".format(h.connect_to))
+ click.echo("Problem fetching facts from {}".format(host.connect_to))
continue
- default_facts_lines.append(",".join([h.connect_to,
- h.ip,
- h.public_ip,
- h.hostname,
- h.public_hostname]))
- output = "%s\n%s" % (output, ",".join([h.connect_to,
- h.ip,
- h.public_ip,
- h.hostname,
- h.public_hostname]))
+ default_facts_lines.append(",".join([host.connect_to,
+ host.ip,
+ host.public_ip,
+ host.hostname,
+ host.public_hostname]))
+ output = "%s\n%s" % (output, ",".join([host.connect_to,
+ host.ip,
+ host.public_ip,
+ host.hostname,
+ host.public_hostname]))
output = "%s\n%s" % (output, notes)
click.echo(output)
@@ -534,7 +552,7 @@ def error_if_missing_info(oo_cfg):
oo_cfg.settings['variant_version'] = version.name
# check that all listed host roles are included
- listed_roles = get_host_roles_set(oo_cfg)
+ listed_roles = oo_cfg.get_host_roles_set()
configured_roles = set([role for role in oo_cfg.deployment.roles])
if listed_roles != configured_roles:
missing_info = True
@@ -544,16 +562,7 @@ def error_if_missing_info(oo_cfg):
sys.exit(1)
-def get_host_roles_set(oo_cfg):
- roles_set = set()
- for host in oo_cfg.deployment.hosts:
- for role in host.roles:
- roles_set.add(role)
-
- return roles_set
-
-
-def get_proxy_hostnames_and_excludes():
+def get_proxy_hosts_excludes():
message = """
If a proxy is needed to reach HTTP and HTTPS traffic, please enter the
name below. This proxy will be configured by default for all processes
@@ -635,7 +644,8 @@ https://docs.openshift.com/enterprise/latest/admin_guide/install/prerequisites.h
click.clear()
if 'master_routingconfig_subdomain' not in oo_cfg.deployment.variables:
- oo_cfg.deployment.variables['master_routingconfig_subdomain'] = get_master_routingconfig_subdomain()
+ oo_cfg.deployment.variables['master_routingconfig_subdomain'] = \
+ get_routingconfig_subdomain()
click.clear()
# Are any proxy vars already presisted?
@@ -644,7 +654,7 @@ https://docs.openshift.com/enterprise/latest/admin_guide/install/prerequisites.h
saved_proxy_vars = [pv for pv in proxy_vars
if oo_cfg.deployment.variables.get(pv, 'UNSET') is not 'UNSET']
- installer_log.debug("Evaluated proxy settings, found %s presisted values",
+ INSTALLER_LOG.debug("Evaluated proxy settings, found %s presisted values",
len(saved_proxy_vars))
current_version = parse_version(
oo_cfg.settings.get('variant_version', '0.0'))
@@ -654,8 +664,8 @@ https://docs.openshift.com/enterprise/latest/admin_guide/install/prerequisites.h
# recognizes proxy parameters. We must prompt the user for values
# if this conditional is true.
if not saved_proxy_vars and current_version >= min_version:
- installer_log.debug("Prompting user to enter proxy values")
- http_proxy, https_proxy, proxy_excludes = get_proxy_hostnames_and_excludes()
+ INSTALLER_LOG.debug("Prompting user to enter proxy values")
+ http_proxy, https_proxy, proxy_excludes = get_proxy_hosts_excludes()
oo_cfg.deployment.variables['proxy_http'] = http_proxy
oo_cfg.deployment.variables['proxy_https'] = https_proxy
oo_cfg.deployment.variables['proxy_exclude_hosts'] = proxy_excludes
@@ -695,8 +705,10 @@ def get_installed_hosts(hosts, callback_facts):
for host in [h for h in hosts if h.is_master() or h.is_node()]:
if host.connect_to in callback_facts.keys():
if is_installed_host(host, callback_facts):
+ INSTALLER_LOG.debug("%s is already installed", str(host))
installed_hosts.append(host)
else:
+ INSTALLER_LOG.debug("%s is not installed", str(host))
uninstalled_hosts.append(host)
return installed_hosts, uninstalled_hosts
@@ -709,82 +721,85 @@ def is_installed_host(host, callback_facts):
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):
-
- # Copy the list of existing hosts so we can remove any already installed nodes.
- hosts_to_run_on = list(oo_cfg.deployment.hosts)
+def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force):
+ """
+ We get here once there are hosts in oo_cfg and we need to find out what
+ state they are in. There are several different cases that might occur:
+
+ 1. All hosts in oo_cfg are uninstalled. In this case, we should proceed
+ with a normal installation.
+ 2. All hosts in oo_cfg are installed. In this case, ask the user if they
+ want to force reinstall or exit. We can also hint in this case about
+ the scaleup workflow.
+ 3. Some hosts are installed and some are uninstalled. In this case, prompt
+ the user if they want to force (re)install all hosts specified or direct
+ them to the scaleup workflow and exit.
+ """
+ hosts_to_run_on = []
# Check if master or nodes already have something installed
- installed_hosts, uninstalled_hosts = get_installed_hosts(oo_cfg.deployment.hosts, callback_facts)
- if len(installed_hosts) > 0:
- click.echo('Installed environment detected.')
- # This check has to happen before we start removing hosts later in this method
+ installed_hosts, uninstalled_hosts = get_installed_hosts(oo_cfg.deployment.hosts,
+ callback_facts)
+ nodes = [host for host in oo_cfg.deployment.hosts if host.is_node()]
+ masters_and_nodes = [host for host in oo_cfg.deployment.hosts if host.is_master() or host.is_node()]
+
+ in_hosts = [str(h) for h in installed_hosts]
+ un_hosts = [str(h) for h in uninstalled_hosts]
+ all_hosts = [str(h) for h in oo_cfg.deployment.hosts]
+ m_and_n = [str(h) for h in masters_and_nodes]
+
+ INSTALLER_LOG.debug("installed hosts: %s", ", ".join(in_hosts))
+ INSTALLER_LOG.debug("uninstalled hosts: %s", ", ".join(un_hosts))
+ INSTALLER_LOG.debug("deployment hosts: %s", ", ".join(all_hosts))
+ INSTALLER_LOG.debug("masters and nodes: %s", ", ".join(m_and_n))
+
+ # Case (1): All uninstalled hosts
+ if len(uninstalled_hosts) == len(nodes):
+ click.echo('All hosts in config are uninstalled. Proceeding with installation...')
+ hosts_to_run_on = list(oo_cfg.deployment.hosts)
+ else:
+ # Case (2): All installed hosts
+ if len(installed_hosts) == len(masters_and_nodes):
+ message = """
+All specified hosts in specified environment are installed.
+"""
+ # Case (3): Some installed, some uninstalled
+ else:
+ message = """
+A mix of installed and uninstalled hosts have been detected in your environment.
+Please make sure your environment was installed successfully before adding new nodes.
+"""
+
+ # Still inside the case 2/3 else condition
+ mixed_msg = """
+\tInstalled hosts:
+\t\t{inst_hosts}
+
+\tUninstalled hosts:
+\t\t{uninst_hosts}""".format(inst_hosts=", ".join(in_hosts), uninst_hosts=", ".join(un_hosts))
+ click.echo(mixed_msg)
+
+ # Out of the case 2/3 if/else
+ click.echo(message)
+
+ if not unattended:
+ response = click.confirm('Do you want to (re)install the environment?\n\n'
+ 'Note: This will potentially erase any custom changes.')
+ if response:
+ hosts_to_run_on = list(oo_cfg.deployment.hosts)
+ force = True
+ elif unattended and force:
+ hosts_to_run_on = list(oo_cfg.deployment.hosts)
if not force:
- if not unattended:
- 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 '
- 'potentially erasing any custom changes?',
- type=int)
- # TODO: this should be reworked with error handling.
- # Click can certainly do this for us.
- # This should be refactored as soon as we add a 3rd option.
- if response == 1:
- force = False
- if response == 2:
- force = True
-
- # present a message listing already installed hosts and remove hosts if needed
- for host in installed_hosts:
- if host.is_master():
- click.echo("{} is already an OpenShift master".format(host))
- # Masters stay in the list, we need to run against them when adding
- # new nodes.
- elif host.is_node():
- click.echo("{} is already an OpenShift node".format(host))
- # force is only used for reinstalls so we don't want to remove
- # anything.
- if not force:
- hosts_to_run_on.remove(host)
-
- # Handle the cases where we know about uninstalled systems
- # TODO: This logic is getting hard to understand.
- # we should revise all this to be cleaner.
- if not force and len(uninstalled_hosts) > 0:
- 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 '
- '`atomic-openshift-installer install --force`')
+ message = """
+If you want to force reinstall of your environment, run:
+`atomic-openshift-installer install --force`
+
+If you want to add new nodes to this environment, run:
+`atomic-openshift-installer scaleup`
+"""
+ click.echo(message)
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 '
- '`atomic-openshift-installer install --force`')
- sys.exit(1)
- else:
- if not force:
- new_nodes = collect_new_nodes(oo_cfg)
-
- hosts_to_run_on.extend(new_nodes)
- oo_cfg.deployment.hosts.extend(new_nodes)
-
- openshift_ansible.set_config(oo_cfg)
- 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 "
- "{} for details.".format(oo_cfg.settings['ansible_log_path']))
- sys.exit(1)
- else:
- pass # proceeding as normal should do a clean install
return hosts_to_run_on, callback_facts
@@ -800,6 +815,49 @@ def set_infra_nodes(hosts):
host.node_labels = "{'region': 'infra'}"
+def run_config_playbook(oo_cfg, hosts_to_run_on, unattended, verbose, gen_inventory):
+ # Write Ansible inventory file to disk:
+ inventory_file = openshift_ansible.generate_inventory(hosts_to_run_on)
+
+ click.echo()
+ click.echo('Wrote atomic-openshift-installer config: %s' % oo_cfg.config_path)
+ click.echo("Wrote Ansible inventory: %s" % inventory_file)
+ click.echo()
+
+ if gen_inventory:
+ sys.exit(0)
+
+ click.echo('Ready to run installation process.')
+ message = """
+If changes are needed please edit the config file above and re-run.
+"""
+ if not unattended:
+ confirm_continue(message)
+
+ error = openshift_ansible.run_main_playbook(inventory_file, oo_cfg.deployment.hosts,
+ hosts_to_run_on, verbose)
+
+ if error:
+ # The bootstrap script will print out the log location.
+ message = """
+An error was detected. After resolving the problem please relaunch the
+installation process.
+"""
+ click.echo(message)
+ sys.exit(1)
+ else:
+ message = """
+The installation was successful!
+
+If this is your first time installing please take a look at the Administrator
+Guide for advanced options related to routing, storage, authentication, and
+more:
+
+http://docs.openshift.com/enterprise/latest/admin_guide/overview.html
+"""
+ click.echo(message)
+
+
@click.group()
@click.pass_context
@click.option('--unattended', '-u', is_flag=True, default=False)
@@ -846,8 +904,8 @@ def cli(ctx, unattended, configuration, ansible_playbook_directory, ansible_log_
# highest), anything below that (we only use debug/warning
# presently) is not logged. If '-d' is given though, we'll
# lower the threshold to debug (almost everything gets through)
- installer_log.setLevel(logging.DEBUG)
- installer_log.debug("Quick Installer debugging initialized")
+ INSTALLER_LOG.setLevel(logging.DEBUG)
+ INSTALLER_LOG.debug("Quick Installer debugging initialized")
ctx.obj = {}
ctx.obj['unattended'] = unattended
@@ -857,8 +915,8 @@ def cli(ctx, unattended, configuration, ansible_playbook_directory, ansible_log_
try:
oo_cfg = OOConfig(ctx.obj['configuration'])
- except OOConfigInvalidHostError as e:
- click.echo(e)
+ except OOConfigInvalidHostError as err:
+ click.echo(err)
sys.exit(1)
# If no playbook dir on the CLI, check the config:
@@ -916,7 +974,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=too-many-statements
+# pylint: disable=too-many-statements,too-many-branches
def upgrade(ctx, latest_minor, next_major):
oo_cfg = ctx.obj['oo_cfg']
@@ -969,7 +1027,7 @@ def upgrade(ctx, latest_minor, next_major):
sys.exit(0)
playbook = mapping['major_playbook']
new_version = mapping['major_version']
- # Update config to reflect the version we're targetting, we'll write
+ # Update config to reflect the version we're targeting, we'll write
# to disk once Ansible completes successfully, not before.
oo_cfg.settings['variant_version'] = new_version
if oo_cfg.settings['variant'] == 'enterprise':
@@ -1013,15 +1071,17 @@ def upgrade(ctx, latest_minor, next_major):
def install(ctx, force, gen_inventory):
oo_cfg = ctx.obj['oo_cfg']
verbose = ctx.obj['verbose']
+ unattended = ctx.obj['unattended']
- if ctx.obj['unattended']:
+ if unattended:
error_if_missing_info(oo_cfg)
else:
oo_cfg = get_missing_info_from_user(oo_cfg)
- check_hosts_config(oo_cfg, ctx.obj['unattended'])
+ check_hosts_config(oo_cfg, unattended)
- print_installation_summary(oo_cfg.deployment.hosts, oo_cfg.settings.get('variant_version', None))
+ 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)
@@ -1031,62 +1091,92 @@ def install(ctx, force, gen_inventory):
"Please see {} for details.".format(oo_cfg.settings['ansible_log_path']))
sys.exit(1)
- hosts_to_run_on, callback_facts = get_hosts_to_run_on(
- oo_cfg, callback_facts, ctx.obj['unattended'], force, verbose)
+ hosts_to_run_on, callback_facts = get_hosts_to_run_on(oo_cfg,
+ callback_facts,
+ unattended,
+ force)
# We already verified this is not the case for unattended installs, so this can
# only trigger for live CLI users:
- # TODO: if there are *new* nodes and this is a live install, we may need the user
- # to confirm the settings for new nodes. Look into this once we're distinguishing
- # between new and pre-existing nodes.
if not ctx.obj['unattended'] and len(oo_cfg.calc_missing_facts()) > 0:
confirm_hosts_facts(oo_cfg, callback_facts)
# Write quick installer config file to disk:
oo_cfg.save_to_disk()
- # Write Ansible inventory file to disk:
- inventory_file = openshift_ansible.generate_inventory(hosts_to_run_on)
+ run_config_playbook(oo_cfg, hosts_to_run_on, unattended, verbose, gen_inventory)
- click.echo()
- click.echo('Wrote atomic-openshift-installer config: %s' % oo_cfg.config_path)
- click.echo("Wrote Ansible inventory: %s" % inventory_file)
- click.echo()
- if gen_inventory:
- sys.exit(0)
+@click.command()
+@click.option('--gen-inventory', is_flag=True, default=False,
+ help="Generate an Ansible inventory file and exit.")
+@click.pass_context
+def scaleup(ctx, gen_inventory):
+ oo_cfg = ctx.obj['oo_cfg']
+ verbose = ctx.obj['verbose']
+ unattended = ctx.obj['unattended']
- click.echo('Ready to run installation process.')
+ installed_hosts = list(oo_cfg.deployment.hosts)
+
+ if len(installed_hosts) == 0:
+ click.echo('No hosts specified.')
+ sys.exit(1)
+
+ click.echo('Welcome to the OpenShift Enterprise 3 Scaleup utility.')
+
+ print_installation_summary(installed_hosts,
+ oo_cfg.settings['variant_version'],
+ verbose=False,)
message = """
-If changes are needed please edit the config file above and re-run.
-"""
- if not ctx.obj['unattended']:
- confirm_continue(message)
+---
- error = openshift_ansible.run_main_playbook(inventory_file, oo_cfg.deployment.hosts,
- hosts_to_run_on, verbose)
+We have detected this previously installed OpenShift environment.
- if error:
- # The bootstrap script will print out the log location.
- message = """
-An error was detected. After resolving the problem please relaunch the
-installation process.
+This tool will guide you through the process of adding additional
+nodes to your cluster.
"""
- click.echo(message)
+ confirm_continue(message)
+
+ error_if_missing_info(oo_cfg)
+ check_hosts_config(oo_cfg, True)
+
+ installed_masters = [host for host in installed_hosts if host.is_master()]
+ new_nodes = collect_new_nodes(oo_cfg)
+
+ oo_cfg.deployment.hosts.extend(new_nodes)
+ hosts_to_run_on = installed_masters + new_nodes
+
+ openshift_ansible.set_config(oo_cfg)
+ 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 "
+ "{} for details.".format(oo_cfg.settings['ansible_log_path']))
sys.exit(1)
- else:
- message = """
-The installation was successful!
-If this is your first time installing please take a look at the Administrator
-Guide for advanced options related to routing, storage, authentication, and
-more:
+ 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)
+
+ if error or callback_facts is None:
+ click.echo("There was a problem fetching the required information. "
+ "Please see {} for details.".format(oo_cfg.settings['ansible_log_path']))
+ sys.exit(1)
+
+ # We already verified this is not the case for unattended installs, so this can
+ # only trigger for live CLI users:
+ if not ctx.obj['unattended'] and len(oo_cfg.calc_missing_facts()) > 0:
+ confirm_hosts_facts(oo_cfg, callback_facts)
+
+ # Write quick installer config file to disk:
+ oo_cfg.save_to_disk()
+ run_config_playbook(oo_cfg, hosts_to_run_on, unattended, verbose, gen_inventory)
-http://docs.openshift.com/enterprise/latest/admin_guide/overview.html
-"""
- click.echo(message)
cli.add_command(install)
+cli.add_command(scaleup)
cli.add_command(upgrade)
cli.add_command(uninstall)
diff --git a/utils/src/ooinstall/oo_config.py b/utils/src/ooinstall/oo_config.py
index 697ac9c08..64eb340f3 100644
--- a/utils/src/ooinstall/oo_config.py
+++ b/utils/src/ooinstall/oo_config.py
@@ -120,6 +120,10 @@ class Host(object):
def is_storage(self):
return 'storage' in self.roles
+ def is_etcd(self):
+ """ Does this host have the etcd role """
+ return 'etcd' in self.roles
+
def is_etcd_member(self, all_hosts):
""" Will this host be a member of a standalone etcd cluster. """
if not self.is_master():
@@ -436,3 +440,11 @@ class OOConfig(object):
if host.connect_to == name:
return host
return None
+
+ def get_host_roles_set(self):
+ roles_set = set()
+ for host in self.deployment.hosts:
+ for role in host.roles:
+ roles_set.add(role)
+
+ return roles_set
diff --git a/utils/src/ooinstall/openshift_ansible.py b/utils/src/ooinstall/openshift_ansible.py
index 80a79a6d2..f542fb376 100644
--- a/utils/src/ooinstall/openshift_ansible.py
+++ b/utils/src/ooinstall/openshift_ansible.py
@@ -48,9 +48,6 @@ def set_config(cfg):
def generate_inventory(hosts):
global CFG
- masters = [host for host in hosts if host.is_master()]
- multiple_masters = len(masters) > 1
-
new_nodes = [host for host in hosts if host.is_node() and host.new_host]
scaleup = len(new_nodes) > 0
@@ -61,7 +58,7 @@ def generate_inventory(hosts):
write_inventory_children(base_inventory, scaleup)
- write_inventory_vars(base_inventory, multiple_masters, lb)
+ write_inventory_vars(base_inventory, lb)
# write_inventory_hosts
for role in CFG.deployment.roles:
@@ -106,7 +103,7 @@ def write_inventory_children(base_inventory, scaleup):
# pylint: disable=too-many-branches
-def write_inventory_vars(base_inventory, multiple_masters, lb):
+def write_inventory_vars(base_inventory, lb):
global CFG
base_inventory.write('\n[OSEv3:vars]\n')
@@ -123,7 +120,7 @@ def write_inventory_vars(base_inventory, multiple_masters, lb):
if CFG.deployment.variables['ansible_ssh_user'] != 'root':
base_inventory.write('ansible_become=yes\n')
- if multiple_masters and lb is not None:
+ if lb is not None:
base_inventory.write('openshift_master_cluster_method=native\n')
base_inventory.write("openshift_master_cluster_hostname={}\n".format(lb.hostname))
base_inventory.write(
@@ -317,6 +314,10 @@ def run_uninstall_playbook(hosts, verbose=False):
facts_env['ANSIBLE_LOG_PATH'] = CFG.settings['ansible_log_path']
if 'ansible_config' in CFG.settings:
facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_config']
+ # override the ansible config for our main playbook run
+ if 'ansible_quiet_config' in CFG.settings:
+ facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_quiet_config']
+
return run_ansible(playbook, inventory_file, facts_env, verbose)
@@ -331,4 +332,8 @@ def run_upgrade_playbook(hosts, playbook, verbose=False):
facts_env['ANSIBLE_LOG_PATH'] = CFG.settings['ansible_log_path']
if 'ansible_config' in CFG.settings:
facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_config']
+ # override the ansible config for our main playbook run
+ if 'ansible_quiet_config' in CFG.settings:
+ facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_quiet_config']
+
return run_ansible(playbook, inventory_file, facts_env, verbose)
diff --git a/utils/src/ooinstall/utils.py b/utils/src/ooinstall/utils.py
index eb27a57e4..85a77c75e 100644
--- a/utils/src/ooinstall/utils.py
+++ b/utils/src/ooinstall/utils.py
@@ -1,4 +1,6 @@
import logging
+import re
+
installer_log = logging.getLogger('installer')
@@ -8,3 +10,12 @@ def debug_env(env):
if k.startswith("OPENSHIFT") or k.startswith("ANSIBLE") or k.startswith("OO"):
installer_log.debug("{key}: {value}".format(
key=k, value=env[k]))
+
+
+def is_valid_hostname(hostname):
+ if not hostname or len(hostname) > 255:
+ return False
+ if hostname[-1] == ".":
+ hostname = hostname[:-1] # strip exactly one dot from the right, if present
+ allowed = re.compile(r"(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
+ return all(allowed.match(x) for x in hostname.split("."))
diff --git a/utils/src/ooinstall/variants.py b/utils/src/ooinstall/variants.py
index 6993794fe..39772bb2e 100644
--- a/utils/src/ooinstall/variants.py
+++ b/utils/src/ooinstall/variants.py
@@ -40,24 +40,25 @@ class Variant(object):
# WARNING: Keep the versions ordered, most recent first:
OSE = Variant('openshift-enterprise', 'OpenShift Container Platform',
[
- Version('3.3', 'openshift-enterprise'),
+ Version('3.4', 'openshift-enterprise'),
]
)
REG = Variant('openshift-enterprise', 'Registry',
[
- Version('3.3', 'openshift-enterprise', 'registry'),
+ Version('3.4', 'openshift-enterprise', 'registry'),
]
)
origin = Variant('origin', 'OpenShift Origin',
[
- Version('1.2', 'origin'),
+ Version('1.4', 'origin'),
]
)
LEGACY = Variant('openshift-enterprise', 'OpenShift Container Platform',
[
+ Version('3.3', 'openshift-enterprise'),
Version('3.2', 'openshift-enterprise'),
Version('3.1', 'openshift-enterprise'),
Version('3.0', 'openshift-enterprise'),
diff --git a/utils/test-requirements.txt b/utils/test-requirements.txt
index f2216a177..af91ab6a7 100644
--- a/utils/test-requirements.txt
+++ b/utils/test-requirements.txt
@@ -9,3 +9,4 @@ flake8
PyYAML
click
backports.functools_lru_cache
+pyOpenSSL
diff --git a/utils/test/cli_installer_tests.py b/utils/test/cli_installer_tests.py
index 34392777b..36dc18034 100644
--- a/utils/test/cli_installer_tests.py
+++ b/utils/test/cli_installer_tests.py
@@ -842,7 +842,7 @@ class AttendedCliTests(OOCliFixture):
# interactive with config file and some installed some uninstalled hosts
@patch('ooinstall.openshift_ansible.run_main_playbook')
@patch('ooinstall.openshift_ansible.load_system_facts')
- def test_add_nodes(self, load_facts_mock, run_playbook_mock):
+ def test_scaleup_hint(self, load_facts_mock, run_playbook_mock):
# Modify the mock facts to return a version indicating OpenShift
# is already installed on our master, and the first node.
@@ -866,13 +866,12 @@ class AttendedCliTests(OOCliFixture):
result = self.runner.invoke(cli.cli,
self.cli_args,
input=cli_input)
- self.assert_result(result, 0)
- self._verify_load_facts(load_facts_mock)
- self._verify_run_playbook(run_playbook_mock, 3, 2)
+ # This is testing the install workflow so we want to make sure we
+ # exit with the appropriate hint.
+ self.assertTrue('scaleup' in result.output)
+ self.assert_result(result, 1)
- written_config = read_yaml(self.config_file)
- self._verify_config_hosts(written_config, 3)
@patch('ooinstall.openshift_ansible.run_main_playbook')
@patch('ooinstall.openshift_ansible.load_system_facts')
@@ -897,30 +896,30 @@ class AttendedCliTests(OOCliFixture):
written_config = read_yaml(config_file)
self._verify_config_hosts(written_config, 3)
- #interactive with config file and all installed hosts
- @patch('ooinstall.openshift_ansible.run_main_playbook')
- @patch('ooinstall.openshift_ansible.load_system_facts')
- def test_get_hosts_to_run_on(self, load_facts_mock, run_playbook_mock):
- mock_facts = copy.deepcopy(MOCK_FACTS)
- mock_facts['10.0.0.1']['common']['version'] = "3.0.0"
- mock_facts['10.0.0.2']['common']['version'] = "3.0.0"
-
- cli_input = build_input(hosts=[
- ('10.0.0.1', True, False),
- ],
- add_nodes=[('10.0.0.2', False, False)],
- ssh_user='root',
- variant_num=1,
- schedulable_masters_ok=True,
- confirm_facts='y',
- storage='10.0.0.1',)
-
- self._verify_get_hosts_to_run_on(mock_facts, load_facts_mock,
- run_playbook_mock,
- cli_input,
- exp_hosts_len=2,
- exp_hosts_to_run_on_len=2,
- force=False)
+# #interactive with config file and all installed hosts
+# @patch('ooinstall.openshift_ansible.run_main_playbook')
+# @patch('ooinstall.openshift_ansible.load_system_facts')
+# def test_get_hosts_to_run_on(self, load_facts_mock, run_playbook_mock):
+# mock_facts = copy.deepcopy(MOCK_FACTS)
+# mock_facts['10.0.0.1']['common']['version'] = "3.0.0"
+# mock_facts['10.0.0.2']['common']['version'] = "3.0.0"
+#
+# cli_input = build_input(hosts=[
+# ('10.0.0.1', True, False),
+# ],
+# add_nodes=[('10.0.0.2', False, False)],
+# ssh_user='root',
+# variant_num=1,
+# schedulable_masters_ok=True,
+# confirm_facts='y',
+# storage='10.0.0.1',)
+#
+# self._verify_get_hosts_to_run_on(mock_facts, load_facts_mock,
+# run_playbook_mock,
+# cli_input,
+# exp_hosts_len=2,
+# exp_hosts_to_run_on_len=2,
+# force=False)
#interactive multimaster: one more node than master
@patch('ooinstall.openshift_ansible.run_main_playbook')
diff --git a/utils/test/fixture.py b/utils/test/fixture.py
index a883e5c56..62135c761 100644
--- a/utils/test/fixture.py
+++ b/utils/test/fixture.py
@@ -138,8 +138,8 @@ class OOCliFixture(OOInstallFixture):
written_config = read_yaml(config_file)
self._verify_config_hosts(written_config, exp_hosts_len)
- if "Uninstalled" in result.output:
- # verify we exited on seeing uninstalled hosts
+ if "If you want to force reinstall" in result.output:
+ # verify we exited on seeing installed hosts
self.assertEqual(result.exit_code, 1)
else:
self.assert_result(result, 0)
@@ -156,7 +156,7 @@ class OOCliFixture(OOInstallFixture):
#pylint: disable=too-many-arguments,too-many-branches,too-many-statements
def build_input(ssh_user=None, hosts=None, variant_num=None,
add_nodes=None, confirm_facts=None, schedulable_masters_ok=None,
- master_lb=None, storage=None):
+ master_lb=('', False), storage=None):
"""
Build an input string simulating a user entering values in an interactive
attended install.
@@ -204,11 +204,11 @@ def build_input(ssh_user=None, hosts=None, variant_num=None,
i += 1
# You can pass a single master_lb or a list if you intend for one to get rejected:
- if master_lb:
- if isinstance(master_lb[0], list) or isinstance(master_lb[0], tuple):
- inputs.extend(master_lb[0])
- else:
- inputs.append(master_lb[0])
+ if isinstance(master_lb[0], list) or isinstance(master_lb[0], tuple):
+ inputs.extend(master_lb[0])
+ else:
+ inputs.append(master_lb[0])
+ if master_lb[0]:
inputs.append('y' if master_lb[1] else 'n')
if storage:
@@ -248,6 +248,7 @@ def build_input(ssh_user=None, hosts=None, variant_num=None,
inputs.extend([
confirm_facts,
'y', # lets do this
+ 'y',
])
return '\n'.join(inputs)
diff --git a/utils/test/test_utils.py b/utils/test/test_utils.py
new file mode 100644
index 000000000..2e59d86f2
--- /dev/null
+++ b/utils/test/test_utils.py
@@ -0,0 +1,100 @@
+"""
+Unittests for ooinstall utils.
+"""
+
+import unittest
+import logging
+import sys
+import copy
+from ooinstall.utils import debug_env, is_valid_hostname
+import mock
+
+
+class TestUtils(unittest.TestCase):
+ """
+ Parent unittest TestCase.
+ """
+
+ def setUp(self):
+ self.debug_all_params = {
+ 'OPENSHIFT_FOO': 'bar',
+ 'ANSIBLE_FOO': 'bar',
+ 'OO_FOO': 'bar'
+ }
+
+ self.expected = [
+ mock.call('ANSIBLE_FOO: bar'),
+ mock.call('OPENSHIFT_FOO: bar'),
+ mock.call('OO_FOO: bar'),
+ ]
+
+ # python 2.x has assertItemsEqual, python 3.x has assertCountEqual
+ if sys.version_info.major > 3:
+ self.assertItemsEqual = self.assertCountEqual
+
+ ######################################################################
+ # Validate ooinstall.utils.debug_env functionality
+
+ def test_utils_debug_env_all_debugged(self):
+ """Verify debug_env debugs specific env variables"""
+
+ with mock.patch('ooinstall.utils.installer_log') as _il:
+ debug_env(self.debug_all_params)
+ print _il.debug.call_args_list
+
+ # Debug was called for each item we expect
+ self.assertEqual(
+ len(self.debug_all_params),
+ _il.debug.call_count)
+
+ # Each item we expect was logged
+ self.assertItemsEqual(
+ self.expected,
+ _il.debug.call_args_list)
+
+ def test_utils_debug_env_some_debugged(self):
+ """Verify debug_env skips non-wanted env variables"""
+ debug_some_params = copy.deepcopy(self.debug_all_params)
+ # This will not be logged by debug_env
+ debug_some_params['MG_FRBBR'] = "SKIPPED"
+
+ with mock.patch('ooinstall.utils.installer_log') as _il:
+ debug_env(debug_some_params)
+
+ # The actual number of debug calls was less than the
+ # number of items passed to debug_env
+ self.assertLess(
+ _il.debug.call_count,
+ len(debug_some_params))
+
+ self.assertItemsEqual(
+ self.expected,
+ _il.debug.call_args_list)
+
+ ######################################################################
+ def test_utils_is_valid_hostname_invalid(self):
+ """Verify is_valid_hostname can detect None or too-long hostnames"""
+ # A hostname that's empty, None, or more than 255 chars is invalid
+ empty_hostname = ''
+ res = is_valid_hostname(empty_hostname)
+ self.assertFalse(res)
+
+ none_hostname = None
+ res = is_valid_hostname(none_hostname)
+ self.assertFalse(res)
+
+ too_long_hostname = "a" * 256
+ res = is_valid_hostname(too_long_hostname)
+ self.assertFalse(res)
+
+ def test_utils_is_valid_hostname_ends_with_dot(self):
+ """Verify is_valid_hostname can parse hostnames with trailing periods"""
+ hostname = "foo.example.com."
+ res = is_valid_hostname(hostname)
+ self.assertTrue(res)
+
+ def test_utils_is_valid_hostname_normal_hostname(self):
+ """Verify is_valid_hostname can parse regular hostnames"""
+ hostname = "foo.example.com"
+ res = is_valid_hostname(hostname)
+ self.assertTrue(res)
diff --git a/utils/workflows/enterprise_deploy/openshift.sh b/utils/workflows/enterprise_deploy/openshift.sh
deleted file mode 100644
index 040a9a84d..000000000
--- a/utils/workflows/enterprise_deploy/openshift.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-# This file is not used for OpenShift 3.0. It's merely an artifact of the the
-# installation framework originally used for OpenShift 2.x.