summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/src/ooinstall/cli_installer.py233
-rw-r--r--utils/src/ooinstall/oo_config.py199
-rw-r--r--utils/src/ooinstall/openshift_ansible.py125
-rw-r--r--utils/src/ooinstall/variants.py14
-rw-r--r--utils/test/cli_installer_tests.py453
-rw-r--r--utils/test/fixture.py55
-rw-r--r--utils/test/oo_config_tests.py195
7 files changed, 758 insertions, 516 deletions
diff --git a/utils/src/ooinstall/cli_installer.py b/utils/src/ooinstall/cli_installer.py
index eacf340aa..c9c13501d 100644
--- a/utils/src/ooinstall/cli_installer.py
+++ b/utils/src/ooinstall/cli_installer.py
@@ -1,15 +1,16 @@
# 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
+# pylint: disable=bad-continuation,missing-docstring,no-self-use,invalid-name,no-value-for-parameter,too-many-lines
-import click
import os
import re
import sys
+from distutils.version import LooseVersion
+import click
from ooinstall import openshift_ansible
from ooinstall import OOConfig
from ooinstall.oo_config import OOConfigInvalidHostError
-from ooinstall.oo_config import Host
+from ooinstall.oo_config import Host, Role
from ooinstall.variants import find_variant, get_variant_version_combos
DEFAULT_ANSIBLE_CONFIG = '/usr/share/atomic-openshift-utils/ansible.cfg'
@@ -31,7 +32,7 @@ def is_valid_hostname(hostname):
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 is_valid_hostname(hostname):
return hostname
raise click.BadParameter('Invalid hostname. Please double-check this value and re-enter it.')
@@ -120,21 +121,23 @@ http://docs.openshift.com/enterprise/latest/architecture/infrastructure_componen
click.echo(message)
hosts = []
+ roles = set(['master', 'node', 'storage'])
more_hosts = True
num_masters = 0
while more_hosts:
host_props = {}
+ host_props['roles'] = []
host_props['connect_to'] = click.prompt('Enter hostname or IP address',
value_proc=validate_prompt_hostname)
if not masters_set:
if click.confirm('Will this host be an OpenShift Master?'):
- host_props['master'] = True
+ host_props['roles'].append('master')
num_masters += 1
if oo_cfg.settings['variant_version'] == '3.0':
masters_set = True
- host_props['node'] = True
+ host_props['roles'].append('node')
host_props['containerized'] = False
if oo_cfg.settings['variant_version'] != '3.0':
@@ -145,15 +148,13 @@ http://docs.openshift.com/enterprise/latest/architecture/infrastructure_componen
if rpm_or_container == 'container':
host_props['containerized'] = True
- if existing_env:
- host_props['new_host'] = True
- else:
- host_props['new_host'] = False
+ host_props['new_host'] = existing_env
host = Host(**host_props)
hosts.append(host)
+
if print_summary:
print_installation_summary(hosts, oo_cfg.settings['variant_version'])
@@ -165,11 +166,12 @@ http://docs.openshift.com/enterprise/latest/architecture/infrastructure_componen
if num_masters >= 3:
collect_master_lb(hosts)
+ roles.add('master_lb')
if not existing_env:
collect_storage_host(hosts)
- return hosts
+ return hosts, roles
def print_installation_summary(hosts, version=None):
@@ -186,9 +188,9 @@ def print_installation_summary(hosts, version=None):
for host in hosts:
print_host_summary(hosts, host)
- masters = [host for host in hosts if host.master]
- nodes = [host for host in hosts if host.node]
- dedicated_nodes = [host for host in hosts if host.node and not host.master]
+ masters = [host for host in hosts if host.is_master()]
+ nodes = [host for host in hosts if host.is_node()]
+ dedicated_nodes = [host for host in hosts if host.is_node() and not host.is_master()]
click.echo('')
click.echo('Total OpenShift Masters: %s' % len(masters))
click.echo('Total OpenShift Nodes: %s' % len(nodes))
@@ -228,26 +230,26 @@ deployment."""
def print_host_summary(all_hosts, host):
click.echo("- %s" % host.connect_to)
- if host.master:
+ if host.is_master():
click.echo(" - OpenShift Master")
- if host.node:
+ if host.is_node():
if host.is_dedicated_node():
click.echo(" - OpenShift Node (Dedicated)")
elif host.is_schedulable_node(all_hosts):
click.echo(" - OpenShift Node")
else:
click.echo(" - OpenShift Node (Unscheduled)")
- if host.master_lb:
+ if host.is_master_lb():
if host.preconfigured:
click.echo(" - Load Balancer (Preconfigured)")
else:
click.echo(" - Load Balancer (HAProxy)")
- if host.master:
+ if host.is_master():
if host.is_etcd_member(all_hosts):
click.echo(" - Etcd Member")
else:
click.echo(" - Etcd (Embedded)")
- if host.storage:
+ if host.is_storage():
click.echo(" - Storage")
@@ -281,7 +283,7 @@ hostname.
# Make sure this host wasn't already specified:
for host in hosts:
- if host.connect_to == hostname and (host.master or host.node):
+ if host.connect_to == hostname and (host.is_master() or host.is_node()):
raise click.BadParameter('Cannot re-use "%s" as a load balancer, '
'please specify a separate host' % hostname)
return hostname
@@ -291,9 +293,7 @@ hostname.
install_haproxy = \
click.confirm('Should the reference haproxy load balancer be installed on this host?')
host_props['preconfigured'] = not install_haproxy
- host_props['master'] = False
- host_props['node'] = False
- host_props['master_lb'] = True
+ host_props['roles'] = ['master_lb']
master_lb = Host(**host_props)
hosts.append(master_lb)
@@ -311,14 +311,14 @@ Note: Containerized storage hosts are not currently supported.
click.echo(message)
host_props = {}
- first_master = next(host for host in hosts if host.master)
+ 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)
existing, existing_host = is_host_already_node_or_master(hostname_or_ip, hosts)
- if existing and existing_host.node:
- existing_host.storage = True
+ if existing and existing_host.is_node():
+ existing_host.roles.append('storage')
else:
host_props['connect_to'] = hostname_or_ip
host_props['preconfigured'] = False
@@ -333,14 +333,14 @@ def is_host_already_node_or_master(hostname, hosts):
existing_host = None
for host in hosts:
- if host.connect_to == hostname and (host.master or host.node):
+ if host.connect_to == hostname and (host.is_master() or host.is_node()):
is_existing = True
existing_host = host
return is_existing, existing_host
def confirm_hosts_facts(oo_cfg, callback_facts):
- hosts = oo_cfg.hosts
+ hosts = oo_cfg.deployment.hosts
click.clear()
message = """
A list of the facts gathered from the provided hosts follows. Because it is
@@ -376,7 +376,7 @@ Notes:
default_facts_lines = []
default_facts = {}
for h in hosts:
- if h.preconfigured == True:
+ if h.preconfigured:
continue
try:
default_facts[h.connect_to] = {}
@@ -416,19 +416,20 @@ Edit %s with the desired values and run `atomic-openshift-installer --unattended
def check_hosts_config(oo_cfg, unattended):
click.clear()
- masters = [host for host in oo_cfg.hosts if host.master]
+ masters = [host for host in oo_cfg.deployment.hosts if host.is_master()]
if len(masters) == 2:
click.echo("A minimum of 3 Masters are required for HA deployments.")
sys.exit(1)
if len(masters) > 1:
- master_lb = [host for host in oo_cfg.hosts if host.master_lb]
+ master_lb = [host for host in oo_cfg.deployment.hosts if host.is_master_lb()]
+
if len(master_lb) > 1:
click.echo('ERROR: More than one Master load balancer specified. Only one is allowed.')
sys.exit(1)
elif len(master_lb) == 1:
- if master_lb[0].master or master_lb[0].node:
+ 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. ' \
'Please correct this.')
sys.exit(1)
@@ -442,7 +443,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.hosts if host.node and not host.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
@@ -483,7 +485,7 @@ def confirm_continue(message):
def error_if_missing_info(oo_cfg):
missing_info = False
- if not oo_cfg.hosts:
+ if not oo_cfg.deployment.hosts:
missing_info = True
click.echo('For unattended installs, hosts must be specified on the '
'command line or in the config file: %s' % oo_cfg.config_path)
@@ -510,16 +512,24 @@ def error_if_missing_info(oo_cfg):
sys.exit(1)
oo_cfg.settings['variant_version'] = version.name
- missing_facts = oo_cfg.calc_missing_facts()
- if len(missing_facts) > 0:
+ # check that all listed host roles are included
+ listed_roles = get_host_roles_set(oo_cfg)
+ configured_roles = set([role for role in oo_cfg.deployment.roles])
+ if listed_roles != configured_roles:
missing_info = True
- click.echo('For unattended installs, facts must be provided for all masters/nodes:')
- for host in missing_facts:
- click.echo('Host "%s" missing facts: %s' % (host, ", ".join(missing_facts[host])))
+ click.echo('Any roles assigned to hosts must be defined.')
if missing_info:
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():
message = """
If a proxy is needed to reach HTTP and HTTPS traffic please enter the name below.
@@ -576,34 +586,51 @@ https://docs.openshift.com/enterprise/latest/admin_guide/install/prerequisites.h
confirm_continue(message)
click.clear()
- if oo_cfg.settings.get('ansible_ssh_user', '') == '':
+ if not oo_cfg.settings.get('ansible_ssh_user', ''):
oo_cfg.settings['ansible_ssh_user'] = get_ansible_ssh_user()
click.clear()
- if oo_cfg.settings.get('variant', '') == '':
+ if not oo_cfg.settings.get('variant', ''):
variant, version = get_variant_and_version()
oo_cfg.settings['variant'] = variant.name
oo_cfg.settings['variant_version'] = version.name
click.clear()
- if not oo_cfg.hosts:
- oo_cfg.hosts = collect_hosts(oo_cfg)
+ if not oo_cfg.deployment.hosts:
+ oo_cfg.deployment.hosts, roles = collect_hosts(oo_cfg)
+
+ for role in roles:
+ oo_cfg.deployment.roles[role] = Role(name=role, variables={})
click.clear()
- if not oo_cfg.settings.get('master_routingconfig_subdomain', None):
- oo_cfg.settings['master_routingconfig_subdomain'] = get_master_routingconfig_subdomain()
+ if not 'master_routingconfig_subdomain' 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):
+ if not oo_cfg.settings.get('openshift_http_proxy', None) and \
+ LooseVersion(oo_cfg.settings.get('variant_version', '0.0')) >= LooseVersion('3.2'):
http_proxy, https_proxy, proxy_excludes = get_proxy_hostnames_and_excludes()
- oo_cfg.settings['openshift_http_proxy'] = http_proxy
- oo_cfg.settings['openshift_https_proxy'] = https_proxy
- oo_cfg.settings['openshift_no_proxy'] = proxy_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
click.clear()
return oo_cfg
+def get_role_variable(oo_cfg, role_name, variable_name):
+ try:
+ target_role = next(role for role in oo_cfg.deployment.roles if role.name is role_name)
+ target_variable = target_role.variables[variable_name]
+ return target_variable
+ 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 ***')
@@ -611,14 +638,15 @@ def collect_new_nodes(oo_cfg):
Add new nodes here
"""
click.echo(message)
- return collect_hosts(oo_cfg, existing_env=True, masters_set=True, print_summary=False)
+ 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 = []
# count nativeha lb as an installed host
try:
- first_master = next(host for host in hosts if host.master)
+ first_master = next(host for host in hosts if host.is_master())
lb_hostname = callback_facts[first_master.connect_to]['master'].get('cluster_hostname', '')
lb_host = \
next(host for host in hosts if host.ip == callback_facts[lb_hostname]['common']['ip'])
@@ -637,17 +665,17 @@ def is_installed_host(host, callback_facts):
callback_facts[host.connect_to]['common'].get('version', '') and \
callback_facts[host.connect_to]['common'].get('version', '') != 'None'
- return version_found or host.master_lb or host.preconfigured
+ 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.hosts)
+ hosts_to_run_on = list(oo_cfg.deployment.hosts)
# Check if master or nodes already have something installed
- installed_hosts = get_installed_hosts(oo_cfg.hosts, callback_facts)
+ installed_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
@@ -669,11 +697,11 @@ def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force, verbose):
# present a message listing already installed hosts and remove hosts if needed
for host in installed_hosts:
- if host.master:
+ 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.node:
+ 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.
@@ -700,11 +728,11 @@ def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force, verbose):
new_nodes = collect_new_nodes(oo_cfg)
hosts_to_run_on.extend(new_nodes)
- oo_cfg.hosts.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.hosts, verbose)
+ 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']))
@@ -801,14 +829,14 @@ def uninstall(ctx):
oo_cfg = ctx.obj['oo_cfg']
verbose = ctx.obj['verbose']
- if len(oo_cfg.hosts) == 0:
+ if len(oo_cfg.deployment.hosts) == 0:
click.echo("No hosts defined in: %s" % oo_cfg.config_path)
sys.exit(1)
click.echo("OpenShift will be uninstalled from the following hosts:\n")
if not ctx.obj['unattended']:
# Prompt interactively to confirm:
- for host in oo_cfg.hosts:
+ for host in oo_cfg.deployment.hosts:
click.echo(" * %s" % host.connect_to)
proceed = click.confirm("\nDo you wish to proceed?")
if not proceed:
@@ -822,50 +850,68 @@ 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
def upgrade(ctx, latest_minor, next_major):
oo_cfg = ctx.obj['oo_cfg']
verbose = ctx.obj['verbose']
+ # major/minor fields are optional, as we don't always support minor/major
+ # upgrade for what you're currently running.
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_playbook':'v3_2/upgrade.yml',
'major_version' :'3.2',
- }
+ },
+ '3.2':{
+ 'minor_playbook':'v3_2/upgrade.yml',
+# Uncomment these when we're ready to support 3.3.
+# 'major_version' :'3.3',
+# 'major_playbook':'v3_1_to_v3_2/upgrade.yml',
+ },
}
- if len(oo_cfg.hosts) == 0:
+ if len(oo_cfg.deployment.hosts) == 0:
click.echo("No hosts defined in: %s" % oo_cfg.config_path)
sys.exit(1)
- old_variant = oo_cfg.settings['variant']
+ variant = oo_cfg.settings['variant']
+ if find_variant(variant)[0] is None:
+ click.echo("%s is not a supported variant for upgrade." % variant)
+ sys.exit(0)
+
old_version = oo_cfg.settings['variant_version']
mapping = upgrade_mappings.get(old_version)
message = """
This tool will help you upgrade your existing OpenShift installation.
+ Currently running: %s %s
"""
- click.echo(message)
+ click.echo(message % (variant, old_version))
+ # Map the dynamic upgrade options to the playbook to run for each.
+ # Index offset by 1.
+ # List contains tuples of booleans for (latest_minor, next_major)
+ selections = []
if not (latest_minor or next_major):
- click.echo("Version {} found. Do you want to update to the latest version of {} " \
- "or migrate to the next major release?".format(old_version, old_version))
- response = click.prompt("(1) Update to latest {} " \
- "(2) Migrate to next release".format(old_version),
- type=click.Choice(['1', '2']),)
- if response == "1":
- latest_minor = True
- if response == "2":
- next_major = True
+ i = 0
+ if 'minor_playbook' in mapping:
+ click.echo("(%s) Update to latest %s" % (i + 1, old_version))
+ selections.append((True, False))
+ i += 1
+ if 'major_playbook' in mapping:
+ click.echo("(%s) Upgrade to next release: %s" % (i + 1, mapping['major_version']))
+ selections.append((False, True))
+ i += 1
+
+ response = click.prompt("\nChoose an option from above",
+ type=click.Choice(list(map(str, range(1, len(selections) + 1)))))
+ latest_minor, next_major = selections[int(response) - 1]
if next_major:
+ if 'major_playbook' not in mapping:
+ 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']
new_version = mapping['major_version']
# Update config to reflect the version we're targetting, we'll write
@@ -875,12 +921,16 @@ def upgrade(ctx, latest_minor, next_major):
oo_cfg.settings['variant'] = 'openshift-enterprise'
if latest_minor:
+ if 'minor_playbook' not in mapping:
+ 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']
- new_version = mapping['minor_version']
+ new_version = old_version
- click.echo("Openshift will be upgraded from %s %s to %s %s on the following hosts:\n" % (
- old_variant, old_version, oo_cfg.settings['variant'], new_version))
- for host in oo_cfg.hosts:
+ click.echo("Openshift will be upgraded from %s %s to latest %s %s on the following hosts:\n" % (
+ variant, old_version, oo_cfg.settings['variant'], new_version))
+ for host in oo_cfg.deployment.hosts:
click.echo(" * %s" % host.connect_to)
if not ctx.obj['unattended']:
@@ -915,10 +965,11 @@ def install(ctx, force, gen_inventory):
check_hosts_config(oo_cfg, ctx.obj['unattended'])
- print_installation_summary(oo_cfg.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.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']))
@@ -933,11 +984,12 @@ def install(ctx, force, gen_inventory):
# 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 len(oo_cfg.calc_missing_facts()) > 0:
+ 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)
@@ -956,8 +1008,9 @@ 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.hosts,
+ 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 = """
diff --git a/utils/src/ooinstall/oo_config.py b/utils/src/ooinstall/oo_config.py
index 24dfbe013..fc06a0c4a 100644
--- a/utils/src/ooinstall/oo_config.py
+++ b/utils/src/ooinstall/oo_config.py
@@ -1,26 +1,32 @@
-# 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,too-many-instance-attributes,too-few-public-methods
import os
+import sys
import yaml
from pkg_resources import resource_filename
-PERSIST_SETTINGS = [
+CONFIG_PERSIST_SETTINGS = [
'ansible_ssh_user',
+ 'ansible_callback_facts_yaml',
'ansible_config',
+ 'ansible_inventory_path',
'ansible_log_path',
- 'master_routingconfig_subdomain',
- 'proxy',
- 'proxy_exclude_hosts',
+ 'deployment',
+ 'version',
'variant',
'variant_version',
- 'version',
]
+
+DEPLOYMENT_PERSIST_SETTINGS = [
+ 'master_routingconfig_subdomain',
+ 'proxy_http',
+ 'proxy_https',
+ 'proxy_exclude_hosts',
+]
+
DEFAULT_REQUIRED_FACTS = ['ip', 'public_ip', 'hostname', 'public_hostname']
PRECONFIGURED_REQUIRED_FACTS = ['hostname', 'public_hostname']
-
class OOConfigFileError(Exception):
"""The provided config file path can't be read/written
"""
@@ -40,31 +46,19 @@ 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.preconfigured = kwargs.get('preconfigured', None)
+ self.schedulable = kwargs.get('schedulable', None)
self.new_host = kwargs.get('new_host', 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.master_lb = kwargs.get('master_lb', False)
-
- # Should this host run as an HAProxy:
- self.storage = kwargs.get('storage', False)
-
self.containerized = kwargs.get('containerized', False)
+ self.node_labels = kwargs.get('node_labels', '')
- if self.connect_to is None:
- raise OOConfigInvalidHostError("You must specify either an ip " \
- "or hostname as 'connect_to'")
+ # allowable roles: master, node, etcd, storage, master_lb, new
+ self.roles = kwargs.get('roles', [])
- if self.master is False and self.node is False and \
- self.master_lb is False and self.storage is False:
+ if self.connect_to is None:
raise OOConfigInvalidHostError(
- "You must specify each host as either a master or a node.")
+ "You must specify either an ip or hostname as 'connect_to'")
def __str__(self):
return self.connect_to
@@ -75,41 +69,83 @@ class Host(object):
def to_dict(self):
""" Used when exporting to yaml. """
d = {}
- for prop in ['ip', 'hostname', 'public_ip', 'public_hostname',
- 'master', 'node', 'master_lb', 'storage', 'containerized',
- 'connect_to', 'preconfigured', 'new_host']:
+
+ for prop in ['ip', 'hostname', 'public_ip', 'public_hostname', 'connect_to',
+ 'preconfigured', 'containerized', 'schedulable', 'roles', 'node_labels']:
# If the property is defined (not None or False), export it:
if getattr(self, prop):
d[prop] = getattr(self, prop)
return d
+ def is_master(self):
+ return 'master' in self.roles
+
+ def is_node(self):
+ return 'node' in self.roles
+
+ def is_master_lb(self):
+ return 'master_lb' in self.roles
+
+ def is_storage(self):
+ return 'storage' in self.roles
+
+
def is_etcd_member(self, all_hosts):
""" Will this host be a member of a standalone etcd cluster. """
- if not self.master:
+ if not self.is_master():
return False
- masters = [host for host in all_hosts if host.master]
+ masters = [host for host in all_hosts if host.is_master()]
if len(masters) > 1:
return True
return False
def is_dedicated_node(self):
""" Will this host be a dedicated node. (not a master) """
- return self.node and not self.master
+ return self.is_node() and not self.is_master()
def is_schedulable_node(self, all_hosts):
""" Will this host be a node marked as schedulable. """
- if not self.node:
+ if not self.is_node():
return False
- if not self.master:
+ if not self.is_master():
return True
- masters = [host for host in all_hosts if host.master]
- nodes = [host for host in all_hosts if host.node]
+ masters = [host for host in all_hosts if host.is_master()]
+ nodes = [host for host in all_hosts if host.is_node()]
if len(masters) == len(nodes):
return True
return False
+class Role(object):
+ """ A role that will be applied to a host. """
+ def __init__(self, name, variables):
+ self.name = name
+ self.variables = variables
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return self.name
+
+ def to_dict(self):
+ """ Used when exporting to yaml. """
+ d = {}
+ for prop in ['name', 'variables']:
+ # If the property is defined (not None or False), export it:
+ if getattr(self, prop):
+ d[prop] = getattr(self, prop)
+ return d
+
+
+class Deployment(object):
+ def __init__(self, **kwargs):
+ self.hosts = kwargs.get('hosts', [])
+ self.roles = kwargs.get('roles', {})
+ self.variables = kwargs.get('variables', {})
+
+
class OOConfig(object):
default_dir = os.path.normpath(
os.environ.get('XDG_CONFIG_HOME',
@@ -122,32 +158,51 @@ class OOConfig(object):
else:
self.config_path = os.path.normpath(self.default_dir +
self.default_file)
+ self.deployment = Deployment(hosts=[], roles={}, variables={})
self.settings = {}
self._read_config()
self._set_defaults()
+
def _read_config(self):
- self.hosts = []
try:
if os.path.exists(self.config_path):
- cfgfile = open(self.config_path, 'r')
- self.settings = yaml.safe_load(cfgfile.read())
- cfgfile.close()
+ with open(self.config_path, 'r') as cfgfile:
+ loaded_config = yaml.safe_load(cfgfile.read())
# Use the presence of a Description as an indicator this is
# a legacy config file:
if 'Description' in self.settings:
self._upgrade_legacy_config()
+ try:
+ host_list = loaded_config['deployment']['hosts']
+ role_list = loaded_config['deployment']['roles']
+ except KeyError as e:
+ print "Error loading config, no such key: {}".format(e)
+ sys.exit(0)
+
+ for setting in CONFIG_PERSIST_SETTINGS:
+ try:
+ self.settings[setting] = str(loaded_config[setting])
+ except KeyError:
+ continue
+
+ for setting in DEPLOYMENT_PERSIST_SETTINGS:
+ try:
+ self.deployment.variables[setting] = \
+ str(loaded_config['deployment'][setting])
+ except KeyError:
+ continue
+
# Parse the hosts into DTO objects:
- if 'hosts' in self.settings:
- for host in self.settings['hosts']:
- self.hosts.append(Host(**host))
+ for host in host_list:
+ self.deployment.hosts.append(Host(**host))
+
+ # Parse the roles into Objects
+ for name, variables in role_list.iteritems():
+ self.deployment.roles.update({name: Role(name, variables)})
- # Watchout for the variant_version coming in as a float:
- if 'variant_version' in self.settings:
- self.settings['variant_version'] = \
- str(self.settings['variant_version'])
except IOError, ferr:
raise OOConfigFileError('Cannot open config file "{}": {}'.format(ferr.filename,
@@ -179,18 +234,21 @@ class OOConfig(object):
self.settings['variant'] = 'openshift-enterprise'
self.settings['variant_version'] = '3.0'
+ def _upgrade_v1_config(self):
+ #TODO write code to upgrade old config
+ return
+
def _set_defaults(self):
if 'ansible_inventory_directory' not in self.settings:
- self.settings['ansible_inventory_directory'] = \
- self._default_ansible_inv_dir()
+ self.settings['ansible_inventory_directory'] = self._default_ansible_inv_dir()
if not os.path.exists(self.settings['ansible_inventory_directory']):
os.makedirs(self.settings['ansible_inventory_directory'])
if 'ansible_plugins_directory' not in self.settings:
self.settings['ansible_plugins_directory'] = \
resource_filename(__name__, 'ansible_plugins')
if 'version' not in self.settings:
- self.settings['version'] = 'v1'
+ self.settings['version'] = 'v2'
if 'ansible_callback_facts_yaml' not in self.settings:
self.settings['ansible_callback_facts_yaml'] = '%s/callback_facts.yaml' % \
@@ -219,7 +277,7 @@ class OOConfig(object):
"""
result = {}
- for host in self.hosts:
+ for host in self.deployment.hosts:
missing_facts = []
if host.preconfigured:
required_facts = PRECONFIGURED_REQUIRED_FACTS
@@ -240,17 +298,36 @@ class OOConfig(object):
def persist_settings(self):
p_settings = {}
- for setting in PERSIST_SETTINGS:
+
+ for setting in CONFIG_PERSIST_SETTINGS:
if setting in self.settings and self.settings[setting]:
p_settings[setting] = self.settings[setting]
- p_settings['hosts'] = []
- for host in self.hosts:
- p_settings['hosts'].append(host.to_dict())
- if self.settings['ansible_inventory_directory'] != \
- self._default_ansible_inv_dir():
- p_settings['ansible_inventory_directory'] = \
- self.settings['ansible_inventory_directory']
+
+ p_settings['deployment'] = {}
+ p_settings['deployment']['hosts'] = []
+ p_settings['deployment']['roles'] = {}
+
+ for setting in DEPLOYMENT_PERSIST_SETTINGS:
+ if setting in self.deployment.variables:
+ p_settings['deployment'][setting] = self.deployment.variables[setting]
+
+ for host in self.deployment.hosts:
+ p_settings['deployment']['hosts'].append(host.to_dict())
+
+ for name, role in self.deployment.roles.iteritems():
+ p_settings['deployment']['roles'][name] = role.variables
+
+ try:
+ p_settings['variant'] = self.settings['variant']
+ p_settings['variant_version'] = self.settings['variant_version']
+
+ if self.settings['ansible_inventory_directory'] != self._default_ansible_inv_dir():
+ p_settings['ansible_inventory_directory'] = self.settings['ansible_inventory_directory']
+ except KeyError as e:
+ print "Error persisting settings: {}".format(e)
+ sys.exit(0)
+
return p_settings
@@ -261,7 +338,7 @@ class OOConfig(object):
return self.yaml()
def get_host(self, name):
- for host in self.hosts:
+ for host in self.deployment.hosts:
if host.connect_to == name:
return host
return None
diff --git a/utils/src/ooinstall/openshift_ansible.py b/utils/src/ooinstall/openshift_ansible.py
index 5ace63918..b93178e77 100644
--- a/utils/src/ooinstall/openshift_ansible.py
+++ b/utils/src/ooinstall/openshift_ansible.py
@@ -11,15 +11,32 @@ from ooinstall.variants import find_variant
CFG = None
+ROLES_TO_GROUPS_MAP = {
+ 'master': 'masters',
+ 'node': 'nodes',
+ 'storage': 'nfs'
+}
+
+VARIABLES_MAP = {
+ 'ansible_ssh_user': 'ansible_ssh_user',
+ 'ansible_config': 'ansible_config',
+ 'ansible_log_path': 'ansible_log_path',
+ 'deployment_type': 'deployment_type',
+ 'master_routingconfig_subdomain':'openshift_master_default_subdomain',
+ 'proxy_http':'openshift_http_proxy',
+ 'proxy_https': 'openshift_https_proxy',
+ 'proxy_exclude_hosts': 'openshift_no_proxy',
+}
+
def set_config(cfg):
global CFG
CFG = 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]
- new_nodes = [host for host in hosts if host.node and host.new_host]
+ masters = [host for host in hosts if host.is_master()]
+ nodes = [host for host in hosts if host.is_node()]
+ new_nodes = [host for host in hosts if host.is_node() and host.new_host]
proxy = determine_proxy_configuration(hosts)
storage = determine_storage_configuration(hosts)
multiple_masters = len(masters) > 1
@@ -28,27 +45,11 @@ def generate_inventory(hosts):
base_inventory_path = CFG.settings['ansible_inventory_path']
base_inventory = open(base_inventory_path, 'w')
- write_inventory_children(base_inventory, multiple_masters, proxy, storage, scaleup)
+ write_inventory_children(base_inventory, multiple_masters, proxy, scaleup)
write_inventory_vars(base_inventory, multiple_masters, proxy)
- # Find the correct deployment type for ansible:
- ver = find_variant(CFG.settings['variant'],
- version=CFG.settings.get('variant_version', None))[1]
- base_inventory.write('deployment_type={}\n'.format(ver.ansible_key))
- if 'OO_INSTALL_ADDITIONAL_REGISTRIES' in os.environ:
- base_inventory.write('openshift_docker_additional_registries={}\n'
- .format(os.environ['OO_INSTALL_ADDITIONAL_REGISTRIES']))
- if 'OO_INSTALL_INSECURE_REGISTRIES' in os.environ:
- base_inventory.write('openshift_docker_insecure_registries={}\n'
- .format(os.environ['OO_INSTALL_INSECURE_REGISTRIES']))
- if 'OO_INSTALL_PUDDLE_REPO' in os.environ:
- # We have to double the '{' here for literals
- base_inventory.write("openshift_additional_repos=[{{'id': 'ose-devel', "
- "'name': 'ose-devel', "
- "'baseurl': '{}', "
- "'enabled': 1, 'gpgcheck': 0}}]\n".format(os.environ['OO_INSTALL_PUDDLE_REPO']))
base_inventory.write('\n[masters]\n')
for master in masters:
@@ -66,7 +67,7 @@ def generate_inventory(hosts):
schedulable = None
# If the node is also a master, we must explicitly set schedulablity:
- if node.master:
+ if node.is_master():
schedulable = node.is_schedulable_node(hosts)
write_host(node, base_inventory, schedulable)
@@ -88,7 +89,7 @@ def generate_inventory(hosts):
return base_inventory_path
def determine_proxy_configuration(hosts):
- proxy = next((host for host in hosts if host.master_lb), None)
+ proxy = next((host for host in hosts if host.is_master_lb()), None)
if proxy:
if proxy.hostname == None:
proxy.hostname = proxy.connect_to
@@ -97,44 +98,100 @@ def determine_proxy_configuration(hosts):
return proxy
def determine_storage_configuration(hosts):
- storage = next((host for host in hosts if host.storage), None)
+ storage = next((host for host in hosts if host.is_storage()), None)
return storage
-def write_inventory_children(base_inventory, multiple_masters, proxy, storage, scaleup):
+def write_inventory_children(base_inventory, multiple_masters, proxy, scaleup):
global CFG
base_inventory.write('\n[OSEv3:children]\n')
- base_inventory.write('masters\n')
- base_inventory.write('nodes\n')
+ for role in CFG.deployment.roles:
+ child = ROLES_TO_GROUPS_MAP.get(role, role)
+ base_inventory.write('{}\n'.format(child))
+
if scaleup:
base_inventory.write('new_nodes\n')
if multiple_masters:
base_inventory.write('etcd\n')
if not getattr(proxy, 'preconfigured', True):
base_inventory.write('lb\n')
- if storage:
- base_inventory.write('nfs\n')
def write_inventory_vars(base_inventory, multiple_masters, proxy):
global CFG
base_inventory.write('\n[OSEv3:vars]\n')
- base_inventory.write('ansible_ssh_user={}\n'.format(CFG.settings['ansible_ssh_user']))
+
+ for variable, value in CFG.settings.iteritems():
+ inventory_var = VARIABLES_MAP.get(variable, None)
+ if inventory_var and value:
+ base_inventory.write('{}={}\n'.format(inventory_var, value))
+
+ for variable, value in CFG.deployment.variables.iteritems():
+ inventory_var = VARIABLES_MAP.get(variable, variable)
+ if value:
+ base_inventory.write('{}={}\n'.format(inventory_var, value))
+
if CFG.settings['ansible_ssh_user'] != 'root':
base_inventory.write('ansible_become=yes\n')
+
if multiple_masters and proxy is not None:
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))
- if CFG.settings.get('master_routingconfig_subdomain', False):
- base_inventory.write(
- "openshift_master_default_subdomain={}\n".format(
- CFG.settings['master_routingconfig_subdomain']))
+
if CFG.settings.get('variant_version', None) == '3.1':
#base_inventory.write('openshift_image_tag=v{}\n'.format(CFG.settings.get('variant_version')))
base_inventory.write('openshift_image_tag=v{}\n'.format('3.1.1.6'))
+ write_proxy_settings(base_inventory)
+
+ # Find the correct deployment type for ansible:
+ ver = find_variant(CFG.settings['variant'],
+ version=CFG.settings.get('variant_version', None))[1]
+ base_inventory.write('deployment_type={}\n'.format(ver.ansible_key))
+
+ if 'OO_INSTALL_ADDITIONAL_REGISTRIES' in os.environ:
+ base_inventory.write('openshift_docker_additional_registries={}\n'
+ .format(os.environ['OO_INSTALL_ADDITIONAL_REGISTRIES']))
+ if 'OO_INSTALL_INSECURE_REGISTRIES' in os.environ:
+ base_inventory.write('openshift_docker_insecure_registries={}\n'
+ .format(os.environ['OO_INSTALL_INSECURE_REGISTRIES']))
+ if 'OO_INSTALL_PUDDLE_REPO' in os.environ:
+ # We have to double the '{' here for literals
+ base_inventory.write("openshift_additional_repos=[{{'id': 'ose-devel', "
+ "'name': 'ose-devel', "
+ "'baseurl': '{}', "
+ "'enabled': 1, 'gpgcheck': 0}}]\n".format(os.environ['OO_INSTALL_PUDDLE_REPO']))
+
+ for name, role_obj in CFG.deployment.roles.iteritems():
+ if role_obj.variables:
+ group_name = ROLES_TO_GROUPS_MAP.get(name, name)
+ base_inventory.write("\n[{}:vars]\n".format(group_name))
+ for variable, value in role_obj.variables.iteritems():
+ inventory_var = VARIABLES_MAP.get(variable, variable)
+ if value:
+ base_inventory.write('{}={}\n'.format(inventory_var, value))
+ base_inventory.write("\n")
+
+
+def write_proxy_settings(base_inventory):
+ try:
+ base_inventory.write("openshift_http_proxy={}\n".format(
+ CFG.settings['openshift_http_proxy']))
+ except KeyError:
+ pass
+ try:
+ base_inventory.write("openshift_https_proxy={}\n".format(
+ CFG.settings['openshift_https_proxy']))
+ except KeyError:
+ pass
+ try:
+ base_inventory.write("openshift_no_proxy={}\n".format(
+ CFG.settings['openshift_no_proxy']))
+ except KeyError:
+ pass
+
def write_host(host, inventory, schedulable=None):
global CFG
@@ -150,8 +207,6 @@ def write_host(host, inventory, schedulable=None):
facts += ' openshift_public_hostname={}'.format(host.public_hostname)
if host.containerized:
facts += ' containerized={}'.format(host.containerized)
- # TODO: For not write_host is handles both master and nodes.
- # Technically only nodes will ever need this.
# Distinguish between three states, no schedulability specified (use default),
# explicitly set to True, or explicitly set to False:
diff --git a/utils/src/ooinstall/variants.py b/utils/src/ooinstall/variants.py
index 9d98379bb..8889e42e6 100644
--- a/utils/src/ooinstall/variants.py
+++ b/utils/src/ooinstall/variants.py
@@ -33,7 +33,7 @@ class Variant(object):
return self.versions[0]
-# WARNING: Keep the versions ordered, most recent last:
+# WARNING: Keep the versions ordered, most recent first:
OSE = Variant('openshift-enterprise', 'OpenShift Enterprise',
[
Version('3.2', 'openshift-enterprise'),
@@ -49,9 +49,15 @@ AEP = Variant('atomic-enterprise', 'Atomic Enterprise Platform',
]
)
-# Ordered list of variants we can install, first is the default.
-SUPPORTED_VARIANTS = (OSE, AEP)
+origin = Variant('origin', 'OpenShift Origin',
+ [
+ Version('1.2', 'origin'),
+ ]
+)
+# Ordered list of variants we can install, first is the default.
+SUPPORTED_VARIANTS = (OSE, AEP, origin)
+DISPLAY_VARIANTS = (OSE, AEP)
def find_variant(name, version=None):
"""
@@ -72,7 +78,7 @@ def find_variant(name, version=None):
def get_variant_version_combos():
combos = []
- for variant in SUPPORTED_VARIANTS:
+ for variant in DISPLAY_VARIANTS:
for ver in variant.versions:
combos.append((variant, ver))
return combos
diff --git a/utils/test/cli_installer_tests.py b/utils/test/cli_installer_tests.py
index 66ed66660..13973f22f 100644
--- a/utils/test/cli_installer_tests.py
+++ b/utils/test/cli_installer_tests.py
@@ -76,6 +76,14 @@ MOCK_FACTS_QUICKHA = {
'common': {
'ip': '10.0.0.4',
'public_ip': '10.0.0.4',
+ 'hostname': 'node3-private.example.com',
+ 'public_hostname': 'node3.example.com'
+ }
+ },
+ '10.0.0.5': {
+ 'common': {
+ 'ip': '10.0.0.5',
+ 'public_ip': '10.0.0.5',
'hostname': 'proxy-private.example.com',
'public_hostname': 'proxy.example.com'
}
@@ -94,221 +102,279 @@ MOCK_FACTS_QUICKHA = {
BAD_CONFIG = """
variant: %s
ansible_ssh_user: root
-hosts:
- - connect_to: 10.0.0.1
- ip: 10.0.0.1
- hostname: master-private.example.com
- public_ip: 24.222.0.1
- public_hostname: master.example.com
- master: true
- node: true
- - ip: 10.0.0.2
- hostname: node1-private.example.com
- public_ip: 24.222.0.2
- public_hostname: node1.example.com
- node: true
- - connect_to: 10.0.0.3
- ip: 10.0.0.3
- hostname: node2-private.example.com
- public_ip: 24.222.0.3
- public_hostname: node2.example.com
- node: true
+deployment:
+ hosts:
+ - connect_to: 10.0.0.1
+ ip: 10.0.0.1
+ hostname: master-private.example.com
+ public_ip: 24.222.0.1
+ public_hostname: master.example.com
+ roles:
+ - master
+ - node
+ - ip: 10.0.0.2
+ hostname: node1-private.example.com
+ public_ip: 24.222.0.2
+ public_hostname: node1.example.com
+ roles:
+ - node
+ - connect_to: 10.0.0.3
+ ip: 10.0.0.3
+ hostname: node2-private.example.com
+ public_ip: 24.222.0.3
+ public_hostname: node2.example.com
+ roles:
+ - node
+ roles:
+ master:
+ node:
"""
QUICKHA_CONFIG = """
variant: %s
ansible_ssh_user: root
-master_routingconfig_subdomain: example.com
-hosts:
- - connect_to: 10.0.0.1
- ip: 10.0.0.1
- hostname: master-private.example.com
- public_ip: 24.222.0.1
- public_hostname: master.example.com
- master: true
- node: true
- - connect_to: 10.0.0.2
- ip: 10.0.0.2
- hostname: node1-private.example.com
- public_ip: 24.222.0.2
- public_hostname: node1.example.com
- master: true
- node: true
- - connect_to: 10.0.0.3
- ip: 10.0.0.3
- hostname: node2-private.example.com
- public_ip: 24.222.0.3
- public_hostname: node2.example.com
- node: true
- master: true
- - connect_to: 10.0.0.4
- ip: 10.0.0.4
- hostname: node3-private.example.com
- public_ip: 24.222.0.4
- public_hostname: node3.example.com
- node: true
- - connect_to: 10.0.0.5
- ip: 10.0.0.5
- hostname: proxy-private.example.com
- public_ip: 24.222.0.5
- public_hostname: proxy.example.com
- master_lb: true
- - connect_to: 10.1.0.1
- ip: 10.1.0.1
- hostname: storage-private.example.com
- public_ip: 24.222.0.6
- public_hostname: storage.example.com
- storage: true
+deployment:
+ hosts:
+ - connect_to: 10.0.0.1
+ ip: 10.0.0.1
+ hostname: master-private.example.com
+ public_ip: 24.222.0.1
+ public_hostname: master.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.2
+ ip: 10.0.0.2
+ hostname: node1-private.example.com
+ public_ip: 24.222.0.2
+ public_hostname: node1.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.3
+ ip: 10.0.0.3
+ hostname: node2-private.example.com
+ public_ip: 24.222.0.3
+ public_hostname: node2.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.4
+ ip: 10.0.0.4
+ hostname: node3-private.example.com
+ public_ip: 24.222.0.4
+ public_hostname: node3.example.com
+ roles:
+ - node
+ - connect_to: 10.0.0.5
+ ip: 10.0.0.5
+ hostname: proxy-private.example.com
+ public_ip: 24.222.0.5
+ public_hostname: proxy.example.com
+ roles:
+ - master_lb
+ - connect_to: 10.1.0.1
+ ip: 10.1.0.1
+ hostname: storage-private.example.com
+ public_ip: 24.222.0.6
+ public_hostname: storage.example.com
+ roles:
+ - storage
+ roles:
+ master:
+ master_lb:
+ node:
+ storage:
"""
QUICKHA_2_MASTER_CONFIG = """
variant: %s
ansible_ssh_user: root
-hosts:
- - connect_to: 10.0.0.1
- ip: 10.0.0.1
- hostname: master-private.example.com
- public_ip: 24.222.0.1
- public_hostname: master.example.com
- master: true
- node: true
- - connect_to: 10.0.0.2
- ip: 10.0.0.2
- hostname: node1-private.example.com
- public_ip: 24.222.0.2
- public_hostname: node1.example.com
- master: true
- node: true
- - connect_to: 10.0.0.4
- ip: 10.0.0.4
- hostname: node3-private.example.com
- public_ip: 24.222.0.4
- public_hostname: node3.example.com
- node: true
- - connect_to: 10.0.0.5
- ip: 10.0.0.5
- hostname: proxy-private.example.com
- public_ip: 24.222.0.5
- public_hostname: proxy.example.com
- master_lb: true
- - connect_to: 10.1.0.1
- ip: 10.1.0.1
- hostname: storage-private.example.com
- public_ip: 24.222.0.6
- public_hostname: storage.example.com
- storage: true
+deployment:
+ hosts:
+ - connect_to: 10.0.0.1
+ ip: 10.0.0.1
+ hostname: master-private.example.com
+ public_ip: 24.222.0.1
+ public_hostname: master.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.2
+ ip: 10.0.0.2
+ hostname: node1-private.example.com
+ public_ip: 24.222.0.2
+ public_hostname: node1.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.4
+ ip: 10.0.0.4
+ hostname: node3-private.example.com
+ public_ip: 24.222.0.4
+ public_hostname: node3.example.com
+ roles:
+ - node
+ - connect_to: 10.0.0.5
+ ip: 10.0.0.5
+ hostname: proxy-private.example.com
+ public_ip: 24.222.0.5
+ public_hostname: proxy.example.com
+ roles:
+ - master_lb
+ - connect_to: 10.1.0.1
+ ip: 10.1.0.1
+ hostname: storage-private.example.com
+ public_ip: 24.222.0.6
+ public_hostname: storage.example.com
+ roles:
+ - storage
+ roles:
+ master:
+ master_lb:
+ node:
+ storage:
"""
QUICKHA_CONFIG_REUSED_LB = """
variant: %s
ansible_ssh_user: root
-hosts:
- - connect_to: 10.0.0.1
- ip: 10.0.0.1
- hostname: master-private.example.com
- public_ip: 24.222.0.1
- public_hostname: master.example.com
- master: true
- node: true
- - connect_to: 10.0.0.2
- ip: 10.0.0.2
- hostname: node1-private.example.com
- public_ip: 24.222.0.2
- public_hostname: node1.example.com
- master: true
- node: true
- master_lb: true
- - connect_to: 10.0.0.3
- ip: 10.0.0.3
- hostname: node2-private.example.com
- public_ip: 24.222.0.3
- public_hostname: node2.example.com
- node: true
- master: true
- - connect_to: 10.1.0.1
- ip: 10.1.0.1
- hostname: storage-private.example.com
- public_ip: 24.222.0.6
- public_hostname: storage.example.com
- storage: true
+deployment:
+ hosts:
+ - connect_to: 10.0.0.1
+ ip: 10.0.0.1
+ hostname: master-private.example.com
+ public_ip: 24.222.0.1
+ public_hostname: master.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.2
+ ip: 10.0.0.2
+ hostname: node1-private.example.com
+ public_ip: 24.222.0.2
+ public_hostname: node1.example.com
+ roles:
+ - master
+ - node
+ - master_lb
+ - connect_to: 10.0.0.3
+ ip: 10.0.0.3
+ hostname: node2-private.example.com
+ public_ip: 24.222.0.3
+ public_hostname: node2.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.1.0.1
+ ip: 10.1.0.1
+ hostname: storage-private.example.com
+ public_ip: 24.222.0.6
+ public_hostname: storage.example.com
+ roles:
+ - storage
+ roles:
+ master:
+ node:
+ storage:
"""
QUICKHA_CONFIG_NO_LB = """
variant: %s
ansible_ssh_user: root
-hosts:
- - connect_to: 10.0.0.1
- ip: 10.0.0.1
- hostname: master-private.example.com
- public_ip: 24.222.0.1
- public_hostname: master.example.com
- master: true
- node: true
- - connect_to: 10.0.0.2
- ip: 10.0.0.2
- hostname: node1-private.example.com
- public_ip: 24.222.0.2
- public_hostname: node1.example.com
- master: true
- node: true
- - connect_to: 10.0.0.3
- ip: 10.0.0.3
- hostname: node2-private.example.com
- public_ip: 24.222.0.3
- public_hostname: node2.example.com
- node: true
- master: true
- - connect_to: 10.1.0.1
- ip: 10.1.0.1
- hostname: storage-private.example.com
- public_ip: 24.222.0.6
- public_hostname: storage.example.com
- storage: true
+deployment:
+ hosts:
+ - connect_to: 10.0.0.1
+ ip: 10.0.0.1
+ hostname: master-private.example.com
+ public_ip: 24.222.0.1
+ public_hostname: master.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.2
+ ip: 10.0.0.2
+ hostname: node1-private.example.com
+ public_ip: 24.222.0.2
+ public_hostname: node1.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.3
+ ip: 10.0.0.3
+ hostname: node2-private.example.com
+ public_ip: 24.222.0.3
+ public_hostname: node2.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.1.0.1
+ ip: 10.1.0.1
+ hostname: storage-private.example.com
+ public_ip: 24.222.0.6
+ public_hostname: storage.example.com
+ roles:
+ - storage
+ roles:
+ master:
+ node:
+ storage:
"""
QUICKHA_CONFIG_PRECONFIGURED_LB = """
variant: %s
ansible_ssh_user: root
-master_routingconfig_subdomain: example.com
-hosts:
- - connect_to: 10.0.0.1
- ip: 10.0.0.1
- hostname: master-private.example.com
- public_ip: 24.222.0.1
- public_hostname: master.example.com
- master: true
- node: true
- - connect_to: 10.0.0.2
- ip: 10.0.0.2
- hostname: node1-private.example.com
- public_ip: 24.222.0.2
- public_hostname: node1.example.com
- master: true
- node: true
- - connect_to: 10.0.0.3
- ip: 10.0.0.3
- hostname: node2-private.example.com
- public_ip: 24.222.0.3
- public_hostname: node2.example.com
- node: true
- master: true
- - connect_to: 10.0.0.4
- ip: 10.0.0.4
- hostname: node3-private.example.com
- public_ip: 24.222.0.4
- public_hostname: node3.example.com
- node: true
- - connect_to: proxy-private.example.com
- hostname: proxy-private.example.com
- public_hostname: proxy.example.com
- master_lb: true
- preconfigured: true
- - connect_to: 10.1.0.1
- ip: 10.1.0.1
- hostname: storage-private.example.com
- public_ip: 24.222.0.6
- public_hostname: storage.example.com
- storage: true
+deployment:
+ hosts:
+ - connect_to: 10.0.0.1
+ ip: 10.0.0.1
+ hostname: master-private.example.com
+ public_ip: 24.222.0.1
+ public_hostname: master.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.2
+ ip: 10.0.0.2
+ hostname: node1-private.example.com
+ public_ip: 24.222.0.2
+ public_hostname: node1.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.3
+ ip: 10.0.0.3
+ hostname: node2-private.example.com
+ public_ip: 24.222.0.3
+ public_hostname: node2.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.4
+ ip: 10.0.0.4
+ hostname: node3-private.example.com
+ public_ip: 24.222.0.4
+ public_hostname: node3.example.com
+ roles:
+ - node
+ - connect_to: proxy-private.example.com
+ hostname: proxy-private.example.com
+ public_hostname: proxy.example.com
+ preconfigured: true
+ roles:
+ - master_lb
+ - connect_to: 10.1.0.1
+ ip: 10.1.0.1
+ hostname: storage-private.example.com
+ public_ip: 24.222.0.6
+ public_hostname: storage.example.com
+ roles:
+ - storage
+ roles:
+ master:
+ master_lb:
+ node:
+ storage:
"""
class UnattendedCliTests(OOCliFixture):
@@ -439,10 +505,7 @@ class UnattendedCliTests(OOCliFixture):
@patch('ooinstall.openshift_ansible.run_main_playbook')
@patch('ooinstall.openshift_ansible.load_system_facts')
def test_inventory_write(self, load_facts_mock, run_playbook_mock):
-
- # Add an ssh user so we can verify it makes it to the inventory file:
- merged_config = "%s\n%s" % (SAMPLE_CONFIG % 'openshift-enterprise',
- "ansible_ssh_user: bob")
+ merged_config = SAMPLE_CONFIG % 'openshift-enterprise'
load_facts_mock.return_value = (MOCK_FACTS, 0)
run_playbook_mock.return_value = 0
@@ -456,7 +519,7 @@ class UnattendedCliTests(OOCliFixture):
# Check the inventory file looks as we would expect:
inventory = ConfigParser.ConfigParser(allow_no_value=True)
inventory.read(os.path.join(self.work_dir, 'hosts'))
- self.assertEquals('bob',
+ self.assertEquals('root',
inventory.get('OSEv3:vars', 'ansible_ssh_user'))
self.assertEquals('openshift-enterprise',
inventory.get('OSEv3:vars', 'deployment_type'))
diff --git a/utils/test/fixture.py b/utils/test/fixture.py
index e01eaebaf..006df739b 100644
--- a/utils/test/fixture.py
+++ b/utils/test/fixture.py
@@ -10,28 +10,36 @@ from click.testing import CliRunner
# Substitute in a product name before use:
SAMPLE_CONFIG = """
variant: %s
+variant_version: 3.2
ansible_ssh_user: root
master_routingconfig_subdomain: example.com
-hosts:
- - connect_to: 10.0.0.1
- ip: 10.0.0.1
- hostname: master-private.example.com
- public_ip: 24.222.0.1
- public_hostname: master.example.com
- master: true
- node: true
- - connect_to: 10.0.0.2
- ip: 10.0.0.2
- hostname: node1-private.example.com
- public_ip: 24.222.0.2
- public_hostname: node1.example.com
- node: true
- - connect_to: 10.0.0.3
- ip: 10.0.0.3
- hostname: node2-private.example.com
- public_ip: 24.222.0.3
- public_hostname: node2.example.com
- node: true
+deployment:
+ hosts:
+ - connect_to: 10.0.0.1
+ ip: 10.0.0.1
+ hostname: master-private.example.com
+ public_ip: 24.222.0.1
+ public_hostname: master.example.com
+ roles:
+ - master
+ - node
+ - connect_to: 10.0.0.2
+ ip: 10.0.0.2
+ hostname: node1-private.example.com
+ public_ip: 24.222.0.2
+ public_hostname: node1.example.com
+ roles:
+ - node
+ - connect_to: 10.0.0.3
+ ip: 10.0.0.3
+ hostname: node2-private.example.com
+ public_ip: 24.222.0.3
+ public_hostname: node2.example.com
+ roles:
+ - node
+ roles:
+ master:
+ node:
"""
def read_yaml(config_file_path):
@@ -87,12 +95,13 @@ class OOCliFixture(OOInstallFixture):
self.assertEquals(exp_hosts_to_run_on_len, len(hosts_to_run_on))
def _verify_config_hosts(self, written_config, host_count):
- self.assertEquals(host_count, len(written_config['hosts']))
- for host in written_config['hosts']:
+ self.assertEquals(host_count, len(written_config['deployment']['hosts']))
+ for host in written_config['deployment']['hosts']:
self.assertTrue('hostname' in host)
self.assertTrue('public_hostname' in host)
if 'preconfigured' not in host:
- self.assertTrue('node' in host or 'storage' in host)
+ if 'roles' in host:
+ self.assertTrue('node' in host['roles'] or 'storage' in host['roles'])
self.assertTrue('ip' in host)
self.assertTrue('public_ip' in host)
diff --git a/utils/test/oo_config_tests.py b/utils/test/oo_config_tests.py
index 9f5f8e244..c19fe9e0d 100644
--- a/utils/test/oo_config_tests.py
+++ b/utils/test/oo_config_tests.py
@@ -12,27 +12,35 @@ from ooinstall.oo_config import OOConfig, Host, OOConfigInvalidHostError
SAMPLE_CONFIG = """
variant: openshift-enterprise
+variant_version: 3.2
ansible_ssh_user: root
-hosts:
- - connect_to: master-private.example.com
- ip: 10.0.0.1
- hostname: master-private.example.com
- public_ip: 24.222.0.1
- public_hostname: master.example.com
- master: true
- node: true
- - connect_to: node1-private.example.com
- ip: 10.0.0.2
- hostname: node1-private.example.com
- public_ip: 24.222.0.2
- public_hostname: node1.example.com
- node: true
- - connect_to: node2-private.example.com
- ip: 10.0.0.3
- hostname: node2-private.example.com
- public_ip: 24.222.0.3
- public_hostname: node2.example.com
- node: true
+deployment:
+ hosts:
+ - connect_to: master-private.example.com
+ ip: 10.0.0.1
+ hostname: master-private.example.com
+ public_ip: 24.222.0.1
+ public_hostname: master.example.com
+ roles:
+ - master
+ - node
+ - connect_to: node1-private.example.com
+ ip: 10.0.0.2
+ hostname: node1-private.example.com
+ public_ip: 24.222.0.2
+ public_hostname: node1.example.com
+ roles:
+ - node
+ - connect_to: node2-private.example.com
+ ip: 10.0.0.3
+ hostname: node2-private.example.com
+ public_ip: 24.222.0.3
+ public_hostname: node2.example.com
+ roles:
+ - node
+ roles:
+ master:
+ node:
"""
# Used to test automatic upgrading of config:
@@ -56,45 +64,59 @@ validated_facts:
CONFIG_INCOMPLETE_FACTS = """
-hosts:
- - connect_to: 10.0.0.1
- ip: 10.0.0.1
- hostname: master-private.example.com
- public_ip: 24.222.0.1
- public_hostname: master.example.com
- master: true
- - connect_to: 10.0.0.2
- ip: 10.0.0.2
- hostname: 24.222.0.2
- public_ip: 24.222.0.2
- node: true
- - connect_to: 10.0.0.3
- ip: 10.0.0.3
- node: true
+deployment:
+ hosts:
+ - connect_to: 10.0.0.1
+ ip: 10.0.0.1
+ hostname: master-private.example.com
+ public_ip: 24.222.0.1
+ public_hostname: master.example.com
+ roles:
+ - master
+ - connect_to: 10.0.0.2
+ ip: 10.0.0.2
+ hostname: 24.222.0.2
+ public_ip: 24.222.0.2
+ roles:
+ - node
+ - connect_to: 10.0.0.3
+ ip: 10.0.0.3
+ roles:
+ - node
+ roles:
+ master:
+ node:
"""
CONFIG_BAD = """
variant: openshift-enterprise
ansible_ssh_user: root
-hosts:
- - connect_to: master-private.example.com
- ip: 10.0.0.1
- hostname: master-private.example.com
- public_ip: 24.222.0.1
- public_hostname: master.example.com
- master: true
- node: true
- - ip: 10.0.0.2
- hostname: node1-private.example.com
- public_ip: 24.222.0.2
- public_hostname: node1.example.com
- node: true
- - connect_to: node2-private.example.com
- ip: 10.0.0.3
- hostname: node2-private.example.com
- public_ip: 24.222.0.3
- public_hostname: node2.example.com
- node: true
+deployment:
+ hosts:
+ - connect_to: master-private.example.com
+ ip: 10.0.0.1
+ hostname: master-private.example.com
+ public_ip: 24.222.0.1
+ public_hostname: master.example.com
+ roles:
+ - master
+ - node
+ - ip: 10.0.0.2
+ hostname: node1-private.example.com
+ public_ip: 24.222.0.2
+ public_hostname: node1.example.com
+ roles:
+ - node
+ - connect_to: node2-private.example.com
+ ip: 10.0.0.3
+ hostname: node2-private.example.com
+ public_ip: 24.222.0.3
+ public_hostname: node2.example.com
+ roles:
+ - node
+ roles:
+ master:
+ node:
"""
class OOInstallFixture(unittest.TestCase):
@@ -123,47 +145,6 @@ class OOInstallFixture(unittest.TestCase):
return path
-class LegacyOOConfigTests(OOInstallFixture):
-
- def setUp(self):
- OOInstallFixture.setUp(self)
- self.cfg_path = self.write_config(os.path.join(self.work_dir,
- 'ooinstall.conf'), LEGACY_CONFIG)
- self.cfg = OOConfig(self.cfg_path)
-
- def test_load_config_memory(self):
- self.assertEquals('openshift-enterprise', self.cfg.settings['variant'])
- self.assertEquals('3.0', self.cfg.settings['variant_version'])
- self.assertEquals('v1', self.cfg.settings['version'])
-
- self.assertEquals(3, len(self.cfg.hosts))
- h1 = self.cfg.get_host('10.0.0.1')
- self.assertEquals('10.0.0.1', h1.ip)
- self.assertEquals('24.222.0.1', h1.public_ip)
- self.assertEquals('master-private.example.com', h1.hostname)
- self.assertEquals('master.example.com', h1.public_hostname)
-
- h2 = self.cfg.get_host('10.0.0.2')
- self.assertEquals('10.0.0.2', h2.ip)
- self.assertEquals('24.222.0.2', h2.public_ip)
- self.assertEquals('node1-private.example.com', h2.hostname)
- self.assertEquals('node1.example.com', h2.public_hostname)
-
- h3 = self.cfg.get_host('10.0.0.3')
- self.assertEquals('10.0.0.3', h3.ip)
- self.assertEquals('24.222.0.3', h3.public_ip)
- self.assertEquals('node2-private.example.com', h3.hostname)
- self.assertEquals('node2.example.com', h3.public_hostname)
-
- self.assertFalse('masters' in self.cfg.settings)
- self.assertFalse('nodes' in self.cfg.settings)
- self.assertFalse('Description' in self.cfg.settings)
- self.assertFalse('Name' in self.cfg.settings)
- self.assertFalse('Subscription' in self.cfg.settings)
- self.assertFalse('Vendor' in self.cfg.settings)
- self.assertFalse('Version' in self.cfg.settings)
- self.assertFalse('validates_facts' in self.cfg.settings)
-
class OOConfigTests(OOInstallFixture):
@@ -173,16 +154,16 @@ class OOConfigTests(OOInstallFixture):
'ooinstall.conf'), SAMPLE_CONFIG)
ooconfig = OOConfig(cfg_path)
- self.assertEquals(3, len(ooconfig.hosts))
- self.assertEquals("master-private.example.com", ooconfig.hosts[0].connect_to)
- self.assertEquals("10.0.0.1", ooconfig.hosts[0].ip)
- self.assertEquals("master-private.example.com", ooconfig.hosts[0].hostname)
+ self.assertEquals(3, len(ooconfig.deployment.hosts))
+ self.assertEquals("master-private.example.com", ooconfig.deployment.hosts[0].connect_to)
+ self.assertEquals("10.0.0.1", ooconfig.deployment.hosts[0].ip)
+ self.assertEquals("master-private.example.com", ooconfig.deployment.hosts[0].hostname)
self.assertEquals(["10.0.0.1", "10.0.0.2", "10.0.0.3"],
- [host['ip'] for host in ooconfig.settings['hosts']])
+ [host.ip for host in ooconfig.deployment.hosts])
self.assertEquals('openshift-enterprise', ooconfig.settings['variant'])
- self.assertEquals('v1', ooconfig.settings['version'])
+ self.assertEquals('v2', ooconfig.settings['version'])
def test_load_bad_config(self):
@@ -222,8 +203,10 @@ class OOConfigTests(OOInstallFixture):
written_config = yaml.safe_load(f.read())
f.close()
- self.assertEquals(3, len(written_config['hosts']))
- for h in written_config['hosts']:
+
+
+ self.assertEquals(3, len(written_config['deployment']['hosts']))
+ for h in written_config['deployment']['hosts']:
self.assertTrue('ip' in h)
self.assertTrue('public_ip' in h)
self.assertTrue('hostname' in h)
@@ -231,7 +214,7 @@ class OOConfigTests(OOInstallFixture):
self.assertTrue('ansible_ssh_user' in written_config)
self.assertTrue('variant' in written_config)
- self.assertEquals('v1', written_config['version'])
+ self.assertEquals('v2', written_config['version'])
# Some advanced settings should not get written out if they
# were not specified by the user:
@@ -256,7 +239,3 @@ class HostTests(OOInstallFixture):
'public_hostname': 'a.example.com',
}
self.assertRaises(OOConfigInvalidHostError, Host, **yaml_props)
-
-
-
-