summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/docs/config.md8
-rw-r--r--utils/setup.py2
-rw-r--r--utils/src/ooinstall/cli_installer.py273
-rw-r--r--utils/src/ooinstall/oo_config.py66
-rw-r--r--utils/src/ooinstall/openshift_ansible.py (renamed from utils/src/ooinstall/install_transactions.py)67
-rw-r--r--utils/src/ooinstall/variants.py7
-rw-r--r--utils/test/cli_installer_tests.py70
-rw-r--r--utils/test/oo_config_tests.py64
8 files changed, 403 insertions, 154 deletions
diff --git a/utils/docs/config.md b/utils/docs/config.md
index 9399409dd..2729f8d37 100644
--- a/utils/docs/config.md
+++ b/utils/docs/config.md
@@ -7,6 +7,7 @@ The default location this config file will be written to ~/.config/openshift/ins
## Example
```
+version: v1
variant: openshift-enterprise
variant_version: 3.0
ansible_ssh_user: root
@@ -18,20 +19,27 @@ hosts:
master: true
node: true
containerized: true
+ connect_to: 24.222.0.1
- 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.2
- ip: 10.0.0.3
hostname: node2-private.example.com
public_ip: 24.222.0.3
public_hostname: node2.example.com
node: true
+ connect_to: 10.0.0.3
```
## Primary Settings
+### version
+
+Indicates the version of configuration this file was written with. Current implementation is v1.
+
### variant
The OpenShift variant to install. Currently valid options are:
diff --git a/utils/setup.py b/utils/setup.py
index 6e2fdd9c0..eac1b4b2e 100644
--- a/utils/setup.py
+++ b/utils/setup.py
@@ -79,7 +79,7 @@ setup(
# pip to create the appropriate form of executable for the target platform.
entry_points={
'console_scripts': [
- 'oo-install=ooinstall.cli_installer:main',
+ 'oo-install=ooinstall.cli_installer:cli',
],
},
)
diff --git a/utils/src/ooinstall/cli_installer.py b/utils/src/ooinstall/cli_installer.py
index c2ae00bd1..8c2421183 100644
--- a/utils/src/ooinstall/cli_installer.py
+++ b/utils/src/ooinstall/cli_installer.py
@@ -6,12 +6,13 @@ import click
import os
import re
import sys
-from ooinstall import install_transactions
+from ooinstall import openshift_ansible
from ooinstall import OOConfig
from ooinstall.oo_config import Host
from ooinstall.variants import find_variant, get_variant_version_combos
DEFAULT_ANSIBLE_CONFIG = '/usr/share/atomic-openshift-util/ansible.cfg'
+DEFAULT_PLAYBOOK_DIR = '/usr/share/ansible/openshift-ansible/'
def validate_ansible_dir(path):
if not path:
@@ -94,24 +95,19 @@ The OpenShift Node provides the runtime environments for containers. It will
host the required services to be managed by the Master.
http://docs.openshift.com/enterprise/latest/architecture/infrastructure_components/kubernetes_infrastructure.html#master
-http://docs.openshift.com/enterprise/3.0/architecture/infrastructure_components/kubernetes_infrastructure.html#node
+http://docs.openshift.com/enterprise/latest/architecture/infrastructure_components/kubernetes_infrastructure.html#node
"""
click.echo(message)
hosts = []
more_hosts = True
- ip_regex = re.compile(r'^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$')
-
while more_hosts:
host_props = {}
hostname_or_ip = click.prompt('Enter hostname or IP address:',
default='',
value_proc=validate_prompt_hostname)
- if ip_regex.match(hostname_or_ip):
- host_props['ip'] = hostname_or_ip
- else:
- host_props['hostname'] = hostname_or_ip
+ host_props['connect_to'] = hostname_or_ip
host_props['master'] = click.confirm('Will this host be an OpenShift Master?')
host_props['node'] = True
@@ -149,7 +145,7 @@ Plese confirm that they are correct before moving forward.
notes = """
Format:
-IP,public IP,hostname,public hostname
+connect_to,IP,public IP,hostname,public hostname
Notes:
* The installation host is the hostname from the installer's perspective.
@@ -167,16 +163,15 @@ Notes:
default_facts_lines = []
default_facts = {}
- validated_facts = {}
for h in hosts:
- default_facts[h] = {}
- h.ip = callback_facts[str(h)]["common"]["ip"]
- h.public_ip = callback_facts[str(h)]["common"]["public_ip"]
- h.hostname = callback_facts[str(h)]["common"]["hostname"]
- h.public_hostname = callback_facts[str(h)]["common"]["public_hostname"]
-
- validated_facts[h] = {}
- default_facts_lines.append(",".join([h.ip,
+ 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_lines.append(",".join([h.connect_to,
+ h.ip,
h.public_ip,
h.hostname,
h.public_hostname]))
@@ -190,7 +185,7 @@ Notes:
facts_confirmed = click.confirm("Do the above facts look correct?")
if not facts_confirmed:
message = """
-Edit %s with the desired values and rerun oo-install with --unattended .
+Edit %s with the desired values and rerun atomic-openshift-installer with --unattended .
""" % oo_cfg.config_path
click.echo(message)
# Make sure we actually write out the config file.
@@ -315,10 +310,10 @@ Add new nodes here
def get_installed_hosts(hosts, callback_facts):
installed_hosts = []
for host in hosts:
- if(host.name in callback_facts.keys()
- and 'common' in callback_facts[host.name].keys()
- and callback_facts[host.name]['common'].get('version', '')
- and callback_facts[host.name]['common'].get('version', '') != 'None'):
+ if(host.connect_to in callback_facts.keys()
+ and 'common' in callback_facts[host.connect_to].keys()
+ and callback_facts[host.connect_to]['common'].get('version', '')
+ and callback_facts[host.connect_to]['common'].get('version', '') != 'None'):
installed_hosts.append(host)
return installed_hosts
@@ -330,7 +325,22 @@ def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force):
# Check if master or nodes already have something installed
installed_hosts = get_installed_hosts(oo_cfg.hosts, callback_facts)
if len(installed_hosts) > 0:
- # present a message listing already installed hosts
+ click.echo('Installed environment detected.')
+ # This check has to happen before we start removing hosts later in this method
+ if not force:
+ if not unattended:
+ click.echo('By default the installer only adds new nodes to an installed environment.')
+ response = click.prompt('Do you want to (1) only add additional nodes or ' \
+ '(2) perform a clean install?', 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.master:
click.echo("{} is already an OpenShift Master".format(host))
@@ -338,100 +348,193 @@ def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force):
# new nodes.
elif host.node:
click.echo("{} is already an OpenShift Node".format(host))
- hosts_to_run_on.remove(host)
- # for unattended either continue if they force install or exit if they didn't
- if unattended:
- if not force:
- click.echo('Installed environment detected and no additional nodes specified: ' \
- 'aborting. If you want a fresh install, use --force')
- sys.exit(1)
- # for attended ask the user what to do
+ # 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
+ new_hosts = set(hosts_to_run_on) - set(installed_hosts)
+ if len(new_hosts) > 0:
+ for new_host in new_hosts:
+ click.echo("{} is currently uninstalled".format(new_host))
+
+ # Fall through
+ click.echo('Adding additional nodes...')
else:
- click.echo('Installed environment detected and no additional nodes specified. ')
- response = click.prompt('Do you want to (1) add more nodes or ' \
- '(2) perform a clean install?', type=int)
- if response == 1: # add more nodes
- new_nodes = collect_new_nodes()
-
- hosts_to_run_on.extend(new_nodes)
- oo_cfg.hosts.extend(new_nodes)
-
- install_transactions.set_config(oo_cfg)
- callback_facts, error = install_transactions.default_facts(oo_cfg.hosts)
- if error:
- click.echo("There was a problem fetching the required information. " \
- "See {} for details.".format(oo_cfg.settings['ansible_log_path']))
+ 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:
- pass # proceeding as normal should do a clean install
+ if not force:
+ new_nodes = collect_new_nodes()
+
+ hosts_to_run_on.extend(new_nodes)
+ oo_cfg.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)
+ if error:
+ 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
-@click.command()
+
+@click.group()
+@click.pass_context
+@click.option('--unattended', '-u', is_flag=True, default=False)
@click.option('--configuration', '-c',
- type=click.Path(file_okay=True,
- dir_okay=False,
- writable=True,
- readable=True),
- default=None)
+ type=click.Path(file_okay=True,
+ dir_okay=False,
+ writable=True,
+ readable=True),
+ default=None)
@click.option('--ansible-playbook-directory',
'-a',
type=click.Path(exists=True,
file_okay=False,
dir_okay=True,
- writable=True,
readable=True),
# callback=validate_ansible_dir,
+ default=DEFAULT_PLAYBOOK_DIR,
envvar='OO_ANSIBLE_PLAYBOOK_DIRECTORY')
@click.option('--ansible-config',
- type=click.Path(file_okay=True,
- dir_okay=False,
- writable=True,
- readable=True),
- default=None)
+ type=click.Path(file_okay=True,
+ dir_okay=False,
+ writable=True,
+ readable=True),
+ default=None)
@click.option('--ansible-log-path',
- type=click.Path(file_okay=True,
- dir_okay=False,
- writable=True,
- readable=True),
- default="/tmp/ansible.log")
-@click.option('--unattended', '-u', is_flag=True, default=False)
-@click.option('--force', '-f', is_flag=True, default=False)
+ type=click.Path(file_okay=True,
+ dir_okay=False,
+ writable=True,
+ readable=True),
+ default="/tmp/ansible.log")
#pylint: disable=too-many-arguments
# Main CLI entrypoint, not much we can do about too many arguments.
-def main(configuration, ansible_playbook_directory, ansible_config, ansible_log_path, unattended, force):
- oo_cfg = OOConfig(configuration)
+def cli(ctx, unattended, configuration, ansible_playbook_directory, ansible_config, ansible_log_path):
+ """
+ The main click CLI module. Responsible for handling most common CLI options,
+ assigning any defaults and adding to the context for the sub-commands.
+ """
+ ctx.obj = {}
+ ctx.obj['unattended'] = unattended
+ ctx.obj['configuration'] = configuration
+ ctx.obj['ansible_config'] = ansible_config
+ ctx.obj['ansible_log_path'] = ansible_log_path
+
+ oo_cfg = OOConfig(ctx.obj['configuration'])
+ # If no playbook dir on the CLI, check the config:
if not ansible_playbook_directory:
ansible_playbook_directory = oo_cfg.settings.get('ansible_playbook_directory', '')
+ # If still no playbook dir, check for the default location:
+ if not ansible_playbook_directory and os.path.exists(DEFAULT_PLAYBOOK_DIR):
+ ansible_playbook_directory = DEFAULT_PLAYBOOK_DIR
+ validate_ansible_dir(ansible_playbook_directory)
+ oo_cfg.settings['ansible_playbook_directory'] = ansible_playbook_directory
+ oo_cfg.ansible_playbook_directory = ansible_playbook_directory
+ ctx.obj['ansible_playbook_directory'] = ansible_playbook_directory
- if ansible_config:
- oo_cfg.settings['ansible_config'] = ansible_config
+ if ctx.obj['ansible_config']:
+ oo_cfg.settings['ansible_config'] = ctx.obj['ansible_config']
elif os.path.exists(DEFAULT_ANSIBLE_CONFIG):
# If we're installed by RPM this file should exist and we can use it as our default:
oo_cfg.settings['ansible_config'] = DEFAULT_ANSIBLE_CONFIG
- validate_ansible_dir(ansible_playbook_directory)
- oo_cfg.settings['ansible_playbook_directory'] = ansible_playbook_directory
- oo_cfg.ansible_playbook_directory = ansible_playbook_directory
+ oo_cfg.settings['ansible_log_path'] = ctx.obj['ansible_log_path']
+
+ ctx.obj['oo_cfg'] = oo_cfg
+ openshift_ansible.set_config(oo_cfg)
- oo_cfg.settings['ansible_log_path'] = ansible_log_path
- install_transactions.set_config(oo_cfg)
- if unattended:
+@click.command()
+@click.pass_context
+def uninstall(ctx):
+ oo_cfg = ctx.obj['oo_cfg']
+
+ if len(oo_cfg.hosts) == 0:
+ click.echo("No hosts defined in: %s" % oo_cfg['configuration'])
+ 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:
+ click.echo(" * %s" % host.connect_to)
+ proceed = click.confirm("\nDo you wish to proceed?")
+ if not proceed:
+ click.echo("Uninstall cancelled.")
+ sys.exit(0)
+
+ openshift_ansible.run_uninstall_playbook()
+
+
+@click.command()
+@click.pass_context
+def upgrade(ctx):
+ oo_cfg = ctx.obj['oo_cfg']
+
+ if len(oo_cfg.hosts) == 0:
+ click.echo("No hosts defined in: %s" % oo_cfg['configuration'])
+ sys.exit(1)
+
+ # Update config to reflect the version we're targetting, we'll write
+ # to disk once ansible completes successfully, not before.
+ old_variant = oo_cfg.settings['variant']
+ old_version = oo_cfg.settings['variant_version']
+ if oo_cfg.settings['variant'] == 'enterprise':
+ oo_cfg.settings['variant'] = 'openshift-enterprise'
+ version = find_variant(oo_cfg.settings['variant'])[1]
+ oo_cfg.settings['variant_version'] = version.name
+ 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'],
+ oo_cfg.settings['variant_version']))
+ for host in oo_cfg.hosts:
+ click.echo(" * %s" % host.connect_to)
+
+ if not ctx.obj['unattended']:
+ # Prompt interactively to confirm:
+ proceed = click.confirm("\nDo you wish to proceed?")
+ if not proceed:
+ click.echo("Upgrade cancelled.")
+ sys.exit(0)
+
+ retcode = openshift_ansible.run_upgrade_playbook()
+ if retcode > 0:
+ click.echo("Errors encountered during upgrade, please check %s." %
+ oo_cfg.settings['ansible_log_path'])
+ else:
+ click.echo("Upgrade completed! Rebooting all hosts is recommended.")
+
+
+@click.command()
+@click.option('--force', '-f', is_flag=True, default=False)
+@click.pass_context
+def install(ctx, force):
+ oo_cfg = ctx.obj['oo_cfg']
+
+ if ctx.obj['unattended']:
error_if_missing_info(oo_cfg)
else:
oo_cfg = get_missing_info_from_user(oo_cfg)
click.echo('Gathering information from hosts...')
- callback_facts, error = install_transactions.default_facts(oo_cfg.hosts)
+ callback_facts, error = openshift_ansible.default_facts(oo_cfg.hosts)
if error:
click.echo("There was a problem fetching the required information. " \
"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, unattended, force)
-
+ hosts_to_run_on, callback_facts = get_hosts_to_run_on(oo_cfg, callback_facts, ctx.obj['unattended'], force)
click.echo('Writing config to: %s' % oo_cfg.config_path)
@@ -449,10 +552,10 @@ def main(configuration, ansible_playbook_directory, ansible_config, ansible_log_
message = """
If changes are needed to the values recorded by the installer please update {}.
""".format(oo_cfg.config_path)
- if not unattended:
+ if not ctx.obj['unattended']:
confirm_continue(message)
- error = install_transactions.run_main_playbook(oo_cfg.hosts,
+ error = openshift_ansible.run_main_playbook(oo_cfg.hosts,
hosts_to_run_on)
if error:
# The bootstrap script will print out the log location.
@@ -475,5 +578,11 @@ http://docs.openshift.com/enterprise/latest/admin_guide/overview.html
click.echo(message)
click.pause()
+cli.add_command(install)
+cli.add_command(upgrade)
+cli.add_command(uninstall)
+
if __name__ == '__main__':
- main()
+ # This is expected behaviour for context passing with click library:
+ # pylint: disable=unexpected-keyword-arg
+ cli(obj={})
diff --git a/utils/src/ooinstall/oo_config.py b/utils/src/ooinstall/oo_config.py
index a2f53cf78..f35a8f51b 100644
--- a/utils/src/ooinstall/oo_config.py
+++ b/utils/src/ooinstall/oo_config.py
@@ -12,6 +12,7 @@ PERSIST_SETTINGS = [
'ansible_log_path',
'variant',
'variant_version',
+ 'version',
]
REQUIRED_FACTS = ['ip', 'public_ip', 'hostname', 'public_hostname']
@@ -34,6 +35,7 @@ class Host(object):
self.hostname = kwargs.get('hostname', None)
self.public_ip = kwargs.get('public_ip', None)
self.public_hostname = kwargs.get('public_hostname', None)
+ self.connect_to = kwargs.get('connect_to', None)
# Should this host run as an OpenShift master:
self.master = kwargs.get('master', False)
@@ -42,30 +44,25 @@ class Host(object):
self.node = kwargs.get('node', False)
self.containerized = kwargs.get('containerized', False)
- if self.ip is None and self.hostname is None:
- raise OOConfigInvalidHostError("You must specify either 'ip' or 'hostname'")
+ if self.connect_to is None:
+ raise OOConfigInvalidHostError("You must specify either and 'ip' " \
+ "or 'hostname' to connect to.")
if self.master is False and self.node is False:
raise OOConfigInvalidHostError(
"You must specify each host as either a master or a node.")
- # Hosts can be specified with an ip, hostname, or both. However we need
- # something authoritative we can connect to and refer to the host by.
- # Preference given to the IP if specified as this is more specific.
- # We know one must be set by this point.
- self.name = self.ip if self.ip is not None else self.hostname
-
def __str__(self):
- return self.name
+ return self.connect_to
def __repr__(self):
- return self.name
+ return self.connect_to
def to_dict(self):
""" Used when exporting to yaml. """
d = {}
for prop in ['ip', 'hostname', 'public_ip', 'public_hostname',
- 'master', 'node', 'containerized']:
+ 'master', 'node', 'containerized', 'connect_to']:
# If the property is defined (not None or False), export it:
if getattr(self, prop):
d[prop] = getattr(self, prop)
@@ -73,7 +70,6 @@ class Host(object):
class OOConfig(object):
- new_config = True
default_dir = os.path.normpath(
os.environ.get('XDG_CONFIG_HOME',
os.environ['HOME'] + '/.config/') + '/openshift/')
@@ -86,19 +82,22 @@ class OOConfig(object):
self.config_path = os.path.normpath(self.default_dir +
self.default_file)
self.settings = {}
- self.read_config()
- self.set_defaults()
+ self._read_config()
+ self._set_defaults()
- def read_config(self, is_new=False):
+ def _read_config(self):
self.hosts = []
try:
- new_settings = None
if os.path.exists(self.config_path):
cfgfile = open(self.config_path, 'r')
- new_settings = yaml.safe_load(cfgfile.read())
+ self.settings = yaml.safe_load(cfgfile.read())
cfgfile.close()
- if new_settings:
- self.settings = new_settings
+
+ # Use the presence of a Description as an indicator this is
+ # a legacy config file:
+ if 'Description' in self.settings:
+ self._upgrade_legacy_config()
+
# Parse the hosts into DTO objects:
if 'hosts' in self.settings:
for host in self.settings['hosts']:
@@ -114,9 +113,28 @@ class OOConfig(object):
ferr.strerror))
except yaml.scanner.ScannerError:
raise OOConfigFileError('Config file "{}" is not a valid YAML document'.format(self.config_path))
- self.new_config = is_new
- def set_defaults(self):
+ def _upgrade_legacy_config(self):
+ new_hosts = []
+ if 'validated_facts' in self.settings:
+ for key, value in self.settings['validated_facts'].iteritems():
+ if 'masters' in self.settings and key in self.settings['masters']:
+ value['master'] = True
+ if 'nodes' in self.settings and key in self.settings['nodes']:
+ value['node'] = True
+ new_hosts.append(value)
+ self.settings['hosts'] = new_hosts
+
+ remove_settings = ['validated_facts', 'Description', 'Name',
+ 'Subscription', 'Vendor', 'Version', 'masters', 'nodes']
+ for s in remove_settings:
+ del self.settings[s]
+
+ # A legacy config implies openshift-enterprise 3.0:
+ self.settings['variant'] = 'openshift-enterprise'
+ self.settings['variant_version'] = '3.0'
+
+ def _set_defaults(self):
if 'ansible_inventory_directory' not in self.settings:
self.settings['ansible_inventory_directory'] = \
@@ -125,6 +143,8 @@ class OOConfig(object):
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'
if 'ansible_callback_facts_yaml' not in self.settings:
self.settings['ansible_callback_facts_yaml'] = '%s/callback_facts.yaml' % \
@@ -158,7 +178,7 @@ class OOConfig(object):
if not getattr(host, required_fact):
missing_facts.append(required_fact)
if len(missing_facts) > 0:
- result[host.name] = missing_facts
+ result[host.connect_to] = missing_facts
return result
def save_to_disk(self):
@@ -190,6 +210,6 @@ class OOConfig(object):
def get_host(self, name):
for host in self.hosts:
- if host.name == name:
+ if host.connect_to == name:
return host
return None
diff --git a/utils/src/ooinstall/install_transactions.py b/utils/src/ooinstall/openshift_ansible.py
index cef6662d7..d2399df5c 100644
--- a/utils/src/ooinstall/install_transactions.py
+++ b/utils/src/ooinstall/openshift_ansible.py
@@ -2,7 +2,9 @@
# repo. We will work on these over time.
# pylint: disable=bad-continuation,missing-docstring,no-self-use,invalid-name,global-statement,global-variable-not-assigned
+import socket
import subprocess
+import sys
import os
import yaml
from ooinstall.variants import find_variant
@@ -14,32 +16,33 @@ def set_config(cfg):
CFG = cfg
def generate_inventory(hosts):
- print hosts
global CFG
+
base_inventory_path = CFG.settings['ansible_inventory_path']
base_inventory = open(base_inventory_path, 'w')
base_inventory.write('\n[OSEv3:children]\nmasters\nnodes\n')
base_inventory.write('\n[OSEv3:vars]\n')
base_inventory.write('ansible_ssh_user={}\n'.format(CFG.settings['ansible_ssh_user']))
if CFG.settings['ansible_ssh_user'] != 'root':
- base_inventory.write('ansible_sudo=true\n')
+ base_inventory.write('ansible_become=true\n')
# 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_DEVEL_REGISTRY' in os.environ:
- base_inventory.write('oreg_url=rcm-img-docker01.build.eng.bos.redhat.com:'
- '5001/openshift3/ose-${component}:${version}\n')
- if 'OO_INSTALL_PUDDLE_REPO_ENABLE' in os.environ:
- base_inventory.write("openshift_additional_repos=[{'id': 'ose-devel', "
+ if 'OO_INSTALL_ADDITIONAL_REGISTRIES' in os.environ:
+ base_inventory.write('cli_docker_additional_registries={}\n'
+ .format(os.environ['OO_INSTALL_ADDITIONAL_REGISTRIES']))
+ if 'OO_INSTALL_INSECURE_REGISTRIES' in os.environ:
+ base_inventory.write('cli_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': 'http://buildvm-devops.usersys.redhat.com"
- "/puddle/build/AtomicOpenShift/3.1/latest/RH7-RHAOS-3.1/$basearch/os', "
- "'enabled': 1, 'gpgcheck': 0}]\n")
- if 'OO_INSTALL_STAGE_REGISTRY' in os.environ:
- base_inventory.write('oreg_url=registry.access.stage.redhat.com/openshift3/ose-${component}:${version}\n')
+ "'baseurl': '{}', "
+ "'enabled': 1, 'gpgcheck': 0}}]\n".format(os.environ['OO_INSTALL_PUDDLE_REPO']))
base_inventory.write('\n[masters]\n')
masters = (host for host in hosts if host.master)
@@ -61,6 +64,7 @@ def generate_inventory(hosts):
def write_host(host, inventory, scheduleable=True):
global CFG
+
facts = ''
if host.ip:
facts += ' openshift_ip={}'.format(host.ip)
@@ -74,7 +78,17 @@ def write_host(host, inventory, scheduleable=True):
# Technically only nodes will ever need this.
if not scheduleable:
facts += ' openshift_scheduleable=False'
- inventory.write('{} {}\n'.format(host, facts))
+ installer_host = socket.gethostname()
+ if host.hostname == installer_host or host.public_hostname == installer_host:
+ facts += ' ansible_connection=local'
+ if os.geteuid() != 0:
+ no_pwd_sudo = subprocess.call(['sudo', '-v', '-n'])
+ if no_pwd_sudo == 1:
+ print 'The atomic-openshift-installer requires sudo access without a password.'
+ sys.exit(1)
+ facts += ' ansible_become=true'
+
+ inventory.write('{} {}\n'.format(host.connect_to, facts))
def load_system_facts(inventory_file, os_facts_path, env_vars):
@@ -126,8 +140,35 @@ def run_main_playbook(hosts, hosts_to_run_on):
facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_config']
return run_ansible(main_playbook_path, inventory_file, facts_env)
+
def run_ansible(playbook, inventory, env_vars):
return subprocess.call(['ansible-playbook',
'--inventory-file={}'.format(inventory),
playbook],
env=env_vars)
+
+
+def run_uninstall_playbook():
+ playbook = os.path.join(CFG.settings['ansible_playbook_directory'],
+ 'playbooks/adhoc/uninstall.yml')
+ inventory_file = generate_inventory(CFG.hosts)
+ facts_env = os.environ.copy()
+ if 'ansible_log_path' in CFG.settings:
+ facts_env['ANSIBLE_LOG_PATH'] = CFG.settings['ansible_log_path']
+ if 'ansible_config' in CFG.settings:
+ facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_config']
+ return run_ansible(playbook, inventory_file, facts_env)
+
+
+def run_upgrade_playbook():
+ playbook = os.path.join(CFG.settings['ansible_playbook_directory'],
+ 'playbooks/adhoc/upgrades/upgrade.yml')
+ # TODO: Upgrade inventory for upgrade?
+ inventory_file = generate_inventory(CFG.hosts)
+ facts_env = os.environ.copy()
+ if 'ansible_log_path' in CFG.settings:
+ facts_env['ANSIBLE_LOG_PATH'] = CFG.settings['ansible_log_path']
+ if 'ansible_config' in CFG.settings:
+ facts_env['ANSIBLE_CONFIG'] = CFG.settings['ansible_config']
+ return run_ansible(playbook, inventory_file, facts_env)
+
diff --git a/utils/src/ooinstall/variants.py b/utils/src/ooinstall/variants.py
index ed98429fc..3bb61dddb 100644
--- a/utils/src/ooinstall/variants.py
+++ b/utils/src/ooinstall/variants.py
@@ -29,6 +29,9 @@ class Variant(object):
self.versions = versions
+ def latest_version(self):
+ return self.versions[-1]
+
# WARNING: Keep the versions ordered, most recent last:
OSE = Variant('openshift-enterprise', 'OpenShift Enterprise',
@@ -38,7 +41,7 @@ OSE = Variant('openshift-enterprise', 'OpenShift Enterprise',
]
)
-AEP = Variant('atomic-enterprise', 'Atomic OpenShift Enterprise',
+AEP = Variant('atomic-enterprise', 'Atomic Enterprise Platform',
[
Version('3.1', 'atomic-enterprise')
]
@@ -58,7 +61,7 @@ def find_variant(name, version=None):
for prod in SUPPORTED_VARIANTS:
if prod.name == name:
if version is None:
- return (prod, prod.versions[-1])
+ return (prod, prod.latest_version())
for v in prod.versions:
if v.name == version:
return (prod, v)
diff --git a/utils/test/cli_installer_tests.py b/utils/test/cli_installer_tests.py
index 076fe5dc9..b183f0acb 100644
--- a/utils/test/cli_installer_tests.py
+++ b/utils/test/cli_installer_tests.py
@@ -76,7 +76,7 @@ class OOCliFixture(OOInstallFixture):
self.cli_args = ["-a", self.work_dir]
def run_cli(self):
- return self.runner.invoke(cli.main, self.cli_args)
+ return self.runner.invoke(cli.cli, self.cli_args)
def assert_result(self, result, exit_code):
if result.exception is not None or result.exit_code != exit_code:
@@ -102,8 +102,8 @@ class UnattendedCliTests(OOCliFixture):
OOCliFixture.setUp(self)
self.cli_args.append("-u")
- @patch('ooinstall.install_transactions.run_main_playbook')
- @patch('ooinstall.install_transactions.load_system_facts')
+ @patch('ooinstall.openshift_ansible.run_main_playbook')
+ @patch('ooinstall.openshift_ansible.load_system_facts')
def test_cfg_full_run(self, load_facts_mock, run_playbook_mock):
load_facts_mock.return_value = (MOCK_FACTS, 0)
run_playbook_mock.return_value = 0
@@ -111,8 +111,8 @@ class UnattendedCliTests(OOCliFixture):
config_file = self.write_config(os.path.join(self.work_dir,
'ooinstall.conf'), SAMPLE_CONFIG % 'openshift-enterprise')
- self.cli_args.extend(["-c", config_file])
- result = self.runner.invoke(cli.main, self.cli_args)
+ self.cli_args.extend(["-c", config_file, "install"])
+ result = self.runner.invoke(cli.cli, self.cli_args)
self.assert_result(result, 0)
load_facts_args = load_facts_mock.call_args[0]
@@ -133,8 +133,8 @@ class UnattendedCliTests(OOCliFixture):
self.assertEquals(3, len(hosts))
self.assertEquals(3, len(hosts_to_run_on))
- @patch('ooinstall.install_transactions.run_main_playbook')
- @patch('ooinstall.install_transactions.load_system_facts')
+ @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:
@@ -146,8 +146,8 @@ class UnattendedCliTests(OOCliFixture):
config_file = self.write_config(os.path.join(self.work_dir,
'ooinstall.conf'), merged_config)
- self.cli_args.extend(["-c", config_file])
- result = self.runner.invoke(cli.main, self.cli_args)
+ self.cli_args.extend(["-c", config_file, "install"])
+ result = self.runner.invoke(cli.cli, self.cli_args)
self.assert_result(result, 0)
# Check the inventory file looks as we would expect:
@@ -172,8 +172,8 @@ class UnattendedCliTests(OOCliFixture):
self.assertTrue('openshift_hostname' in master_line)
self.assertTrue('openshift_public_hostname' in master_line)
- @patch('ooinstall.install_transactions.run_main_playbook')
- @patch('ooinstall.install_transactions.load_system_facts')
+ @patch('ooinstall.openshift_ansible.run_main_playbook')
+ @patch('ooinstall.openshift_ansible.load_system_facts')
def test_variant_version_latest_assumed(self, load_facts_mock,
run_playbook_mock):
load_facts_mock.return_value = (MOCK_FACTS, 0)
@@ -182,8 +182,8 @@ class UnattendedCliTests(OOCliFixture):
config_file = self.write_config(os.path.join(self.work_dir,
'ooinstall.conf'), SAMPLE_CONFIG % 'openshift-enterprise')
- self.cli_args.extend(["-c", config_file])
- result = self.runner.invoke(cli.main, self.cli_args)
+ self.cli_args.extend(["-c", config_file, "install"])
+ result = self.runner.invoke(cli.cli, self.cli_args)
self.assert_result(result, 0)
written_config = self._read_yaml(config_file)
@@ -199,8 +199,8 @@ class UnattendedCliTests(OOCliFixture):
self.assertEquals('openshift-enterprise',
inventory.get('OSEv3:vars', 'deployment_type'))
- @patch('ooinstall.install_transactions.run_main_playbook')
- @patch('ooinstall.install_transactions.load_system_facts')
+ @patch('ooinstall.openshift_ansible.run_main_playbook')
+ @patch('ooinstall.openshift_ansible.load_system_facts')
def test_variant_version_preserved(self, load_facts_mock,
run_playbook_mock):
load_facts_mock.return_value = (MOCK_FACTS, 0)
@@ -211,8 +211,8 @@ class UnattendedCliTests(OOCliFixture):
config_file = self.write_config(os.path.join(self.work_dir,
'ooinstall.conf'), config)
- self.cli_args.extend(["-c", config_file])
- result = self.runner.invoke(cli.main, self.cli_args)
+ self.cli_args.extend(["-c", config_file, "install"])
+ result = self.runner.invoke(cli.cli, self.cli_args)
self.assert_result(result, 0)
written_config = self._read_yaml(config_file)
@@ -227,8 +227,8 @@ class UnattendedCliTests(OOCliFixture):
self.assertEquals('enterprise',
inventory.get('OSEv3:vars', 'deployment_type'))
- @patch('ooinstall.install_transactions.run_ansible')
- @patch('ooinstall.install_transactions.load_system_facts')
+ @patch('ooinstall.openshift_ansible.run_ansible')
+ @patch('ooinstall.openshift_ansible.load_system_facts')
def test_no_ansible_config_specified(self, load_facts_mock, run_ansible_mock):
load_facts_mock.return_value = (MOCK_FACTS, 0)
run_ansible_mock.return_value = 0
@@ -238,8 +238,8 @@ class UnattendedCliTests(OOCliFixture):
self._ansible_config_test(load_facts_mock, run_ansible_mock,
config, None, None)
- @patch('ooinstall.install_transactions.run_ansible')
- @patch('ooinstall.install_transactions.load_system_facts')
+ @patch('ooinstall.openshift_ansible.run_ansible')
+ @patch('ooinstall.openshift_ansible.load_system_facts')
def test_ansible_config_specified_cli(self, load_facts_mock, run_ansible_mock):
load_facts_mock.return_value = (MOCK_FACTS, 0)
run_ansible_mock.return_value = 0
@@ -250,8 +250,8 @@ class UnattendedCliTests(OOCliFixture):
self._ansible_config_test(load_facts_mock, run_ansible_mock,
config, ansible_config, ansible_config)
- @patch('ooinstall.install_transactions.run_ansible')
- @patch('ooinstall.install_transactions.load_system_facts')
+ @patch('ooinstall.openshift_ansible.run_ansible')
+ @patch('ooinstall.openshift_ansible.load_system_facts')
def test_ansible_config_specified_in_installer_config(self,
load_facts_mock, run_ansible_mock):
@@ -282,7 +282,8 @@ class UnattendedCliTests(OOCliFixture):
self.cli_args.extend(["-c", config_file])
if ansible_config_cli:
self.cli_args.extend(["--ansible-config", ansible_config_cli])
- result = self.runner.invoke(cli.main, self.cli_args)
+ self.cli_args.append("install")
+ result = self.runner.invoke(cli.cli, self.cli_args)
self.assert_result(result, 0)
# Test the env vars for facts playbook:
@@ -388,8 +389,8 @@ class AttendedCliTests(OOCliFixture):
self.assertTrue('public_ip' in h)
self.assertTrue('public_hostname' in h)
- @patch('ooinstall.install_transactions.run_main_playbook')
- @patch('ooinstall.install_transactions.load_system_facts')
+ @patch('ooinstall.openshift_ansible.run_main_playbook')
+ @patch('ooinstall.openshift_ansible.load_system_facts')
def test_full_run(self, load_facts_mock, run_playbook_mock):
load_facts_mock.return_value = (MOCK_FACTS, 0)
run_playbook_mock.return_value = 0
@@ -401,7 +402,8 @@ class AttendedCliTests(OOCliFixture):
ssh_user='root',
variant_num=1,
confirm_facts='y')
- result = self.runner.invoke(cli.main, self.cli_args,
+ self.cli_args.append("install")
+ result = self.runner.invoke(cli.cli, self.cli_args,
input=cli_input)
self.assert_result(result, 0)
@@ -411,8 +413,8 @@ class AttendedCliTests(OOCliFixture):
written_config = self._read_yaml(self.config_file)
self._verify_config_hosts(written_config, 3)
- @patch('ooinstall.install_transactions.run_main_playbook')
- @patch('ooinstall.install_transactions.load_system_facts')
+ @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):
# Modify the mock facts to return a version indicating OpenShift
@@ -432,7 +434,8 @@ class AttendedCliTests(OOCliFixture):
ssh_user='root',
variant_num=1,
confirm_facts='y')
- result = self.runner.invoke(cli.main,
+ self.cli_args.append("install")
+ result = self.runner.invoke(cli.cli,
self.cli_args,
input=cli_input)
self.assert_result(result, 0)
@@ -443,8 +446,8 @@ class AttendedCliTests(OOCliFixture):
written_config = self._read_yaml(self.config_file)
self._verify_config_hosts(written_config, 3)
- @patch('ooinstall.install_transactions.run_main_playbook')
- @patch('ooinstall.install_transactions.load_system_facts')
+ @patch('ooinstall.openshift_ansible.run_main_playbook')
+ @patch('ooinstall.openshift_ansible.load_system_facts')
def test_fresh_install_with_config(self, load_facts_mock, run_playbook_mock):
load_facts_mock.return_value = (MOCK_FACTS, 0)
run_playbook_mock.return_value = 0
@@ -454,7 +457,8 @@ class AttendedCliTests(OOCliFixture):
SAMPLE_CONFIG % 'openshift-enterprise')
cli_input = self._build_input(confirm_facts='y')
self.cli_args.extend(["-c", config_file])
- result = self.runner.invoke(cli.main,
+ self.cli_args.append("install")
+ result = self.runner.invoke(cli.cli,
self.cli_args,
input=cli_input)
self.assert_result(result, 0)
diff --git a/utils/test/oo_config_tests.py b/utils/test/oo_config_tests.py
index 01af33fd9..6dc335a0e 100644
--- a/utils/test/oo_config_tests.py
+++ b/utils/test/oo_config_tests.py
@@ -32,6 +32,26 @@ hosts:
node: true
"""
+# Used to test automatic upgrading of config:
+LEGACY_CONFIG = """
+Description: This is the configuration file for the OpenShift Ansible-Based Installer.
+Name: OpenShift Ansible-Based Installer Configuration
+Subscription: {type: none}
+Vendor: OpenShift Community
+Version: 0.0.1
+ansible_config: /tmp/notreal/ansible.cfg
+ansible_inventory_directory: /tmp/notreal/.config/openshift/.ansible
+ansible_log_path: /tmp/ansible.log
+ansible_plugins_directory: /tmp/notreal/.python-eggs/ooinstall-3.0.0-py2.7.egg-tmp/ooinstall/ansible_plugins
+masters: [10.0.0.1]
+nodes: [10.0.0.2, 10.0.0.3]
+validated_facts:
+ 10.0.0.1: {hostname: master-private.example.com, ip: 10.0.0.1, public_hostname: master.example.com, public_ip: 24.222.0.1}
+ 10.0.0.2: {hostname: node1-private.example.com, ip: 10.0.0.2, public_hostname: node1.example.com, public_ip: 24.222.0.2}
+ 10.0.0.3: {hostname: node2-private.example.com, ip: 10.0.0.3, public_hostname: node2.example.com, public_ip: 24.222.0.3}
+"""
+
+
CONFIG_INCOMPLETE_FACTS = """
hosts:
- ip: 10.0.0.1
@@ -74,6 +94,48 @@ 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):
def test_load_config(self):
@@ -91,6 +153,7 @@ class OOConfigTests(OOInstallFixture):
[host['ip'] for host in ooconfig.settings['hosts']])
self.assertEquals('openshift-enterprise', ooconfig.settings['variant'])
+ self.assertEquals('v1', ooconfig.settings['version'])
def test_load_complete_facts(self):
cfg_path = self.write_config(os.path.join(self.work_dir,
@@ -128,6 +191,7 @@ class OOConfigTests(OOInstallFixture):
self.assertTrue('ansible_ssh_user' in written_config)
self.assertTrue('variant' in written_config)
+ self.assertEquals('v1', written_config['version'])
# Some advanced settings should not get written out if they
# were not specified by the user: