diff options
-rw-r--r-- | playbooks/byo/openshift-cluster/config.yml | 1 | ||||
-rw-r--r-- | playbooks/common/openshift-cluster/additional_config.yml | 2 | ||||
-rw-r--r-- | playbooks/common/openshift-cluster/openshift_hosted.yml | 3 | ||||
-rw-r--r-- | roles/cockpit-ui/meta/main.yml | 13 | ||||
-rw-r--r-- | roles/cockpit-ui/tasks/main.yml | 44 | ||||
-rw-r--r-- | roles/openshift_examples/defaults/main.yml | 2 | ||||
-rw-r--r-- | roles/openshift_examples/files/examples/v1.3/infrastructure-templates/enterprise/registry-console.yaml | 124 | ||||
-rw-r--r-- | roles/openshift_examples/files/examples/v1.3/infrastructure-templates/origin/registry-console.yaml | 124 | ||||
-rwxr-xr-x | roles/openshift_facts/library/openshift_facts.py | 12 | ||||
-rw-r--r-- | roles/openshift_facts/tasks/main.yml | 2 | ||||
-rw-r--r-- | utils/Makefile | 10 | ||||
-rw-r--r-- | utils/src/ooinstall/ansible_plugins/facts_callback.py | 9 | ||||
-rw-r--r-- | utils/src/ooinstall/cli_installer.py | 161 | ||||
-rw-r--r-- | utils/src/ooinstall/oo_config.py | 10 | ||||
-rw-r--r-- | utils/src/ooinstall/openshift_ansible.py | 45 | ||||
-rw-r--r-- | utils/src/ooinstall/variants.py | 37 |
16 files changed, 471 insertions, 128 deletions
diff --git a/playbooks/byo/openshift-cluster/config.yml b/playbooks/byo/openshift-cluster/config.yml index 389ba3419..0b85b2485 100644 --- a/playbooks/byo/openshift-cluster/config.yml +++ b/playbooks/byo/openshift-cluster/config.yml @@ -26,3 +26,4 @@ openshift_cluster_id: "{{ cluster_id | default('default') }}" openshift_debug_level: "{{ debug_level | default(2) }}" openshift_deployment_type: "{{ deployment_type }}" + openshift_deployment_subtype: "{{ deployment_subtype | default(none) }}" diff --git a/playbooks/common/openshift-cluster/additional_config.yml b/playbooks/common/openshift-cluster/additional_config.yml index ebbd45a67..26b31d313 100644 --- a/playbooks/common/openshift-cluster/additional_config.yml +++ b/playbooks/common/openshift-cluster/additional_config.yml @@ -15,6 +15,6 @@ when: openshift.common.use_manageiq | bool - role: cockpit when: not openshift.common.is_atomic and ( deployment_type in ['atomic-enterprise','openshift-enterprise'] ) and - (osm_use_cockpit | bool or osm_use_cockpit is undefined ) + (osm_use_cockpit | bool or osm_use_cockpit is undefined ) and ( openshift.common.deployment_subtype != 'registry' ) - role: flannel_register when: openshift.common.use_flannel | bool diff --git a/playbooks/common/openshift-cluster/openshift_hosted.yml b/playbooks/common/openshift-cluster/openshift_hosted.yml index c90c85cbd..f65b7a2cd 100644 --- a/playbooks/common/openshift-cluster/openshift_hosted.yml +++ b/playbooks/common/openshift-cluster/openshift_hosted.yml @@ -1,3 +1,4 @@ +--- - name: Create persistent volumes hosts: oo_first_master tags: @@ -43,3 +44,5 @@ - role: openshift_hosted - role: openshift_metrics when: openshift.hosted.metrics.deploy | bool + - role: cockpit-ui + when: ( openshift.common.deployment_subtype == 'registry' ) diff --git a/roles/cockpit-ui/meta/main.yml b/roles/cockpit-ui/meta/main.yml new file mode 100644 index 000000000..6ad2e324a --- /dev/null +++ b/roles/cockpit-ui/meta/main.yml @@ -0,0 +1,13 @@ +--- +galaxy_info: + author: Samuel Munilla + description: Deploy and Enable cockpit-ui + company: Red Hat, Inc. + license: Apache License, Version 2.0 + min_ansible_version: 2.1 + platforms: + - name: EL + versions: + - 7 + categories: + - cloud diff --git a/roles/cockpit-ui/tasks/main.yml b/roles/cockpit-ui/tasks/main.yml new file mode 100644 index 000000000..00a7da4a9 --- /dev/null +++ b/roles/cockpit-ui/tasks/main.yml @@ -0,0 +1,44 @@ +--- +- name: Expose docker-registry + command: > + {{ openshift.common.client_binary }} expose service docker-registry -n default + register: expose_docker_registry + changed_when: "'already exists' not in expose_docker_registry.stderr" + failed_when: "'already exists' not in expose_docker_registry.stderr and expose_docker_registry.rc != 0" + +- name: Create passthrough route for registry-console + command: > + {{ openshift.common.client_binary }} create route passthrough + --service registry-console + --port registry-console + -n default + register: create_registry_console_route + changed_when: "'already exists' not in create_registry_console_route.stderr" + failed_when: "'already exists' not in create_registry_console_route.stderr and create_registry_console_route.rc != 0" + +- name: Retrieve docker-registry route + command: "{{ openshift.common.client_binary }} get route docker-registry -n default --template='{{ '{{' }} .spec.host {{ '}}' }}'" + register: docker_registry_route + failed_when: false + changed_when: false + +- name: Retrieve cockpit kube url + command: "{{ openshift.common.client_binary }} get route registry-console -n default --template='https://{{ '{{' }} .spec.host {{ '}}' }}'" + register: registry_console_cockpit_kube_url + failed_when: false + changed_when: false + +- set_fact: + cockpit_image_prefix: "{{ '-p IMAGE_PREFIX=' ~ openshift_cockpit_deployer_prefix | default('') }}" + +- name: Deploy registry-console + command: > + {{ openshift.common.client_binary }} new-app --template=registry-console + {{ cockpit_image_prefix }} + -p OPENSHIFT_OAUTH_PROVIDER_URL="{{ openshift.master.public_api_url }}" + -p REGISTRY_HOST="{{ docker_registry_route.stdout }}" + -p COCKPIT_KUBE_URL="{{ registry_console_cockpit_kube_url.stdout }}" + -n default + register: deploy_registry_console + changed_when: "'already exists' not in deploy_registry_console.stderr" + failed_when: "'already exists' not in deploy_registry_console.stderr and deploy_registry_console.rc != 0" diff --git a/roles/openshift_examples/defaults/main.yml b/roles/openshift_examples/defaults/main.yml index a15285417..e843049f9 100644 --- a/roles/openshift_examples/defaults/main.yml +++ b/roles/openshift_examples/defaults/main.yml @@ -20,6 +20,8 @@ xpaas_templates_base: "{{ examples_base }}/xpaas-templates" quickstarts_base: "{{ examples_base }}/quickstart-templates" infrastructure_origin_base: "{{ examples_base }}/infrastructure-templates/origin" infrastructure_enterprise_base: "{{ examples_base }}/infrastructure-templates/enterprise" +cockpit_ui_base: "{{ examples_base }}/infrastructure-templates/enterprise" + openshift_examples_import_command: "create" registry_url: "" diff --git a/roles/openshift_examples/files/examples/v1.3/infrastructure-templates/enterprise/registry-console.yaml b/roles/openshift_examples/files/examples/v1.3/infrastructure-templates/enterprise/registry-console.yaml new file mode 100644 index 000000000..11478263c --- /dev/null +++ b/roles/openshift_examples/files/examples/v1.3/infrastructure-templates/enterprise/registry-console.yaml @@ -0,0 +1,124 @@ +kind: Template +apiVersion: v1 +metadata: + name: "registry-console" + annotations: + description: "Template for deploying registry web console. Requires cluster-admin." + tags: infrastructure +labels: + createdBy: "registry-console-template" +objects: + - kind: DeploymentConfig + apiVersion: v1 + metadata: + name: "registry-console" + labels: + name: "registry-console" + spec: + triggers: + - type: ConfigChange + replicas: 1 + selector: + name: "registry-console" + template: + metadata: + labels: + name: "registry-console" + spec: + containers: + - name: registry-console + image: ${IMAGE_PREFIX}registry-console:${IMAGE_VERSION} + ports: + - containerPort: 9090 + protocol: TCP + livenessProbe: + failureThreshold: 3 + httpGet: + path: /ping + port: 9090 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + readinessProbe: + failureThreshold: 3 + httpGet: + path: /ping + port: 9090 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + env: + - name: OPENSHIFT_OAUTH_PROVIDER_URL + value: "${OPENSHIFT_OAUTH_PROVIDER_URL}" + - name: OPENSHIFT_OAUTH_CLIENT_ID + value: "${OPENSHIFT_OAUTH_CLIENT_ID}" + - name: KUBERNETES_INSECURE + value: "false" + - name: COCKPIT_KUBE_INSECURE + value: "false" + - name: REGISTRY_ONLY + value: "true" + - name: REGISTRY_HOST + value: "${REGISTRY_HOST}" + - kind: Service + apiVersion: v1 + metadata: + name: "registry-console" + labels: + name: "registry-console" + spec: + type: ClusterIP + ports: + - name: registry-console + protocol: TCP + port: 9000 + targetPort: 9090 + selector: + name: "registry-console" + - kind: ImageStream + apiVersion: v1 + metadata: + name: registry-console + annotations: + description: Atomic Registry console + spec: + tags: + - annotations: null + from: + kind: DockerImage + name: ${IMAGE_PREFIX}registry-console + name: ${IMAGE_VERSION} + - kind: OAuthClient + apiVersion: v1 + metadata: + name: "${OPENSHIFT_OAUTH_CLIENT_ID}" + respondWithChallenges: false + secret: "${OPENSHIFT_OAUTH_CLIENT_SECRET}" + redirectURIs: + - "${COCKPIT_KUBE_URL}" +parameters: + - description: 'Specify "registry/repository" prefix for container image; e.g. for "registry.access.redhat.com/openshift3/registry-console:latest", set prefix "registry.access.redhat.com/openshift3/"' + name: IMAGE_PREFIX + value: "registry.access.redhat.com/openshift3/" + - description: 'Specify image version; e.g. for "registry.access.redhat.com/openshift3/registry-console:3.3", set version "3.3"' + name: IMAGE_VERSION + value: "3.3" + - description: "The public URL for the Openshift OAuth Provider, e.g. https://openshift.example.com:8443" + name: OPENSHIFT_OAUTH_PROVIDER_URL + required: true + - description: "The registry console URL. This should be created beforehand using 'oc create route passthrough --service registry-console --port registry-console -n default', e.g. https://registry-console-default.example.com" + name: COCKPIT_KUBE_URL + required: true + - description: "Oauth client secret" + name: OPENSHIFT_OAUTH_CLIENT_SECRET + from: "user[a-zA-Z0-9]{64}" + generate: expression + - description: "Oauth client id" + name: OPENSHIFT_OAUTH_CLIENT_ID + value: "cockpit-oauth-client" + - description: "The integrated registry hostname exposed via route, e.g. registry.example.com" + name: REGISTRY_HOST + required: true diff --git a/roles/openshift_examples/files/examples/v1.3/infrastructure-templates/origin/registry-console.yaml b/roles/openshift_examples/files/examples/v1.3/infrastructure-templates/origin/registry-console.yaml new file mode 100644 index 000000000..80cc4233b --- /dev/null +++ b/roles/openshift_examples/files/examples/v1.3/infrastructure-templates/origin/registry-console.yaml @@ -0,0 +1,124 @@ +kind: Template +apiVersion: v1 +metadata: + name: "registry-console" + annotations: + description: "Template for deploying registry web console. Requires cluster-admin." + tags: infrastructure +labels: + createdBy: "registry-console-template" +objects: + - kind: DeploymentConfig + apiVersion: v1 + metadata: + name: "registry-console" + labels: + name: "registry-console" + spec: + triggers: + - type: ConfigChange + replicas: 1 + selector: + name: "registry-console" + template: + metadata: + labels: + name: "registry-console" + spec: + containers: + - name: registry-console + image: ${IMAGE_NAME}:${IMAGE_VERSION} + ports: + - containerPort: 9090 + protocol: TCP + livenessProbe: + failureThreshold: 3 + httpGet: + path: /ping + port: 9090 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + readinessProbe: + failureThreshold: 3 + httpGet: + path: /ping + port: 9090 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + env: + - name: OPENSHIFT_OAUTH_PROVIDER_URL + value: "${OPENSHIFT_OAUTH_PROVIDER_URL}" + - name: OPENSHIFT_OAUTH_CLIENT_ID + value: "${OPENSHIFT_OAUTH_CLIENT_ID}" + - name: KUBERNETES_INSECURE + value: "false" + - name: COCKPIT_KUBE_INSECURE + value: "false" + - name: REGISTRY_ONLY + value: "true" + - name: REGISTRY_HOST + value: "${REGISTRY_HOST}" + - kind: Service + apiVersion: v1 + metadata: + name: "registry-console" + labels: + name: "registry-console" + spec: + type: ClusterIP + ports: + - name: registry-console + protocol: TCP + port: 9000 + targetPort: 9090 + selector: + name: "registry-console" + - kind: ImageStream + apiVersion: v1 + metadata: + name: registry-console + annotations: + description: Atomic Registry console + spec: + tags: + - annotations: null + from: + kind: DockerImage + name: ${IMAGE_NAME} + name: ${IMAGE_VERSION} + - kind: OAuthClient + apiVersion: v1 + metadata: + name: "${OPENSHIFT_OAUTH_CLIENT_ID}" + respondWithChallenges: false + secret: "${OPENSHIFT_OAUTH_CLIENT_SECRET}" + redirectURIs: + - "${COCKPIT_KUBE_URL}" +parameters: + - description: "Container image name" + name: IMAGE_NAME + value: "cockpit/kubernetes" + - description: 'Specify image version; e.g. for "cockpit/kubernetes:latest", set version "latest"' + name: IMAGE_VERSION + value: latest + - description: "The public URL for the Openshift OAuth Provider, e.g. https://openshift.example.com:8443" + name: OPENSHIFT_OAUTH_PROVIDER_URL + required: true + - description: "The registry console URL. This should be created beforehand using 'oc create route passthrough --service registry-console --port registry-console -n default', e.g. https://registry-console-default.example.com" + name: COCKPIT_KUBE_URL + required: true + - description: "Oauth client secret" + name: OPENSHIFT_OAUTH_CLIENT_SECRET + from: "user[a-zA-Z0-9]{64}" + generate: expression + - description: "Oauth client id" + name: OPENSHIFT_OAUTH_CLIENT_ID + value: "cockpit-oauth-client" + - description: "The integrated registry hostname exposed via route, e.g. registry.example.com" + name: REGISTRY_HOST + required: true diff --git a/roles/openshift_facts/library/openshift_facts.py b/roles/openshift_facts/library/openshift_facts.py index ff4d9c946..ebd799466 100755 --- a/roles/openshift_facts/library/openshift_facts.py +++ b/roles/openshift_facts/library/openshift_facts.py @@ -797,7 +797,7 @@ def set_deployment_facts_if_unset(facts): curr_disabled_features = set(facts['master']['disabled_features']) facts['master']['disabled_features'] = list(curr_disabled_features.union(openshift_features)) else: - if deployment_type == 'atomic-enterprise': + if facts['common']['deployment_subtype'] == 'registry': facts['master']['disabled_features'] = openshift_features if 'node' in facts: @@ -1657,7 +1657,12 @@ class OpenShiftFacts(object): else: deployment_type = 'origin' - defaults = self.get_defaults(roles, deployment_type) + if 'common' in local_facts and 'deployment_subtype' in local_facts['common']: + deployment_subtype = local_facts['common']['deployment_subtype'] + else: + deployment_subtype = 'basic' + + defaults = self.get_defaults(roles, deployment_type, deployment_subtype) provider_facts = self.init_provider_facts() facts = apply_provider_facts(defaults, provider_facts) facts = merge_facts(facts, @@ -1689,7 +1694,7 @@ class OpenShiftFacts(object): facts = set_installed_variant_rpm_facts(facts) return dict(openshift=facts) - def get_defaults(self, roles, deployment_type): + def get_defaults(self, roles, deployment_type, deployment_subtype): """ Get default fact values Args: @@ -1709,6 +1714,7 @@ class OpenShiftFacts(object): defaults['common'] = dict(use_openshift_sdn=True, ip=ip_addr, public_ip=ip_addr, deployment_type=deployment_type, + deployment_subtype=deployment_subtype, hostname=hostname, public_hostname=hostname, portal_net='172.30.0.0/16', diff --git a/roles/openshift_facts/tasks/main.yml b/roles/openshift_facts/tasks/main.yml index 4dbbd7f45..afeb78f95 100644 --- a/roles/openshift_facts/tasks/main.yml +++ b/roles/openshift_facts/tasks/main.yml @@ -24,6 +24,7 @@ local_facts: # TODO: Deprecate deployment_type in favor of openshift_deployment_type deployment_type: "{{ openshift_deployment_type | default(deployment_type) }}" + deployment_subtype: "{{ openshift_deployment_subtype | default(None) }}" cluster_id: "{{ openshift_cluster_id | default('default') }}" hostname: "{{ openshift_hostname | default(None) }}" ip: "{{ openshift_ip | default(None) }}" @@ -40,4 +41,3 @@ - name: Set repoquery command set_fact: repoquery_cmd: "{{ 'dnf repoquery --latest-limit 1 -d 0' if ansible_pkg_mgr == 'dnf' else 'repoquery --plugins' }}" - diff --git a/utils/Makefile b/utils/Makefile index b1a3874ae..dd0b5cdd0 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -75,15 +75,7 @@ ci-pep8: @echo "#############################################" @echo "# Running PEP8 Compliance Tests in virtualenv" @echo "#############################################" - @echo "Skipping PEP8 tests until we clean them up" -# . $(NAME)env/bin/activate && pep8 --ignore=E501,E121,E124 src/$(SHORTNAME)/ - -ci-pep8-real: - @echo "#############################################" - @echo "# Running PEP8 Compliance Tests in virtualenv" - @echo "#############################################" . $(NAME)env/bin/activate && pep8 --ignore=E501,E121,E124 src/$(SHORTNAME)/ - -ci: clean virtualenv ci-list-deps ci-pylint ci-pep8 ci-unittests ci-pyflakes +ci: clean virtualenv ci-list-deps ci-pep8 ci-pylint ci-pyflakes ci-unittests : diff --git a/utils/src/ooinstall/ansible_plugins/facts_callback.py b/utils/src/ooinstall/ansible_plugins/facts_callback.py index 2537a099f..e51890a22 100644 --- a/utils/src/ooinstall/ansible_plugins/facts_callback.py +++ b/utils/src/ooinstall/ansible_plugins/facts_callback.py @@ -6,6 +6,7 @@ import os import yaml from ansible.plugins.callback import CallbackBase + # pylint: disable=super-init-not-called class CallbackModule(CallbackBase): @@ -19,9 +20,9 @@ class CallbackModule(CallbackBase): self.hosts_yaml_name = os.environ['OO_INSTALL_CALLBACK_FACTS_YAML'] except KeyError: raise ValueError('The OO_INSTALL_CALLBACK_FACTS_YAML environment ' - 'variable must be set.') + 'variable must be set.') self.hosts_yaml = os.open(self.hosts_yaml_name, os.O_CREAT | - os.O_WRONLY) + os.O_WRONLY) def v2_on_any(self, *args, **kwargs): pass @@ -72,9 +73,9 @@ class CallbackModule(CallbackBase): def v2_playbook_on_task_start(self, name, is_conditional): pass - #pylint: disable=too-many-arguments + # pylint: disable=too-many-arguments def v2_playbook_on_vars_prompt(self, varname, private=True, prompt=None, - encrypt=None, confirm=False, salt_size=None, salt=None, default=None): + encrypt=None, confirm=False, salt_size=None, salt=None, default=None): pass def v2_playbook_on_setup(self): diff --git a/utils/src/ooinstall/cli_installer.py b/utils/src/ooinstall/cli_installer.py index 230891e7f..4d678fb98 100644 --- a/utils/src/ooinstall/cli_installer.py +++ b/utils/src/ooinstall/cli_installer.py @@ -28,25 +28,26 @@ DEFAULT_ANSIBLE_CONFIG = '/usr/share/atomic-openshift-utils/ansible.cfg' DEFAULT_PLAYBOOK_DIR = '/usr/share/ansible/openshift-ansible/' UPGRADE_MAPPINGS = { - '3.0':{ - 'minor_version' :'3.0', - 'minor_playbook':'v3_0_minor/upgrade.yml', - 'major_version' :'3.1', - 'major_playbook':'v3_0_to_v3_1/upgrade.yml', - }, - '3.1':{ - 'minor_version' :'3.1', - 'minor_playbook':'v3_1_minor/upgrade.yml', - 'major_playbook':'v3_1_to_v3_2/upgrade.yml', - 'major_version' :'3.2', - }, - '3.2':{ - 'minor_version' :'3.2', - 'minor_playbook':'v3_2/upgrade.yml', - 'major_playbook':'v3_2/upgrade.yml', - 'major_version' :'3.3', - } - } + '3.0': { + 'minor_version': '3.0', + 'minor_playbook': 'v3_0_minor/upgrade.yml', + 'major_version': '3.1', + 'major_playbook': 'v3_0_to_v3_1/upgrade.yml', + }, + '3.1': { + 'minor_version': '3.1', + 'minor_playbook': 'v3_1_minor/upgrade.yml', + 'major_playbook': 'v3_1_to_v3_2/upgrade.yml', + 'major_version': '3.2', + }, + '3.2': { + 'minor_version': '3.2', + 'minor_playbook': 'v3_2/upgrade.yml', + 'major_playbook': 'v3_2/upgrade.yml', + 'major_version': '3.3', + } +} + def validate_ansible_dir(path): if not path: @@ -55,6 +56,7 @@ def validate_ansible_dir(path): # if not os.path.exists(path)): # raise click.BadParameter("Path \"{}\" doesn't exist".format(path)) + def is_valid_hostname(hostname): if not hostname or len(hostname) > 255: return False @@ -63,11 +65,13 @@ def is_valid_hostname(hostname): allowed = re.compile(r"(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE) return all(allowed.match(x) for x in hostname.split(".")) + def validate_prompt_hostname(hostname): if hostname == '' or is_valid_hostname(hostname): return hostname raise click.BadParameter('Invalid hostname. Please double-check this value and re-enter it.') + def get_ansible_ssh_user(): click.clear() message = """ @@ -78,6 +82,7 @@ passwordless sudo access. click.echo(message) return click.prompt('User for ssh access', default='root') + def get_master_routingconfig_subdomain(): click.clear() message = """ @@ -86,15 +91,17 @@ You might want to override the default subdomain used for exposed routes. If you click.echo(message) return click.prompt('New default subdomain (ENTER for none)', default='') + def list_hosts(hosts): hosts_idx = range(len(hosts)) for idx in hosts_idx: click.echo(' {}: {}'.format(idx, hosts[idx])) + def delete_hosts(hosts): while True: list_hosts(hosts) - del_idx = click.prompt('Select host to delete, y/Y to confirm, ' \ + del_idx = click.prompt('Select host to delete, y/Y to confirm, ' 'or n/N to add more hosts', default='n') try: del_idx = int(del_idx) @@ -111,6 +118,7 @@ def delete_hosts(hosts): click.echo("\"{}\" doesn't correspond to any valid input.".format(del_idx)) return hosts, None + def collect_hosts(oo_cfg, existing_env=False, masters_set=False, print_summary=True): """ Collect host information from user. This will later be filled in using @@ -186,7 +194,6 @@ http://docs.openshift.com/enterprise/latest/architecture/infrastructure_componen hosts.append(host) - if print_summary: print_installation_summary(hosts, oo_cfg.settings['variant_version']) @@ -329,6 +336,7 @@ hostname. master_lb = Host(**host_props) hosts.append(master_lb) + def collect_storage_host(hosts): """ Get a valid host for storage from the user and append it to the list of @@ -346,8 +354,8 @@ Note: Containerized storage hosts are not currently supported. first_master = next(host for host in hosts if host.is_master()) hostname_or_ip = click.prompt('Enter hostname or IP address', - value_proc=validate_prompt_hostname, - default=first_master.connect_to) + value_proc=validate_prompt_hostname, + default=first_master.connect_to) existing, existing_host = is_host_already_node_or_master(hostname_or_ip, hosts) if existing and existing_host.is_node(): existing_host.roles.append('storage') @@ -358,6 +366,7 @@ Note: Containerized storage hosts are not currently supported. storage = Host(**host_props) hosts.append(storage) + def is_host_already_node_or_master(hostname, hosts): is_existing = False existing_host = None @@ -369,6 +378,7 @@ def is_host_already_node_or_master(hostname, hosts): return is_existing, existing_host + def confirm_hosts_facts(oo_cfg, callback_facts): hosts = oo_cfg.deployment.hosts click.clear() @@ -443,7 +453,6 @@ Edit %s with the desired values and run `atomic-openshift-installer --unattended return default_facts - def check_hosts_config(oo_cfg, unattended): click.clear() masters = [host for host in oo_cfg.deployment.hosts if host.is_master()] @@ -460,7 +469,7 @@ def check_hosts_config(oo_cfg, unattended): sys.exit(1) elif len(master_lb) == 1: if master_lb[0].is_master() or master_lb[0].is_node(): - click.echo('ERROR: The master load balancer is configured as a master or node. ' \ + click.echo('ERROR: The master load balancer is configured as a master or node. ' 'Please correct this.') sys.exit(1) else: @@ -473,8 +482,8 @@ https://docs.openshift.org/latest/install_config/install/advanced_install.html#m click.echo(message) sys.exit(1) - dedicated_nodes = [host for host in oo_cfg.deployment.hosts \ - if host.is_node() and not host.is_master()] + dedicated_nodes = [host for host in oo_cfg.deployment.hosts + if host.is_node() and not host.is_master()] if len(dedicated_nodes) == 0: message = """ WARNING: No dedicated nodes specified. By default, colocated masters have @@ -488,6 +497,7 @@ as schedulable. return + def get_variant_and_version(multi_master=False): message = "\nWhich variant would you like to install?\n\n" @@ -495,7 +505,7 @@ def get_variant_and_version(multi_master=False): combos = get_variant_version_combos() for (variant, version) in combos: message = "%s\n(%s) %s %s" % (message, i, variant.description, - version.name) + version.name) i = i + 1 message = "%s\n" % message @@ -507,12 +517,14 @@ def get_variant_and_version(multi_master=False): return product, version + def confirm_continue(message): if message: click.echo(message) click.confirm("Are you ready to continue?", default=False, abort=True) return + def error_if_missing_info(oo_cfg): missing_info = False if not oo_cfg.deployment.hosts: @@ -552,6 +564,7 @@ def error_if_missing_info(oo_cfg): if missing_info: sys.exit(1) + def get_host_roles_set(oo_cfg): roles_set = set() for host in oo_cfg.deployment.hosts: @@ -560,6 +573,7 @@ def get_host_roles_set(oo_cfg): return roles_set + def get_proxy_hostnames_and_excludes(): message = """ If a proxy is needed to reach HTTP and HTTPS traffic, please enter the name below. @@ -588,6 +602,7 @@ Please provide any additional hosts to be added to NO_PROXY. (ENTER for none) return http_proxy_hostname, https_proxy_hostname, proxy_excludes + def get_missing_info_from_user(oo_cfg): """ Prompts the user for any information missing from the given configuration. """ click.clear() @@ -623,6 +638,7 @@ https://docs.openshift.com/enterprise/latest/admin_guide/install/prerequisites.h variant, version = get_variant_and_version() oo_cfg.settings['variant'] = variant.name oo_cfg.settings['variant_version'] = version.name + oo_cfg.settings['variant_subtype'] = version.subtype click.clear() if not oo_cfg.deployment.hosts: @@ -633,9 +649,8 @@ https://docs.openshift.com/enterprise/latest/admin_guide/install/prerequisites.h oo_cfg.deployment.roles[role] = Role(name=role, variables={}) click.clear() - if not 'master_routingconfig_subdomain' in oo_cfg.deployment.variables: - oo_cfg.deployment.variables['master_routingconfig_subdomain'] = \ - get_master_routingconfig_subdomain() + if 'master_routingconfig_subdomain' not in oo_cfg.deployment.variables: + oo_cfg.deployment.variables['master_routingconfig_subdomain'] = get_master_routingconfig_subdomain() click.clear() if not oo_cfg.settings.get('openshift_http_proxy', None) and \ @@ -657,10 +672,12 @@ def get_role_variable(oo_cfg, role_name, variable_name): except (StopIteration, KeyError): return None + def set_role_variable(oo_cfg, role_name, variable_name, variable_value): target_role = next(role for role in oo_cfg.deployment.roles if role.name is role_name) target_role[variable_name] = variable_value + def collect_new_nodes(oo_cfg): click.clear() click.echo('*** New Node Configuration ***') @@ -671,6 +688,7 @@ Add new nodes here new_nodes, _ = collect_hosts(oo_cfg, existing_env=True, masters_set=True, print_summary=False) return new_nodes + def get_installed_hosts(hosts, callback_facts): installed_hosts = [] uninstalled_hosts = [] @@ -682,13 +700,15 @@ def get_installed_hosts(hosts, callback_facts): uninstalled_hosts.append(host) return installed_hosts, uninstalled_hosts + def is_installed_host(host, callback_facts): version_found = 'common' in callback_facts[host.connect_to].keys() and \ - callback_facts[host.connect_to]['common'].get('version', '') and \ - callback_facts[host.connect_to]['common'].get('version', '') != 'None' + callback_facts[host.connect_to]['common'].get('version', '') and \ + callback_facts[host.connect_to]['common'].get('version', '') != 'None' return version_found + # pylint: disable=too-many-branches # This pylint error will be corrected shortly in separate PR. def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force, verbose): @@ -703,10 +723,10 @@ def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force, verbose): # This check has to happen before we start removing hosts later in this method if not force: if not unattended: - click.echo('By default the installer only adds new nodes ' \ + click.echo('By default the installer only adds new nodes ' 'to an installed environment.') - response = click.prompt('Do you want to (1) only add additional nodes or ' \ - '(2) reinstall the existing hosts ' \ + response = click.prompt('Do you want to (1) only add additional nodes or ' + '(2) reinstall the existing hosts ' 'potentially erasing any custom changes?', type=int) # TODO: this should be reworked with error handling. @@ -735,16 +755,16 @@ def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force, verbose): for uninstalled_host in uninstalled_hosts: click.echo("{} is currently uninstalled".format(uninstalled_host)) # Fall through - click.echo('\nUninstalled hosts have been detected in your environment. ' \ - 'Please make sure your environment was installed successfully ' \ - 'before adding new nodes. If you want a fresh install, use ' \ + click.echo('\nUninstalled hosts have been detected in your environment. ' + 'Please make sure your environment was installed successfully ' + 'before adding new nodes. If you want a fresh install, use ' '`atomic-openshift-installer install --force`') sys.exit(1) else: if unattended: if not force: - click.echo('Installed environment detected and no additional ' \ - 'nodes specified: aborting. If you want a fresh install, use ' \ + click.echo('Installed environment detected and no additional ' + 'nodes specified: aborting. If you want a fresh install, use ' '`atomic-openshift-installer install --force`') sys.exit(1) else: @@ -758,14 +778,15 @@ def get_hosts_to_run_on(oo_cfg, callback_facts, unattended, force, verbose): click.echo('Gathering information from hosts...') callback_facts, error = openshift_ansible.default_facts(oo_cfg.deployment.hosts, verbose) if error or callback_facts is None: - click.echo("There was a problem fetching the required information. See " \ + click.echo("There was a problem fetching the required information. See " "{} for details.".format(oo_cfg.settings['ansible_log_path'])) sys.exit(1) else: - pass # proceeding as normal should do a clean install + pass # proceeding as normal should do a clean install return hosts_to_run_on, callback_facts + def set_infra_nodes(hosts): if all(host.is_master() for host in hosts): infra_list = hosts @@ -781,11 +802,11 @@ def set_infra_nodes(hosts): @click.pass_context @click.option('--unattended', '-u', is_flag=True, default=False) @click.option('--configuration', '-c', - type=click.Path(file_okay=True, - dir_okay=False, - writable=True, - readable=True), - default=None) + type=click.Path(file_okay=True, + dir_okay=False, + writable=True, + readable=True), + default=None) @click.option('--ansible-playbook-directory', '-a', type=click.Path(exists=True, @@ -796,25 +817,25 @@ def set_infra_nodes(hosts): default=DEFAULT_PLAYBOOK_DIR, envvar='OO_ANSIBLE_PLAYBOOK_DIRECTORY') @click.option('--ansible-config', - type=click.Path(file_okay=True, - dir_okay=False, - writable=True, - readable=True), - default=None) + type=click.Path(file_okay=True, + dir_okay=False, + writable=True, + readable=True), + default=None) @click.option('--ansible-log-path', - type=click.Path(file_okay=True, - dir_okay=False, - writable=True, - readable=True), - default="/tmp/ansible.log") + type=click.Path(file_okay=True, + dir_okay=False, + writable=True, + readable=True), + default="/tmp/ansible.log") @click.option('-v', '--verbose', - is_flag=True, default=False) + is_flag=True, default=False) @click.option('-d', '--debug', - help="Enable installer debugging (/tmp/installer.log)", - is_flag=True, default=False) + help="Enable installer debugging (/tmp/installer.log)", + is_flag=True, default=False) @click.help_option('--help', '-h') -#pylint: disable=too-many-arguments -#pylint: disable=line-too-long +# pylint: disable=too-many-arguments +# pylint: disable=line-too-long # Main CLI entrypoint, not much we can do about too many arguments. def cli(ctx, unattended, configuration, ansible_playbook_directory, ansible_config, ansible_log_path, verbose, debug): """ @@ -859,7 +880,7 @@ def cli(ctx, unattended, configuration, ansible_playbook_directory, ansible_conf if ctx.obj['ansible_config']: oo_cfg.settings['ansible_config'] = ctx.obj['ansible_config'] elif 'ansible_config' not in oo_cfg.settings and \ - os.path.exists(DEFAULT_ANSIBLE_CONFIG): + os.path.exists(DEFAULT_ANSIBLE_CONFIG): # If we're installed by RPM this file should exist and we can use it as our default: oo_cfg.settings['ansible_config'] = DEFAULT_ANSIBLE_CONFIG @@ -900,7 +921,7 @@ def uninstall(ctx): @click.option('--latest-minor', '-l', is_flag=True, default=False) @click.option('--next-major', '-n', is_flag=True, default=False) @click.pass_context -#pylint: disable=bad-builtin,too-many-statements +# pylint: disable=bad-builtin,too-many-statements def upgrade(ctx, latest_minor, next_major): oo_cfg = ctx.obj['oo_cfg'] @@ -943,7 +964,7 @@ def upgrade(ctx, latest_minor, next_major): if next_major: if 'major_playbook' not in mapping: - click.echo("No major upgrade supported for %s %s with this version "\ + click.echo("No major upgrade supported for %s %s with this version " "of atomic-openshift-utils." % (variant, old_version)) sys.exit(0) playbook = mapping['major_playbook'] @@ -956,7 +977,7 @@ def upgrade(ctx, latest_minor, next_major): if latest_minor: if 'minor_playbook' not in mapping: - click.echo("No minor upgrade supported for %s %s with this version "\ + click.echo("No minor upgrade supported for %s %s with this version " "of atomic-openshift-utils." % (variant, old_version)) sys.exit(0) playbook = mapping['minor_playbook'] @@ -978,7 +999,7 @@ def upgrade(ctx, latest_minor, next_major): ctx.obj['verbose']) if retcode > 0: click.echo("Errors encountered during upgrade, please check %s." % - oo_cfg.settings['ansible_log_path']) + oo_cfg.settings['ansible_log_path']) else: oo_cfg.save_to_disk() click.echo("Upgrade completed! Rebooting all hosts is recommended.") @@ -1003,10 +1024,10 @@ def install(ctx, force, gen_inventory): print_installation_summary(oo_cfg.deployment.hosts, oo_cfg.settings.get('variant_version', None)) click.echo('Gathering information from hosts...') callback_facts, error = openshift_ansible.default_facts(oo_cfg.deployment.hosts, - verbose) + verbose) if error or callback_facts is None: - click.echo("There was a problem fetching the required information. " \ + click.echo("There was a problem fetching the required information. " "Please see {} for details.".format(oo_cfg.settings['ansible_log_path'])) sys.exit(1) diff --git a/utils/src/ooinstall/oo_config.py b/utils/src/ooinstall/oo_config.py index 0e855f437..351c9905d 100644 --- a/utils/src/ooinstall/oo_config.py +++ b/utils/src/ooinstall/oo_config.py @@ -17,8 +17,9 @@ CONFIG_PERSIST_SETTINGS = [ 'deployment', 'version', 'variant', + 'variant_subtype', 'variant_version', - ] +] DEPLOYMENT_VARIABLES_BLACKLIST = [ 'hosts', @@ -28,6 +29,7 @@ DEPLOYMENT_VARIABLES_BLACKLIST = [ DEFAULT_REQUIRED_FACTS = ['ip', 'public_ip', 'hostname', 'public_hostname'] PRECONFIGURED_REQUIRED_FACTS = ['hostname', 'public_hostname'] + def print_read_config_error(error, path='the configuration file'): message = """ Error loading config. {}. @@ -103,7 +105,6 @@ class Host(object): 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.is_master(): @@ -189,7 +190,7 @@ class OOConfig(object): with open(self.config_path, 'r') as cfgfile: loaded_config = yaml.safe_load(cfgfile.read()) - if not 'version' in loaded_config: + if 'version' not in loaded_config: print_read_config_error('Legacy configuration file found', self.config_path) sys.exit(0) @@ -242,7 +243,6 @@ class OOConfig(object): for name, variables in role_list.iteritems(): self.deployment.roles.update({name: Role(name, variables)}) - except IOError, ferr: raise OOConfigFileError('Cannot open config file "{}": {}'.format(ferr.filename, ferr.strerror)) @@ -251,7 +251,6 @@ class OOConfig(object): 'Config file "{}" is not a valid YAML document'.format(self.config_path)) installer_log.debug("Parsed the config file") - def _upgrade_v1_config(self, config): new_config_data = {} new_config_data['deployment'] = {} @@ -396,7 +395,6 @@ class OOConfig(object): print "Error persisting settings: {}".format(e) sys.exit(0) - return p_settings def yaml(self): diff --git a/utils/src/ooinstall/openshift_ansible.py b/utils/src/ooinstall/openshift_ansible.py index 570b48dda..09dd1ebc4 100644 --- a/utils/src/ooinstall/openshift_ansible.py +++ b/utils/src/ooinstall/openshift_ansible.py @@ -22,16 +22,19 @@ ROLES_TO_GROUPS_MAP = { VARIABLES_MAP = { 'ansible_ssh_user': 'ansible_ssh_user', 'deployment_type': 'deployment_type', - 'master_routingconfig_subdomain':'openshift_master_default_subdomain', - 'proxy_http':'openshift_http_proxy', + 'variant_subtype': 'deployment_subtype', + '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 @@ -50,8 +53,7 @@ def generate_inventory(hosts): write_inventory_vars(base_inventory, multiple_masters, lb) - - #write_inventory_hosts + # write_inventory_hosts for role in CFG.deployment.roles: # write group block group = ROLES_TO_GROUPS_MAP.get(role, role) @@ -70,15 +72,17 @@ def generate_inventory(hosts): base_inventory.close() return base_inventory_path + def determine_lb_configuration(hosts): lb = next((host for host in hosts if host.is_master_lb()), None) if lb: - if lb.hostname == None: + if lb.hostname is None: lb.hostname = lb.connect_to lb.public_hostname = lb.connect_to return lb + def write_inventory_children(base_inventory, scaleup): global CFG @@ -116,28 +120,30 @@ def write_inventory_vars(base_inventory, multiple_masters, lb): "openshift_master_cluster_public_hostname={}\n".format(lb.public_hostname)) 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(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] + version=CFG.settings.get('variant_version', None))[1] base_inventory.write('deployment_type={}\n'.format(ver.ansible_key)) + if getattr(ver, 'variant_subtype', False): + base_inventory.write('deployment_subtype={}\n'.format(ver.deployment_subtype)) if 'OO_INSTALL_ADDITIONAL_REGISTRIES' in os.environ: - base_inventory.write('openshift_docker_additional_registries={}\n' - .format(os.environ['OO_INSTALL_ADDITIONAL_REGISTRIES'])) + 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'])) + 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'])) + "'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: @@ -153,17 +159,17 @@ def write_inventory_vars(base_inventory, multiple_masters, lb): def write_proxy_settings(base_inventory): try: base_inventory.write("openshift_http_proxy={}\n".format( - CFG.settings['openshift_http_proxy'])) + CFG.settings['openshift_http_proxy'])) except KeyError: pass try: base_inventory.write("openshift_https_proxy={}\n".format( - CFG.settings['openshift_https_proxy'])) + CFG.settings['openshift_https_proxy'])) except KeyError: pass try: base_inventory.write("openshift_no_proxy={}\n".format( - CFG.settings['openshift_no_proxy'])) + CFG.settings['openshift_no_proxy'])) except KeyError: pass @@ -193,7 +199,6 @@ def write_host(host, role, inventory, schedulable=None): if role == 'node': facts += ' openshift_node_labels="{}"'.format(host.node_labels) - # Distinguish between three states, no schedulability specified (use default), # explicitly set to True, or explicitly set to False: if role != 'node' or schedulable is None: @@ -290,7 +295,7 @@ def run_ansible(playbook, inventory, env_vars, verbose=False): def run_uninstall_playbook(hosts, verbose=False): playbook = os.path.join(CFG.settings['ansible_playbook_directory'], - 'playbooks/adhoc/uninstall.yml') + 'playbooks/adhoc/uninstall.yml') inventory_file = generate_inventory(hosts) facts_env = os.environ.copy() if 'ansible_log_path' in CFG.settings: @@ -302,7 +307,7 @@ def run_uninstall_playbook(hosts, verbose=False): def run_upgrade_playbook(hosts, playbook, verbose=False): playbook = os.path.join(CFG.settings['ansible_playbook_directory'], - 'playbooks/byo/openshift-cluster/upgrades/{}'.format(playbook)) + 'playbooks/byo/openshift-cluster/upgrades/{}'.format(playbook)) # TODO: Upgrade inventory for upgrade? inventory_file = generate_inventory(hosts) diff --git a/utils/src/ooinstall/variants.py b/utils/src/ooinstall/variants.py index ce4d772ee..8f82655fd 100644 --- a/utils/src/ooinstall/variants.py +++ b/utils/src/ooinstall/variants.py @@ -16,10 +16,11 @@ installer_log = logging.getLogger('installer') class Version(object): - def __init__(self, name, ansible_key): + def __init__(self, name, ansible_key, subtype=''): self.name = name # i.e. 3.0, 3.1 self.ansible_key = ansible_key + self.subtype = subtype class Variant(object): @@ -38,28 +39,35 @@ class Variant(object): # WARNING: Keep the versions ordered, most recent first: OSE = Variant('openshift-enterprise', 'OpenShift Container Platform', - [ - Version('3.3', 'openshift-enterprise'), - ] + [ + Version('3.3', 'openshift-enterprise'), + ] +) + +REG = Variant('openshift-enterprise', 'Registry', + [ + Version('3.2', 'openshift-enterprise', 'registry'), + ] ) origin = Variant('origin', 'OpenShift Origin', - [ - Version('1.2', 'origin'), - ] + [ + Version('1.2', 'origin'), + ] ) LEGACY = Variant('openshift-enterprise', 'OpenShift Container Platform', - [ - Version('3.2', 'openshift-enterprise'), - Version('3.1', 'openshift-enterprise'), - Version('3.0', 'openshift-enterprise'), - ] + [ + Version('3.2', 'openshift-enterprise'), + Version('3.1', 'openshift-enterprise'), + Version('3.0', 'openshift-enterprise'), + ] ) # Ordered list of variants we can install, first is the default. -SUPPORTED_VARIANTS = (OSE, origin, LEGACY) -DISPLAY_VARIANTS = (OSE, ) +SUPPORTED_VARIANTS = (OSE, REG, origin, LEGACY) +DISPLAY_VARIANTS = (OSE, REG,) + def find_variant(name, version=None): """ @@ -78,6 +86,7 @@ def find_variant(name, version=None): return (None, None) + def get_variant_version_combos(): combos = [] for variant in DISPLAY_VARIANTS: |