diff options
58 files changed, 1048 insertions, 205 deletions
diff --git a/.gitignore b/.gitignore index 8f46c269f..081659a94 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ gce.ini multi_ec2.yaml multi_inventory.yaml .vagrant +.tags* diff --git a/.tito/packages/openshift-ansible b/.tito/packages/openshift-ansible index e3f5491cd..bc2fab995 100644 --- a/.tito/packages/openshift-ansible +++ b/.tito/packages/openshift-ansible @@ -1 +1 @@ -3.0.37-1 ./ +3.0.38-1 ./ diff --git a/README_GCE.md b/README_GCE.md index ea673b44d..9439b569e 100644 --- a/README_GCE.md +++ b/README_GCE.md @@ -42,12 +42,17 @@ Create a gce.ini file for GCE Mandatory customization variables (check the values according to your tenant): * zone = europe-west1-d * network = default -* gce_machine_type = n1-standard-2 -* gce_machine_master_type = n1-standard-1 -* gce_machine_node_type = n1-standard-2 -* gce_machine_image = preinstalled-slave-50g-v5 -* gce_machine_master_image = preinstalled-slave-50g-v5 -* gce_machine_node_image = preinstalled-slave-50g-v5 + +Optional Variable Overrides: +* gce_ssh_user - ssh user, defaults to the current logged in user +* gce_machine_type = n1-standard-1 - default machine type +* gce_machine_etcd_type = n1-standard-1 - machine type for etcd hosts +* gce_machine_master_type = n1-standard-1 - machine type for master hosts +* gce_machine_node_type = n1-standard-1 - machine type for node hosts +* gce_machine_image = centos-7 - default image +* gce_machine_etcd_image = centos-7 - image for etcd hosts +* gce_machine_master_image = centos-7 - image for master hosts +* gce_machine_node_image = centos-7 - image for node hosts 1. vi ~/.gce/gce.ini @@ -62,9 +67,9 @@ network = default gce_machine_type = n1-standard-2 gce_machine_master_type = n1-standard-1 gce_machine_node_type = n1-standard-2 -gce_machine_image = preinstalled-slave-50g-v5 -gce_machine_master_image = preinstalled-slave-50g-v5 -gce_machine_node_image = preinstalled-slave-50g-v5 +gce_machine_image = centos-7 +gce_machine_master_image = centos-7 +gce_machine_node_image = centos-7 ``` 1. Define the environment variable GCE_INI_PATH so gce.py can pick it up and bin/cluster can also read it @@ -92,10 +97,15 @@ argument will result in all gce instances being listed) Creating a cluster ------------------ -1. To create a cluster with one master and two nodes +1. To create a cluster with one master, one infra node, and two compute nodes ``` bin/cluster create gce <cluster-id> ``` +1. To create a cluster with 3 masters, 3 etcd hosts, 2 infra nodes and 10 +compute nodes +``` + bin/cluster create gce -m 3 -e 3 -i 2 -n 10 <cluster-id> +``` Updating a cluster --------------------- @@ -104,6 +114,16 @@ Updating a cluster bin/cluster update gce <cluster-id> ``` +Add additional nodes +--------------------- +1. To add additional infra nodes +``` + bin/cluster add-nodes gce -i <num nodes> <cluster-id> +``` +1. To add additional compute nodes +``` + bin/cluster add-nodes gce -n <num nodes> <cluster-id> +``` Terminating a cluster --------------------- 1. To terminate the cluster diff --git a/filter_plugins/oo_filters.py b/filter_plugins/oo_filters.py index 2b39bb59e..289e3b8f7 100644 --- a/filter_plugins/oo_filters.py +++ b/filter_plugins/oo_filters.py @@ -556,6 +556,96 @@ class FilterModule(object): except Exception as my_e: raise errors.AnsibleFilterError('Failed to convert: %s', my_e) + @staticmethod + def oo_openshift_env(hostvars): + ''' Return facts which begin with "openshift_" + Ex: hostvars = {'openshift_fact': 42, + 'theyre_taking_the_hobbits_to': 'isengard'} + returns = {'openshift_fact': 42} + ''' + if not issubclass(type(hostvars), dict): + raise errors.AnsibleFilterError("|failed expects hostvars is a dict") + + facts = {} + regex = re.compile('^openshift_.*') + for key in hostvars: + if regex.match(key): + facts[key] = hostvars[key] + return facts + + @staticmethod + # pylint: disable=too-many-branches + def oo_persistent_volumes(hostvars, groups, persistent_volumes=None): + """ Generate list of persistent volumes based on oo_openshift_env + storage options set in host variables. + """ + if not issubclass(type(hostvars), dict): + raise errors.AnsibleFilterError("|failed expects hostvars is a dict") + if not issubclass(type(groups), dict): + raise errors.AnsibleFilterError("|failed expects groups is a dict") + if persistent_volumes != None and not issubclass(type(persistent_volumes), list): + raise errors.AnsibleFilterError("|failed expects persistent_volumes is a list") + + if persistent_volumes == None: + persistent_volumes = [] + for component in hostvars['openshift']['hosted']: + kind = hostvars['openshift']['hosted'][component]['storage']['kind'] + create_pv = hostvars['openshift']['hosted'][component]['storage']['create_pv'] + if kind != None and create_pv: + if kind == 'nfs': + host = hostvars['openshift']['hosted'][component]['storage']['host'] + if host == None: + if len(groups['oo_nfs_to_config']) > 0: + host = groups['oo_nfs_to_config'][0] + else: + raise errors.AnsibleFilterError("|failed no storage host detected") + directory = hostvars['openshift']['hosted'][component]['storage']['nfs']['directory'] + volume = hostvars['openshift']['hosted'][component]['storage']['volume']['name'] + path = directory + '/' + volume + size = hostvars['openshift']['hosted'][component]['storage']['volume']['size'] + access_modes = hostvars['openshift']['hosted'][component]['storage']['access_modes'] + persistent_volume = dict( + name="{0}-volume".format(volume), + capacity=size, + access_modes=access_modes, + storage=dict( + nfs=dict( + server=host, + path=path))) + persistent_volumes.append(persistent_volume) + else: + msg = "|failed invalid storage kind '{0}' for component '{1}'".format( + kind, + component) + raise errors.AnsibleFilterError(msg) + return persistent_volumes + + @staticmethod + def oo_persistent_volume_claims(hostvars, persistent_volume_claims=None): + """ Generate list of persistent volume claims based on oo_openshift_env + storage options set in host variables. + """ + if not issubclass(type(hostvars), dict): + raise errors.AnsibleFilterError("|failed expects hostvars is a dict") + if persistent_volume_claims != None and not issubclass(type(persistent_volume_claims), list): + raise errors.AnsibleFilterError("|failed expects persistent_volume_claims is a list") + + if persistent_volume_claims == None: + persistent_volume_claims = [] + for component in hostvars['openshift']['hosted']: + kind = hostvars['openshift']['hosted'][component]['storage']['kind'] + create_pv = hostvars['openshift']['hosted'][component]['storage']['create_pv'] + if kind != None and create_pv: + volume = hostvars['openshift']['hosted'][component]['storage']['volume']['name'] + size = hostvars['openshift']['hosted'][component]['storage']['volume']['size'] + access_modes = hostvars['openshift']['hosted'][component]['storage']['access_modes'] + persistent_volume_claim = dict( + name="{0}-claim".format(volume), + capacity=size, + access_modes=access_modes) + persistent_volume_claims.append(persistent_volume_claim) + return persistent_volume_claims + def filters(self): """ returns a mapping of filters to methods """ return { @@ -578,4 +668,7 @@ class FilterModule(object): "oo_generate_secret": self.oo_generate_secret, "to_padded_yaml": self.to_padded_yaml, "oo_nodes_with_label": self.oo_nodes_with_label, + "oo_openshift_env": self.oo_openshift_env, + "oo_persistent_volumes": self.oo_persistent_volumes, + "oo_persistent_volume_claims": self.oo_persistent_volume_claims, } diff --git a/inventory/byo/hosts.aep.example b/inventory/byo/hosts.aep.example index 05aef586f..7f4a1a9d2 100644 --- a/inventory/byo/hosts.aep.example +++ b/inventory/byo/hosts.aep.example @@ -74,7 +74,7 @@ deployment_type=atomic-enterprise #openshift_additional_repos=[{'id': 'aep-devel', 'name': 'aep-devel', 'baseurl': 'http://example.com/puddle/build/AtomicOpenShift/3.1/latest/RH7-RHOSE-3.0/$basearch/os', 'enabled': 1, 'gpgcheck': 0}] # htpasswd auth -openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/htpasswd'}] +openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/master/htpasswd'}] # Allow all auth #openshift_master_identity_providers=[{'name': 'allow_all', 'login': 'true', 'challenge': 'true', 'kind': 'AllowAllPasswordIdentityProvider'}] @@ -203,6 +203,40 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', # Configure dnsIP in the node config #openshift_dns_ip=172.30.0.1 +# Persistent Storage Options +# +## Registry Storage Options +## +## Storage Kind +## Specifies which storage kind will be used for the registry. +## "nfs" is the only supported kind at this time. +##openshift_hosted_registry_storage_kind=nfs +## +## Storage Host +## This variable can be used to identify a pre-existing storage host +## if a storage host group corresponding to the storage kind (such as +## [nfs]) is not specified, +##openshift_hosted_registry_storage_host=nfs.example.com +## +## NFS Export Options +##openshift_hosted_registry_storage_nfs_options='*(rw,root_squash)' +## +## NFS Export Directory +## Specify the root exports directory. This directory will be created +## if specifying an [nfs] host group. +## This variable must be supplied if using a pre-existing nfs server. +##openshift_hosted_registry_storage_nfs_directory=/exports +## +## Registry Volume Name +## Specify the storage volume name. This directory will be created +## within openshift_hosted_registry_storage_nfs_directory if +## specifying an [nfs] group. Ex. /exports/registry +## This variable must be supplied if using a pre-existing nfs server. +##openshift_hosted_registry_storage_volume_name=registry +## +## Persistent Volume Access Mode +##openshift_hosted_registry_storage_access_modes=['ReadWriteMany'] + # Configure node kubelet arguments #openshift_node_kubelet_args={'max-pods': ['40'], 'image-gc-high-threshold': ['90'], 'image-gc-low-threshold': ['80']} @@ -210,6 +244,13 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', # See: https://github.com/nickhammond/ansible-logrotate #logrotate_scripts=[{"name": "syslog", "path": "/var/log/cron\n/var/log/maillog\n/var/log/messages\n/var/log/secure\n/var/log/spooler\n", "options": ["daily", "rotate 7", "compress", "sharedscripts", "missingok"], "scripts": {"postrotate": "/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true"}}] +# openshift-ansible will wait indefinitely for your input when it detects that the +# value of openshift_hostname resolves to an IP address not bound to any local +# interfaces. This mis-configuration is problematic for any pod leveraging host +# networking and liveness or readiness probes. +# Setting this variable to true will override that check. +#openshift_override_hostname_check=true + # host group for masters [masters] aep3-master[1:3]-ansible.test.example.com diff --git a/inventory/byo/hosts.origin.example b/inventory/byo/hosts.origin.example index 7b240622d..aae987796 100644 --- a/inventory/byo/hosts.origin.example +++ b/inventory/byo/hosts.origin.example @@ -79,7 +79,7 @@ deployment_type=origin #openshift_additional_repos=[{'id': 'fedora-openshift-origin-copr', 'name': 'OpenShift Origin COPR for Fedora', 'baseurl': 'https://copr-be.cloud.fedoraproject.org/results/maxamillion/fedora-openshift/fedora-$releasever-$basearch/', 'enabled': 1, 'gpgcheck': 1, gpgkey: 'https://copr-be.cloud.fedoraproject.org/results/maxamillion/fedora-openshift/pubkey.gpg'}] # htpasswd auth -openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/htpasswd'}] +openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/master/htpasswd'}] # Allow all auth #openshift_master_identity_providers=[{'name': 'allow_all', 'login': 'true', 'challenge': 'true', 'kind': 'AllowAllPasswordIdentityProvider'}] @@ -208,10 +208,39 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', # Configure dnsIP in the node config #openshift_dns_ip=172.30.0.1 -# NFS Options -#openshift_nfs_exports_dir=/var/export -#openshift_nfs_registry_volume=regvol -#openshift_nfs_export_options='*(rw,sync,all_squash)' +# Persistent Storage Options +# +## Registry Storage Options +## +## Storage Kind +## Specifies which storage kind will be used for the registry. +## nfs is the only supported kind at this time. +##openshift_hosted_registry_storage_kind=nfs +## +## Storage Host +## This variable can be used to identify a pre-existing storage host +## if a storage host group corresponding to the storage kind (such as +## [nfs]) is not specified, +##openshift_hosted_registry_storage_host=nfs.example.com +## +## NFS Export Options +##openshift_hosted_registry_storage_nfs_options='*(rw,root_squash)' +## +## NFS Export Directory +## Specify the root exports directory. This directory will be created +## if specifying an [nfs] host group. +## This variable must be supplied if using a pre-existing nfs server. +##openshift_hosted_registry_storage_nfs_directory=/exports +## +## Registry Volume Name +## Specify the storage volume name. This directory will be created +## within openshift_hosted_registry_storage_nfs_directory if +## specifying an [nfs] group. Ex: /exports/registry +## This variable must be supplied if using a pre-existing nfs server. +##openshift_hosted_registry_storage_volume_name=registry +## +## Persistent Volume Access Mode +##openshift_hosted_registry_storage_access_modes=['ReadWriteMany'] # Configure node kubelet arguments #openshift_node_kubelet_args={'max-pods': ['40'], 'image-gc-high-threshold': ['90'], 'image-gc-low-threshold': ['80']} @@ -220,6 +249,13 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', # See: https://github.com/nickhammond/ansible-logrotate #logrotate_scripts=[{"name": "syslog", "path": "/var/log/cron\n/var/log/maillog\n/var/log/messages\n/var/log/secure\n/var/log/spooler\n", "options": ["daily", "rotate 7", "compress", "sharedscripts", "missingok"], "scripts": {"postrotate": "/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true"}}] +# openshift-ansible will wait indefinitely for your input when it detects that the +# value of openshift_hostname resolves to an IP address not bound to any local +# interfaces. This mis-configuration is problematic for any pod leveraging host +# networking and liveness or readiness probes. +# Setting this variable to true will override that check. +#openshift_override_hostname_check=true + # host group for masters [masters] ose3-master[1:3]-ansible.test.example.com diff --git a/inventory/byo/hosts.ose.example b/inventory/byo/hosts.ose.example index e44d1abc9..f017f9a6e 100644 --- a/inventory/byo/hosts.ose.example +++ b/inventory/byo/hosts.ose.example @@ -74,7 +74,7 @@ deployment_type=openshift-enterprise #openshift_additional_repos=[{'id': 'ose-devel', 'name': 'ose-devel', 'baseurl': 'http://example.com/puddle/build/AtomicOpenShift/3.1/latest/RH7-RHOSE-3.0/$basearch/os', 'enabled': 1, 'gpgcheck': 0}] # htpasswd auth -openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/htpasswd'}] +openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/master/htpasswd'}] # Allow all auth #openshift_master_identity_providers=[{'name': 'allow_all', 'login': 'true', 'challenge': 'true', 'kind': 'AllowAllPasswordIdentityProvider'}] @@ -203,6 +203,40 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', # Configure dnsIP in the node config #openshift_dns_ip=172.30.0.1 +# Persistent Storage Options +# +## Registry Storage Options +## +## Storage Kind +## Specifies which storage kind will be used for the registry. +## "nfs" is the only supported kind at this time. +##openshift_hosted_registry_storage_kind=nfs +## +## Storage Host +## This variable can be used to identify a pre-existing storage host +## if a storage host group corresponding to the storage kind (such as +## [nfs]) is not specified, +##openshift_hosted_registry_storage_host=nfs.example.com +## +## NFS Export Options +##openshift_hosted_registry_storage_nfs_options='*(rw,root_squash)' +## +## NFS Export Directory +## Specify the root exports directory. This directory will be created +## if specifying an [nfs] host group. +## This variable must be supplied if using a pre-existing nfs server. +##openshift_hosted_registry_storage_nfs_directory=/exports +## +## Registry Volume Name +## Specify the storage volume name. This directory will be created +## within openshift_hosted_registry_storage_nfs_directory if +## specifying an [nfs] group Ex: /exports/registry +## This variable must be supplied if using a pre-existing nfs server. +##openshift_hosted_registry_storage_volume_name=registry +## +## Persistent Volume Access Mode +##openshift_hosted_registry_storage_access_modes=['ReadWriteMany'] + # Configure node kubelet arguments #openshift_node_kubelet_args={'max-pods': ['40'], 'image-gc-high-threshold': ['90'], 'image-gc-low-threshold': ['80']} @@ -210,6 +244,13 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', # See: https://github.com/nickhammond/ansible-logrotate #logrotate_scripts=[{"name": "syslog", "path": "/var/log/cron\n/var/log/maillog\n/var/log/messages\n/var/log/secure\n/var/log/spooler\n", "options": ["daily", "rotate 7", "compress", "sharedscripts", "missingok"], "scripts": {"postrotate": "/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true"}}] +# openshift-ansible will wait indefinitely for your input when it detects that the +# value of openshift_hostname resolves to an IP address not bound to any local +# interfaces. This mis-configuration is problematic for any pod leveraging host +# networking and liveness or readiness probes. +# Setting this variable to true will override that check. +#openshift_override_hostname_check=true + # host group for masters [masters] ose3-master[1:3]-ansible.test.example.com diff --git a/openshift-ansible.spec b/openshift-ansible.spec index 051a6d966..218c714f5 100644 --- a/openshift-ansible.spec +++ b/openshift-ansible.spec @@ -5,7 +5,7 @@ } Name: openshift-ansible -Version: 3.0.37 +Version: 3.0.38 Release: 1%{?dist} Summary: Openshift and Atomic Enterprise Ansible License: ASL 2.0 @@ -259,6 +259,30 @@ Atomic OpenShift Utilities includes %changelog +* Tue Feb 02 2016 Brenton Leanhardt <bleanhar@redhat.com> 3.0.38-1 +- aoi: Ask for osm_default_subdomain in interactive mode (smunilla@redhat.com) +- add item to hold number of stray OVS rules found/removed (jdiaz@redhat.com) +- changed adhoc playbook to match new host monitoring container + (mwoodson@redhat.com) +- Multi-master fixes for provider playbooks (jdetiber@redhat.com) +- zabbix: added master local api items and triggers (mwoodson@redhat.com) +- Added docs around oo_nodes_with_label (jdetiber@redhat.com) +- fix for terminate (jdetiber@redhat.com) +- Fix node tags for aws provider (jdetiber@redhat.com) +- use yaml for loading lable info instead of json (jdetiber@redhat.com) +- infra_node fixes (jdetiber@redhat.com) +- removing extraneous comments (rharriso@redhat.com) +- Remove commented lines and fix pylint check (rharriso@redhat.com) +- Cleaning up the dyn ansible module for merging (rharriso@redhat.com) +- Fix missing bool filter (sdodson@redhat.com) +- Sync platest imagestreams (sdodson@redhat.com) +- Fixing last pylint error (rharriso@redhat.com) +- Fix hostname for aws cloud provider (jdetiber@redhat.com) +- Fixing pylint errors (rharriso@redhat.com) +- Give openvswitch container some time to start (jprovazn@redhat.com) +- s3_registry no filter named 'lookup' (florian.lambert@enovance.com) +- WIP adding the lib_dyn role for the dyn_record module (rharriso@redhat.com) + * Fri Jan 29 2016 Kenny Woodson <kwoodson@redhat.com> 3.0.37-1 - Adding ip address option (kwoodson@redhat.com) - Enable cockpit when not is_atomic. (abutcher@redhat.com) diff --git a/playbooks/adhoc/docker_storage_cleanup/docker_storage_cleanup.yml b/playbooks/adhoc/docker_storage_cleanup/docker_storage_cleanup.yml index a19291a9f..b6dde357e 100644 --- a/playbooks/adhoc/docker_storage_cleanup/docker_storage_cleanup.yml +++ b/playbooks/adhoc/docker_storage_cleanup/docker_storage_cleanup.yml @@ -57,7 +57,7 @@ # leaving off the '-t' for docker exec. With it, it doesn't work with ansible and tty support - name: update zabbix docker items - command: docker exec -i oso-rhel7-zagg-client /usr/local/bin/cron-send-docker-metrics.py + command: docker exec -i oso-rhel7-host-monitoring /usr/local/bin/cron-send-docker-metrics.py # Get and show docker info again. - name: Get docker info diff --git a/playbooks/adhoc/s3_registry/s3_registry.yml b/playbooks/adhoc/s3_registry/s3_registry.yml index 0814efae2..38ce92e92 100644 --- a/playbooks/adhoc/s3_registry/s3_registry.yml +++ b/playbooks/adhoc/s3_registry/s3_registry.yml @@ -14,7 +14,7 @@ aws_access_key: "{{ lookup('env', 'S3_ACCESS_KEY_ID') }}" aws_secret_key: "{{ lookup('env', 'S3_SECRET_ACCESS_KEY') }}" aws_bucket_name: "{{ aws_bucket | default(clusterid ~ '-docker') }}" - aws_bucket_region: "{{ aws_region | lookup('env', 'S3_REGION') | default('us-east-1') }}" + aws_bucket_region: "{{ aws_region | default(lookup('env', 'S3_REGION') | default('us-east-1', true)) }}" tasks: diff --git a/playbooks/aws/openshift-cluster/config.yml b/playbooks/aws/openshift-cluster/config.yml index 86f3ae624..9fba856a2 100644 --- a/playbooks/aws/openshift-cluster/config.yml +++ b/playbooks/aws/openshift-cluster/config.yml @@ -10,6 +10,7 @@ openshift_debug_level: "{{ debug_level }}" openshift_deployment_type: "{{ deployment_type }}" openshift_public_hostname: "{{ ec2_ip_address }}" + openshift_registry_selector: 'type=infra' openshift_router_selector: 'type=infra' openshift_infra_nodes: "{{ g_infra_hosts }}" openshift_node_labels: '{"region": "{{ ec2_region }}", "type": "{{ hostvars[inventory_hostname]["ec2_tag_sub-host-type"] if inventory_hostname in groups["tag_host-type_node"] else hostvars[inventory_hostname]["ec2_tag_host-type"] }}"}' diff --git a/playbooks/byo/openshift-cluster/cluster_hosts.yml b/playbooks/byo/openshift-cluster/cluster_hosts.yml index e093b2580..10872e738 100644 --- a/playbooks/byo/openshift-cluster/cluster_hosts.yml +++ b/playbooks/byo/openshift-cluster/cluster_hosts.yml @@ -7,6 +7,8 @@ g_master_hosts: "{{ groups.masters | default([]) }}" g_node_hosts: "{{ groups.nodes | default([]) }}" +g_new_node_hosts: "{{ groups.new_nodes | default([]) }}" + g_nfs_hosts: "{{ groups.nfs | default([]) }}" g_all_hosts: "{{ g_master_hosts | union(g_node_hosts) | union(g_etcd_hosts) diff --git a/playbooks/byo/openshift_facts.yml b/playbooks/byo/openshift_facts.yml index babdfb952..916dfd0a6 100644 --- a/playbooks/byo/openshift_facts.yml +++ b/playbooks/byo/openshift_facts.yml @@ -5,5 +5,6 @@ - openshift_facts tasks: - openshift_facts: + openshift_env: "{{ hostvars[inventory_hostname] | oo_openshift_env }}" register: result - debug: var=result diff --git a/playbooks/common/openshift-cluster/config.yml b/playbooks/common/openshift-cluster/config.yml index 11e5b68f6..2cad4b362 100644 --- a/playbooks/common/openshift-cluster/config.yml +++ b/playbooks/common/openshift-cluster/config.yml @@ -1,6 +1,8 @@ --- - include: evaluate_groups.yml +- include: validate_hostnames.yml + - include: ../openshift-docker/config.yml - include: ../openshift-etcd/config.yml diff --git a/playbooks/common/openshift-cluster/evaluate_groups.yml b/playbooks/common/openshift-cluster/evaluate_groups.yml index db7105ed5..7917bfba5 100644 --- a/playbooks/common/openshift-cluster/evaluate_groups.yml +++ b/playbooks/common/openshift-cluster/evaluate_groups.yml @@ -47,7 +47,7 @@ # Use g_new_node_hosts if it exists otherwise g_node_hosts - set_fact: - g_node_hosts_to_config: "{{ g_new_node_hosts | default(g_node_hosts | default([])) }}" + g_node_hosts_to_config: "{{ g_new_node_hosts | default(g_node_hosts | default([], true), true) }}" - name: Evaluate oo_nodes_to_config add_host: diff --git a/playbooks/common/openshift-cluster/validate_hostnames.yml b/playbooks/common/openshift-cluster/validate_hostnames.yml new file mode 100644 index 000000000..047431b63 --- /dev/null +++ b/playbooks/common/openshift-cluster/validate_hostnames.yml @@ -0,0 +1,26 @@ +--- +- include: evaluate_groups.yml + +- name: Gather and set facts for node hosts + hosts: oo_nodes_to_config + roles: + - openshift_facts + tasks: + - openshift_facts: + role: "{{ item.role }}" + local_facts: "{{ item.local_facts }}" + with_items: + - role: common + local_facts: + hostname: "{{ openshift_hostname | default(None) }}" + public_hostname: "{{ openshift_public_hostname | default(None) }}" + - shell: + getent ahostsv4 {{ openshift.common.hostname }} | head -n 1 | awk '{ print $1 }' + register: lookupip + changed_when: false + failed_when: false + - name: Warn user about bad openshift_hostname values + pause: + prompt: "The hostname \"{{ openshift.common.hostname }}\" for \"{{ ansible_nodename }}\" doesn't resolve to an ip address owned by this host. Please set openshift_hostname variable to a hostname that when resolved on the host in question resolves to an IP address matching an interface on this host. This host will fail liveness checks for pods utilizing hostPorts, press CTRL-C to continue." + seconds: "{{ 10 if openshift_override_hostname_check | default(false) | bool else omit }}" + when: lookupip.stdout not in ansible_all_ipv4_addresses diff --git a/playbooks/common/openshift-etcd/config.yml b/playbooks/common/openshift-etcd/config.yml index d23a54511..93eb157cb 100644 --- a/playbooks/common/openshift-etcd/config.yml +++ b/playbooks/common/openshift-etcd/config.yml @@ -69,8 +69,32 @@ validate_checksum: yes with_items: etcd_needing_server_certs -- name: Configure etcd hosts - hosts: oo_etcd_to_config +# Configure a first etcd host to avoid conflicts in choosing a leader +# if other members come online too quickly. +- name: Configure first etcd host + hosts: oo_first_etcd + vars: + sync_tmpdir: "{{ hostvars.localhost.g_etcd_mktemp.stdout }}" + etcd_url_scheme: https + etcd_peer_url_scheme: https + etcd_peers_group: oo_etcd_to_config + pre_tasks: + - name: Ensure certificate directory exists + file: + path: "{{ etcd_cert_config_dir }}" + state: directory + - name: Unarchive the tarball on the etcd host + unarchive: + src: "{{ sync_tmpdir }}/{{ etcd_cert_subdir }}.tgz" + dest: "{{ etcd_cert_config_dir }}" + when: etcd_server_certs_missing + roles: + - etcd + - role: nickhammond.logrotate + +# Configure the remaining etcd hosts, skipping the first one we dealt with above. +- name: Configure remaining etcd hosts + hosts: oo_etcd_to_config:!oo_first_etcd vars: sync_tmpdir: "{{ hostvars.localhost.g_etcd_mktemp.stdout }}" etcd_url_scheme: https diff --git a/playbooks/common/openshift-master/config.yml b/playbooks/common/openshift-master/config.yml index 6f86703d6..3d646be64 100644 --- a/playbooks/common/openshift-master/config.yml +++ b/playbooks/common/openshift-master/config.yml @@ -53,6 +53,11 @@ console_use_ssl: "{{ openshift_master_console_use_ssl | default(None) }}" public_console_url: "{{ openshift_master_public_console_url | default(None) }}" portal_net: "{{ openshift_master_portal_net | default(None) }}" + - openshift_facts: + role: hosted + openshift_env: + openshift_hosted_registry_storage_kind: 'nfs' + when: openshift_hosted_registry_storage_kind is not defined and groups.oo_nfs_to_config is defined and groups.oo_nfs_to_config | length > 0 - name: Check status of external etcd certificatees stat: path: "{{ openshift.common.config_base }}/master/{{ item }}" @@ -402,24 +407,20 @@ - name: Configure service accounts hosts: oo_first_master - vars: accounts: ["router", "registry"] - roles: - openshift_serviceaccounts -- name: Create services +- name: Create persistent volumes and services hosts: oo_first_master vars: - attach_registry_volume: "{{ groups.oo_nfs_to_config | length > 0 }}" - pre_tasks: - - set_fact: - nfs_host: "{{ groups.oo_nfs_to_config.0 }}" - registry_volume_path: "{{ hostvars[groups.oo_nfs_to_config.0].openshift.nfs.exports_dir + '/' + hostvars[groups.oo_nfs_to_config.0].openshift.nfs.registry_volume }}" - when: attach_registry_volume | bool + persistent_volumes: "{{ hostvars[groups.oo_first_master.0] | oo_persistent_volumes(groups) }}" + persistent_volume_claims: "{{ hostvars[groups.oo_first_master.0] | oo_persistent_volume_claims }}" roles: + - role: openshift_persistent_volumes + when: persistent_volumes | length > 0 or persistent_volume_claims | length > 0 - role: openshift_router when: openshift.master.infra_nodes is defined - role: openshift_registry - when: openshift.master.infra_nodes is defined and attach_registry_volume | bool + when: openshift.master.infra_nodes is defined and openshift.hosted.registry.storage.kind != None diff --git a/playbooks/common/openshift-nfs/config.yml b/playbooks/common/openshift-nfs/config.yml index e3f5c17ca..ba7530ed7 100644 --- a/playbooks/common/openshift-nfs/config.yml +++ b/playbooks/common/openshift-nfs/config.yml @@ -2,4 +2,5 @@ - name: Configure nfs hosts hosts: oo_nfs_to_config roles: + - role: openshift_facts - role: openshift_storage_nfs diff --git a/playbooks/common/openshift-node/config.yml b/playbooks/common/openshift-node/config.yml index 81ec9ab6d..e07de0e99 100644 --- a/playbooks/common/openshift-node/config.yml +++ b/playbooks/common/openshift-node/config.yml @@ -80,6 +80,7 @@ when: etcd_client_flannel_certs_missing is defined and etcd_client_flannel_certs_missing roles: - role: etcd_certificates + when: openshift_use_flannel | default(false) | bool post_tasks: - name: Create a tarball of the etcd flannel certs command: > diff --git a/playbooks/gce/openshift-cluster/add_nodes.yml b/playbooks/gce/openshift-cluster/add_nodes.yml new file mode 100644 index 000000000..765e03fdc --- /dev/null +++ b/playbooks/gce/openshift-cluster/add_nodes.yml @@ -0,0 +1,43 @@ +--- +- name: Launch instance(s) + hosts: localhost + connection: local + become: no + gather_facts: no + vars_files: + - vars.yml + vars: + oo_extend_env: True + tasks: + - fail: + msg: Deployment type not supported for gce provider yet + when: deployment_type == 'enterprise' + + - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml + vars: + type: "compute" + count: "{{ num_nodes }}" + - include: tasks/launch_instances.yml + vars: + instances: "{{ node_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" + g_sub_host_type: "{{ sub_host_type }}" + gce_machine_type: "{{ lookup('env', 'gce_machine_node_type') | default(lookup('env', 'gce_machine_type'), true) }}" + gce_machine_image: "{{ lookup('env', 'gce_machine_node_image') | default(lookup('env', 'gce_machine_image'), true) }}" + + - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml + vars: + type: "infra" + count: "{{ num_infra }}" + - include: tasks/launch_instances.yml + vars: + instances: "{{ node_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" + g_sub_host_type: "{{ sub_host_type }}" + gce_machine_type: "{{ lookup('env', 'gce_machine_node_type') | default(lookup('env', 'gce_machine_type'), true) }}" + gce_machine_image: "{{ lookup('env', 'gce_machine_node_image') | default(lookup('env', 'gce_machine_image'), true) }}" + +- include: scaleup.yml +- include: list.yml diff --git a/playbooks/gce/openshift-cluster/config.yml b/playbooks/gce/openshift-cluster/config.yml index 455bf6ead..ba37a3a1f 100644 --- a/playbooks/gce/openshift-cluster/config.yml +++ b/playbooks/gce/openshift-cluster/config.yml @@ -1,6 +1,4 @@ --- -# TODO: fix firewall related bug with GCE and origin, since GCE is overriding -# /etc/sysconfig/iptables - include: ../../common/openshift-cluster/config.yml vars_files: - ../../gce/openshift-cluster/vars.yml @@ -13,6 +11,7 @@ openshift_debug_level: "{{ debug_level }}" openshift_deployment_type: "{{ deployment_type }}" openshift_hostname: "{{ gce_private_ip }}" + openshift_registry_selector: 'type=infra' openshift_router_selector: 'type=infra' openshift_infra_nodes: "{{ g_infra_hosts }}" openshift_master_cluster_method: 'native' diff --git a/playbooks/gce/openshift-cluster/join_node.yml b/playbooks/gce/openshift-cluster/join_node.yml deleted file mode 100644 index 75343dffa..000000000 --- a/playbooks/gce/openshift-cluster/join_node.yml +++ /dev/null @@ -1,51 +0,0 @@ ---- -- name: Populate oo_hosts_to_update group - hosts: localhost - connection: local - become: no - gather_facts: no - vars_files: - - vars.yml - - cluster_hosts.yml - tasks: - - name: Evaluate oo_hosts_to_update - add_host: - name: "{{ node_ip }}" - groups: oo_hosts_to_update - ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" - ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" - -- include: ../../common/openshift-cluster/update_repos_and_packages.yml - -- name: Populate oo_masters_to_config host group - hosts: localhost - connection: local - become: no - gather_facts: no - vars_files: - - vars.yml - - cluster_hosts.yml - tasks: - - name: Evaluate oo_nodes_to_config - add_host: - name: "{{ node_ip }}" - ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" - ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" - groups: oo_nodes_to_config - - - name: Evaluate oo_first_master - add_host: - name: "{{ master_hosts | first }}" - ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" - ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" - groups: oo_first_master - when: master_hosts is defined and master_hosts|length > 0 - -#- include: config.yml -- include: ../../common/openshift-node/config.yml - vars: - openshift_cluster_id: "{{ cluster_id }}" - openshift_debug_level: 4 - openshift_deployment_type: "{{ deployment_type }}" - openshift_hostname: "{{ ansible_default_ipv4.address }}" - openshift_node_labels: "{{ lookup('oo_option', 'openshift_node_labels') }} " diff --git a/playbooks/gce/openshift-cluster/launch.yml b/playbooks/gce/openshift-cluster/launch.yml index 562bf8d29..7532a678b 100644 --- a/playbooks/gce/openshift-cluster/launch.yml +++ b/playbooks/gce/openshift-cluster/launch.yml @@ -10,6 +10,17 @@ - fail: msg="Deployment type not supported for gce provider yet" when: deployment_type == 'enterprise' + - include: ../../common/openshift-cluster/tasks/set_etcd_launch_facts.yml + - include: tasks/launch_instances.yml + vars: + instances: "{{ etcd_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" + g_sub_host_type: "default" + gce_machine_type: "{{ lookup('env', 'gce_machine_etcd_type') | default(lookup('env', 'gce_machine_type'), true) }}" + gce_machine_image: "{{ lookup('env', 'gce_machine_etcd_image') | default(lookup('env', 'gce_machine_image'), true) }}" + + - include: ../../common/openshift-cluster/tasks/set_master_launch_facts.yml - include: tasks/launch_instances.yml vars: @@ -43,6 +54,8 @@ cluster: "{{ cluster_id }}" type: "{{ k8s_type }}" g_sub_host_type: "{{ sub_host_type }}" + gce_machine_type: "{{ lookup('env', 'gce_machine_node_type') | default(lookup('env', 'gce_machine_type'), true) }}" + gce_machine_image: "{{ lookup('env', 'gce_machine_node_image') | default(lookup('env', 'gce_machine_image'), true) }}" - add_host: name: "{{ master_names.0 }}" @@ -50,17 +63,5 @@ when: master_names is defined and master_names.0 is defined - include: update.yml -# -#- name: Deploy OpenShift Services -# hosts: service_master -# connection: ssh -# gather_facts: yes -# roles: -# - openshift_registry -# - openshift_router -# -#- include: ../../common/openshift-cluster/create_services.yml -# vars: -# g_svc_master: "{{ service_master }}" - include: list.yml diff --git a/playbooks/gce/openshift-cluster/list.yml b/playbooks/gce/openshift-cluster/list.yml index e67685912..f3004ede9 100644 --- a/playbooks/gce/openshift-cluster/list.yml +++ b/playbooks/gce/openshift-cluster/list.yml @@ -14,7 +14,7 @@ - add_host: name: "{{ item }}" groups: oo_list_hosts - ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" with_items: groups[scratch_group] | default([], true) | difference(['localhost']) | difference(groups.status_terminated | default([], true)) @@ -23,4 +23,4 @@ gather_facts: no tasks: - debug: - msg: "private ip:{{ hostvars[inventory_hostname].gce_private_ip }}" + msg: "public ip: {{ hostvars[inventory_hostname].gce_public_ip }} private ip:{{ hostvars[inventory_hostname].gce_private_ip }}" diff --git a/playbooks/gce/openshift-cluster/service.yml b/playbooks/gce/openshift-cluster/service.yml index 8925de4cb..914f38c1f 100644 --- a/playbooks/gce/openshift-cluster/service.yml +++ b/playbooks/gce/openshift-cluster/service.yml @@ -14,14 +14,14 @@ - add_host: name: "{{ item }}" groups: g_service_nodes - ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" with_items: "{{ node_hosts | default([]) | difference(['localhost']) | difference(groups.status_terminated) }}" - add_host: name: "{{ item }}" groups: g_service_masters - ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" with_items: "{{ master_hosts | default([]) | difference(['localhost']) | difference(groups.status_terminated) }}" diff --git a/playbooks/gce/openshift-cluster/tasks/launch_instances.yml b/playbooks/gce/openshift-cluster/tasks/launch_instances.yml index 488b62eb9..8ebf71cd4 100644 --- a/playbooks/gce/openshift-cluster/tasks/launch_instances.yml +++ b/playbooks/gce/openshift-cluster/tasks/launch_instances.yml @@ -1,7 +1,4 @@ --- -# TODO: when we are ready to go to ansible 1.9+ support only, we can update to -# the gce task to use the disk_auto_delete parameter to avoid having to delete -# the disk as a separate step on termination - name: Launch instance(s) gce: instance_names: "{{ instances }}" @@ -41,7 +38,7 @@ add_host: hostname: "{{ item.name }}" ansible_ssh_host: "{{ item.public_ip }}" - ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" groups: "{{ item.tags | oo_prepend_strings_in_list('tag_') | join(',') }}" gce_public_ip: "{{ item.public_ip }}" diff --git a/playbooks/gce/openshift-cluster/terminate.yml b/playbooks/gce/openshift-cluster/terminate.yml index faa46c0d6..94b4ab14b 100644 --- a/playbooks/gce/openshift-cluster/terminate.yml +++ b/playbooks/gce/openshift-cluster/terminate.yml @@ -10,7 +10,7 @@ - add_host: name: "{{ item }}" groups: oo_hosts_to_terminate - ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" with_items: (groups['tag_clusterid-' ~ cluster_id] | default([])) | difference(['localhost']) diff --git a/playbooks/gce/openshift-cluster/update.yml b/playbooks/gce/openshift-cluster/update.yml index dadceae58..2dc540978 100644 --- a/playbooks/gce/openshift-cluster/update.yml +++ b/playbooks/gce/openshift-cluster/update.yml @@ -12,7 +12,7 @@ add_host: name: "{{ item }}" groups: oo_hosts_to_update - ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" with_items: "{{ g_all_hosts | default([]) }}" diff --git a/playbooks/gce/openshift-cluster/vars.yml b/playbooks/gce/openshift-cluster/vars.yml index f004a9e6b..1ae73fd68 100644 --- a/playbooks/gce/openshift-cluster/vars.yml +++ b/playbooks/gce/openshift-cluster/vars.yml @@ -4,14 +4,14 @@ debug_level: 2 deployment_rhel7_ent_base: image: rhel-7 machine_type: n1-standard-1 - ssh_user: + ssh_user: "{{ lookup('env', 'gce_ssh_user') | default(ansible_ssh_user, true) }}" sudo: yes deployment_vars: origin: - image: preinstalled-slave-50g-v5 + image: centos-7 machine_type: n1-standard-1 - ssh_user: root + ssh_user: "{{ lookup('env', 'gce_ssh_user') | default(ansible_ssh_user, true) }}" sudo: yes online: image: libra-rhel7 diff --git a/playbooks/gce/openshift-cluster/wip.yml b/playbooks/gce/openshift-cluster/wip.yml deleted file mode 100644 index 0e3757546..000000000 --- a/playbooks/gce/openshift-cluster/wip.yml +++ /dev/null @@ -1,27 +0,0 @@ ---- -- name: WIP - hosts: localhost - become: no - connection: local - gather_facts: no - vars_files: - - vars.yml - tasks: - - name: Evaluate oo_masters_for_deploy - add_host: - name: "{{ item }}" - groups: oo_masters_for_deploy - ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" - ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" - with_items: "{{ g_master_hosts | default([]) }}" - -- name: Deploy OpenShift Services - hosts: oo_masters_for_deploy - connection: ssh - gather_facts: yes - user: root - vars_files: - - vars.yml - roles: - - openshift_registry - - openshift_router diff --git a/playbooks/libvirt/openshift-cluster/config.yml b/playbooks/libvirt/openshift-cluster/config.yml index 87ac3acb6..0e003ef67 100644 --- a/playbooks/libvirt/openshift-cluster/config.yml +++ b/playbooks/libvirt/openshift-cluster/config.yml @@ -13,6 +13,7 @@ openshift_cluster_id: "{{ cluster_id }}" openshift_debug_level: "{{ debug_level }}" openshift_deployment_type: "{{ deployment_type }}" + openshift_registry_selector: 'type=infra' openshift_router_selector: 'type=infra' openshift_infra_nodes: "{{ g_infra_hosts }}" openshift_master_cluster_method: 'native' diff --git a/playbooks/openstack/openshift-cluster/config.yml b/playbooks/openstack/openshift-cluster/config.yml index cb7fe0c8a..438d5e24f 100644 --- a/playbooks/openstack/openshift-cluster/config.yml +++ b/playbooks/openstack/openshift-cluster/config.yml @@ -11,6 +11,7 @@ openshift_debug_level: "{{ debug_level }}" openshift_deployment_type: "{{ deployment_type }}" openshift_hostname: "{{ ansible_default_ipv4.address }}" + openshift_registry_selector: 'type=infra' openshift_router_selector: 'type=infra' openshift_infra_nodes: "{{ g_infra_hosts }}" openshift_master_cluster_method: 'native' diff --git a/roles/etcd_common/tasks/main.yml b/roles/etcd_common/tasks/main.yml index cd108495d..be75fdab2 100644 --- a/roles/etcd_common/tasks/main.yml +++ b/roles/etcd_common/tasks/main.yml @@ -5,9 +5,9 @@ - fail: msg: "Interface {{ item.value.etcd_interface }} not found on host {{ item.key }}" when: "'etcd_interface' in item.value and 'interface' not in item.value" - with_dict: etcd_host_int_map + with_dict: etcd_host_int_map | default({}) - fail: msg: IPv4 address not found for {{ item.value.interface.device }} on host {{ item.key }} when: "'ipv4' not in item.value.interface or 'address' not in item.value.interface.ipv4" - with_dict: etcd_host_int_map + with_dict: etcd_host_int_map | default({}) diff --git a/roles/lib_dyn/README.md b/roles/lib_dyn/README.md new file mode 100644 index 000000000..1eec9f81c --- /dev/null +++ b/roles/lib_dyn/README.md @@ -0,0 +1,27 @@ +lib_dyn +========= + +A role containing the dyn_record module for managing DNS records through Dyn's +API + +Requirements +------------ + +The module requires the `dyn` python module for interacting with the Dyn API. +https://github.com/dyninc/dyn-python + +Example Playbook +---------------- + +To make sure the `dyn_record` module is available for use include the role +before it is used. + + - hosts: servers + roles: + - lib_dyn + +License +------- + +Apache + diff --git a/roles/lib_dyn/library/dyn_record.py b/roles/lib_dyn/library/dyn_record.py new file mode 100644 index 000000000..5e088a674 --- /dev/null +++ b/roles/lib_dyn/library/dyn_record.py @@ -0,0 +1,269 @@ +#!/usr/bin/python +# +# (c) 2015, Russell Harrison <rharriso@redhat.com> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +'''Ansible module to manage records in the Dyn Managed DNS service''' +DOCUMENTATION = ''' +--- +module: dyn_record +version_added: "1.9" +short_description: Manage records in the Dyn Managed DNS service. +description: + - "Manages DNS records via the REST API of the Dyn Managed DNS service. It + - "handles records only; there is no manipulation of zones or account support" + - "yet. See: U(https://help.dyn.com/dns-api-knowledge-base/)" +options: + state: + description: + -"Whether the record should be c(present) or c(absent). Optionally the" + - "state c(list) can be used to return the current value of a record." + required: true + choices: [ 'present', 'absent', 'list' ] + default: present + + customer_name: + description: + - "The Dyn customer name for your account. If not set the value of the" + - "c(DYNECT_CUSTOMER_NAME) environment variable is used." + required: false + default: nil + + user_name: + description: + - "The Dyn user name to log in with. If not set the value of the" + - "c(DYNECT_USER_NAME) environment variable is used." + required: false + default: null + + user_password: + description: + - "The Dyn user's password to log in with. If not set the value of the" + - "c(DYNECT_PASSWORD) environment variable is used." + required: false + default: null + + zone: + description: + - "The DNS zone in which your record is located." + required: true + default: null + + record_fqdn: + description: + - "Fully qualified domain name of the record name to get, create, delete," + - "or update." + required: true + default: null + + record_type: + description: + - "Record type." + required: true + choices: [ 'A', 'AAAA', 'CNAME', 'PTR', 'TXT' ] + default: null + + record_value: + description: + - "Record value. If record_value is not specified; no changes will be" + - "made and the module will fail" + required: false + default: null + + record_ttl: + description: + - 'Record's "Time to live". Number of seconds the record remains cached' + - 'in DNS servers or c(0) to use the default TTL for the zone.' + required: false + default: 0 + +notes: + - The module makes a broad assumption that there will be only one record per "node" (FQDN). + - This module returns record(s) in the "result" element when 'state' is set to 'present'. This value can be be registered and used in your playbooks. + +requirements: [ dyn ] +author: "Russell Harrison" +''' + +try: + IMPORT_ERROR = False + from dyn.tm.session import DynectSession + from dyn.tm.zones import Zone + import dyn.tm.errors + import os + +except ImportError as error: + IMPORT_ERROR = str(error) + +# Each of the record types use a different method for the value. +RECORD_PARAMS = { + 'A' : {'value_param': 'address'}, + 'AAAA' : {'value_param': 'address'}, + 'CNAME' : {'value_param': 'cname'}, + 'PTR' : {'value_param': 'ptrdname'}, + 'TXT' : {'value_param': 'txtdata'} +} + +# You'll notice that the value_param doesn't match the key (records_key) +# in the dict returned from Dyn when doing a dyn_node.get_all_records() +# This is a frustrating lookup dict to allow mapping to the RECORD_PARAMS +# dict so we can lookup other values in it efficiently + +def get_record_type(record_key): + '''Get the record type represented by the keys returned from get_any_records.''' + return record_key.replace('_records', '').upper() + +def get_record_key(record_type): + '''Get the key to look up records in the dictionary returned from get_any_records.''' + return record_type.lower() + '_records' + +def get_any_records(module, node): + '''Get any records for a given node''' + # Lets get a list of the A records for the node + try: + records = node.get_any_records() + except dyn.tm.errors.DynectGetError as error: + if 'Not in zone' in str(error): + # The node isn't in the zone so we'll return an empty dictionary + return {} + else: + # An unknown error happened so we'll need to return it. + module.fail_json(msg='Unable to get records', + error=str(error)) + + # Return a dictionary of the record objects + return records + +def get_record_values(records): + '''Get the record values for each record returned by get_any_records.''' + # This simply returns the values from a dictionary of record objects + ret_dict = {} + for key in records.keys(): + record_type = get_record_type(key) + record_value_param = RECORD_PARAMS[record_type]['value_param'] + ret_dict[key] = [getattr(elem, record_value_param) for elem in records[key]] + return ret_dict + +def main(): + '''Ansible module for managing Dyn DNS records.''' + module = AnsibleModule( + argument_spec=dict( + state=dict(required=True, choices=['present', 'absent', 'list']), + customer_name=dict(default=os.environ.get('DYNECT_CUSTOMER_NAME', None), type='str'), + user_name=dict(default=os.environ.get('DYNECT_USER_NAME', None), type='str', no_log=True), + user_password=dict(default=os.environ.get('DYNECT_PASSWORD', None), type='str', no_log=True), + zone=dict(required=True), + record_fqdn=dict(required=False), + record_type=dict(required=False, choices=[ + 'A', 'AAAA', 'CNAME', 'PTR', 'TXT']), + record_value=dict(required=False), + record_ttl=dict(required=False, default=0, type='int'), + ), + required_together=( + ['record_fqdn', 'record_value', 'record_ttl', 'record_type'] + ) + ) + + if IMPORT_ERROR: + module.fail_json(msg="Unable to import dyn module: https://pypi.python.org/pypi/dyn", + error=IMPORT_ERROR) + + # Start the Dyn session + try: + _ = DynectSession(module.params['customer_name'], + module.params['user_name'], + module.params['user_password']) + except dyn.tm.errors.DynectAuthError as error: + module.fail_json(msg='Unable to authenticate with Dyn', + error=str(error)) + + # Retrieve zone object + try: + dyn_zone = Zone(module.params['zone']) + except dyn.tm.errors.DynectGetError as error: + if 'No such zone' in str(error): + module.fail_json( + msg="Not a valid zone for this account", + zone=module.params['zone'] + ) + else: + module.fail_json(msg="Unable to retrieve zone", + error=str(error)) + + + # To retrieve the node object we need to remove the zone name from the FQDN + dyn_node_name = module.params['record_fqdn'].replace('.' + module.params['zone'], '') + + # Retrieve the zone object from dyn + dyn_zone = Zone(module.params['zone']) + + # Retrieve the node object from dyn + dyn_node = dyn_zone.get_node(node=dyn_node_name) + + # All states will need a list of the exiting records for the zone. + dyn_node_records = get_any_records(module, dyn_node) + + if module.params['state'] == 'list': + module.exit_json(changed=False, + records=get_record_values( + dyn_node_records, + )) + + if module.params['state'] == 'present': + + # First get a list of existing records for the node + values = get_record_values(dyn_node_records) + value_key = get_record_key(module.params['record_type']) + + # Check to see if the record is already in place before doing anything. + if (dyn_node_records and + dyn_node_records[value_key][0].ttl == module.params['record_ttl'] and + module.params['record_value'] in values[value_key]): + + module.exit_json(changed=False) + + + # Working on the assumption that there is only one record per + # node we will first delete the node if there are any records before + # creating the correct record + if dyn_node_records: + dyn_node.delete() + + # Now lets create the correct node entry. + dyn_zone.add_record(dyn_node_name, + module.params['record_type'], + module.params['record_value'], + module.params['record_ttl'] + ) + + # Now publish the zone since we've updated it. + dyn_zone.publish() + module.exit_json(changed=True, + msg="Created node %s in zone %s" % (dyn_node_name, module.params['zone'])) + + if module.params['state'] == 'absent': + # If there are any records present we'll want to delete the node. + if dyn_node_records: + dyn_node.delete() + # Publish the zone since we've modified it. + dyn_zone.publish() + module.exit_json(changed=True, + msg="Removed node %s from zone %s" % (dyn_node_name, module.params['zone'])) + else: + module.exit_json(changed=False) + +# Ansible tends to need a wild card import so we'll use it here +# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled +from ansible.module_utils.basic import * +if __name__ == '__main__': + main() diff --git a/roles/lib_dyn/meta/main.yml b/roles/lib_dyn/meta/main.yml new file mode 100644 index 000000000..5475c6971 --- /dev/null +++ b/roles/lib_dyn/meta/main.yml @@ -0,0 +1,33 @@ +--- +galaxy_info: + author: Russell Harrison + description: A role to provide the dyn_record module + company: Red Hat, Inc. + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + license: Apache + min_ansible_version: 1.9 + platforms: + - name: EL + versions: + - 7 + #- name: Fedora + # versions: + # - 19 + # - 20 + # - 21 + # - 22 + # Below are all categories currently available. Just as with + # the platforms above, uncomment those that apply to your role. + categories: + - networking +dependencies: [] + # List your role dependencies here, one per line. + # Be sure to remove the '[]' above if you add dependencies + # to this list. + # + # No role dependencies at this time. The module contained in this role does + # require the dyn python module. + # https://pypi.python.org/pypi/dyn + diff --git a/roles/lib_dyn/tasks/main.yml b/roles/lib_dyn/tasks/main.yml new file mode 100644 index 000000000..9b3b1b0b9 --- /dev/null +++ b/roles/lib_dyn/tasks/main.yml @@ -0,0 +1,5 @@ +--- +# tasks file for lib_dyn + +- name: Make sure python-dyn is installed + yum: name=python-dyn state=present diff --git a/roles/openshift_common/tasks/main.yml b/roles/openshift_common/tasks/main.yml index ff8c3b50f..98b0b11ea 100644 --- a/roles/openshift_common/tasks/main.yml +++ b/roles/openshift_common/tasks/main.yml @@ -39,11 +39,15 @@ action: "{{ ansible_pkg_mgr }} name={{ openshift.common.service_type }}{{ openshift_version | default('') }} state=present" when: not openshift.common.is_containerized | bool -- name: Set version facts +# This invocation also updates the version facts which are necessary +# for setting the hostname below. +- name: openshift_facts openshift_facts: + role: hosted + openshift_env: "{{ hostvars[inventory_hostname] | oo_openshift_env }}" - # For enterprise versions < 3.1 and origin versions < 1.1 we want to set the - # hostname by default. +# For enterprise versions < 3.1 and origin versions < 1.1 we want to set the +# hostname by default. - set_fact: set_hostname_default: "{{ not openshift.common.version_greater_than_3_1_or_1_1 }}" diff --git a/roles/openshift_facts/library/openshift_facts.py b/roles/openshift_facts/library/openshift_facts.py index 40e54d706..85c8abdf0 100755 --- a/roles/openshift_facts/library/openshift_facts.py +++ b/roles/openshift_facts/library/openshift_facts.py @@ -957,12 +957,12 @@ def merge_facts(orig, new, additive_facts_to_overwrite): # Fact is additive so we'll combine orig and new. if isinstance(value, list) and isinstance(new[key], list): new_fact = [] - for item in copy.deepcopy(value) + copy.copy(new[key]): + for item in copy.deepcopy(value) + copy.deepcopy(new[key]): if item not in new_fact: new_fact.append(item) facts[key] = new_fact else: - facts[key] = copy.copy(new[key]) + facts[key] = copy.deepcopy(new[key]) else: facts[key] = copy.deepcopy(value) new_keys = set(new.keys()) - set(orig.keys()) @@ -1108,9 +1108,11 @@ class OpenShiftFacts(object): Raises: OpenShiftFactsUnsupportedRoleError: """ - known_roles = ['common', 'master', 'node', 'etcd', 'nfs'] + known_roles = ['common', 'master', 'node', 'etcd', 'hosted'] - def __init__(self, role, filename, local_facts, additive_facts_to_overwrite=False): + # Disabling too-many-arguments, this should be cleaned up as a TODO item. + # pylint: disable=too-many-arguments + def __init__(self, role, filename, local_facts, additive_facts_to_overwrite=False, openshift_env=None): self.changed = False self.filename = filename if role not in self.known_roles: @@ -1119,9 +1121,9 @@ class OpenShiftFacts(object): ) self.role = role self.system_facts = ansible_facts(module) - self.facts = self.generate_facts(local_facts, additive_facts_to_overwrite) + self.facts = self.generate_facts(local_facts, additive_facts_to_overwrite, openshift_env) - def generate_facts(self, local_facts, additive_facts_to_overwrite): + def generate_facts(self, local_facts, additive_facts_to_overwrite, openshift_env): """ Generate facts Args: @@ -1133,7 +1135,7 @@ class OpenShiftFacts(object): Returns: dict: The generated facts """ - local_facts = self.init_local_facts(local_facts, additive_facts_to_overwrite) + local_facts = self.init_local_facts(local_facts, additive_facts_to_overwrite, openshift_env) roles = local_facts.keys() defaults = self.get_defaults(roles) @@ -1205,10 +1207,23 @@ class OpenShiftFacts(object): iptables_sync_period='5s', set_node_ip=False) defaults['node'] = node - if 'nfs' in roles: - nfs = dict(exports_dir='/var/export', registry_volume='regvol', - export_options='*(rw,sync,all_squash)') - defaults['nfs'] = nfs + defaults['hosted'] = dict( + registry=dict( + storage=dict( + kind=None, + volume=dict( + name='registry', + size='5Gi' + ), + nfs=dict( + directory='/exports', + options='*(rw,root_squash)'), + host=None, + access_modes=['ReadWriteMany'], + create_pv=True + ) + ) + ) return defaults @@ -1287,7 +1302,9 @@ class OpenShiftFacts(object): ) return provider_facts - def init_local_facts(self, facts=None, additive_facts_to_overwrite=False): + # Disabling too-many-branches. This should be cleaned up as a TODO item. + #pylint: disable=too-many-branches + def init_local_facts(self, facts=None, additive_facts_to_overwrite=False, openshift_env=None): """ Initialize the provider facts Args: @@ -1300,10 +1317,27 @@ class OpenShiftFacts(object): local facts """ changed = False - facts_to_set = {self.role: dict()} + + facts_to_set = dict() + if facts is not None: facts_to_set[self.role] = facts + if openshift_env != {} and openshift_env != None: + for fact, value in openshift_env.iteritems(): + oo_env_facts = dict() + current_level = oo_env_facts + keys = fact.split('_')[1:] + if keys[0] != self.role: + continue + for key in keys: + if key == keys[-1]: + current_level[key] = value + elif key not in current_level: + current_level[key] = dict() + current_level = current_level[key] + facts_to_set = merge_facts(facts_to_set, oo_env_facts, []) + local_facts = get_local_facts_from_file(self.filename) for arg in ['labels', 'annotations']: @@ -1314,11 +1348,12 @@ class OpenShiftFacts(object): new_local_facts = merge_facts(local_facts, facts_to_set, additive_facts_to_overwrite) for facts in new_local_facts.values(): keys_to_delete = [] - for fact, value in facts.iteritems(): - if value == "" or value is None: - keys_to_delete.append(fact) - for key in keys_to_delete: - del facts[key] + if isinstance(facts, dict): + for fact, value in facts.iteritems(): + if value == "" or value is None: + keys_to_delete.append(fact) + for key in keys_to_delete: + del facts[key] if new_local_facts != local_facts: self.validate_local_facts(new_local_facts) @@ -1406,6 +1441,7 @@ def main(): choices=OpenShiftFacts.known_roles), local_facts=dict(default=None, type='dict', required=False), additive_facts_to_overwrite=dict(default=[], type='list', required=False), + openshift_env=dict(default={}, type='dict', required=False) ), supports_check_mode=True, add_file_common_args=True, @@ -1414,9 +1450,15 @@ def main(): role = module.params['role'] local_facts = module.params['local_facts'] additive_facts_to_overwrite = module.params['additive_facts_to_overwrite'] + openshift_env = module.params['openshift_env'] + fact_file = '/etc/ansible/facts.d/openshift.fact' - openshift_facts = OpenShiftFacts(role, fact_file, local_facts, additive_facts_to_overwrite) + openshift_facts = OpenShiftFacts(role, + fact_file, + local_facts, + additive_facts_to_overwrite, + openshift_env) file_params = module.params.copy() file_params['path'] = fact_file diff --git a/roles/openshift_persistent_volumes/README.md b/roles/openshift_persistent_volumes/README.md new file mode 100644 index 000000000..34ae89536 --- /dev/null +++ b/roles/openshift_persistent_volumes/README.md @@ -0,0 +1,60 @@ +OpenShift NFS Server +==================== + +OpenShift Persistent Volumes + +Requirements +------------ + +Role Variables +-------------- + +From this role: +| Name | Default value | | +|--------------------------|---------------|-------------------------------------------------------------------------------------| +| persistent_volumes | [] | List of persistent volume dictionaries, keys: name, capacity, access_modes, storage | +| persistent_volume_claims | [] | List of persistent volume claim dictionaries, keys: name, capacity, access_modes | + + +From openshift_common: +| Name | Default Value | | +|-------------------------------|----------------|----------------------------------------| +| openshift_debug_level | 2 | Global openshift debug log verbosity | + + +Dependencies +------------ + + +Example Playbook +---------------- + +- name: Create persistent volumes/claims + hosts: oo_first_master + vars: + persistent_volumes: + - name: "registry-volume" + capacity: "5Gi" + access_modes: + - "ReadWriteMany" + storage: + nfs: + server: "nfs.example.com" + path: "/var/exports/registry" + persistent_volume_claims: + - name: "registry-claim" + capacity: "5Gi" + access_modes: + - "ReadWriteMany" + roles: + - role: openshift_persistent_volumes + +License +------- + +Apache License, Version 2.0 + +Author Information +------------------ + +Andrew Butcher (abutcher@redhat.com) diff --git a/roles/openshift_persistent_volumes/meta/main.yml b/roles/openshift_persistent_volumes/meta/main.yml new file mode 100644 index 000000000..d9f6fc01a --- /dev/null +++ b/roles/openshift_persistent_volumes/meta/main.yml @@ -0,0 +1,13 @@ +--- +galaxy_info: + author: Andrew Butcher + description: OpenShift Persistent Volumes + company: Red Hat, Inc. + license: Apache License, Version 2.0 + min_ansible_version: 1.9 + platforms: + - name: EL + versions: + - 7 +dependencies: +- { role: openshift_common } diff --git a/roles/openshift_persistent_volumes/tasks/main.yml b/roles/openshift_persistent_volumes/tasks/main.yml new file mode 100644 index 000000000..2455fc792 --- /dev/null +++ b/roles/openshift_persistent_volumes/tasks/main.yml @@ -0,0 +1,50 @@ +--- +- name: Create temp directory for volume definitions + command: mktemp -d /tmp/openshift-ansible-XXXXXXX + register: mktemp + changed_when: False + +- name: Copy the admin client config(s) + command: > + cp {{ openshift_master_config_dir }}/admin.kubeconfig {{ mktemp.stdout }}/admin.kubeconfig + changed_when: False + +- name: Deploy PersistentVolume definitions + template: + dest: "{{ mktemp.stdout }}/persistent-volumes.yml" + src: persistent-volume.yml.j2 + when: persistent_volumes | length > 0 + changed_when: False + +- name: Create PersistentVolumes + command: > + {{ openshift.common.client_binary }} create + -f {{ mktemp.stdout }}/persistent-volumes.yml + --config={{ mktemp.stdout }}/admin.kubeconfig + register: pv_create_output + when: persistent_volumes | length > 0 + failed_when: ('already exists' not in pv_create_output.stderr if pv_create_output.stderr else False) or ('created' not in pv_create_output.stdout if pv_create_output.stdout else False) + changed_when: ('created' in pv_create_output.stdout) + +- name: Deploy PersistentVolumeClaim definitions + template: + dest: "{{ mktemp.stdout }}/persistent-volume-claims.yml" + src: persistent-volume-claim.yml.j2 + when: persistent_volume_claims | length > 0 + changed_when: False + +- name: Create PersistentVolumeClaims + command: > + {{ openshift.common.client_binary }} create + -f {{ mktemp.stdout }}/persistent-volume-claims.yml + --config={{ mktemp.stdout }}/admin.kubeconfig + register: pvc_create_output + when: persistent_volume_claims | length > 0 + failed_when: ('already exists' not in pvc_create_output.stderr if pvc_create_output.stderr else False) or ('created' not in pvc_create_output.stdout if pvc_create_output.stdout else False) + changed_when: ('created' in pvc_create_output.stdout) + +- name: Delete temp directory + file: + name: "{{ mktemp.stdout }}" + state: absent + changed_when: False diff --git a/roles/openshift_persistent_volumes/templates/persistent-volume-claim.yml.j2 b/roles/openshift_persistent_volumes/templates/persistent-volume-claim.yml.j2 new file mode 100644 index 000000000..58b3e1c67 --- /dev/null +++ b/roles/openshift_persistent_volumes/templates/persistent-volume-claim.yml.j2 @@ -0,0 +1,14 @@ +--- +apiVersion: "v1" +kind: "List" +items: +{% for claim in persistent_volume_claims %} +- kind: "PersistentVolumeClaim" + metadata: + name: "{{ claim.name }}" + spec: + accessModes: {{ claim.access_modes | to_padded_yaml(2, 2) }} + resources: + requests: + storage: "{{ claim.capacity }}" +{% endfor %} diff --git a/roles/openshift_persistent_volumes/templates/persistent-volume.yml.j2 b/roles/openshift_persistent_volumes/templates/persistent-volume.yml.j2 new file mode 100644 index 000000000..5714b6b0d --- /dev/null +++ b/roles/openshift_persistent_volumes/templates/persistent-volume.yml.j2 @@ -0,0 +1,14 @@ +--- +apiVersion: v1 +kind: List +items: +{% for volume in persistent_volumes %} +- kind: PersistentVolume + metadata: + name: "{{ volume.name }}" + spec: + capacity: + storage: "{{ volume.capacity }}" + accessModes: {{ volume.access_modes | to_padded_yaml(2, 2) }} + {{ volume.storage.keys()[0] }}: {{ volume.storage[volume.storage.keys()[0]] | to_padded_yaml(3, 2) }} +{% endfor %} diff --git a/roles/openshift_persistent_volumes/vars/main.yml b/roles/openshift_persistent_volumes/vars/main.yml new file mode 100644 index 000000000..9967e26f4 --- /dev/null +++ b/roles/openshift_persistent_volumes/vars/main.yml @@ -0,0 +1,2 @@ +--- +openshift_master_config_dir: "{{ openshift.common.config_base }}/master" diff --git a/roles/openshift_registry/defaults/main.yml b/roles/openshift_registry/defaults/main.yml new file mode 100644 index 000000000..17a0d5301 --- /dev/null +++ b/roles/openshift_registry/defaults/main.yml @@ -0,0 +1,2 @@ +--- +registry_volume_claim: 'registry-claim' diff --git a/roles/openshift_registry/tasks/main.yml b/roles/openshift_registry/tasks/main.yml index 2804e8f2e..1eeec2fbb 100644 --- a/roles/openshift_registry/tasks/main.yml +++ b/roles/openshift_registry/tasks/main.yml @@ -1,28 +1,24 @@ --- -- set_fact: _oreg_images="--images='{{ openshift.master.registry_url }}'" - -- set_fact: _oreg_selector="--selector='{{ openshift.master.registry_selector }}'" - - name: Deploy OpenShift Registry command: > {{ openshift.common.admin_binary }} registry - --create --service-account=registry {{ _oreg_selector }} - --credentials={{ openshift_master_config_dir }}/openshift-registry.kubeconfig {{ _oreg_images }} - register: _oreg_results - changed_when: "'service exists' not in _oreg_results.stdout" + --create --replicas={{ openshift.master.infra_nodes | length }} + --service-account=registry {{ oreg_selector }} + --credentials={{ openshift_master_config_dir }}/openshift-registry.kubeconfig {{ oreg_images }} + register: oreg_results + changed_when: "'service exists' not in oreg_results.stdout" -- name: Determine if nfs volume is already attached +- name: Determine if volume is already attached to dc/docker-registry command: "{{ openshift.common.client_binary }} get -o template dc/docker-registry --template=\\{\\{.spec.template.spec.volumes\\}\\}" + changed_when: false register: registry_volumes_output - when: attach_registry_volume | bool - set_fact: - volume_already_attached: "{{ 'server:' + nfs_host in registry_volumes_output.stdout and 'path:' + registry_volume_path in registry_volumes_output.stdout }}" - when: attach_registry_volume | bool + volume_attached: "{{ registry_volume_claim in registry_volumes_output.stdout }}" -- name: Add nfs volume to dc/docker-registry +- name: Add volume to dc/docker-registry command: > {{ openshift.common.client_binary }} volume dc/docker-registry - --add --overwrite --name=registry-storage --mount-path=/registry - --source='{"nfs": {"server": "{{ nfs_host }}", "path": "{{ registry_volume_path }}"}}' - when: attach_registry_volume | bool and not volume_already_attached | bool + --add --overwrite -t persistentVolumeClaim --claim-name={{ registry_volume_claim }} + --name=registry-storage + when: not volume_attached | bool diff --git a/roles/openshift_registry/vars/main.yml b/roles/openshift_registry/vars/main.yml index 9967e26f4..306350a5a 100644 --- a/roles/openshift_registry/vars/main.yml +++ b/roles/openshift_registry/vars/main.yml @@ -1,2 +1,4 @@ --- openshift_master_config_dir: "{{ openshift.common.config_base }}/master" +oreg_images: "--images='{{ openshift.master.registry_url }}'" +oreg_selector: "--selector='{{ openshift.master.registry_selector }}'" diff --git a/roles/openshift_storage_nfs/README.md b/roles/openshift_storage_nfs/README.md index 548e146cb..dd988b849 100644 --- a/roles/openshift_storage_nfs/README.md +++ b/roles/openshift_storage_nfs/README.md @@ -15,11 +15,11 @@ Role Variables -------------- From this role: -| Name | Default value | | -|-------------------------------|-----------------------|--------------------------------------------------| -| openshift_nfs_exports_dir | /var/export | Root export directory. | -| openshift_nfs_registry_volume | regvol | Registry volume within openshift_nfs_exports_dir | -| openshift_nfs_export_options | *(rw,sync,all_squash) | NFS options for configured exports. | +| Name | Default value | | +|-------------------------------------------------|-----------------------|-------------------------------------------------------------| +| openshift_hosted_registry_storage_nfs_directory | /exports | Root export directory. | +| openshift_hosted_registry_storage_volume_name | registry | Registry volume within openshift_hosted_registry_volume_dir | +| openshift_hosted_registry_storage_nfs_options | *(rw,root_squash) | NFS options for configured exports. | From openshift_common: @@ -31,8 +31,6 @@ From openshift_common: Dependencies ------------ - - Example Playbook ---------------- diff --git a/roles/openshift_storage_nfs/defaults/main.yml b/roles/openshift_storage_nfs/defaults/main.yml index e25062c00..5f6893129 100644 --- a/roles/openshift_storage_nfs/defaults/main.yml +++ b/roles/openshift_storage_nfs/defaults/main.yml @@ -1,7 +1,13 @@ --- -exports_dir: /var/export -registry_volume: regvol -export_options: '*(rw,sync,all_squash)' +openshift: + hosted: + registry: + storage: + nfs: + directory: "/exports" + options: "*(rw,root_squash)" + volume: + name: "registry" os_firewall_use_firewalld: False os_firewall_allow: - service: nfs diff --git a/roles/openshift_storage_nfs/tasks/main.yml b/roles/openshift_storage_nfs/tasks/main.yml index 64b121ade..fdd7bd3f1 100644 --- a/roles/openshift_storage_nfs/tasks/main.yml +++ b/roles/openshift_storage_nfs/tasks/main.yml @@ -1,31 +1,34 @@ --- -- name: Set nfs facts - openshift_facts: - role: nfs - local_facts: - exports_dir: "{{ openshift_nfs_exports_dir | default(None) }}" - export_options: "{{ openshift_nfs_export_options | default(None) }}" - registry_volume: "{{ openshift_nfs_registry_volume | default(None) }}" - - name: Install nfs-utils yum: pkg: nfs-utils state: present +- name: Configure NFS + lineinfile: + dest: /etc/sysconfig/nfs + regexp: '^RPCNFSDARGS=.*$' + line: 'RPCNFSDARGS="-N 2 -N 3"' + register: nfs_config + +- name: Restart nfs-config + service: name=nfs-config state=restarted + when: nfs_config | changed + - name: Ensure exports directory exists file: - path: "{{ openshift.nfs.exports_dir }}" + path: "{{ openshift.hosted.registry.storage.nfs.directory }}" state: directory - name: Ensure export directories exist file: - path: "{{ openshift.nfs.exports_dir }}/{{ item }}" + path: "{{ openshift.hosted.registry.storage.nfs.directory }}/{{ item }}" state: directory mode: 0777 owner: nfsnobody group: nfsnobody with_items: - - "{{ openshift.nfs.registry_volume }}" + - "{{ openshift.hosted.registry.storage.volume.name }}" - name: Configure exports template: @@ -44,6 +47,4 @@ - nfs-server - set_fact: - nfs_service_status_changed: "{{ True in (start_result.results - | map(attribute='changed') - | list) }}" + nfs_service_status_changed: "{{ start_result | changed }}" diff --git a/roles/openshift_storage_nfs/templates/exports.j2 b/roles/openshift_storage_nfs/templates/exports.j2 index 702473040..c1e1994b0 100644 --- a/roles/openshift_storage_nfs/templates/exports.j2 +++ b/roles/openshift_storage_nfs/templates/exports.j2 @@ -1 +1 @@ -{{ openshift.nfs.exports_dir }}/{{ openshift.nfs.registry_volume }} {{ openshift.nfs.export_options }} +{{ openshift.hosted.registry.storage.nfs.directory }}/{{ openshift.hosted.registry.storage.volume.name }} {{ openshift.hosted.registry.storage.nfs.options }} diff --git a/roles/os_zabbix/vars/template_openshift_node.yml b/roles/os_zabbix/vars/template_openshift_node.yml index ce28b1048..ff65ef158 100644 --- a/roles/os_zabbix/vars/template_openshift_node.yml +++ b/roles/os_zabbix/vars/template_openshift_node.yml @@ -20,6 +20,12 @@ g_template_openshift_node: applications: - Openshift Node + - key: openshift.node.ovs.stray.rules + description: Number of OVS stray rules found/removed + type: int + applications: + - Openshift Node + ztriggers: - name: 'Openshift Node process not running on {HOST.NAME}' expression: '{Template Openshift Node:openshift.node.process.count.max(#3)}<1' diff --git a/utils/src/ooinstall/cli_installer.py b/utils/src/ooinstall/cli_installer.py index 1aacf3a4b..3046d4d58 100644 --- a/utils/src/ooinstall/cli_installer.py +++ b/utils/src/ooinstall/cli_installer.py @@ -45,6 +45,15 @@ passwordless sudo access. click.echo(message) return click.prompt('User for ssh access', default='root') +def get_master_routingconfig_subdomain(): + click.clear() + message = """ +You might want to override the default subdomain uses for exposed routes. If you don't know what +this is, use the default value. +""" + 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: @@ -498,6 +507,10 @@ https://docs.openshift.com/enterprise/latest/admin_guide/install/prerequisites.h oo_cfg.hosts = collect_hosts(oo_cfg) click.clear() + if not oo_cfg.settings.get('master_routingconfig_subdomain', None): + oo_cfg.settings['master_routingconfig_subdomain'] = get_master_routingconfig_subdomain() + click.clear() + return oo_cfg diff --git a/utils/src/ooinstall/openshift_ansible.py b/utils/src/ooinstall/openshift_ansible.py index c0d115fdc..cbb6f33e1 100644 --- a/utils/src/ooinstall/openshift_ansible.py +++ b/utils/src/ooinstall/openshift_ansible.py @@ -114,6 +114,9 @@ def write_inventory_vars(base_inventory, multiple_masters, proxy): 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['master_routingconfig_subdomain']: + base_inventory.write("osm_default_subdomain={}\n".format(CFG.settings['master_routingconfig_subdomain'])) + def write_host(host, inventory, schedulable=None): diff --git a/utils/test/cli_installer_tests.py b/utils/test/cli_installer_tests.py index 72e8521d0..baab5d56f 100644 --- a/utils/test/cli_installer_tests.py +++ b/utils/test/cli_installer_tests.py @@ -102,6 +102,7 @@ hosts: 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 @@ -228,6 +229,7 @@ hosts: 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 diff --git a/utils/test/fixture.py b/utils/test/fixture.py index be759578a..1b1c2e5c2 100644 --- a/utils/test/fixture.py +++ b/utils/test/fixture.py @@ -11,6 +11,7 @@ from click.testing import CliRunner SAMPLE_CONFIG = """ variant: %s ansible_ssh_user: root +master_routingconfig_subdomain: example.com hosts: - connect_to: 10.0.0.1 ip: 10.0.0.1 @@ -196,6 +197,8 @@ def build_input(ssh_user=None, hosts=None, variant_num=None, inputs.append(master_lb[0]) inputs.append('y' if master_lb[1] else 'n') + inputs.append('example.com') + # TODO: support option 2, fresh install if add_nodes: if schedulable_masters_ok: @@ -228,4 +231,3 @@ def build_input(ssh_user=None, hosts=None, variant_num=None, ]) return '\n'.join(inputs) - |