diff --git a/Makefile b/Makefile index d992246dd6..e8f57436f1 100644 --- a/Makefile +++ b/Makefile @@ -53,11 +53,11 @@ new_role: create_new_role role_molecule ## Create a new Ansible role and related ##@ Setup steps .PHONY: setup_tests setup_tests: ## Setup the environment - bash scripts/setup_env + bash scripts/setup_env 2>&1 | tee $(LOG_DIR)/setup_env.log .PHONY: setup_molecule setup_molecule: setup_tests ## Setup molecule environment - bash scripts/setup_molecule + bash scripts/setup_molecule 2>&1 | tee $(LOG_DIR)/setup_molecule.log ##@ General testing .PHONY: tests diff --git a/ci/playbooks/pre-ci-bootstrap.yml b/ci/playbooks/bootstrap-networking-mapper.yml similarity index 94% rename from ci/playbooks/pre-ci-bootstrap.yml rename to ci/playbooks/bootstrap-networking-mapper.yml index ccd448c7d4..e4120002db 100644 --- a/ci/playbooks/pre-ci-bootstrap.yml +++ b/ci/playbooks/bootstrap-networking-mapper.yml @@ -31,6 +31,7 @@ ~/test-python/bin/ansible-playbook {{ ansible_user_dir }}/networking_mapper.yml -i {{ ansible_user_dir }}/ci-framework-data/artifacts/zuul_inventory.yml -e @scenarios/centos-9/base.yml + -e cifmw_networking_mapper_ifaces_info_path=/etc/ci/env/interfaces-info.yml -e "@{{ ansible_user_dir }}/ci-framework-data/artifacts/parameters/zuul-params.yml" {% if nodepool is defined %} -e "@{{ ansible_user_dir }}/ci-framework-data/artifacts/nodepool_params.yml" diff --git a/ci/playbooks/molecule-test.yml b/ci/playbooks/molecule-test.yml index d95da5bbdb..871988d9f3 100644 --- a/ci/playbooks/molecule-test.yml +++ b/ci/playbooks/molecule-test.yml @@ -1,8 +1,16 @@ --- - name: "Run ci/playbooks/molecule-test.yml" hosts: "{{ cifmw_zuul_target_host | default('controller') }}" - gather_facts: true + gather_facts: false tasks: + - name: Gather required facts + ansible.builtin.setup: + gather_subset: + - "!all" + - "!min" + - "user_dir" + - "env" + - name: Load environment var if instructed to when: - cifmw_reproducer_molecule_env_file is defined diff --git a/ci/playbooks/pre-doc.yml b/ci/playbooks/pre-doc.yml index 2d0b9e2d49..4bd9ac6a67 100644 --- a/ci/playbooks/pre-doc.yml +++ b/ci/playbooks/pre-doc.yml @@ -43,7 +43,7 @@ - name: Download and extract golang ansible.builtin.unarchive: - src: "https://golang.org/dl/go{{ go_version | default('1.20.14') }}.linux-amd64.tar.gz" + src: "https://golang.org/dl/go{{ go_version | default('1.21.13') }}.linux-amd64.tar.gz" dest: "/usr/local" remote_src: true extra_opts: diff --git a/deploy-ocp.yml b/deploy-ocp.yml index d3d65100ff..b1f0062796 100644 --- a/deploy-ocp.yml +++ b/deploy-ocp.yml @@ -67,3 +67,21 @@ ansible.builtin.import_role: name: "libvirt_manager" tasks_from: "deploy_layout.yml" + + # Run from the hypervisor + - name: Ensure OCP cluster is stable + vars: + _auth_path: >- + {{ + ( + cifmw_devscripts_repo_dir, + 'ocp', + cifmw_devscripts_config.cluster_name, + 'auth' + ) | ansible.builtin.path_join + }} + cifmw_openshift_adm_op: "stable" + cifmw_openshift_kubeconfig: >- + {{ (_auth_path, 'kubeconfig') | ansible.builtin.path_join }} + ansible.builtin.include_role: + name: openshift_adm diff --git a/docs/dictionary/en-custom.txt b/docs/dictionary/en-custom.txt index 78550f06e8..3b633102e5 100644 --- a/docs/dictionary/en-custom.txt +++ b/docs/dictionary/en-custom.txt @@ -496,6 +496,7 @@ tempestconf testcases testenv timestamper +timesync tldca tls tmp diff --git a/docs/source/usage/01_usage.md b/docs/source/usage/01_usage.md index 0caed9361f..d8bc7418fe 100644 --- a/docs/source/usage/01_usage.md +++ b/docs/source/usage/01_usage.md @@ -66,11 +66,13 @@ are shared among multiple roles: - `cifmw_nolog`: (Bool) Toggle `no_log` value for selected tasks. Defaults to `true` (hiding those logs by default). - `cifmw_parent_scenario`: (String or List(String)) path to existing scenario/parameter file to inherit from. - `cifmw_configure_switches`: (Bool) Specifies whether switches should be configured. Computes in `reproducer.yml` playbook. Defaults to `false`. +- `cifmw_use_ocp_overlay`: (Boolean) Specifies whether OCP nodes deployed via devscripts should use overlay images. Using overlay images speeds up the redeployment when using the reproducer role locally but in CI each job is cleaned up and redeployed. Creating the overlay image takes time so should be disabled when not used. Defaults to `true`. - `cifmw_crc_default_network`: (String) name of the untagged network used to address DNS on the crc node. Default is `default`. - `cifmw_run_operators_compliance_scans`: (Bool) Specifies whether to run operator compliance scans. Defaults to `false`. - `cifmw_run_compute_compliance_scans`: (Bool) Specifies whether to run compliance scans on the first compute. Defaults to `false`. - `cifmw_run_id`: (String) CI Framework run identifier. This is used in libvirt_manager, to add some uniqueness to some types of virtual machines (anything that's not OCP, CRC nor controller). If not set, the Framework will generate a random string for you, and store it on the target host, in `{{ cifmw_basedir }}/artifacts/run-id` +- `cifmw_deploy_architecture_args`: (String) additional args and parameters to pass to the deploy-architecture script. Default is `''`. ```{admonition} Words of caution :class: danger diff --git a/docs/toolbelt-catalog.yaml b/docs/toolbelt-catalog.yaml new file mode 100644 index 0000000000..d2576823f1 --- /dev/null +++ b/docs/toolbelt-catalog.yaml @@ -0,0 +1,41 @@ +# Catalog entry for Backstage [backstage.io] + +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: ci-framework + title: ci-framework + description: | + CI Framework - used for CI, QE and Devs to run OSP 18+ jobs in a converged way + annotations: + github.com/project-slug: openstack-k8s-operators/ci-framework + feedback/type: JIRA + feedback/host: https://issues.redhat.com + jira/project-key: OSPRH + links: + - title: docs + url: https://ci-framework.readthedocs.io/en/latest/ + icon: docs + - title: code + url: https://github.com/openstack-k8s-operators/ci-framework + icon: github + - title: "#osp-podified-ci-support" + url: https://app.slack.com/client/E030G10V24F/C03MD4LG22Z + icon: chat + tags: + - testing + - test-execution + - test-framework + - test-management + - test-reporting + - provisioning + - python + - openstack + - openshift + - cloud + - continuous-integration + namespace: quality-community +spec: + type: tool + owner: group:redhat/openstack-k8s-operators-ci + lifecycle: production diff --git a/hooks/playbooks/fetch_compute_facts.yml b/hooks/playbooks/fetch_compute_facts.yml index f7d5a9532d..96c3c183f8 100644 --- a/hooks/playbooks/fetch_compute_facts.yml +++ b/hooks/playbooks/fetch_compute_facts.yml @@ -26,6 +26,10 @@ - name: Load parameters ansible.builtin.include_vars: dir: "{{ item }}" + ignore_unknown_extensions: true + extensions: + - yaml + - yml loop: - "{{ cifmw_basedir }}/artifacts/parameters" - "/etc/ci/env" diff --git a/playbooks/ceph.yml b/playbooks/ceph.yml index 09ed924786..8bdc4ba86e 100644 --- a/playbooks/ceph.yml +++ b/playbooks/ceph.yml @@ -58,7 +58,7 @@ - name: Distribute SSH keypair to target nodes tags: admin - hosts: "{{ cifmw_ceph_target | default('computes') }}" + hosts: "{{ cifmw_ceph_target | default('computes') }}" gather_facts: false become: true vars: @@ -265,7 +265,12 @@ gather_facts: false vars: _target_hosts: "{{ groups[cifmw_ceph_target | default('computes')] | default([]) }}" - ansible_ssh_private_key_file: "{{ lookup('env', 'ANSIBLE_SSH_PRIVATE_KEY') }}" + _target: "{{ _target_hosts | first }}" + ansible_ssh_private_key_file: >- + {{ + hostvars[_target]['ansible_ssh_private_key_file'] | + default(lookup('env', 'ANSIBLE_SSH_PRIVATE_KEY')) + }} cifmw_cephadm_spec_ansible_host: /tmp/ceph_spec.yml cifmw_cephadm_bootstrap_conf: /tmp/initial_ceph.conf cifmw_ceph_client_vars: /tmp/ceph_client.yml @@ -279,6 +284,7 @@ pg_autoscale_mode: true target_size_ratio: 0.3 application: rbd + trash_purge_enabled: true - name: backups pg_autoscale_mode: true target_size_ratio: 0.1 @@ -402,7 +408,7 @@ tasks_from: rgw vars: # cifmw_cephadm_vip is computed or passed as an override via -e @extra.yml - cifmw_cephadm_rgw_vip: "{{ cifmw_cephadm_vip }}/{{ cidr }}" + cifmw_cephadm_rgw_vip: "{{ cifmw_cephadm_vip }}" - name: Configure Monitoring Stack when: cifmw_ceph_daemons_layout.dashboard_enabled | default(false) | bool @@ -449,6 +455,9 @@ ansible.builtin.import_role: name: cifmw_cephadm tasks_from: post + vars: + cifmw_cephadm_dashboard_crt: "{{ cifmw_cephadm_certificate }}" + cifmw_cephadm_dashboard_key: "{{ cifmw_cephadm_key }}" - name: Render Ceph client configuration tags: client diff --git a/plugins/module_utils/net_map/exceptions.py b/plugins/module_utils/net_map/exceptions.py index 2a7fcb806f..eaff49ab8c 100644 --- a/plugins/module_utils/net_map/exceptions.py +++ b/plugins/module_utils/net_map/exceptions.py @@ -6,9 +6,10 @@ class NetworkMappingError(Exception, ansible_encoding.RawConvertibleObject): - def __init__(self, message) -> None: + def __init__(self, message, **kwargs) -> None: super().__init__(message) self.message = message + self.details = kwargs def to_raw(self) -> typing.Dict[str, typing.Any]: return ansible_encoding.decode_ansible_raw(vars(self)) @@ -22,8 +23,9 @@ def __init__( invalid_value=None, parent_name=None, parent_type=None, + **kwargs, ) -> None: - super().__init__(message) + super().__init__(message, **kwargs) self.field = field self.invalid_value = invalid_value self.parent_name = parent_name @@ -31,8 +33,8 @@ def __init__( class HostNetworkRangeCollisionValidationError(NetworkMappingValidationError): - def __init__(self, message, range_1=None, range_2=None) -> None: - super().__init__(message) + def __init__(self, message, range_1=None, range_2=None, **kwargs) -> None: + super().__init__(message, **kwargs) self.range_1 = range_1 self.range_2 = range_2 @@ -48,8 +50,9 @@ def __init__( invalid_value=None, parent_name=None, parent_type=None, + **kwargs, ) -> None: - super().__init__(message) + super().__init__(message, **kwargs) self.field = field self.invalid_value = invalid_value self.parent_name = parent_name diff --git a/plugins/module_utils/net_map/networking_definition.py b/plugins/module_utils/net_map/networking_definition.py index 067b6e6f79..e82bd81524 100644 --- a/plugins/module_utils/net_map/networking_definition.py +++ b/plugins/module_utils/net_map/networking_definition.py @@ -170,6 +170,7 @@ def _validate_fields_one_of( parent_type: str = None, alone_field: str = None, mandatory: bool = False, + **kwargs, ) -> bool: fields_present = any( field_name in raw_definition.keys() for field_name in fields_list @@ -183,6 +184,7 @@ def _validate_fields_one_of( f"at least one of {mandatory_fields} must be provided", parent_name=parent_name, parent_type=parent_type, + **kwargs, ) if alone_field and alone_field in raw_definition: rest = [ @@ -198,6 +200,7 @@ def _validate_fields_one_of( invalid_value=raw_definition[alone_field], parent_name=parent_name, parent_type=parent_type, + **kwargs, ) return True @@ -2100,6 +2103,7 @@ def __parse_raw_net_ranges( parent_name=self.__group_name, parent_type=self.__OBJECT_TYPE_NAME, alone_field=self.__FIELD_NETWORK_RANGE, + network_name=network_definition.name, ) if not ranges_present: return None, None diff --git a/reproducer.yml b/reproducer.yml index 3c7745767c..b3e1b54a2d 100644 --- a/reproducer.yml +++ b/reproducer.yml @@ -89,4 +89,4 @@ poll: 20 delegate_to: controller-0 ansible.builtin.command: - cmd: "/home/zuul/deploy-architecture.sh" + cmd: "/home/zuul/deploy-architecture.sh {{ cifmw_deploy_architecture_args | default('') }}" diff --git a/roles/ci_gen_kustomize_values/README.md b/roles/ci_gen_kustomize_values/README.md index 73d19daa34..4fd81bcb4f 100644 --- a/roles/ci_gen_kustomize_values/README.md +++ b/roles/ci_gen_kustomize_values/README.md @@ -35,6 +35,8 @@ with a message. * `ci_gen_kustomize_fetch_ocp_state`: (Boolean) If true it enables generating CI templates based on the OCP state. Defaults to `true`. * `cifmw_ci_gen_kustomize_values_storage_class_prefix`: (String) Prefix for `storageClass` in generated values.yaml files. Defaults to `"lvms-"` only if `cifmw_use_lvms` is True, otherwise it defaults to `""`. The prefix is prepended to the `cifmw_ci_gen_kustomize_values_storage_class`. It is not recommended to override this value, instead set `cifmw_use_lvms` True or False. * `cifmw_ci_gen_kustomize_values_storage_class`: (String) Value for `storageClass` in generated values.yaml files. Defaults to `"lvms-local-storage"` only if `cifmw_use_lvms` is True, otherwise it defaults to `"local-storage"`. +* `cifmw_ci_gen_kustomize_values_remove_keys_expressions`: (List) Remove keys matching the regular expressions from source ConfigMaps (values.yaml). + Defaults to `["^nodes$", "^node(_[0-9]+)?$"]`. ### Specific parameters for edpm-values This configMap needs some more parameters in order to properly override the `architecture` provided one. diff --git a/roles/ci_gen_kustomize_values/defaults/main.yml b/roles/ci_gen_kustomize_values/defaults/main.yml index 8e1bd7ec35..25b81fc785 100644 --- a/roles/ci_gen_kustomize_values/defaults/main.yml +++ b/roles/ci_gen_kustomize_values/defaults/main.yml @@ -71,6 +71,9 @@ cifmw_ci_gen_kustomize_values_storage_class_prefix: "{{ 'lvms-' if cifmw_use_lvm cifmw_ci_gen_kustomize_values_storage_class: "{{ cifmw_ci_gen_kustomize_values_storage_class_prefix }}local-storage" cifmw_ci_gen_kustomize_values_primary_ip_version: 4 +cifmw_ci_gen_kustomize_values_remove_keys_expressions: + - ^nodes$ + - ^node(_[0-9]+)?$ # Those parameter must be set if you want to edit an "edpm-values" # cifmw_ci_gen_kustomize_values_ssh_authorizedkeys diff --git a/roles/ci_gen_kustomize_values/tasks/generate_snippets.yml b/roles/ci_gen_kustomize_values/tasks/generate_snippets.yml index b42ba876d2..fe6d535786 100644 --- a/roles/ci_gen_kustomize_values/tasks/generate_snippets.yml +++ b/roles/ci_gen_kustomize_values/tasks/generate_snippets.yml @@ -80,8 +80,9 @@ _cifmw_gen_kustomize_values_base_cm_content: >- {{ _config_map_content | - ansible.utils.remove_keys(target=['^nodes?(_[0-9]+)?$'], - matching_parameter='regex') + ansible.utils.remove_keys( + target=cifmw_ci_gen_kustomize_values_remove_keys_expressions, + matching_parameter='regex') }} cacheable: false diff --git a/roles/ci_gen_kustomize_values/templates/bgp/network-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/bgp/network-values/values.yaml.j2 index 2c023b48f7..a900c08826 100644 --- a/roles/ci_gen_kustomize_values/templates/bgp/network-values/values.yaml.j2 +++ b/roles/ci_gen_kustomize_values/templates/bgp/network-values/values.yaml.j2 @@ -5,18 +5,16 @@ lb_tools={}) %} data: {% for host in cifmw_networking_env_definition.instances.keys() -%} -{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() -%} +{% if host is match('^(ocp|crc).*') %} + node_{{ ns.ocp_index }}: + name: {{ cifmw_networking_env_definition.instances[host]['hostname'] }} +{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() %} {% set ns.interfaces = ns.interfaces | combine({network.network_name: (network.parent_interface | default(network.interface_name) ) }, - recursive=true) -%} -{% endfor -%} -{% if host is match('^(ocp|crc).*') %} - node_{{ ns.ocp_index }}: - name: {{ cifmw_networking_env_definition.instances[host]['hostname'] }} -{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() %} + recursive=true) %} {{ network.network_name }}_ip: {{ network.ip_v4 }} {% endfor %} {% set node_net_orig_content = original_content.data.bgp['net-attach-def']['node' ~ ns.ocp_index] %} diff --git a/roles/ci_gen_kustomize_values/templates/bgp_dt01/network-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/bgp_dt01/network-values/values.yaml.j2 index b3642eb868..2c6caa6823 100644 --- a/roles/ci_gen_kustomize_values/templates/bgp_dt01/network-values/values.yaml.j2 +++ b/roles/ci_gen_kustomize_values/templates/bgp_dt01/network-values/values.yaml.j2 @@ -6,20 +6,16 @@ data: {% for host in cifmw_networking_env_definition.instances.keys() -%} {% set hostname = cifmw_networking_env_definition.instances[host]['hostname'] %} -{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() -%} -{% if 'worker-3' != hostname %} +{% if host is match('^(ocp|crc).*') %} + node_{{ ns.ocp_index }}: + name: {{ hostname }} +{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() %} {% set ns.interfaces = ns.interfaces | combine({network.network_name: (network.parent_interface | default(network.interface_name) ) }, - recursive=true) -%} -{% endif %} -{% endfor -%} -{% if host is match('^(ocp|crc).*') %} - node_{{ ns.ocp_index }}: - name: {{ hostname }} -{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() %} + recursive=true) %} {{ network.network_name }}_ip: {{ network.ip_v4 }} {% if 'worker-3' == hostname and 'ctlplane' == network.network_name %} base_if: {{ network.interface_name }} diff --git a/roles/ci_gen_kustomize_values/templates/common/edpm-nodeset-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/common/edpm-nodeset-values/values.yaml.j2 index 92fde75b77..cf676889a4 100644 --- a/roles/ci_gen_kustomize_values/templates/common/edpm-nodeset-values/values.yaml.j2 +++ b/roles/ci_gen_kustomize_values/templates/common/edpm-nodeset-values/values.yaml.j2 @@ -47,9 +47,9 @@ data: {% for net in cifmw_networking_env_definition.instances[instance].networks.keys() %} - name: {{ net }} subnetName: subnet1 + fixedIP: {{ cifmw_networking_env_definition.instances[instance].networks[net][_ipv.ip_vX] }} {% if net is match('ctlplane') %} defaultRoute: true - fixedIP: {{ cifmw_networking_env_definition.instances[instance].networks.ctlplane[_ipv.ip_vX] }} {% endif %} {% endfor %} {% endfor %} diff --git a/roles/ci_gen_kustomize_values/templates/common/network-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/common/network-values/values.yaml.j2 index 1c1df833ea..5f3cf99b28 100644 --- a/roles/ci_gen_kustomize_values/templates/common/network-values/values.yaml.j2 +++ b/roles/ci_gen_kustomize_values/templates/common/network-values/values.yaml.j2 @@ -6,19 +6,17 @@ lb_tools={}) %} data: {% for host in cifmw_networking_env_definition.instances.keys() -%} -{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() -%} -{% set ns.interfaces = ns.interfaces | - combine({network.network_name: (network.parent_interface | - default(network.interface_name) - ) - }, - recursive=true) -%} -{% endfor -%} {% if host is match('^(ocp|crc).*') %} node_{{ ns.ocp_index }}: {% set ns.ocp_index = ns.ocp_index+1 %} name: {{ cifmw_networking_env_definition.instances[host]['hostname'] }} {% for network in cifmw_networking_env_definition.instances[host]['networks'].values() %} +{% set ns.interfaces = ns.interfaces | + combine({network.network_name: (network.parent_interface | + default(network.interface_name) + ) + }, + recursive=true) %} {{ network.network_name }}_ip: {{ network[_ipv.ip_vX] }} {% endfor %} {% endif %} diff --git a/roles/ci_gen_kustomize_values/templates/shiftstack/network-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/shiftstack/network-values/values.yaml.j2 index 685e773bbb..f9b4a4933a 100644 --- a/roles/ci_gen_kustomize_values/templates/shiftstack/network-values/values.yaml.j2 +++ b/roles/ci_gen_kustomize_values/templates/shiftstack/network-values/values.yaml.j2 @@ -4,19 +4,17 @@ data: {% for host in cifmw_networking_env_definition.instances.keys() -%} -{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() -%} -{% set ns.interfaces = ns.interfaces | - combine({network.network_name: (network.parent_interface | - default(network.interface_name) - ) - }, - recursive=true) -%} -{% endfor -%} {% if host is match('^(ocp|crc).*') %} node_{{ ns.ocp_index }}: {% set ns.ocp_index = ns.ocp_index+1 %} name: {{ cifmw_networking_env_definition.instances[host]['hostname'] }} {% for network in cifmw_networking_env_definition.instances[host]['networks'].values() %} +{% set ns.interfaces = ns.interfaces | + combine({network.network_name: (network.parent_interface | + default(network.interface_name) + ) + }, + recursive=true) %} {{ network.network_name }}_ip: {{ network.ip_v4 }} {% endfor %} {% endif %} diff --git a/roles/ci_gen_kustomize_values/templates/uni01alpha/network-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/uni01alpha/network-values/values.yaml.j2 index db5cf61228..11b7f5230a 100644 --- a/roles/ci_gen_kustomize_values/templates/uni01alpha/network-values/values.yaml.j2 +++ b/roles/ci_gen_kustomize_values/templates/uni01alpha/network-values/values.yaml.j2 @@ -6,19 +6,17 @@ lb_tools={}) %} data: {% for host in cifmw_networking_env_definition.instances.keys() -%} -{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() -%} -{% set ns.interfaces = ns.interfaces | - combine({network.network_name: (network.parent_interface | - default(network.interface_name) - ) - }, - recursive=true) -%} -{% endfor -%} {% if host is match('^(ocp|crc).*') %} node_{{ ns.ocp_index }}: {% set ns.ocp_index = ns.ocp_index+1 %} name: {{ cifmw_networking_env_definition.instances[host]['hostname'] }} {% for network in cifmw_networking_env_definition.instances[host]['networks'].values() %} +{% set ns.interfaces = ns.interfaces | + combine({network.network_name: (network.parent_interface | + default(network.interface_name) + ) + }, + recursive=true) %} {{ network.network_name }}_ip: {{ network[_ipv.ip_vX] }} {% endfor %} {% endif %} diff --git a/roles/ci_gen_kustomize_values/templates/uni04delta-ipv6/network-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/uni04delta-ipv6/network-values/values.yaml.j2 index dfd093af96..3b48d68758 100644 --- a/roles/ci_gen_kustomize_values/templates/uni04delta-ipv6/network-values/values.yaml.j2 +++ b/roles/ci_gen_kustomize_values/templates/uni04delta-ipv6/network-values/values.yaml.j2 @@ -6,14 +6,6 @@ lb_tools={}) %} data: {% for host in cifmw_networking_env_definition.instances.keys() -%} -{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() -%} -{% set ns.interfaces = ns.interfaces | - combine({network.network_name: (network.parent_interface | - default(network.interface_name) - ) - }, - recursive=true) -%} -{% endfor -%} {% if host is match('^(ocp|crc).*') %} node_{{ ns.ocp_index }}: {% set ns.ocp_index = ns.ocp_index+1 %} @@ -22,6 +14,12 @@ data: {# Because devscripts use fqdn for node names when ipv6 #} node_name: {{ cifmw_networking_env_definition.instances[host]['hostname'] }}.ocp.openstack.lab {% for network in cifmw_networking_env_definition.instances[host]['networks'].values() %} +{% set ns.interfaces = ns.interfaces | + combine({network.network_name: (network.parent_interface | + default(network.interface_name) + ) + }, + recursive=true) %} {{ network.network_name }}_ip: {{ network[_ipv.ip_vX] }} {% endfor %} {% endif %} diff --git a/roles/ci_gen_kustomize_values/templates/uni05epsilon/network-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/uni05epsilon/network-values/values.yaml.j2 index df35482f9c..526b09deb6 100644 --- a/roles/ci_gen_kustomize_values/templates/uni05epsilon/network-values/values.yaml.j2 +++ b/roles/ci_gen_kustomize_values/templates/uni05epsilon/network-values/values.yaml.j2 @@ -6,19 +6,17 @@ lb_tools={}) %} data: {% for host in cifmw_networking_env_definition.instances.keys() -%} -{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() -%} -{% set ns.interfaces = ns.interfaces | - combine({network.network_name: (network.parent_interface | - default(network.interface_name) - ) - }, - recursive=true) -%} -{% endfor -%} {% if host is match('^(ocp|crc).*') %} node_{{ ns.ocp_index }}: {% set ns.ocp_index = ns.ocp_index+1 %} name: {{ cifmw_networking_env_definition.instances[host]['hostname'] }} {% for network in cifmw_networking_env_definition.instances[host]['networks'].values() %} +{% set ns.interfaces = ns.interfaces | + combine({network.network_name: (network.parent_interface | + default(network.interface_name) + ) + }, + recursive=true) %} {{ network.network_name }}_ip: {{ network[_ipv.ip_vX] }} {% endfor %} {% endif %} diff --git a/roles/ci_gen_kustomize_values/templates/uni06zeta/network-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/uni06zeta/network-values/values.yaml.j2 index 7e61b53a8b..a88987a16d 100644 --- a/roles/ci_gen_kustomize_values/templates/uni06zeta/network-values/values.yaml.j2 +++ b/roles/ci_gen_kustomize_values/templates/uni06zeta/network-values/values.yaml.j2 @@ -6,19 +6,17 @@ lb_tools={}) %} data: {% for host in cifmw_networking_env_definition.instances.keys() -%} -{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() -%} -{% set ns.interfaces = ns.interfaces | - combine({network.network_name: (network.parent_interface | - default(network.interface_name) - ) - }, - recursive=true) -%} -{% endfor -%} {% if host is match('^(ocp|crc).*') %} node_{{ ns.ocp_index }}: {% set ns.ocp_index = ns.ocp_index+1 %} name: {{ cifmw_networking_env_definition.instances[host]['hostname'] }} {% for network in cifmw_networking_env_definition.instances[host]['networks'].values() %} +{% set ns.interfaces = ns.interfaces | + combine({network.network_name: (network.parent_interface | + default(network.interface_name) + ) + }, + recursive=true) %} {{ network.network_name }}_ip: {{ network[_ipv.ip_vX] }} {% endfor %} {% endif %} diff --git a/roles/ci_gen_kustomize_values/templates/uni07eta/network-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/uni07eta/network-values/values.yaml.j2 index 6c6f68cc16..2df6024b6c 100644 --- a/roles/ci_gen_kustomize_values/templates/uni07eta/network-values/values.yaml.j2 +++ b/roles/ci_gen_kustomize_values/templates/uni07eta/network-values/values.yaml.j2 @@ -6,19 +6,17 @@ lb_tools={}) %} data: {% for host in cifmw_networking_env_definition.instances.keys() -%} -{% for network in cifmw_networking_env_definition.instances[host]['networks'].values() -%} -{% set ns.interfaces = ns.interfaces | - combine({network.network_name: (network.parent_interface | - default(network.interface_name) - ) - }, - recursive=true) -%} -{% endfor -%} {% if host is match('^(ocp|crc).*') %} node_{{ ns.ocp_index }}: {% set ns.ocp_index = ns.ocp_index+1 %} name: {{ cifmw_networking_env_definition.instances[host]['hostname'] }} {% for network in cifmw_networking_env_definition.instances[host]['networks'].values() %} +{% set ns.interfaces = ns.interfaces | + combine({network.network_name: (network.parent_interface | + default(network.interface_name) + ) + }, + recursive=true) %} {{ network.network_name }}_ip: {{ network[_ipv.ip_vX] }} {% endfor %} {% endif %} diff --git a/roles/cifmw_cephadm/defaults/main.yml b/roles/cifmw_cephadm/defaults/main.yml index 66fcfecf9d..4354ade258 100644 --- a/roles/cifmw_cephadm/defaults/main.yml +++ b/roles/cifmw_cephadm/defaults/main.yml @@ -138,3 +138,5 @@ cifmw_cephadm_update_log_commands: # Get last cephadm logs in case of failure - type: "mod_cephadm" cmd: "log last cephadm" +cifmw_cephadm_wait_for_dashboard_retries: 10 +cifmw_cephadm_wait_for_dashboard_delay: 20 diff --git a/roles/cifmw_cephadm/tasks/configure_object.yml b/roles/cifmw_cephadm/tasks/configure_object.yml index 2540fb1717..649e3ea7c1 100644 --- a/roles/cifmw_cephadm/tasks/configure_object.yml +++ b/roles/cifmw_cephadm/tasks/configure_object.yml @@ -92,8 +92,8 @@ script: |- oc -n {{ cifmw_cephadm_ns }} rsh openstackclient openstack role add --user {{ all_uuids.results.0.stdout }} --project {{ project_service_uuid.stdout }} {{ all_uuids.results.2.stdout }} oc -n {{ cifmw_cephadm_ns }} rsh openstackclient openstack role add --user {{ all_uuids.results.0.stdout }} --project {{ project_service_uuid.stdout }} {{ all_uuids.results.3.stdout }} - oc -n {{ cifmw_cephadm_ns }} rsh openstackclient openstack endpoint create --region regionOne {{ all_uuids.results.1.stdout }} public {{ cifmw_cephadm_urischeme }}://{{ cifmw_external_dns_vip_ext.values() | first if cifmw_external_dns_vip_ext is defined else cifmw_cephadm_vip }}:8080/swift/v1/AUTH_%\(tenant_id\)s - oc -n {{ cifmw_cephadm_ns }} rsh openstackclient openstack endpoint create --region regionOne {{ all_uuids.results.1.stdout }} internal {{ cifmw_cephadm_urischeme }}://{{ cifmw_external_dns_vip_int.values() | first if cifmw_external_dns_vip_int is defined else cifmw_cephadm_vip }}:8080/swift/v1/AUTH_%\(tenant_id\)s + oc -n {{ cifmw_cephadm_ns }} rsh openstackclient openstack endpoint create --region regionOne {{ all_uuids.results.1.stdout }} public {{ cifmw_cephadm_urischeme }}://{{ cifmw_external_dns_vip_ext.values() | first if cifmw_external_dns_vip_ext is defined else cifmw_cephadm_rgw_vip | ansible.utils.ipaddr('address') }}:8080/swift/v1/AUTH_%\(tenant_id\)s + oc -n {{ cifmw_cephadm_ns }} rsh openstackclient openstack endpoint create --region regionOne {{ all_uuids.results.1.stdout }} internal {{ cifmw_cephadm_urischeme }}://{{ cifmw_external_dns_vip_int.values() | first if cifmw_external_dns_vip_int is defined else cifmw_cephadm_rgw_vip | ansible.utils.ipaddr('address') }}:8080/swift/v1/AUTH_%\(tenant_id\)s oc -n {{ cifmw_cephadm_ns }} rsh openstackclient openstack role add --project {{ all_uuids.results.4.stdout }} --user {{ all_uuids.results.5.stdout }} {{ all_uuids.results.6.stdout }} delegate_to: localhost when: diff --git a/roles/cifmw_cephadm/tasks/dashboard/configure_dashboard_backends.yml b/roles/cifmw_cephadm/tasks/dashboard/configure_dashboard_backends.yml index ad20445360..52f7881daa 100644 --- a/roles/cifmw_cephadm/tasks/dashboard/configure_dashboard_backends.yml +++ b/roles/cifmw_cephadm/tasks/dashboard/configure_dashboard_backends.yml @@ -34,5 +34,5 @@ ansible.builtin.command: | {{ cifmw_cephadm_ceph_cli }} config set \ mgr mgr/dashboard/{{ current_mgr }}/server_addr \ - {{ hostvars[item][all_addresses] | ansible.utils.ipaddr(cifmw_cephadm_rgw_network) | first }} + {{ hostvars[item][all_addresses] | ansible.utils.ipaddr(cifmw_cephadm_monitoring_network) | first }} become: true diff --git a/roles/cifmw_cephadm/tasks/dashboard/validation.yml b/roles/cifmw_cephadm/tasks/dashboard/validation.yml index bb64d6e5e9..b8e6569b89 100644 --- a/roles/cifmw_cephadm/tasks/dashboard/validation.yml +++ b/roles/cifmw_cephadm/tasks/dashboard/validation.yml @@ -1,15 +1,47 @@ +--- +# Copyright 2024 Red Hat, Inc. +# All Rights Reserved. +# +# 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. + +- name: Update urischeme based on cert/key + ansible.builtin.set_fact: + cifmw_cephadm_urischeme_dashboard: "https" + when: + - cifmw_cephadm_dashboard_crt | default("") | length > 0 + - cifmw_cephadm_dashboard_key | default("") | length > 0 + - name: Validate connection to dashboard service ansible.builtin.get_url: - url: "http://{{ grafana_server_addr }}:{{ cifmw_cephadm_dashboard_port }}" + url: "{{ cifmw_cephadm_urischeme_dashboard | default('http') }}://{{ grafana_server_addr }}:{{ cifmw_cephadm_dashboard_port }}" dest: "/tmp/dash_response" + validate_certs: false register: dashboard_response failed_when: dashboard_response.failed == true + until: dashboard_response.failed == false + retries: "{{ cifmw_cephadm_wait_for_dashboard_retries }}" + delay: "{{ cifmw_cephadm_wait_for_dashboard_delay }}" + - name: Check http response code from dashboard service with login ansible.builtin.get_url: - url: "http://{{ grafana_server_addr }}:{{ cifmw_cephadm_dashboard_port }}" + url: "{{ cifmw_cephadm_urischeme_dashboard | default('http') }}://{{ grafana_server_addr }}:{{ cifmw_cephadm_dashboard_port }}" dest: "/tmp/dash_http_response" + validate_certs: false username: admin password: admin register: dashboard_resp failed_when: dashboard_resp.status_code != 200 + until: dashboard_resp.status_code == 200 + retries: "{{ cifmw_cephadm_wait_for_dashboard_retries }}" + delay: "{{ cifmw_cephadm_wait_for_dashboard_delay }}" diff --git a/roles/cifmw_cephadm/tasks/pools.yml b/roles/cifmw_cephadm/tasks/pools.yml index 5c34cc7eda..d88ff0525d 100644 --- a/roles/cifmw_cephadm/tasks/pools.yml +++ b/roles/cifmw_cephadm/tasks/pools.yml @@ -47,8 +47,9 @@ - name: Configure the RBD trash purge scheduler when: - - cifmw_enabled_services | default([]) | intersect(['cinder_volume']) - cifmw_cephadm_enable_trash_scheduler | default(false) + - cifmw_cephadm_pools is defined + - cifmw_cephadm_pools | length > 0 block: - name: Get the RBD ceph_cli ansible.builtin.include_tasks: ceph_cli.yml @@ -56,10 +57,11 @@ ceph_command: rbd - name: Set trash interval + when: item.trash_purge_enabled | default(false) ansible.builtin.command: - cmd: | - {{ cifmw_cephadm_ceph_cli }} trash purge schedule add \ - {{ cifmw_cephadm_rbd_trash_interval | default(15) }} --pool {{ item }} + cmd: >- + {{ cifmw_cephadm_ceph_cli }} trash purge schedule add + {{ cifmw_cephadm_rbd_trash_interval | default(15) }} --pool {{ item.name }} changed_when: false become: true - loop: "{{ [ cinder_pool.name | default('volumes') ] + cinder_pool.cinder_extra_pools | default([]) }}" + loop: "{{ cifmw_cephadm_pools | default([]) }}" diff --git a/roles/cifmw_cephadm/tasks/post.yml b/roles/cifmw_cephadm/tasks/post.yml index a23ee2e932..d6ec394ed2 100644 --- a/roles/cifmw_cephadm/tasks/post.yml +++ b/roles/cifmw_cephadm/tasks/post.yml @@ -46,8 +46,14 @@ loop: "{{ cifmw_cephadm_log_commands }}" - name: Configure ceph object store to use external ceph object gateway + when: + - cifmw_cephadm_vip is defined + - cifmw_cephadm_vip | default("") | length > 0 + - cifmw_ceph_daemons_layout.rgw_enabled | default(true) | bool ansible.builtin.include_tasks: configure_object.yml - when: cifmw_ceph_daemons_layout.rgw_enabled | default(true) | bool + vars: + cifmw_cephadm_rgw_vip: "{{ cifmw_cephadm_vip }}" + - name: Dashboard service validation ansible.builtin.include_tasks: dashboard/validation.yml diff --git a/roles/cifmw_cephadm/tasks/rgw.yml b/roles/cifmw_cephadm/tasks/rgw.yml index 4a600c1867..2135d76eed 100644 --- a/roles/cifmw_cephadm/tasks/rgw.yml +++ b/roles/cifmw_cephadm/tasks/rgw.yml @@ -27,12 +27,12 @@ - name: Define cifmw_external_dns_vip_ext ansible.builtin.set_fact: cifmw_external_dns_vip_ext: "{{ cifmw_external_dns_vip_ext | default({}) | - combine({ (cifmw_cephadm_vip): 'rgw-external.ceph.local' }) }}" + combine({ (cifmw_cephadm_rgw_vip | ansible.utils.ipaddr('address')): 'rgw-external.ceph.local' }) }}" - name: Define cifmw_external_dns_vip_int ansible.builtin.set_fact: cifmw_external_dns_vip_int: "{{ cifmw_external_dns_vip_ext | default({}) | - combine({ (cifmw_cephadm_vip): 'rgw-internal.ceph.local' }) }}" + combine({ (cifmw_cephadm_rgw_vip | ansible.utils.ipaddr('address')): 'rgw-internal.ceph.local' }) }}" - name: Create DNS domain and certificate ansible.builtin.include_role: diff --git a/roles/cifmw_cephadm/templates/ceph_monitoring_stack.yml.j2 b/roles/cifmw_cephadm/templates/ceph_monitoring_stack.yml.j2 index ee968d5875..7e07d650f6 100644 --- a/roles/cifmw_cephadm/templates/ceph_monitoring_stack.yml.j2 +++ b/roles/cifmw_cephadm/templates/ceph_monitoring_stack.yml.j2 @@ -11,7 +11,7 @@ placement: - {{ _hosts[0] }} count: 1 networks: -- {{ cifmw_cephadm_rgw_network }} +- {{ cifmw_cephadm_monitoring_network }} --- service_type: prometheus service_id: prometheus @@ -21,7 +21,7 @@ placement: - {{ _hosts[0] }} count: 1 networks: -- {{ cifmw_cephadm_rgw_network }} +- {{ cifmw_cephadm_monitoring_network }} --- service_type: alertmanager service_id: alertmanager @@ -31,4 +31,4 @@ placement: - {{ _hosts[0] }} count: 1 networks: -- {{ cifmw_cephadm_rgw_network }} +- {{ cifmw_cephadm_monitoring_network }} diff --git a/roles/cifmw_cephadm/templates/ceph_rgw.yml.j2 b/roles/cifmw_cephadm/templates/ceph_rgw.yml.j2 index dbf42ae222..0c0b2f52c4 100644 --- a/roles/cifmw_cephadm/templates/ceph_rgw.yml.j2 +++ b/roles/cifmw_cephadm/templates/ceph_rgw.yml.j2 @@ -31,7 +31,7 @@ spec: monitor_port: 8999 virtual_interface_networks: - {{ cifmw_cephadm_rgw_network }} - virtual_ip: {{ cifmw_cephadm_vip }} + virtual_ip: {{ cifmw_cephadm_rgw_vip }}/{{ cidr }} {% if rgw_frontend_cert is defined %} ssl_cert: | {{ rgw_frontend_cert | indent( width=6 ) }} diff --git a/roles/cifmw_ntp/README.md b/roles/cifmw_ntp/README.md new file mode 100644 index 0000000000..f7c71248c9 --- /dev/null +++ b/roles/cifmw_ntp/README.md @@ -0,0 +1,25 @@ +# cifmw_ntp + +This role allows to install and configure an NTP service (chrony) on an host. +It's a *heavily* stripped down version of the [timesync](https://github.com/linux-system-roles/timesync) role. +It shouldn't be used outside the cifmw scope because it only sets the NTP server/pool to use. + +## Privilege escalation + +Privilege escalation is needed to install packages,render the templates in /etc directory and deal with systemd services. + +## Parameters +* `cifmw_ntp_servers` (list) List of NTP servers or pool of NTP servers. It defaults to `pool.ntp.org` if the (global) variable `cifmw_ntp_server` isn't defined. +* `cifmw_ntp_chrony_conf_file` (string) The path of the chrony configuration file. It defaults to `/etc/chrony.conf`. +* `cifmw_ntp_chrony_extra_conf_file` (string) The path of the custom configuration file for chrony. It defaults to `/etc/chrony-cifmw.conf`. + +## Examples + +``` +- name: Configure chrony on controller-0 + hosts: controller-0 + vars: + cifmw_ntp_server: "custom.ntp.server" + roles: + - role: "cifmw_ntp" +``` diff --git a/roles/cifmw_ntp/defaults/main.yml b/roles/cifmw_ntp/defaults/main.yml new file mode 100644 index 0000000000..3c7b0af488 --- /dev/null +++ b/roles/cifmw_ntp/defaults/main.yml @@ -0,0 +1,23 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + + +# All variables intended for modification should be placed in this file. +# All variables within this role should have a prefix of "cifmw_ntp" + +cifmw_ntp_servers: "{{ [ cifmw_ntp_server | default('pool.ntp.org') ] | list }}" +cifmw_ntp_chrony_conf_file: /etc/chrony.conf +cifmw_ntp_chrony_extra_conf_file: /etc/chrony-cifmw.conf diff --git a/roles/cifmw_ntp/handlers/main.yml b/roles/cifmw_ntp/handlers/main.yml new file mode 100644 index 0000000000..7abca89274 --- /dev/null +++ b/roles/cifmw_ntp/handlers/main.yml @@ -0,0 +1,21 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + +- name: Restart chrony + become: true + ansible.builtin.systemd_service: + name: chronyd.service + state: restarted diff --git a/roles/cifmw_ntp/meta/main.yml b/roles/cifmw_ntp/meta/main.yml new file mode 100644 index 0000000000..827bc3a70d --- /dev/null +++ b/roles/cifmw_ntp/meta/main.yml @@ -0,0 +1,30 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + + +galaxy_info: + author: CI Framework + description: CI Framework Role -- cifmw_ntp + company: Red Hat + license: Apache-2.0 + min_ansible_version: "2.14" + namespace: cifmw + galaxy_tags: + - cifmw + +# List your role dependencies here, one per line. Be sure to remove the '[]' above, +# if you add dependencies to this list. +dependencies: [] diff --git a/roles/cifmw_ntp/molecule/default/cleanup.yml b/roles/cifmw_ntp/molecule/default/cleanup.yml new file mode 100644 index 0000000000..9f801a92f1 --- /dev/null +++ b/roles/cifmw_ntp/molecule/default/cleanup.yml @@ -0,0 +1,24 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + + +- name: Cleanup + hosts: all + tasks: + - name: Cleanup chrony role + ansible.builtin.include_role: + name: cifmw_ntp + tasks_from: cleanup.yml diff --git a/roles/cifmw_ntp/molecule/default/converge.yml b/roles/cifmw_ntp/molecule/default/converge.yml new file mode 100644 index 0000000000..15bbf5a382 --- /dev/null +++ b/roles/cifmw_ntp/molecule/default/converge.yml @@ -0,0 +1,23 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + + +- name: Converge + hosts: all + vars_files: + - ../vars.yml + roles: + - role: "cifmw_ntp" diff --git a/roles/cifmw_ntp/molecule/default/molecule.yml b/roles/cifmw_ntp/molecule/default/molecule.yml new file mode 100644 index 0000000000..6c31fa930b --- /dev/null +++ b/roles/cifmw_ntp/molecule/default/molecule.yml @@ -0,0 +1,17 @@ +--- +# Mainly used to override the defaults set in .config/molecule/ +# By default, it uses the "config_podman.yml" - in CI, it will use +# "config_local.yml". + +provisioner: + name: ansible + log: true + env: + ANSIBLE_STDOUT_CALLBACK: yaml + +scenario: + test_sequence: + - prepare + - converge + - verify + - cleanup diff --git a/roles/cifmw_ntp/molecule/default/verify.yml b/roles/cifmw_ntp/molecule/default/verify.yml new file mode 100644 index 0000000000..1569fd9f34 --- /dev/null +++ b/roles/cifmw_ntp/molecule/default/verify.yml @@ -0,0 +1,67 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + + +- name: Verify + hosts: all + vars_files: + - ../vars.yml + - ../../defaults/main.yml + tasks: + - name: Get service facts + ansible.builtin.service_facts: + + - name: Assert that the service exists, is enabled and running + ansible.builtin.assert: + that: + - ansible_facts.services["chronyd.service"] is defined + - ansible_facts.services["chronyd.service"]["state"] == "running" + - ansible_facts.services["chronyd.service"]["status"] == "enabled" + + - name: Check if the chrony.conf file has been configured properly + ansible.builtin.lineinfile: + path: "{{ cifmw_ntp_chrony_conf_file }}" + regexp: "{{ item.regexp | default(omit) }}" + line: "{{ item.line }}" + backrefs: "{{ item.backrefs | default(omit) }}" + state: present + check_mode: true + register: _check_chrony_conf + loop: + - { regexp: "^(server.*)$", line: "#\\g<1>", backrefs: true } + - { line: "include {{ cifmw_ntp_chrony_extra_conf_file }}" } + + - name: Check if the provided ntp server is configured in the custom configuration file + ansible.builtin.lineinfile: + path: "{{ cifmw_ntp_chrony_extra_conf_file }}" + regexp: ^(server\ ).*(\ iburst)$ + line: \g<1>{{ cifmw_ntp_servers }}\g<2> + backrefs: true + state: present + check_mode: true + register: _check_ntp_server + + - name: Assert that chrony.conf has been correctly configured + ansible.builtin.assert: + that: item is not changed + fail_msg: "{{ cifmw_ntp_chrony_conf_file }} isn't correctly configured, please check." + loop: "{{ _check_chrony_conf.results }}" + + - name: Assert that the correct server is configured in the custom configuration file + ansible.builtin.assert: + that: _check_ntp_server is not changed + fail_msg: "{{ cifmw_ntp_servers }} wasn't found in the {{ cifmw_ntp_chrony_extra_conf_file }} file" + success_msg: "{{ cifmw_ntp_servers }} was successfully configured in {{ cifmw_ntp_chrony_extra_conf_file }} file" diff --git a/roles/cifmw_ntp/molecule/vars.yml b/roles/cifmw_ntp/molecule/vars.yml new file mode 100644 index 0000000000..0719bff30a --- /dev/null +++ b/roles/cifmw_ntp/molecule/vars.yml @@ -0,0 +1,17 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + +cifmw_ntp_server: 'rhel.pool.ntp.org' diff --git a/roles/cifmw_ntp/tasks/cleanup.yml b/roles/cifmw_ntp/tasks/cleanup.yml new file mode 100644 index 0000000000..01fd1fe660 --- /dev/null +++ b/roles/cifmw_ntp/tasks/cleanup.yml @@ -0,0 +1,34 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + +- name: Disable and remove chrony and its custom configuration + become: true + block: + - name: Disable chrony service + ansible.builtin.systemd_service: + name: chronyd.service + state: stopped + enabled: false + + - name: Delete chrony custom config file + ansible.builtin.file: + path: "{{ cifmw_ntp_chrony_extra_conf_file }}" + state: absent + + - name: Uninstall chrony + ansible.builtin.dnf: + name: chrony + state: absent diff --git a/roles/cifmw_ntp/tasks/main.yml b/roles/cifmw_ntp/tasks/main.yml new file mode 100644 index 0000000000..7b2d5a0038 --- /dev/null +++ b/roles/cifmw_ntp/tasks/main.yml @@ -0,0 +1,53 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + + +- name: Install, configure, and enable chrony + become: true + block: + - name: Install chrony + ansible.builtin.dnf: + name: chrony + state: present + + - name: Configure original chrony.conf file + ansible.builtin.lineinfile: + path: "{{ cifmw_ntp_chrony_conf_file }}" + regexp: "{{ item.regexp | default(omit) }}" + line: "{{ item.line }}" + insertafter: "{{ item.insertafter | default(omit) }}" + backrefs: "{{ item.backrefs | default(omit) }}" + state: present + backup: true + loop: + - { regexp: "^(server.*)$", line: "#\\g<1>", backrefs: true } + - { line: "include {{ cifmw_ntp_chrony_extra_conf_file }}", insertafter: "EOF" } + + - name: Render chrony extra config file + ansible.builtin.template: + src: chrony.conf.j2 + dest: "{{ cifmw_ntp_chrony_extra_conf_file }}" + owner: root + group: root + mode: '0644' + backup: true + notify: Restart chrony + + - name: Enable chrony service + ansible.builtin.systemd_service: + name: chronyd.service + state: started + enabled: true diff --git a/roles/cifmw_ntp/templates/chrony.conf.j2 b/roles/cifmw_ntp/templates/chrony.conf.j2 new file mode 100644 index 0000000000..cd4d6ae53d --- /dev/null +++ b/roles/cifmw_ntp/templates/chrony.conf.j2 @@ -0,0 +1,5 @@ +{{ ansible_managed | comment }} + +{% for ntp_host in cifmw_ntp_servers %} +{{ 'pool' if 'pool' in ntp_host else 'server' }} {{ ntp_host }} iburst +{% endfor %} diff --git a/roles/devscripts/tasks/300_post.yml b/roles/devscripts/tasks/300_post.yml index 814e9608fd..6e03cd8d23 100644 --- a/roles/devscripts/tasks/300_post.yml +++ b/roles/devscripts/tasks/300_post.yml @@ -26,42 +26,10 @@ - not cifmw_devscripts_ocp_online | bool ansible.builtin.import_tasks: set_cluster_fact.yml -- name: Prepare for disk overlay configuration. - tags: - - devscripts_deploy +- name: Prepare for disk overlay configuration when: - not cifmw_devscripts_ocp_comply | bool + - cifmw_use_ocp_overlay | default(true) | bool + tags: + - devscripts_deploy ansible.builtin.include_tasks: 310_prepare_overlay.yml - -- name: Bringing cluster online. - when: - - not cifmw_use_reproducer | default(false) | bool - block: - - name: Deploy layout on target host - tags: - - libvirt_layout - when: - - not cifmw_devscripts_ocp_comply | bool - ansible.builtin.include_role: - name: libvirt_manager - tasks_from: deploy_layout - - - name: Apply VLAN configuration for vnet interfaces. - tags: - - devscripts_post - when: - - cifmw_libvirt_manager_configuration_gen.networks is defined - become: true - cifmw.general.bridge_vlan: - networks: >- - {{ - cifmw_libvirt_manager_configuration_gen.networks.keys() | list - }} - failed_when: false - - - name: Ensure the OpenShift cluster is accessible. - tags: - - devscripts_post - when: - - not cifmw_devscripts_ocp_online | bool - ansible.builtin.include_tasks: 330_wait_ocp.yml diff --git a/roles/devscripts/vars/main.yml b/roles/devscripts/vars/main.yml index 97bcc6b7bd..3cb58f4872 100644 --- a/roles/devscripts/vars/main.yml +++ b/roles/devscripts/vars/main.yml @@ -28,11 +28,7 @@ cifmw_devscripts_packages: - python3-jmespath cifmw_devscripts_repo: "https://github.com/openshift-metal3/dev-scripts.git" -# Note(Chandan): Pinning devscripts at https://github.com/openshift-metal3/dev-scripts/commit/5756e9cf094d8c4256461b0fd4242cd84dea8c93 -# as https://github.com/openshift-metal3/dev-scripts/pull/1694 broke IPv6 job -# More details are here: https://issues.redhat.com/browse/OSPCIX-443. -# We should unpin it as more updates needed from devscript. -cifmw_devscripts_repo_branch: 5756e9cf094d8c4256461b0fd4242cd84dea8c93 +cifmw_devscripts_repo_branch: HEAD cifmw_devscripts_config_defaults: working_dir: "/home/dev-scripts" diff --git a/roles/libvirt_manager/tasks/create_vms.yml b/roles/libvirt_manager/tasks/create_vms.yml index 4f8b20d13e..0e586abe8d 100644 --- a/roles/libvirt_manager/tasks/create_vms.yml +++ b/roles/libvirt_manager/tasks/create_vms.yml @@ -29,12 +29,12 @@ _workload: "{{ cifmw_libvirt_manager_basedir }}/workload" _img_dir: "{{ cifmw_libvirt_manager_basedir }}/images" _chdir: >- - {{ (is_base_img | default(false) | bool) | ternary(_img_dir, _workload) }} + {{ + (_is_base_img | default(false) | bool) | + ansible.builtin.ternary(_img_dir, _workload) + }} block: - name: "Create VM image for {{ vm }}" - vars: - _vm_img: >- - {{ vm }}.qcow2 ansible.builtin.command: cmd: >- qemu-img create @@ -48,9 +48,6 @@ chdir: "{{ _chdir }}" - name: "Ensure file ownership and rights for {{ vm }}" - vars: - _vm_img: >- - {{ vm }}.qcow2 ansible.builtin.file: path: "{{ (_chdir, _vm_img) | path_join }}" group: "qemu" diff --git a/roles/libvirt_manager/tasks/deploy_layout.yml b/roles/libvirt_manager/tasks/deploy_layout.yml index c10506bd81..fc590981e8 100644 --- a/roles/libvirt_manager/tasks/deploy_layout.yml +++ b/roles/libvirt_manager/tasks/deploy_layout.yml @@ -198,6 +198,8 @@ }} pub_key: "{{ pub_ssh_key.content | b64decode }}" priv_key: "{{ priv_ssh_key.content | b64decode }}" + _vm_img: >- + {{ vm }}.qcow2 ansible.builtin.include_tasks: file: create_vms.yml loop: "{{ cifmw_libvirt_manager_all_vms | dict2items }}" diff --git a/roles/libvirt_manager/tasks/ocp_layout.yml b/roles/libvirt_manager/tasks/ocp_layout.yml index 5ffbbee081..f7333c07ae 100644 --- a/roles/libvirt_manager/tasks/ocp_layout.yml +++ b/roles/libvirt_manager/tasks/ocp_layout.yml @@ -6,7 +6,7 @@ notify: Restart firewalld ansible.builtin.command: cmd: >- - firewall-cmd --permanent --zone libvirt --add-forward + firewall-cmd --permanent --zone libvirt --add-forward - name: Enable masquerading for public traffic when: cifmw_libvirt_manager_firewalld_default_zone_masquerade | default(true) | bool @@ -64,6 +64,7 @@ state: directory loop: - "{{ cifmw_libvirt_manager_basedir }}/images" + - "{{ cifmw_libvirt_manager_basedir }}/workload" - "{{ cifmw_libvirt_manager_ocp_pool_dir }}" - name: Create pool in libvirt @@ -79,7 +80,9 @@ {{ _ocp_layout.vms[vm_type] }} - is_base_img: true + _vm_img: >- + {{ vm }}.qcow2 + _is_base_img: "{{ cifmw_use_ocp_overlay | default(true) | bool }}" ansible.builtin.include_role: name: "libvirt_manager" tasks_from: "create_vms.yml" diff --git a/roles/reproducer/README.md b/roles/reproducer/README.md index e517e40d7b..0b884bc5cf 100644 --- a/roles/reproducer/README.md +++ b/roles/reproducer/README.md @@ -27,6 +27,7 @@ Those parameters shouldn't be used, unless the user is able to understand potent * `cifmw_reproducer_validate_network`: (Bool) Toggle network validations. Those validations ensure all of listed networks in VMs are defined. Defaults to `true`. * `cifmw_reproducer_validate_ocp_layout`: (Bool) Toggle OCP layout validations. Those validations ensure volumes, amounts and resources are properly defined for OCP cluster members (masters and workers). Defaults to `true`. +* `cifmw_reproducer_validate_network_host`: (String) Specify the hostname that should be pinged in order to validate network connectivity from the ctlplane network. Default value is `controller-0.utility` ### run_job and run_content_provider booleans and risks. diff --git a/roles/reproducer/defaults/main.yml b/roles/reproducer/defaults/main.yml index f911056ebe..8ce55ee5b6 100644 --- a/roles/reproducer/defaults/main.yml +++ b/roles/reproducer/defaults/main.yml @@ -49,4 +49,5 @@ cifmw_reproducer_controller_basedir: >- # Allow to disable validations - user toggle this at their # own risks! cifmw_reproducer_validate_network: true +cifmw_reproducer_validate_network_host: "controller-0.utility" cifmw_reproducer_validate_ocp_layout: true diff --git a/roles/reproducer/tasks/configure_computes.yml b/roles/reproducer/tasks/configure_computes.yml index 75706d2305..3cf4dabc32 100644 --- a/roles/reproducer/tasks/configure_computes.yml +++ b/roles/reproducer/tasks/configure_computes.yml @@ -5,7 +5,7 @@ - name: Ensure we can ping controller-0 from ctlplane ansible.builtin.command: cmd: | - ping -c2 controller-0.utility + ping -c2 {{ cifmw_reproducer_validate_network_host }} - name: Tweak dnf configuration become: true diff --git a/roles/reproducer/tasks/configure_controller.yml b/roles/reproducer/tasks/configure_controller.yml index bf4d14d997..cc86bc3db6 100644 --- a/roles/reproducer/tasks/configure_controller.yml +++ b/roles/reproducer/tasks/configure_controller.yml @@ -472,3 +472,7 @@ register: _sync_dep_install_result until: _sync_dep_install_result.finished retries: 20 + + - name: Configure ntp service + ansible.builtin.include_role: + name: cifmw_ntp diff --git a/roles/reproducer/tasks/libvirt_layout.yml b/roles/reproducer/tasks/libvirt_layout.yml index 6bd89a74a3..e474d8123d 100644 --- a/roles/reproducer/tasks/libvirt_layout.yml +++ b/roles/reproducer/tasks/libvirt_layout.yml @@ -98,10 +98,20 @@ - >- (compute.key in (groups['computes'] | default([]))) or (compute.key in (groups['cephs'] | default([]))) or - (compute.key in (groups['networkers'] | default([]))) + (compute.key in (groups['networkers'] | default([]))) or + (compute.key in (groups['dcn1-computes'] | default([]))) or + (compute.key in (groups['dcn2-computes'] | default([]))) vars: _host: "{{ compute.key }}" - _prefix: "{{cifmw_networking_env_definition.networks.ctlplane.network_v4 | ansible.utils.ipaddr('prefix') }}" + _prefix: >- + {% set ctlplane_variants = ['ctlplane', 'ctlplanedcn1', 'ctlplanedcn2'] %} + {{ + cifmw_networking_env_definition.networks + | selectattr('key', 'in', ctlplane_variants) + | map(attribute='value.network_v4') + | first + | ansible.utils.ipaddr('prefix') + }} ansible.builtin.include_tasks: configure_computes.yml loop: >- {{ cifmw_networking_env_definition.instances | dict2items }} diff --git a/roles/reproducer/tasks/ocp_layout.yml b/roles/reproducer/tasks/ocp_layout.yml index d97798c50b..b93f0753a4 100644 --- a/roles/reproducer/tasks/ocp_layout.yml +++ b/roles/reproducer/tasks/ocp_layout.yml @@ -336,8 +336,6 @@ permanent: true - name: Run devscripts role - vars: - cifmw_use_reproducer: true ansible.builtin.include_role: name: devscripts diff --git a/roles/reproducer/tasks/prepare_networking.yml b/roles/reproducer/tasks/prepare_networking.yml index ffe9d29203..237f43a5d7 100644 --- a/roles/reproducer/tasks/prepare_networking.yml +++ b/roles/reproducer/tasks/prepare_networking.yml @@ -216,8 +216,8 @@ - "sushy.utility" - "controller-0.utility" ips: - - "{{ _controller_net.ctlplane.ip_v4 | default('') }}" - - "{{ _controller_net.ctlplane.ip_v6 | default('') }}" + - "{{ _controller_net.ctlplane.ip_v4 | default(_controller_net[_pub_net].ip_v4) | default('') }}" + - "{{ _controller_net.ctlplane.ip_v6 | default(_controller_net[_pub_net].ip_v6) | default('') }}" state: present ansible.builtin.include_role: name: "dnsmasq" diff --git a/roles/sushy_emulator/tasks/collect_details.yml b/roles/sushy_emulator/tasks/collect_details.yml index d8a7378bc7..2791295ec3 100644 --- a/roles/sushy_emulator/tasks/collect_details.yml +++ b/roles/sushy_emulator/tasks/collect_details.yml @@ -69,20 +69,30 @@ when: - cifmw_libvirt_manager_uuids is not defined block: + - name: "Ensure file exists: {{ _uuid_file }}" + register: _uuid_file_status + ansible.builtin.stat: + path: "{{ _uuid_file }}" + - name: "Slurp content of: {{ _uuid_file }}" - ansible.builtin.slurp: - src: "{{ _uuid_file }}" - register: _libvirt_uuids_file + when: _uuid_file_status.stat.exists + block: + - name: "Slurp content of: {{ _uuid_file }}" + ansible.builtin.slurp: + src: "{{ _uuid_file }}" + register: _libvirt_uuids_file - - name: "Set cifmw_libvirt_manager_uuids fact from {{ _uuid_file }}" - vars: - _yaml: "{{ _libvirt_uuids_file.content | b64decode | from_yaml }}" - ansible.builtin.set_fact: - cifmw_libvirt_manager_uuids: "{{ _yaml.libvirt_uuid }}" + - name: "Set cifmw_libvirt_manager_uuids fact from {{ _uuid_file }}" + vars: + _yaml: "{{ _libvirt_uuids_file.content | b64decode | from_yaml }}" + ansible.builtin.set_fact: + cifmw_libvirt_manager_uuids: "{{ _yaml.libvirt_uuid }}" -- name: Set fact related to Libvirt driver +- name: Set _cifmw_sushy_emulator_instance fact when: - cifmw_sushy_emulator_driver == 'libvirt' + - (cifmw_libvirt_manager_uuids is defined and + cifmw_libvirt_manager_uuids | length > 0) block: - name: Generate list of filtered VMs vars: diff --git a/roles/test_operator/README.md b/roles/test_operator/README.md index 83adf6cf09..1d3016a38b 100644 --- a/roles/test_operator/README.md +++ b/roles/test_operator/README.md @@ -11,6 +11,7 @@ Execute tests via the [test-operator](https://openstack-k8s-operators.github.io/ * `cifmw_test_operator_logs_image`: (String) Image that should be used to collect logs from the pods spawned by the test-operator. Default value: `quay.io/quay/busybox` * `cifmw_test_operator_concurrency`: (Integer) Tempest concurrency value. Default value: `8` * `cifmw_test_operator_cleanup`: (Bool) Delete all resources created by the role at the end of the testing. Default value: `false` +* `cifmw_test_operator_tempest_cleanup`: (Bool) Run tempest cleanup after test execution (tempest run) to delete any resources created by tempest that may have been left out. * `cifmw_test_operator_default_groups`: (List) List of groups in the include list to search for tests to be executed. Default value: `[ 'default' ]` * `cifmw_test_operator_default_jobs`: (List) List of jobs in the exclude list to search for tests to be excluded. Default value: `[ 'default' ]` * `cifmw_test_operator_dry_run`: (Boolean) Whether test-operator should run or not. Default value: `false` @@ -25,6 +26,7 @@ Execute tests via the [test-operator](https://openstack-k8s-operators.github.io/ * `cifmw_test_operator_privileged`: (Boolean) Spawn the test pods with `allowPrivilegedEscalation: true` and default linux capabilities. This is required for certain test-operator functionalities to work properly (e.g.: `extraRPMs`, certain set of tobiko tests). Default value: `true` ## Tempest specific parameters +* `cifmw_test_operator_tempest_name`: (String) Value used in the `Tempest.Metadata.Name` field. The value specifies the name of some resources spawned by the test-operator role. Default value: `tempest-tests` * `cifmw_test_operator_tempest_registry`: (String) The registry where to pull tempest container. Default value: `quay.io` * `cifmw_test_operator_tempest_namespace`: (String) Registry's namespace where to pull tempest container. Default value: `podified-antelope-centos9` * `cifmw_test_operator_tempest_container`: (String) Name of the tempest container. Default value: `openstack-tempest` @@ -48,7 +50,7 @@ Execute tests via the [test-operator](https://openstack-k8s-operators.github.io/ apiVersion: test.openstack.org/v1beta1 kind: Tempest metadata: - name: tempest-tests + name: "{{ cifmw_test_operator_tempest_name }}" namespace: "{{ cifmw_test_operator_namespace }}" spec: containerImage: "{{ cifmw_test_operator_tempest_image }}:{{ cifmw_test_operator_tempest_image_tag }}" @@ -69,6 +71,7 @@ Execute tests via the [test-operator](https://openstack-k8s-operators.github.io/ ``` ## Tobiko specific parameters +* `cifmw_test_operator_tobiko_name`: (String) Value used in the `Tobiko.Metadata.Name` field. The value specifies the name of some resources spawned by the test-operator role. Default value: `tobiko-tests` * `cifmw_test_operator_tobiko_registry`: (String) The registry where to pull tobiko container. Default value: `quay.io` * `cifmw_test_operator_tobiko_namespace`: (String) Registry's namespace where to pull tobiko container. Default value: `podified-antelope-centos9` * `cifmw_test_operator_tobiko_container`: (String) Name of the tobiko container. Default value: `openstack-tobiko` @@ -90,7 +93,7 @@ Execute tests via the [test-operator](https://openstack-k8s-operators.github.io/ apiVersion: test.openstack.org/v1beta1 kind: Tobiko metadata: - name: tobiko-tests + name: "{{ cifmw_test_operator_tobiko_name }}" namespace: "{{ cifmw_test_operator_namespace }}" spec: kubeconfigSecretName: "{{ cifmw_test_operator_tobiko_kubeconfig_secret }}" @@ -111,6 +114,7 @@ Execute tests via the [test-operator](https://openstack-k8s-operators.github.io/ ``` ## AnsibleTest specific parameters +* `cifmw_test_operator_ansibletest_name`: (String) Value used in the `Ansibletest.Metadata.Name` field. The value specifies the name of some resources spawned by the test-operator role. Default value: `ansibletest` * `cifmw_test_operator_ansibletest_registry`: (String) The registry where to pull ansibletests container. Default value: `quay.io` * `cifmw_test_operator_ansibletest_namespace`: (String) Registry's namespace where to pull ansibletests container. Default value:podified-antelope-centos9 * `cifmw_test_operator_ansibletest_container`: (String) Name of the ansibletests container. Default value: `openstack-ansible-tests` @@ -134,7 +138,7 @@ Execute tests via the [test-operator](https://openstack-k8s-operators.github.io/ apiVersion: test.openstack.org/v1beta1 kind: AnsibleTest metadata: - name: horizontest-sample + name: "{{ cifmw_test_operator_ansibletest_name }}" namespace: "{{ cifmw_test_operator_namespace }}" spec: containerImage: "{{ cifmw_test_operator_ansibletest_image }}:{{ cifmw_test_operator_ansibletest_image_tag }}" @@ -155,6 +159,7 @@ Execute tests via the [test-operator](https://openstack-k8s-operators.github.io/ ``` ## Horizontest specific parameters +* `cifmw_test_operator_horizontest_name`: (String) Value used in the `Horizontest.Metadata.Name` field. The value specifies the name of some resources spawned by the test-operator role. Default value: `horizontest-tests` * `cifmw_test_operator_horizontest_registry`: (String) The registry where to pull horizontest container. Default value: `quay.io` * `cifmw_test_operator_horizontest_namespace`: (String) Registry's namespace where to pull horizontest container. Default value: `podified-antelope-centos9` * `cifmw_test_operator_horizontest_container`: (String) Name of the horizontest container. Default value: `openstack-horizontest` @@ -178,7 +183,7 @@ Execute tests via the [test-operator](https://openstack-k8s-operators.github.io/ apiVersion: test.openstack.org/v1beta1 kind: HorizonTest metadata: - name: horizontest + name: "{{ cifmw_test_operator_horizontest_name }}" namespace: "{{ cifmw_test_operator_namespace }}" spec: containerImage: "{{ cifmw_test_operator_horizontest_image }}:{{ cifmw_test_operator_horizontest_image_tag }}" @@ -196,3 +201,15 @@ Execute tests via the [test-operator](https://openstack-k8s-operators.github.io/ logsDirectoryName: "{{ cifmw_test_operator_horizontest_logs_directory_name }}" horizonTestDir: "{{ cifmw_test_operator_horizontest_horizon_test_dir }}" ``` + +## Examples + +### Execute the `test-operator` role multiple times within a single job + +If you want to run the `test-operator` role twice within a single job, make sure +that for the second run, you specify a value for the `cifmw_test_operator_*_name` +other than the default one (e.g., `tempest-tests`, `tobiko-tests`, ...): + +``` +cifmw_test_operator_tempest_name: "post-update-tempest-tests" +``` diff --git a/roles/test_operator/defaults/main.yml b/roles/test_operator/defaults/main.yml index da88f8ab44..d0a2be95a3 100644 --- a/roles/test_operator/defaults/main.yml +++ b/roles/test_operator/defaults/main.yml @@ -39,6 +39,7 @@ cifmw_test_operator_delete_logs_pod: false cifmw_test_operator_privileged: true # Section 2: tempest parameters - used when run_test_fw is 'tempest' +cifmw_test_operator_tempest_name: "tempest-tests" cifmw_test_operator_tempest_registry: quay.io cifmw_test_operator_tempest_namespace: podified-antelope-centos9 cifmw_test_operator_tempest_container: openstack-tempest-all @@ -48,6 +49,7 @@ cifmw_test_operator_tempest_network_attachments: [] cifmw_test_operator_tempest_tests_include_override_scenario: false cifmw_test_operator_tempest_tests_exclude_override_scenario: false cifmw_test_operator_tempest_workflow: [] +cifmw_test_operator_tempest_cleanup: false # Enabling SRBAC by default, in jobs where this does not make sense should be turned off explicitly # @@ -117,9 +119,11 @@ cifmw_test_operator_tempest_config: extraRPMs: "{{ cifmw_test_operator_tempest_extra_rpms | default([]) }}" extraImages: "{{ cifmw_test_operator_tempest_extra_images | default([]) }}" tempestconfRun: "{{ cifmw_tempest_tempestconf_config_defaults | combine(cifmw_tempest_tempestconf_config | default({})) }}" + cleanup: "{{ cifmw_test_operator_tempest_cleanup }}" workflow: "{{ cifmw_test_operator_tempest_workflow }}" # Section 3: tobiko parameters - used when run_test_fw is 'tobiko' +cifmw_test_operator_tobiko_name: "tobiko-tests" cifmw_test_operator_tobiko_registry: quay.io cifmw_test_operator_tobiko_namespace: podified-antelope-centos9 cifmw_test_operator_tobiko_container: openstack-tobiko @@ -161,6 +165,7 @@ cifmw_test_operator_tobiko_config: workflow: "{{ cifmw_test_operator_tobiko_workflow }}" # Section 4: ansibletest parameters - used when run_test_fw is 'ansibletest' +cifmw_test_operator_ansibletest_name: "ansibletest" cifmw_test_operator_ansibletest_registry: quay.io cifmw_test_operator_ansibletest_namespace: podified-antelope-centos9 cifmw_test_operator_ansibletest_container: openstack-ansible-tests @@ -204,6 +209,7 @@ cifmw_test_operator_ansibletest_config: debug: "{{ cifmw_test_operator_ansibletest_debug }}" # Section 5: horizontest parameters - used when run_test_fw is 'horizontest' +cifmw_test_operator_horizontest_name: "horizontest-tests" cifmw_test_operator_horizontest_registry: quay.io cifmw_test_operator_horizontest_namespace: podified-antelope-centos9 cifmw_test_operator_horizontest_container: openstack-horizontest diff --git a/roles/test_operator/tasks/run-test-operator-job.yml b/roles/test_operator/tasks/run-test-operator-job.yml index 7ef0c308aa..2299b250b3 100644 --- a/roles/test_operator/tasks/run-test-operator-job.yml +++ b/roles/test_operator/tasks/run-test-operator-job.yml @@ -115,7 +115,7 @@ apiVersion: v1 kind: Pod metadata: - name: "test-operator-logs-pod-{{ run_test_fw }}" + name: "test-operator-logs-pod-{{ run_test_fw }}-{{ test_operator_job_name }}" namespace: "{{ cifmw_test_operator_namespace }}" spec: containers: @@ -134,7 +134,7 @@ context: "{{ cifmw_openshift_context | default(omit) }}" namespace: "{{ cifmw_test_operator_namespace }}" kind: Pod - name: "test-operator-logs-pod-{{ run_test_fw }}" + name: "test-operator-logs-pod-{{ run_test_fw }}-{{ test_operator_job_name }}" wait: true register: logs_pod until: logs_pod.resources[0].status.phase == "Running" @@ -149,7 +149,7 @@ pod_path: mnt/logs-{{ test_operator_job_name }}-step-{{ index }} ansible.builtin.shell: > oc cp -n {{ cifmw_test_operator_namespace }} - openstack/test-operator-logs-pod-{{ run_test_fw }}:{{ pod_path }} + openstack/test-operator-logs-pod-{{ run_test_fw }}-{{ test_operator_job_name }}:{{ pod_path }} {{ cifmw_test_operator_artifacts_basedir }} loop: "{{ logsPVCs.resources }}" loop_control: @@ -228,6 +228,7 @@ name: "{{ test_operator_job_name }}" namespace: "{{ cifmw_test_operator_namespace }}" wait: true + wait_timeout: 600 - name: Delete CRD for {{ run_test_fw }} kubernetes.core.k8s: @@ -240,6 +241,7 @@ name: "{{ test_operator_crd_name }}" namespace: "{{ cifmw_test_operator_namespace }}" wait: true + wait_timeout: 600 - name: Delete test-operator-logs-pod kubernetes.core.k8s: @@ -249,9 +251,10 @@ kind: Pod state: absent api_version: v1 - name: "test-operator-logs-pod-{{ run_test_fw }}" + name: "test-operator-logs-pod-{{ run_test_fw }}-{{ test_operator_job_name }}" namespace: "{{ cifmw_test_operator_namespace }}" wait: true + wait_timeout: 600 when: - cifmw_test_operator_cleanup | bool and not cifmw_test_operator_dry_run | bool or cifmw_test_operator_delete_logs_pod | bool diff --git a/roles/test_operator/vars/main.yml b/roles/test_operator/vars/main.yml index e56ae73a72..d97639b5e7 100644 --- a/roles/test_operator/vars/main.yml +++ b/roles/test_operator/vars/main.yml @@ -14,10 +14,6 @@ # under the License. cifmw_test_operator_controller_priv_key_secret_name: "test-operator-controller-priv-key" -cifmw_test_operator_tempest_name: "tempest-tests" -cifmw_test_operator_tobiko_name: "tobiko-tests" -cifmw_test_operator_ansibletest_name: "ansibletest" -cifmw_test_operator_horizontest_name: "horizontest-tests" cifmw_test_operator_tempest_kind_name: "Tempest" cifmw_test_operator_tobiko_kind_name: "Tobiko" cifmw_test_operator_ansibletest_kind_name: "AnsibleTest" diff --git a/roles/update_containers/defaults/main.yml b/roles/update_containers/defaults/main.yml index 4c6f915e59..95142c4136 100644 --- a/roles/update_containers/defaults/main.yml +++ b/roles/update_containers/defaults/main.yml @@ -39,8 +39,10 @@ cifmw_update_containers_org: "podified-antelope-centos9" cifmw_update_containers_tag: "current-podified" cifmw_update_containers_openstack: false cifmw_update_containers_rollback: false -cifmw_update_containers_cindervolumes: [] -cifmw_update_containers_manilashares: [] +cifmw_update_containers_cindervolumes: + - default +cifmw_update_containers_manilashares: + - default # cifmw_update_containers_ansibleee_image_url: # cifmw_update_containers_edpm_image_url: # cifmw_update_containers_ipa_image_url: diff --git a/scenarios/reproducers/dt-nfv-ovs-dpdk-sriov-hci.yml b/scenarios/reproducers/dt-nfv-ovs-dpdk-sriov-hci.yml index 6ab7985193..4aa27ae06d 100644 --- a/scenarios/reproducers/dt-nfv-ovs-dpdk-sriov-hci.yml +++ b/scenarios/reproducers/dt-nfv-ovs-dpdk-sriov-hci.yml @@ -5,7 +5,7 @@ cifmw_architecture_scenario: "nfv-ovs-dpdk-sriov-hci" # controller-0 as-is and be consumed by the `deploy-va.sh` script. # Please note, all paths are on the controller-0, meaning managed by the # Framework. Please do not edit them! -_arch_repo: "/home/zuul/src/github.com/openstack-k8s-operators/architecture" +_arch_repo: "{{ cifmw_architecture_repo | default('/home/zuul/src/github.com/openstack-k8s-operators/architecture') }}" # HERE if you want to override kustomization, you can uncomment this parameter # and push the data structure you want to apply. diff --git a/scenarios/reproducers/va-dcn.yml b/scenarios/reproducers/va-dcn.yml index 595442ff6f..87af087a83 100644 --- a/scenarios/reproducers/va-dcn.yml +++ b/scenarios/reproducers/va-dcn.yml @@ -15,6 +15,7 @@ cifmw_devscripts_cinder_volume_pvs: [] cifmw_run_tests: false cifmw_arch_automation_file: dcn.yaml cifmw_libvirt_manager_pub_net: ocpbm +cifmw_reproducer_validate_network_host: "192.168.111.9" cifmw_libvirt_manager_default_gw_nets: - ocpbm - dcn1_tr diff --git a/scenarios/reproducers/va-hci.yml b/scenarios/reproducers/va-hci.yml index 7351042fa0..422241a29a 100644 --- a/scenarios/reproducers/va-hci.yml +++ b/scenarios/reproducers/va-hci.yml @@ -114,3 +114,9 @@ cifmw_ceph_daemons_layout: dashboard_enabled: false cephfs_enabled: true ceph_nfs_enabled: false + +# Vars related to update_containers cinder volume and manila share +cifmw_update_containers_cindervolumes: + - ceph +cifmw_update_containers_manilashares: + - share1 diff --git a/scenarios/reproducers/va-pidone.yml b/scenarios/reproducers/va-pidone.yml index 1c4c0a0941..b7f2536182 100644 --- a/scenarios/reproducers/va-pidone.yml +++ b/scenarios/reproducers/va-pidone.yml @@ -61,6 +61,8 @@ cifmw_libvirt_manager_configuration: image_local_dir: "{{ cifmw_basedir }}/images/" disk_file_name: "ocp_master" disksize: "100" + extra_disks_num: 4 + extra_disks_size: "100G" cpus: 10 memory: 32 nets: @@ -74,6 +76,8 @@ cifmw_libvirt_manager_configuration: image_local_dir: "{{ cifmw_basedir }}/images/" disk_file_name: "ocp_worker" disksize: "100" + extra_disks_num: 4 + extra_disks_size: "100G" cpus: 10 memory: 16 nets: @@ -139,3 +143,15 @@ cifmw_test_operator_tolerations: effect: "NoExecute" cifmw_test_operator_node_selector: kubernetes.io/hostname: worker-3 + +cifmw_devscripts_create_logical_volume: true + +# Set Logical Volume Manager Storage by default for local storage +cifmw_use_lvms: true +cifmw_lvms_disk_list: + - /dev/vdb + - /dev/vdc + - /dev/vdd + +# lvms-operator tolerations: +cifmw_lvms_storage_tolerations: "{{ cifmw_test_operator_tolerations }}" diff --git a/tests/unit/module_utils/net_map/test_networking_definitions_group_template.py b/tests/unit/module_utils/net_map/test_networking_definitions_group_template.py index 7de61ecacc..f50d2dfb70 100644 --- a/tests/unit/module_utils/net_map/test_networking_definitions_group_template.py +++ b/tests/unit/module_utils/net_map/test_networking_definitions_group_template.py @@ -266,6 +266,28 @@ def test_group_template_definition_parse_invalid_range_fail(): assert exc_info.value.field == "length" assert exc_info.value.invalid_value == 0 + # Test mix of single and dual-stack fields + invalid_range = {"start": 10, "length": 10} + group_template_definition_raw = { + "networks": { + first_net.name: { + "range": invalid_range, + "range-v4": {"start": 100, "length": 0}, + }, + }, + } + + with pytest.raises(exceptions.NetworkMappingValidationError) as exc_info: + networking_definition.GroupTemplateDefinition( + inventory_group, group_template_definition_raw, networks_definitions + ) + assert exc_info.value.field == "range" + assert exc_info.value.invalid_value == invalid_range + assert "network_name" in exc_info.value.details + assert exc_info.value.details["network_name"] == first_net.name + assert exc_info.value.parent_name == inventory_group + assert exc_info.value.parent_type == "host-template" + def test_group_template_definition_parse_invalid_net_fail(): # Test invalid start value diff --git a/zuul.d/adoption.yaml b/zuul.d/adoption.yaml index 8d700ce779..0fd6b569da 100644 --- a/zuul.d/adoption.yaml +++ b/zuul.d/adoption.yaml @@ -107,6 +107,7 @@ Has ceph, not TLS. Uses a content provider. parent: adoption-standalone-to-crc-ceph files: + # ci-framework - ^playbooks/01-bootstrap.yml - ^playbooks/02-infra.yml - ^playbooks/06-deploy-edpm.yml @@ -119,8 +120,14 @@ - ^roles/repo_setup/(defaults|files|handlers|library|lookup_plugins|module_utils|tasks|templates|vars).* - ^hooks/playbooks/fetch_compute_facts.yml - ^zuul.d/adoption.yaml + # openstack-operator - go.mod - apis/go.mod + - ^config/crd/bases/.* + - ^controllers/core/.* + - ^controllers/dataplane/.* + - ^pkg/dataplane/.* + - ^pkg/openstack/.* required-projects: - openstack-k8s-operators/openstack-operator irrelevant-files: @@ -165,6 +172,7 @@ - roles/virtualbmc - tests?\/functional - zuul.d/molecule.* + - zuui.d/trigger_jobs.yaml # NOTE(marios): need to keep this old job because of zuul branches, see comments at OSPRH-8452 - job: diff --git a/zuul.d/base.yaml b/zuul.d/base.yaml index 0a34670ca6..441b296e22 100644 --- a/zuul.d/base.yaml +++ b/zuul.d/base.yaml @@ -63,6 +63,7 @@ - roles/virtualbmc - roles/validations - zuul.d/molecule.* + - zuui.d/trigger_jobs.yaml # Other openstack operators - containers/ci - .ci-operator.yaml @@ -216,6 +217,7 @@ required-projects: *multinode_edpm_rp roles: *multinode_edpm_roles pre-run: + - ci/playbooks/bootstrap-networking-mapper.yml - ci/playbooks/crc/reconfigure-kubelet.yml - ci/playbooks/multinode-customizations.yml post-run: *multinode_edpm_post_run @@ -236,6 +238,7 @@ required-projects: *multinode_edpm_rp roles: *multinode_edpm_roles pre-run: + - ci/playbooks/bootstrap-networking-mapper.yml - ci/playbooks/crc/reconfigure-kubelet.yml - ci/playbooks/multinode-customizations.yml post-run: *multinode_edpm_post_run @@ -305,4 +308,4 @@ pre-run: - ci/playbooks/e2e-prepare.yml - ci/playbooks/dump_zuul_data.yml - - ci/playbooks/pre-ci-bootstrap.yml + - ci/playbooks/bootstrap-networking-mapper.yml diff --git a/zuul.d/molecule.yaml b/zuul.d/molecule.yaml index 1f574932c9..0835008b87 100644 --- a/zuul.d/molecule.yaml +++ b/zuul.d/molecule.yaml @@ -202,6 +202,17 @@ parent: cifmw-molecule-base vars: TEST_RUN: cifmw_create_admin +- job: + files: + - ^common-requirements.txt + - ^test-requirements.txt + - ^roles/cifmw_ntp/(defaults|files|handlers|library|lookup_plugins|module_utils|molecule|tasks|templates|vars).* + - ^ci/playbooks/molecule.* + - ^.config/molecule/.* + name: cifmw-molecule-cifmw_ntp + parent: cifmw-molecule-base + vars: + TEST_RUN: cifmw_ntp - job: files: - ^common-requirements.txt diff --git a/zuul.d/projects.yaml b/zuul.d/projects.yaml index 10be776c70..c6e5a54e39 100644 --- a/zuul.d/projects.yaml +++ b/zuul.d/projects.yaml @@ -33,6 +33,7 @@ - cifmw-molecule-cifmw_cephadm - cifmw-molecule-cifmw_create_admin - cifmw-molecule-cifmw_external_dns + - cifmw-molecule-cifmw_ntp - cifmw-molecule-cifmw_test_role - cifmw-molecule-compliance - cifmw-molecule-config_drive diff --git a/zuul.d/trigger_jobs.yaml b/zuul.d/trigger_jobs.yaml index f5db1641ad..d226b3ade0 100644 --- a/zuul.d/trigger_jobs.yaml +++ b/zuul.d/trigger_jobs.yaml @@ -9,7 +9,7 @@ - ^roles/cert_manager/(defaults|files|handlers|library|lookup_plugins|module_utils|tasks|templates|vars).* - ^roles/cifmw_ceph*/(defaults|files|handlers|library|lookup_plugins|module_utils|tasks|templates|vars).* - ^roles/cifmw_external_dns/(defaults|files|handlers|library|lookup_plugins|module_utils|tasks|templates|vars).* - - ^roles/ci_gen_kustomize/(defaults|files|handlers|library|lookup_plugins|module_utils|tasks|templates|vars).* + - ^roles/ci_gen_kustomize_values/(defaults|files|handlers|library|lookup_plugins|module_utils|tasks|templates|vars).* - ^roles/ci_lvms_storage/(defaults|files|handlers|library|lookup_plugins|module_utils|tasks|templates|vars).* - ^roles/ci_nmstate/(defaults|files|handlers|library|lookup_plugins|module_utils|tasks|templates|vars).* - ^roles/config_drive/(defaults|files|handlers|library|lookup_plugins|module_utils|tasks|templates|vars).* @@ -28,6 +28,7 @@ - ^roles/ssh_jumper/(defaults|files|handlers|library|lookup_plugins|module_utils|tasks|templates|vars).* - ^roles/virtualbmc/(defaults|files|handlers|library|lookup_plugins|module_utils|tasks|templates|vars).* - ^playbooks/06-deploy-architecture.yml + - ^plugins/module_utils/net_map/(networking_definition.py|exceptions.py) vars: # It will create a file trigger_va_hci trigger_job_name: "va_hci"