From 1baf7b33068674ef214024ad5b252a26e34ba06b Mon Sep 17 00:00:00 2001 From: rabi Date: Sun, 7 Dec 2025 11:51:29 +0530 Subject: [PATCH] [multiple] Changes to run playbooks to zuul host This adds an option to run playbooks on zuul host rather than controller-0 and converts minor update job to use it. Signed-off-by: rabi --- ci/playbooks/edpm/update.yml | 42 +- ci/playbooks/edpm_baremetal_update/run.yml | 116 +++-- ci/playbooks/edpm_baremetal_update/update.yml | 26 +- reproducer.yml | 27 +- roles/reproducer/defaults/main.yml | 5 + roles/reproducer/tasks/ci_job.yml | 130 ++++- .../reproducer/tasks/configure_zuul_host.yml | 455 ++++++++++++++++++ roles/reproducer/tasks/libvirt_layout.yml | 39 +- roles/reproducer/tasks/main.yml | 129 ++++- roles/update/tasks/update_variant_ci.yml | 258 ++++++++++ zuul.d/edpm.yaml | 4 + 11 files changed, 1168 insertions(+), 63 deletions(-) create mode 100644 roles/reproducer/tasks/configure_zuul_host.yml create mode 100644 roles/update/tasks/update_variant_ci.yml diff --git a/ci/playbooks/edpm/update.yml b/ci/playbooks/edpm/update.yml index c2e5e501cd..932c202b81 100644 --- a/ci/playbooks/edpm/update.yml +++ b/ci/playbooks/edpm/update.yml @@ -1,4 +1,6 @@ --- +# When cifmw_run_on_zuul_host is true, this playbook directly imports update-edpm.yml +# instead of running nested ansible-playbook commands. - name: "Run ci/playbooks/edpm/update.yml" hosts: "{{ cifmw_zuul_target_host | default('all') }}" gather_facts: true @@ -15,7 +17,45 @@ path: "{{ ansible_user_dir }}/ci-framework-data/artifacts/edpm-ansible.yml" register: edpm_file - - name: Run Podified EDPM update + - name: Load parameters for direct execution + when: cifmw_run_on_zuul_host | default(false) | bool + block: + - name: Load group vars + ansible.builtin.include_vars: + file: "{{ ansible_user_dir }}/src/github.com/openstack-k8s-operators/ci-framework/group_vars/all.yml" + ignore_errors: true + + - name: Load scenario files + ansible.builtin.include_vars: + file: "{{ item }}" + loop: + - "{{ ansible_user_dir }}/src/github.com/openstack-k8s-operators/ci-framework/scenarios/centos-9/base.yml" + - "{{ ansible_user_dir }}/src/github.com/openstack-k8s-operators/ci-framework/scenarios/centos-9/edpm_ci.yml" + ignore_errors: true + + - name: Load edpm-ansible.yml if exists + when: edpm_file.stat.exists + ansible.builtin.include_vars: + file: "{{ ansible_user_dir }}/ci-framework-data/artifacts/edpm-ansible.yml" + ignore_errors: true + + - name: Load all parameters from parameters directory + vars: + provided_dir: "{{ ansible_user_dir }}/ci-framework-data/artifacts/parameters" + ansible.builtin.include_role: + name: cifmw_helpers + tasks_from: var_dir.yml + + - name: Set update_playbook_run fact + ansible.builtin.set_fact: + update_playbook_run: true + + - name: Directly import update-edpm.yml playbook (zuul host execution) + when: cifmw_run_on_zuul_host | default(false) | bool + ansible.builtin.import_playbook: update-edpm.yml + + - name: Run Podified EDPM update via nested ansible-playbook (controller-0 execution) + when: not (cifmw_run_on_zuul_host | default(false) | bool) ansible.builtin.command: chdir: "{{ ansible_user_dir }}/src/github.com/openstack-k8s-operators/ci-framework" cmd: >- diff --git a/ci/playbooks/edpm_baremetal_update/run.yml b/ci/playbooks/edpm_baremetal_update/run.yml index 0c3d8415f7..8717d8b34c 100644 --- a/ci/playbooks/edpm_baremetal_update/run.yml +++ b/ci/playbooks/edpm_baremetal_update/run.yml @@ -84,44 +84,84 @@ - name: Override operator build output with pre-update index image for Phase 1 ansible.builtin.set_fact: - cifmw_operator_build_output_pre_update: >- - {{ - { - 'cifmw_operator_build_output': { - 'operators': { - 'openstack-operator': { - 'image_catalog': cifmw_minor_update_pre_update_index_image - } - } - } - } - }} + cifmw_operator_build_output: + operators: + openstack-operator: + image_catalog: "{{ cifmw_minor_update_pre_update_index_image }}" - - name: Phase 1 - Deploy with pre-update index image using deploy-edpm.yml + - name: Load parameters for direct execution block: - - name: Write pre-update operator build output to temporary file - ansible.builtin.copy: - dest: "{{ ansible_user_dir }}/ci-framework-data/artifacts/operator_build_output_pre_update.yml" - content: "{{ cifmw_operator_build_output_pre_update | to_nice_yaml }}" - mode: "0644" + - name: Load group vars + block: + - name: Read group vars file + ansible.builtin.slurp: + src: "{{ ansible_user_dir }}/src/github.com/openstack-k8s-operators/ci-framework/group_vars/all.yml" + delegate_to: localhost + register: _group_vars_content + + - name: Set group vars as facts + when: "'content' in _group_vars_content" + ansible.builtin.set_fact: + "{{ item.key }}": "{{ item.value }}" + cacheable: true + loop: "{{ _group_vars_content['content'] | b64decode | from_yaml | dict2items }}" + loop_control: + loop_var: item + + - name: Load scenario files + loop: + - "{{ ansible_user_dir }}/src/github.com/openstack-k8s-operators/ci-framework/scenarios/centos-9/base.yml" + - "{{ ansible_user_dir }}/src/github.com/openstack-k8s-operators/ci-framework/scenarios/centos-9/edpm_baremetal_deployment_ci.yml" + loop_control: + loop_var: scenario_file + block: + - name: Read scenario file + ansible.builtin.slurp: + src: "{{ scenario_file }}" + delegate_to: localhost + register: _scenario_file + + - name: Set scenario vars as facts + when: "'content' in _scenario_file" + ansible.builtin.set_fact: + "{{ fact_item.key }}": "{{ fact_item.value }}" + cacheable: true + loop: "{{ _scenario_file['content'] | b64decode | from_yaml | dict2items }}" + loop_control: + loop_var: fact_item + + - name: Load edpm-ansible.yml if exists + when: edpm_file.stat.exists + block: + - name: Read edpm-ansible.yml file + ansible.builtin.slurp: + src: "{{ ansible_user_dir }}/ci-framework-data/artifacts/edpm-ansible.yml" + delegate_to: localhost + register: _edpm_content + + - name: Set edpm vars as facts + when: "'content' in _edpm_content" + ansible.builtin.set_fact: + "{{ item.key }}": "{{ item.value }}" + cacheable: true + loop: "{{ _edpm_content['content'] | b64decode | from_yaml | dict2items }}" + loop_control: + loop_var: item + + - name: Load all parameters from parameters directory + vars: + provided_dir: "{{ ansible_user_dir }}/ci-framework-data/artifacts/parameters" + ansible.builtin.include_role: + name: cifmw_helpers + tasks_from: var_dir.yml + apply: + delegate_to: localhost + become: false + gather_facts: false + + - name: Set cifmw_prepare_openstackversion fact + ansible.builtin.set_fact: + cifmw_prepare_openstackversion: false - - name: Perform Podified and EDPM deployment on compute nodes with virtual baremetal (pre-update) - ansible.builtin.command: - chdir: "{{ ansible_user_dir }}/src/github.com/openstack-k8s-operators/ci-framework" - cmd: >- - ansible-playbook deploy-edpm.yml - -i "{{ ansible_user_dir }}/ci-framework-data/artifacts/zuul_inventory.yml" - -e @group_vars/all.yml - -e @scenarios/centos-9/base.yml - -e @scenarios/centos-9/edpm_baremetal_deployment_ci.yml - {%- if edpm_file.stat.exists %} - -e @{{ ansible_user_dir }}/ci-framework-data/artifacts/edpm-ansible.yml - {%- endif %} - {%- if cifmw_extras is defined %} - {%- for extra_var in cifmw_extras %} - -e "{{ extra_var }}" - {%- endfor %} - {%- endif %} - -e "@{{ ansible_user_dir }}/ci-framework-data/artifacts/parameters/zuul-params.yml" - -e "@{{ ansible_user_dir }}/ci-framework-data/artifacts/operator_build_output_pre_update.yml" - -e "cifmw_prepare_openstackversion=false" +- name: Phase 1 - Deploy with pre-update index image using deploy-edpm.yml + ansible.builtin.import_playbook: ../../../deploy-edpm.yml diff --git a/ci/playbooks/edpm_baremetal_update/update.yml b/ci/playbooks/edpm_baremetal_update/update.yml index 3e53ab1e41..c4e104bf1f 100644 --- a/ci/playbooks/edpm_baremetal_update/update.yml +++ b/ci/playbooks/edpm_baremetal_update/update.yml @@ -1,7 +1,7 @@ --- # CI playbook orchestrator for OpenStack minor version updates. -# This playbook runs on the controller (cifmw_zuul_target_host) and orchestrates -# the update by calling update-edpm.yml on the target host (cifmw_target_host). +# This playbook runs on the zuul host (cifmw_zuul_target_host) and orchestrates +# the update by calling the update role's update_variant_ci.yml task (no nested ansible-playbook). # This playbook depends on content provider variables from CI jobs. # This is Phase 2 of the baremetal update workflow and should be called # sequentially after run.yml (Phase 1). @@ -39,14 +39,14 @@ mode: "0644" when: cifmw_minor_update_index_image is defined - - name: Run update-edpm.yml on target host - ansible.builtin.command: - chdir: "{{ ansible_user_dir }}/src/github.com/openstack-k8s-operators/ci-framework" - cmd: >- - ansible-playbook ci/playbooks/edpm_baremetal_update/update-edpm.yml - -i "{{ ansible_user_dir }}/ci-framework-data/artifacts/zuul_inventory.yml" - -e @group_vars/all.yml - -e "@{{ ansible_user_dir }}/ci-framework-data/artifacts/parameters/zuul-params.yml" - {%- if cifmw_minor_update_index_image is defined %} - -e "@{{ ansible_user_dir }}/ci-framework-data/artifacts/parameters/minor_update_index_image.yml" - {%- endif %} + - name: Load all parameters from parameters directory + vars: + provided_dir: "{{ ansible_user_dir }}/ci-framework-data/artifacts/parameters" + ansible.builtin.include_role: + name: cifmw_helpers + tasks_from: var_dir.yml + + - name: Run minor update using update role + ansible.builtin.include_role: + name: update + tasks_from: update_variant_ci.yml diff --git a/reproducer.yml b/reproducer.yml index 75a92922a1..474571afa9 100644 --- a/reproducer.yml +++ b/reproducer.yml @@ -94,9 +94,10 @@ name: firewalld state: restarted - - name: Run deployment if instructed to + - name: Run deployment if instructed to (controller-0 legacy mode) when: - cifmw_deploy_architecture | default(false) | bool + - not (cifmw_run_on_zuul_host | default(false) | bool) no_log: "{{ cifmw_nolog | default(true) | bool }}" async: "{{ 7200 + cifmw_test_operator_timeout | default(3600) }}" # 2h should be enough to deploy EDPM and rest for tests. poll: 20 @@ -104,13 +105,35 @@ ansible.builtin.command: cmd: "$HOME/deploy-architecture.sh {{ cifmw_deploy_architecture_args | default('') }}" - - name: Run post deployment if instructed to + - name: Run deployment if instructed to (zuul host direct execution) + when: + - cifmw_deploy_architecture | default(false) | bool + - cifmw_run_on_zuul_host | default(false) | bool + no_log: "{{ cifmw_nolog | default(true) | bool }}" + async: "{{ 7200 + cifmw_test_operator_timeout | default(3600) }}" # 2h should be enough to deploy EDPM and rest for tests. + poll: 20 + ansible.builtin.command: + cmd: "$HOME/deploy-architecture.sh {{ cifmw_deploy_architecture_args | default('') }}" + + - name: Run post deployment if instructed to (controller-0 legacy mode) when: - cifmw_deploy_architecture | default(false) | bool - cifmw_post_deployment | default(true) | bool + - not (cifmw_run_on_zuul_host | default(false) | bool) no_log: "{{ cifmw_nolog | default(true) | bool }}" async: "{{ 7200 + cifmw_test_operator_timeout | default(3600) }}" # 2h should be enough to deploy EDPM and rest for tests. poll: 20 delegate_to: controller-0 ansible.builtin.command: cmd: "$HOME/post_deployment.sh {{ cifmw_post_deploy_args | default('') }}" + + - name: Run post deployment if instructed to (zuul host direct execution) + when: + - cifmw_deploy_architecture | default(false) | bool + - cifmw_post_deployment | default(true) | bool + - cifmw_run_on_zuul_host | default(false) | bool + no_log: "{{ cifmw_nolog | default(true) | bool }}" + async: "{{ 7200 + cifmw_test_operator_timeout | default(3600) }}" # 2h should be enough to deploy EDPM and rest for tests. + poll: 20 + ansible.builtin.command: + cmd: "$HOME/post_deployment.sh {{ cifmw_post_deploy_args | default('') }}" diff --git a/roles/reproducer/defaults/main.yml b/roles/reproducer/defaults/main.yml index ca312765df..e2e5082466 100644 --- a/roles/reproducer/defaults/main.yml +++ b/roles/reproducer/defaults/main.yml @@ -50,3 +50,8 @@ cifmw_reproducer_validate_network_host: "controller-0.utility" cifmw_reproducer_validate_ocp_layout: true cifmw_reproducer_ironic_node_name_prefix: + +# Enable zuul host direct execution (Phase 1-3: parallel with controller-0, Phase 4: required) +# When true, playbooks run directly on zuul host instead of delegating to controller-0 VM +# This eliminates nested ansible-playbook execution +cifmw_run_on_zuul_host: false diff --git a/roles/reproducer/tasks/ci_job.yml b/roles/reproducer/tasks/ci_job.yml index 1495cb589e..9914a1883f 100644 --- a/roles/reproducer/tasks/ci_job.yml +++ b/roles/reproducer/tasks/ci_job.yml @@ -14,7 +14,8 @@ ansible.builtin.set_fact: zuul_plays: "{{ extracted | map('last') | list }}" -- name: Run on controller-0 +- name: Run on controller-0 (legacy mode) + when: not (cifmw_run_on_zuul_host | default(false) | bool) delegate_to: controller-0 block: - name: CI reproducer dedicated tasks @@ -176,3 +177,130 @@ no_log: "{{ cifmw_nolog | default(true) | bool }}" ansible.builtin.command: cmd: "{{ _home }}/03-run-job.sh" + +- name: Run on zuul host (direct execution) + when: cifmw_run_on_zuul_host | default(false) | bool + block: + - name: CI reproducer dedicated tasks + when: + - cifmw_job_uri is defined + block: + - name: Ensure directory exists + ansible.builtin.file: + path: "{{ cifmw_reproducer_controller_user_dir }}/{{ job_id }}-params" + mode: "0755" + state: directory + owner: "{{ cifmw_reproducer_controller_user }}" + group: "{{ cifmw_reproducer_controller_user }}" + + - name: Copy environment files to zuul host + tags: + - bootstrap + ansible.builtin.copy: + src: "{{ _reproducer_basedir }}/parameters/" + dest: "{{ cifmw_reproducer_controller_user_dir }}/{{ job_id }}-params" + mode: "0644" + + - name: Inject reproducer dedicated parameter file + tags: + - bootstrap + ansible.builtin.template: + src: "reproducer_params.yml.j2" + dest: "{{ cifmw_reproducer_controller_user_dir }}/{{ job_id }}-params/reproducer_params.yml" + mode: "0644" + + - name: Generate CI job playbook + tags: + - bootstrap + ansible.builtin.template: + dest: "{{ _cifmw_reproducer_framework_location }}/{{ job_id }}_play.yml" + src: "play.yml.j2" + mode: "0644" + + - name: Push content-provider playbook if needed + tags: + - bootstrap + when: > + (operator_content_provider| default(false) | bool) or + (openstack_content_provider| default(false) | bool) + ansible.builtin.template: + dest: "{{ _cifmw_reproducer_framework_location }}/{{ job_id }}_content-provider.yml" + src: "content-provider.yml.j2" + mode: "0644" + + - name: Push extracted network data on zuul host + when: + - not is_molecule | default(false) + tags: + - bootstrap + ansible.builtin.copy: + dest: "{{ cifmw_reproducer_controller_user_dir }}/zuul-network-data.yml" + content: "{{ {'job_network': ci_job_networking} | to_nice_yaml}}" + mode: "0644" + + - name: Push pre-CI job playbook + tags: + - bootstrap + ansible.builtin.copy: + dest: "{{ _cifmw_reproducer_framework_location }}/pre-ci-play.yml" + src: "pre-ci-play.yml" + mode: "0644" + + - name: Push zuul-params.yml to expected location + tags: + - bootstrap + block: + - name: Push extracted content + vars: + zuul_params_filtered: >- + {{ + zuul_vars.zuul | dict2items | + rejectattr('key', 'equalto', 'cifmw_operator_build_output') | + rejectattr('key', 'equalto', 'content_provider_registry_ip') | + items2dict + }} + ansible.builtin.copy: + dest: "{{ cifmw_reproducer_controller_basedir }}/artifacts/parameters/zuul-params.yml" + content: "{{ {'zuul': zuul_params_filtered} | to_nice_yaml }}" + mode: "0644" + + - name: Check for ansible logs file and rotate it + tags: + - always + ansible.builtin.include_tasks: rotate_log.yml + loop: + - "{{ cifmw_reproducer_controller_user_dir }}/ansible.log" + - "{{ cifmw_reproducer_controller_user_dir }}/ansible-pre-ci.log" + - "{{ cifmw_reproducer_controller_user_dir }}/ansible-{{ job_id }}.log" + - "{{ cifmw_reproducer_controller_user_dir }}/ansible-content-provider-bootstrap.log" + + - name: Run playbooks directly (no nested ansible-playbook) + vars: + _home: "{{ cifmw_reproducer_controller_user_dir }}" + run_directory: "{{ _cifmw_reproducer_framework_location }}" + block: + - name: Load parameters for direct execution + ansible.builtin.include_vars: + file: "{{ cifmw_reproducer_controller_basedir }}/artifacts/parameters/zuul-params.yml" + + - name: Run pre-ci-play directly + when: + - not is_molecule | default(false) + tags: + - bootstrap + no_log: "{{ cifmw_nolog | default(true) | bool }}" + ansible.builtin.import_playbook: "{{ run_directory }}/pre-ci-play.yml" + + - name: Run content-provider directly + when: + - (operator_content_provider | default(false) | bool) or + (openstack_content_provider | default(false) | bool) + - cifmw_reproducer_run_content_provider | bool + no_log: "{{ cifmw_nolog | default(true) | bool }}" + ansible.builtin.import_playbook: "{{ run_directory }}/{{ job_id }}_content-provider.yml" + + - name: Run CI job playbook directly + when: + - cifmw_reproducer_run_job | bool + no_log: "{{ cifmw_nolog | default(true) | bool }}" + ansible.builtin.import_playbook: "{{ run_directory }}/{{ job_id }}_play.yml" diff --git a/roles/reproducer/tasks/configure_zuul_host.yml b/roles/reproducer/tasks/configure_zuul_host.yml new file mode 100644 index 0000000000..804571e02c --- /dev/null +++ b/roles/reproducer/tasks/configure_zuul_host.yml @@ -0,0 +1,455 @@ +--- +# Configure zuul host to run playbooks directly without controller-0 VM +# This is Phase 1 of removing controller-0 VM dependency +# This file sets up the zuul host with all dependencies and configuration +# that were previously done on controller-0 VM +- name: Configure zuul host + when: + - cifmw_run_on_zuul_host | default(false) | bool + hosts: localhost + gather_facts: false + vars: + cifmw_sushy_emulator_hypervisor_target: "{{ inventory_hostname }}" + cifmw_sushy_emulator_install_type: podman + cifmw_sushy_emulator_hypervisor_address: >- + {{ inventory_hostname }}.utility + cifmw_sushy_emulator_basedir: "{{ cifmw_reproducer_controller_basedir }}" + cifmw_sushy_emulator_connection_name: "sushy.utility" + cifmw_sushy_emulator_sshkey_path: "{{ cifmw_reproducer_controller_user_dir }}/.ssh/sushy_emulator-key" + cifmw_podman_user_linger: "{{ cifmw_reproducer_controller_user }}" + cifmw_sushy_emulator_libvirt_user: >- + {{ + hostvars[cifmw_sushy_emulator_hypervisor_target].ansible_user_id | + default('zuul') + }} + block: + - name: Ensure directories exist + ansible.builtin.file: + path: "{{ cifmw_reproducer_controller_basedir }}/{{ item }}" + state: directory + mode: "0755" + loop: + - parameters + - artifacts + - artifacts/parameters + + - name: Make cifmw general plugins available for direct execution + ansible.builtin.include_role: + name: cifmw_helpers + tasks_from: symlink_cifmw_collection.yml + + - name: Tweak dnf configuration + become: true + community.general.ini_file: + no_extra_spaces: true + option: "{{ config.option }}" + path: "/etc/dnf/dnf.conf" + section: "{{ config.section | default('main') }}" + state: "{{ config.state | default(omit) }}" + value: "{{ config.value | default(omit) }}" + mode: "0644" + loop: "{{ cifmw_reproducer_dnf_tweaks }}" + loop_control: + label: "{{ config.option }}" + loop_var: 'config' + + - name: Install custom CA if needed + ansible.builtin.import_role: + name: install_ca + + - name: RHEL repository setup for zuul host + become: true + when: + - cifmw_repo_setup_rhos_release_rpm is defined + block: + - name: Get rhos-release and setup repos + ansible.builtin.import_tasks: rhos_release.yml + + - name: Create bundle for CRC + ansible.builtin.shell: + cmd: >- + set -o pipefail; + cat /etc/pki/ca-trust/source/anchors/* > + /etc/pki/ca-trust/source/anchors/rh.crt + creates: "/etc/pki/ca-trust/source/anchors/rh.crt" + + - name: Install some tools + become: true + async: 600 # 10 minutes should be enough + poll: 0 + register: _async_pkg_install + ansible.builtin.package: + name: + - bash-completion + - bind-utils + - git-core + - make + - podman + - python3-jmespath + - python3-netaddr + - python3-pip + - tmux + - vim + - wget + - jq + + - name: Inject command aliases for faster debugging + become: true + ansible.builtin.copy: + dest: "/etc/profile.d/cifmw-aliases.sh" + mode: "0644" + content: |- + # Aliases managed by ci-framework/reproducer/configure_zuul_host.yml + # Feel free to submit PR to get more aliases in the file. + alias oc-job-log="oc logs -f -l job-name=$1" + + - name: Build job inventory for hook usage + tags: + - bootstrap + ansible.builtin.shell: + cmd: >- + cat {{ cifmw_reproducer_basedir }}/reproducer-inventory/* > + {{ cifmw_reproducer_controller_basedir }}/artifacts/zuul_inventory.yml + + - name: Push the MAC mapping data + tags: + - bootstrap + when: + - cifmw_libvirt_manager_mac_map is defined + ansible.builtin.copy: + mode: "0644" + dest: "{{ cifmw_reproducer_controller_basedir }}/parameters/interfaces-info.yml" + content: "{{ cifmw_libvirt_manager_mac_map | to_nice_yaml }}" + + - name: Inject other Hypervisor SSH keys + when: + - hostvars[host]['priv_ssh_key'] is defined + vars: + _ssh_key: "{{ hostvars[host]['priv_ssh_key']['content'] | b64decode }}" + _ssh_host: >- + {{ + hostvars[host]['ansible_host'] | + default(hostvars[host]['inventory_hostname']) + }} + ansible.builtin.copy: + dest: "{{ cifmw_reproducer_controller_user_dir }}/.ssh/ssh_{{ _ssh_host }}" + content: "{{ _ssh_key }}" + mode: "0600" + loop: "{{ hostvars.keys() }}" + loop_control: + label: "{{ host }}" + loop_var: "host" + + - name: Inject remote hypervisor SSH configuration + when: + - hostvars[host]['priv_ssh_key'] is defined + vars: + _ssh_host: >- + {{ + hostvars[host]['ansible_host'] | + default(hostvars[host]['inventory_hostname']) + }} + ansible.builtin.blockinfile: + create: true + mode: "0600" + path: "{{ cifmw_reproducer_controller_user_dir }}/.ssh/config" + marker: "## {mark} {{ _ssh_host }}" + block: |- + Host {{ _ssh_host }} {{ hostvars[host]['inventory_hostname'] }} + Hostname {{ _ssh_host }} + IdentityFile ~/.ssh/ssh_{{ _ssh_host }} + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + User {{ hostvars[host]['ansible_user'] | default(ansible_user_id) }} + loop: "{{ hostvars.keys() }}" + loop_control: + label: "{{ host }}" + loop_var: "host" + + - name: Inject SSH configuration + when: + - hostvars[host].ansible_host is defined + - hostvars[host].ansible_ssh_user is defined + vars: + _vm_type: "{{ host | regex_replace('\\-[0-9]*', '') }}" + _vm_data: "{{ _cifmw_libvirt_manager_layout.vms[_vm_type] }}" + _ocp_name: >- + {{ + host | replace('_', '-') | + replace('ocp-worker', 'worker') | + replace('ocp-master', 'master') + }} + _hostname: >- + {{ + (host is match('^ocp.*')) | + ternary(_ocp_name, host) + }} + ansible.builtin.blockinfile: + create: true + mode: "0600" + path: "{{ cifmw_reproducer_controller_user_dir }}/.ssh/config" + marker: "## {mark} {{ host }}" + block: |- + Host {{ host }} {{ _hostname }} {{ _hostname }}.utility {{ hostvars[host].ansible_host }} + Hostname {{ _hostname }}.utility + User {{ hostvars[host].ansible_ssh_user }} + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + {% if host is match('^ocp.*') %} + IdentityFile ~/.ssh/devscripts_key + {% elif host is match('^crc.*') %} + IdentityFile ~/.ssh/crc_key + {% else %} + IdentityFile ~/.ssh/id_cifw + {% endif %} + loop: "{{ hostvars.keys() }}" + loop_control: + loop_var: host + label: "{{ host }}" + + - name: Create kube directory + ansible.builtin.file: + path: "{{ cifmw_reproducer_controller_user_dir }}/.kube" + state: directory + owner: "{{ cifmw_reproducer_controller_user }}" + group: "{{ cifmw_reproducer_controller_user }}" + mode: "0750" + + - name: Inject kubeconfig content + when: + - _devscripts_kubeconfig.content is defined or + _crc_kubeconfig.content is defined + ansible.builtin.copy: + dest: "{{ cifmw_reproducer_controller_user_dir }}/.kube/config" + content: >- + {{ + (_use_ocp | bool) | + ternary(_devscripts_kubeconfig.content, _crc_kubeconfig.content) | + b64decode + }} + owner: "{{ cifmw_reproducer_controller_user }}" + group: "{{ cifmw_reproducer_controller_user }}" + mode: "0640" + + - name: Inject kubeadmin-password if exists + when: + - _devscripts_kubeadm.content is defined or + _crc_kubeadm.content is defined + ansible.builtin.copy: + dest: "{{ cifmw_reproducer_controller_user_dir }}/.kube/kubeadmin-password" + content: >- + {{ + (_devscripts_kubeadm.content is defined) | + ternary(_devscripts_kubeadm.content, _crc_kubeadm.content) | + b64decode + }} + owner: "{{ cifmw_reproducer_controller_user }}" + group: "{{ cifmw_reproducer_controller_user }}" + mode: "0600" + + - name: Inject devscripts private key if set + when: + - _devscript_privkey.content is defined + ansible.builtin.copy: + dest: "{{ cifmw_reproducer_controller_user_dir }}/.ssh/devscripts_key" + content: "{{ _devscript_privkey.content | b64decode }}" + owner: "{{ cifmw_reproducer_controller_user }}" + group: "{{ cifmw_reproducer_controller_user }}" + mode: "0400" + + - name: Ensure /etc/ci/env is created + become: true + ansible.builtin.file: + path: /etc/ci/env + state: directory + mode: "0755" + + - name: Manage secrets on zuul host + vars: + cifmw_manage_secrets_basedir: "{{ cifmw_reproducer_controller_basedir }}" + cifmw_manage_secrets_owner: "{{ cifmw_reproducer_controller_user }}" + block: + - name: Initialize secret manager + ansible.builtin.import_role: + name: manage_secrets + + - name: Inject secrets + ansible.builtin.import_role: + name: manage_secrets + tasks_from: reproducer.yml + + - name: Inject FQDN in /etc/hosts + become: true + ansible.builtin.blockinfile: + dest: /etc/hosts + block: |- + 127.0.0.2 {{ ansible_default_ipv4.address | default('127.0.0.1') }} + ::2 {{ ansible_default_ipv4.address | default('::1') }} + + - name: Ensure packages are installed + become: true + block: + - name: Check if async file is still available + register: _async_flag + ansible.builtin.stat: + path: >- + /root/.ansible_async/{{ _async_pkg_install.ansible_job_id }} + + - name: Check package install status + when: + - _async_flag.stat.exists + register: _async_status + ansible.builtin.async_status: + jid: "{{ _async_pkg_install.ansible_job_id }}" + until: _async_status.finished + retries: 100 + delay: 5 + + # Deploy Sushy Emulator on the zuul host + - name: Deploy Sushy Emulator service container + tags: + - bootstrap + - bootstrap_layout + when: cifmw_use_sushy_emulator | default(true) | bool + block: + - name: Deploy Sushy Emulator + ansible.builtin.import_role: + name: sushy_emulator + + - name: Generate baremetal-info fact + ansible.builtin.import_tasks: generate_bm_info.yml + + - name: Verify connection to baremetal VMs via Sushy Emulator + ansible.builtin.include_role: + name: sushy_emulator + tasks_from: verify.yml + + - name: Check if common-requirements.txt exists on zuul host + ansible.builtin.stat: + path: "{{ cifmw_reproducer_controller_user_dir }}/{{ cifmw_project_dir }}/common-requirements.txt" + register: _zuul_common_requirements_check + run_once: true + ignore_errors: true + + - name: Install ansible dependencies + register: _async_dep_install + async: 600 # 10 minutes should be more than enough + poll: 0 + ansible.builtin.pip: + requirements: "{{ have_zuul_reqs | ternary(zuul_reqs, remote) }}" + vars: + have_zuul_reqs: "{{ _zuul_common_requirements_check.stat is defined and _zuul_common_requirements_check.stat.exists }}" + zuul_reqs: "{{ cifmw_reproducer_controller_user_dir }}/{{ cifmw_project_dir }}/common-requirements.txt" + remote: https://raw.githubusercontent.com/openstack-k8s-operators/ci-framework/main/common-requirements.txt + + - name: Inject most of the cifmw_ parameters passed to the reproducer run + tags: + - bootstrap_env + vars: + _filtered_vars: >- + {{ + hostvars[inventory_hostname] | default({}) | + dict2items | + selectattr('key', 'match', + '^(pre|post|cifmw)_(?!install_yamls|devscripts).*') | + rejectattr('key', 'equalto', 'cifmw_target_host') | + rejectattr('key', 'equalto', 'cifmw_basedir') | + rejectattr('key', 'equalto', 'cifmw_path') | + rejectattr('key', 'equalto', 'cifmw_extras') | + rejectattr('key', 'equalto', 'cifmw_openshift_kubeconfig') | + rejectattr('key', 'equalto', 'cifmw_openshift_token') | + rejectattr('key', 'equalto', 'cifmw_networking_env_definition') | + rejectattr('key', 'match', '^cifmw_use_(?!lvms).*') | + rejectattr('key', 'match', '^cifmw_reproducer.*') | + rejectattr('key', 'match', '^cifmw_rhol.*') | + rejectattr('key', 'match', '^cifmw_discover.*') | + rejectattr('key', 'match', '^cifmw_libvirt_manager.*') | + rejectattr('key', 'match', '^cifmw_manage_secrets_(pullsecret|citoken).*') | + items2dict + }} + ansible.builtin.copy: + mode: "0644" + dest: "{{ cifmw_reproducer_controller_basedir }}/parameters/reproducer-variables.yml" + content: "{{ _filtered_vars | to_nice_yaml }}" + + - name: Create reproducer-variables.yml symlink to old location + ansible.builtin.file: + dest: "{{ cifmw_reproducer_controller_user_dir }}/reproducer-variables.yml" + src: "{{ cifmw_reproducer_controller_basedir }}/parameters/reproducer-variables.yml" + state: link + + - name: Inject local environment parameters + ansible.builtin.copy: + mode: "0644" + dest: "{{ cifmw_reproducer_controller_basedir }}/parameters/openshift-environment.yml" + content: |- + {% raw %} + --- + cifmw_basedir: "{{ ansible_user_dir }}/ci-framework-data" + cifmw_openshift_login_password_file: >- + {{ ansible_user_dir }}/.kube/kubeadmin-password + cifmw_openshift_login_kubeconfig: >- + {{ ansible_user_dir }}/.kube/config + cifmw_architecture_automation_file: >- + {{ + ( + cifmw_architecture_repo, + 'automation/vars', + cifmw_architecture_scenario~'.yaml' + ) | ansible.builtin.path_join + }} + {% endraw %} + + - name: Create openshift-environment.yml symlink to old location + ansible.builtin.file: + dest: "{{ cifmw_reproducer_controller_user_dir }}/openshift-environment.yml" + src: "{{ cifmw_reproducer_controller_basedir }}/parameters/openshift-environment.yml" + state: link + + - name: Get interfaces-info content + register: _nic_info + ansible.builtin.slurp: + src: "{{ cifmw_reproducer_controller_basedir }}/parameters/interfaces-info.yml" + + - name: Wait for OCP nodes to be ready + when: + - groups.ocps is defined + - groups.ocps | length > 0 + delegate_to: "{{ item }}" + ansible.builtin.wait_for_connection: + sleep: 2 + timeout: 300 + loop: "{{ groups.ocps }}" + + - name: Generate networking definition + vars: + cifmw_networking_mapper_ifaces_info: >- + {{ _nic_info.content | b64decode | from_yaml }} + cifmw_networking_mapper_network_name: >- + {{ _cifmw_libvirt_manager_layout.vms.controller.nets.1 | default('ctlplane') }} + cifmw_networking_mapper_basedir: "{{ cifmw_reproducer_controller_basedir }}" + ansible.builtin.import_role: + name: networking_mapper + + - name: Inject CRC related content if needed + when: + - _use_crc | bool + block: + - name: Inject CRC ssh key + ansible.builtin.copy: + dest: "{{ cifmw_reproducer_controller_user_dir }}/.ssh/crc_key" + content: "{{ crc_priv_key['content'] | b64decode }}" + mode: "0400" + owner: "{{ cifmw_reproducer_controller_user }}" + group: "{{ cifmw_reproducer_controller_user }}" + + - name: Ensure we have all dependencies installed + ansible.builtin.async_status: + jid: "{{ _async_dep_install.ansible_job_id }}" + 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 be682d42d2..2adcc04281 100644 --- a/roles/reproducer/tasks/libvirt_layout.yml +++ b/roles/reproducer/tasks/libvirt_layout.yml @@ -28,8 +28,9 @@ map(attribute="key") }} -- name: Run tasks on controller-0 hypervisor +- name: Run tasks on controller-0 hypervisor (legacy mode) when: + - not (cifmw_run_on_zuul_host | default(false) | bool) - ( _cifmw_libvirt_manager_layout.vms.controller.target is defined and _cifmw_libvirt_manager_layout.vms.controller.target == inventory_hostname @@ -42,12 +43,31 @@ loop_control: loop_var: "host" - - name: Push generated inventory from hypervisor + - name: Push generated inventory from hypervisor to controller-0 ansible.builtin.command: # noqa: command-instead-of-module cmd: >- rsync -r {{ cifmw_reproducer_basedir }}/reproducer-inventory/ {{ cifmw_reproducer_controller_user }}@controller-0:reproducer-inventory +- name: Run tasks on zuul host (direct execution) + when: + - cifmw_run_on_zuul_host | default(false) | bool + - ( + _cifmw_libvirt_manager_layout.vms.controller.target is defined and + _cifmw_libvirt_manager_layout.vms.controller.target == inventory_hostname + ) or + _cifmw_libvirt_manager_layout.vms.controller.target is undefined + block: + - name: Inject remote inventories onto zuul host + ansible.builtin.include_tasks: gather_inventories.yml + loop: "{{ hostvars.keys() }}" + loop_control: + loop_var: "host" + + - name: Keep inventory on zuul host (no push to controller-0) + ansible.builtin.debug: + msg: "Inventory kept on zuul host at {{ cifmw_reproducer_basedir }}/reproducer-inventory/" + - name: Run post tasks in OCP cluster case when: - _use_ocp | bool @@ -62,16 +82,25 @@ ansible.builtin.import_tasks: ocp_post.yml # Configure the controller before CRC. This one will run the networking_mapper -# role, ensuring we have all the needed data on the controller-0. This -# will allow us to configure the CRC node in order to ensure we have +# role, ensuring we have all the needed data on the controller-0 or zuul host. +# This will allow us to configure the CRC node in order to ensure we have # appropriate settings there. -- name: Configure Controller node +- name: Configure Controller node (controller-0 legacy mode) + when: not (cifmw_run_on_zuul_host | default(false) | bool) tags: - bootstrap - bootstrap_layout - bootstrap_env ansible.builtin.include_tasks: configure_controller.yml +- name: Configure zuul host (direct execution) + when: cifmw_run_on_zuul_host | default(false) | bool + tags: + - bootstrap + - bootstrap_layout + - bootstrap_env + ansible.builtin.include_tasks: configure_zuul_host.yml + - name: Configure CRC node if available when: - _use_crc | bool diff --git a/roles/reproducer/tasks/main.yml b/roles/reproducer/tasks/main.yml index deebf619d0..e21f234ade 100644 --- a/roles/reproducer/tasks/main.yml +++ b/roles/reproducer/tasks/main.yml @@ -252,6 +252,15 @@ ternary(_path, [_path, 'ci-framework'] | path_join) }} +- name: Configure zuul host for direct playbook execution + when: + - cifmw_run_on_zuul_host | default(false) | bool + tags: + - bootstrap + - bootstrap_layout + - bootstrap_env + ansible.builtin.include_tasks: configure_zuul_host.yml + - name: Run only on hypervisor with controller-0 when: - ( @@ -266,8 +275,9 @@ - bootstrap ansible.builtin.include_tasks: push_code.yml - - name: Group tasks on controller-0 - delegate_to: controller-0 + - name: Group tasks on controller-0 or zuul host + delegate_to: "{{ 'localhost' if (cifmw_run_on_zuul_host | default(false) | bool) else 'controller-0' }}" + when: not (cifmw_run_on_zuul_host | default(false) | bool) block: - name: Inject CI Framework motd become: true @@ -324,6 +334,62 @@ name: openshift_setup tasks_from: patch_network_operator.yml + - name: Group tasks on zuul host (direct execution) + when: cifmw_run_on_zuul_host | default(false) | bool + block: + - name: Inject CI Framework motd + become: true + ansible.builtin.template: + dest: "/etc/motd.d/cifmw.motd" + src: "motd.j2" + mode: "0644" + + - name: Rotate some logs + tags: + - always + ansible.builtin.include_tasks: rotate_log.yml + loop: + - "{{ cifmw_reproducer_controller_user_dir }}/ansible-bootstrap.log" + + - name: Bootstrap environment on zuul host + vars: + cifmw_basedir: "{{ cifmw_reproducer_controller_basedir }}" + ansible_user_dir: "{{ cifmw_reproducer_controller_user_dir }}" + ansible_user_id: "{{ cifmw_reproducer_controller_user }}" + no_log: "{{ cifmw_nolog | default(true) | bool }}" + ansible.builtin.import_role: + name: cifmw_setup + tasks_from: bootstrap.yml + + - name: Install dev tools from install_yamls on zuul host + environment: + ANSIBLE_LOG_PATH: "~/ansible-bootstrap.log" + vars: + _devsetup_path: >- + {{ + ( + cifmw_reproducer_controller_user_dir, + 'src/github.com/openstack-k8s-operators/install_yamls', + 'devsetup' + ) | ansible.builtin.path_join + }} + no_log: "{{ cifmw_nolog | default(true) | bool }}" + ansible.builtin.command: + chdir: "{{ _devsetup_path }}" + cmd: >- + ansible-playbook -i ~/ci-framework-data/artifacts/zuul_inventory.yml + download_tools.yaml --tags kustomize,kubectl + creates: "{{ cifmw_reproducer_controller_user_dir }}/bin/kubectl" + + - name: Configure CRC network if needed + when: + - _use_crc | bool + vars: + cifmw_openshift_kubeconfig: "{{ cifmw_reproducer_controller_user_dir }}/.kube/config" + ansible.builtin.include_role: + name: openshift_setup + tasks_from: patch_network_operator.yml + # Run from the hypervisor - name: Ensure OCP cluster is stable when: @@ -348,9 +414,10 @@ ansible.builtin.include_role: name: openshift_adm -- name: Run from controller-0 +- name: Run from controller-0 (legacy mode) when: - _has_openshift + - not (cifmw_run_on_zuul_host | default(false) | bool) - ( _cifmw_libvirt_manager_layout.vms.controller.target is defined and _cifmw_libvirt_manager_layout.vms.controller.target == inventory_hostname @@ -404,3 +471,59 @@ mode: "0755" owner: "{{ cifmw_reproducer_controller_user }}" group: "{{ cifmw_reproducer_controller_user }}" + +- name: Run from zuul host (direct execution) + when: + - _has_openshift + - cifmw_run_on_zuul_host | default(false) | bool + - ( + _cifmw_libvirt_manager_layout.vms.controller.target is defined and + _cifmw_libvirt_manager_layout.vms.controller.target == inventory_hostname + ) or + _cifmw_libvirt_manager_layout.vms.controller.target is undefined + block: + - name: Emulate CI job + when: + - cifmw_job_uri is defined + ansible.builtin.include_tasks: ci_job.yml + + - name: Prepare architecture-based deployment + when: + - cifmw_architecture_scenario is defined + - cifmw_job_uri is undefined + tags: + - deploy_architecture + ansible.builtin.include_tasks: + file: configure_architecture.yml + apply: + tags: + - deploy_architecture + + - name: Prepare architecture-based post deployment + when: + - cifmw_architecture_scenario is defined + - cifmw_job_uri is undefined + tags: + - deploy_architecture + ansible.builtin.include_tasks: + file: configure_post_deployment.yml + + - name: Prepare ci-like EDPM deploy (direct execution) + when: + - cifmw_job_uri is undefined + vars: + run_directory: "{{ _cifmw_reproducer_framework_location }}" + exports: + ANSIBLE_LOG_PATH: "~/ansible-deploy-edpm.log" + default_extravars: + - "@scenarios/centos-9/base.yml" + - "@scenarios/centos-9/edpm_ci.yml" + - "cifmw_openshift_password='{{ cifmw_openshift_password }}'" + extravars: "{{ cifmw_reproducer_play_extravars }}" + playbook: "deploy-edpm.yml" + ansible.builtin.template: + dest: "{{ cifmw_reproducer_controller_user_dir }}/deploy-edpm.sh" + src: "script.sh.j2" + mode: "0755" + owner: "{{ cifmw_reproducer_controller_user }}" + group: "{{ cifmw_reproducer_controller_user }}" diff --git a/roles/update/tasks/update_variant_ci.yml b/roles/update/tasks/update_variant_ci.yml new file mode 100644 index 0000000000..1b4c7162db --- /dev/null +++ b/roles/update/tasks/update_variant_ci.yml @@ -0,0 +1,258 @@ +--- +# CI update variant for OpenStack minor version updates. +# This task file performs a minor version update of an OpenStack deployment +# using index images and install_yamls make targets. +# This task file depends on content provider variables from CI jobs. +# It runs on cifmw_target_host in the same execution context as deploy-edpm.yml, +# so it can use the install_yamls_makes role that was generated during bootstrap. +# This variant is specifically designed for CI workflows with index image-based updates. + +- name: Delete success flag if exists + ansible.builtin.file: + path: "{{ ansible_user_dir }}/cifmw-success" + state: absent + +- name: Set cifmw_basedir if not defined + ansible.builtin.set_fact: + cifmw_basedir: "{{ cifmw_basedir | default(ansible_user_dir ~ '/ci-framework-data') }}" + +- name: Set update artifacts basedir if not defined + ansible.builtin.set_fact: + cifmw_update_artifacts_basedir: "{{ cifmw_update_artifacts_basedir | default(cifmw_basedir ~ '/tests/update') }}" + +- name: Initialize monitoring + ansible.builtin.include_role: + name: update + tasks_from: init_monitoring.yml + +- name: Load parameters files + ansible.builtin.include_vars: + dir: "{{ cifmw_basedir }}/artifacts/parameters" + +- name: Set install_yamls environment for minor update phase + ansible.builtin.set_fact: + cifmw_minor_update_env: >- + {{ + (cifmw_install_yamls_environment | default({})) | + combine({'PATH': cifmw_path | default(ansible_user_dir ~ '/.crc/bin:' ~ ansible_user_dir ~ '/.crc/bin/oc:' ~ ansible_user_dir ~ '/bin:' ~ ansible_env.PATH)}) | + combine({'OPENSTACK_IMG': cifmw_minor_update_index_image}) | + combine({'BMO_CLEANUP': false}) + }} + +- name: Set update step to Running openstack cleanup + ansible.builtin.command: + cmd: > + {{ cifmw_update_artifacts_basedir }}/update_event.sh + Running openstack cleanup + +- name: Run make openstack_cleanup + vars: + make_openstack_cleanup_env: "{{ cifmw_minor_update_env }}" + make_openstack_cleanup_dryrun: false + ansible.builtin.include_role: + name: 'install_yamls_makes' + tasks_from: 'make_openstack_cleanup' + +- name: Set update step to Running openstack wait + ansible.builtin.command: + cmd: > + {{ cifmw_update_artifacts_basedir }}/update_event.sh + Running openstack wait + +- name: Run make openstack_wait (minor update) + vars: + make_openstack_wait_env: "{{ cifmw_minor_update_env }}" + make_openstack_wait_dryrun: false + ansible.builtin.include_role: + name: 'install_yamls_makes' + tasks_from: 'make_openstack_wait' + +- name: Set update step to Running openstack init + ansible.builtin.command: + cmd: > + {{ cifmw_update_artifacts_basedir }}/update_event.sh + Running openstack init + +- name: Run make openstack_init (minor update) + vars: + make_openstack_init_env: "{{ cifmw_minor_update_env }}" + make_openstack_init_dryrun: false + ansible.builtin.include_role: + name: 'install_yamls_makes' + tasks_from: 'make_openstack_init' + +- name: Set update step to Waiting for new version to be available + ansible.builtin.command: + cmd: > + {{ cifmw_update_artifacts_basedir }}/update_event.sh + Waiting for new version to be available + +- name: Wait for availableVersion to be different from deployedVersion + kubernetes.core.k8s_info: + kubeconfig: "{{ cifmw_openshift_kubeconfig }}" + api_key: "{{ cifmw_openshift_token | default(omit) }}" + context: "{{ cifmw_openshift_context | default(omit) }}" + api_version: core.openstack.org/v1beta1 + kind: OpenStackVersion + namespace: "{{ cifmw_install_yamls_defaults['NAMESPACE'] | default('openstack') }}" + register: openstackversion_wait_info + retries: 10 + delay: 60 + until: > + openstackversion_wait_info.resources is defined and + openstackversion_wait_info.resources | length > 0 and + openstackversion_wait_info.resources[0].status.availableVersion is defined and + openstackversion_wait_info.resources[0].status.deployedVersion is defined and + openstackversion_wait_info.resources[0].status.availableVersion != openstackversion_wait_info.resources[0].status.deployedVersion + +- name: Get available version from OpenStackVersion CR + ansible.builtin.set_fact: + cifmw_minor_update_target_version: "{{ openstackversion_wait_info.resources[0].status.availableVersion }}" + +- name: Set update step to Patching OpenStackVersion CR + ansible.builtin.command: + cmd: > + {{ cifmw_update_artifacts_basedir }}/update_event.sh + Patching OpenStackVersion CR with version {{ cifmw_minor_update_target_version }} + +- name: Patch OpenStackVersion CR availableVersion + vars: + make_openstack_patch_version_env: "{{ cifmw_minor_update_env }}" + make_openstack_patch_version_dryrun: false + ansible.builtin.include_role: + name: 'install_yamls_makes' + tasks_from: 'make_openstack_patch_version' + +- name: Set vars related to update_containers content provider + when: + - content_provider_os_registry_url is defined + - content_provider_os_registry_url != 'null' + ansible.builtin.set_fact: + cifmw_update_containers_registry: "{{ content_provider_os_registry_url | split('/') | first }}" + cifmw_update_containers_org: "{{ content_provider_os_registry_url | split('/') | last }}" + cifmw_update_containers_tag: "{{ content_provider_dlrn_md5_hash }}" + cifmw_update_containers_openstack: true + +- name: Set update step to Updating container images + when: >- + (cifmw_update_containers_edpm_image_url is defined and + cifmw_update_containers_openstack is defined and + cifmw_update_containers_openstack | bool) or + (cifmw_update_containers_ansibleee_image_url is defined) or + (cifmw_update_containers_openstack is defined and + cifmw_update_containers_openstack | bool) or + (cifmw_update_containers_watcher is defined and + cifmw_update_containers_watcher | bool) + ansible.builtin.command: + cmd: > + {{ cifmw_update_artifacts_basedir }}/update_event.sh + Updating container images + +- name: Prepare and patch OpenStackVersion CR for update + vars: + cifmw_update_containers_metadata: "controlplane" + cifmw_update_containers: true + ansible.builtin.include_role: + name: update_containers + when: >- + (cifmw_update_containers_edpm_image_url is defined and + cifmw_update_containers_openstack is defined and + cifmw_update_containers_openstack | bool) or + (cifmw_update_containers_ansibleee_image_url is defined) or + (cifmw_update_containers_openstack is defined and + cifmw_update_containers_openstack | bool) or + ( cifmw_update_containers_watcher is defined and + cifmw_update_containers_watcher | bool) + +- name: Set update step to Starting the CI update sequence + ansible.builtin.command: + cmd: > + {{ cifmw_update_artifacts_basedir }}/update_event.sh + Starting the CI update sequence + +- name: Run make openstack_update_run + vars: + make_openstack_update_run_env: "{{ cifmw_minor_update_env }}" + make_openstack_update_run_params: + TIMEOUT: "1200s" + OPENSTACK_VERSION: "{{ cifmw_minor_update_target_version }}" + make_openstack_update_run_dryrun: false + ansible.builtin.include_role: + name: 'install_yamls_makes' + tasks_from: 'make_openstack_update_run' + +- name: Set update step to Verifying update completion + ansible.builtin.command: + cmd: > + {{ cifmw_update_artifacts_basedir }}/update_event.sh + Verifying update completion + +- name: Verify deployed version matches target version + kubernetes.core.k8s_info: + kubeconfig: "{{ cifmw_openshift_kubeconfig }}" + api_key: "{{ cifmw_openshift_token | default(omit) }}" + context: "{{ cifmw_openshift_context | default(omit) }}" + api_version: core.openstack.org/v1beta1 + kind: OpenStackVersion + namespace: "{{ cifmw_install_yamls_defaults['NAMESPACE'] | default('openstack') }}" + register: openstackversion_verify_info + until: > + openstackversion_verify_info.resources is defined and + openstackversion_verify_info.resources | length > 0 and + openstackversion_verify_info.resources[0].status.deployedVersion is defined and + openstackversion_verify_info.resources[0].status.deployedVersion == cifmw_minor_update_target_version + retries: 5 + delay: 2 + +- name: Set update step to CI update sequence complete + ansible.builtin.command: + cmd: > + {{ cifmw_update_artifacts_basedir }}/update_event.sh + CI update verification successful - Target version {{ cifmw_minor_update_target_version }} + matches deployed version {{ openstackversion_verify_info.resources[0].status.deployedVersion }} + +- name: Display update verification result + ansible.builtin.debug: + msg: >- + Update verification successful: Target version {{ cifmw_minor_update_target_version }} + matches deployed version {{ openstackversion_verify_info.resources[0].status.deployedVersion }} + +- name: Stop monitoring + block: + - name: Verify monitoring pid file + ansible.builtin.stat: + path: "{{ cifmw_update_artifacts_basedir }}/monitor_resources_changes.pid" + register: cifmw_update_monitoring_pid + + - name: Stop the monitoring process + ansible.builtin.shell: + cmd: >- + kill + $(cat {{ cifmw_update_artifacts_basedir }}/monitor_resources_changes.pid) + register: _kill_result + failed_when: _kill_result.rc not in [0, 1] + when: cifmw_update_monitoring_pid.stat.exists | bool + +- name: Run post-update admin setup + ansible.builtin.import_role: + name: cifmw_setup + tasks_from: admin_setup.yml + tags: + - admin-setup + +- name: Run post-update tests + vars: + cifmw_test_operator_artifacts_basedir: "{{ cifmw_basedir }}/tests/test_operator_update" + cifmw_test_operator_tempest_name: "post-update-tempest-tests" + ansible.builtin.import_role: + name: cifmw_setup + tasks_from: run_tests.yml + when: cifmw_run_tests | default(false) | bool + tags: + - run-tests + +- name: Inject success flag + ansible.builtin.file: + path: "{{ ansible_user_dir }}/cifmw-success" + state: touch + mode: "0644" diff --git a/zuul.d/edpm.yaml b/zuul.d/edpm.yaml index 87c04e9555..cfe0155db6 100644 --- a/zuul.d/edpm.yaml +++ b/zuul.d/edpm.yaml @@ -43,10 +43,13 @@ # Virtual Baremetal job with CRC for minor update testing. # First deploys with pre-update index image (Phase 1), then updates with PR index image (Phase 2). +# This job runs directly on zuul host without controller-0 VM (no nested ansible-playbook). - job: name: cifmw-crc-podified-edpm-baremetal-minor-update nodeset: centos-9-crc-2-48-0-6xlarge parent: cifmw-base-crc-openstack + pre-run: + - playbooks/cifmw_collection_zuul_executor.yml run: - ci/playbooks/edpm_baremetal_update/run.yml - ci/playbooks/edpm_baremetal_update/update.yml @@ -57,6 +60,7 @@ cifmw_manage_secrets_pullsecret_content: '{}' cifmw_rhol_crc_binary_folder: "/usr/local/bin" cifmw_minor_update_pre_update_tag: "18.0-fr3-latest" + cifmw_run_on_zuul_host: true # Podified galera job - job: