diff --git a/ci/playbooks/edpm_baremetal_update/minor-update-edpm.yml b/ci/playbooks/edpm_baremetal_update/minor-update-edpm.yml new file mode 100644 index 0000000000..7b72be48fc --- /dev/null +++ b/ci/playbooks/edpm_baremetal_update/minor-update-edpm.yml @@ -0,0 +1,133 @@ +--- +# CI playbook for OpenStack minor version updates. +# This playbook performs a minor version update of an OpenStack deployment +# using index images and install_yamls make targets. +# This playbook depends on content provider variables from CI jobs. +# It runs in the same execution context as deploy-edpm.yml, +# so it can use the install_yamls_makes role that was generated during bootstrap. + +- name: OpenStack minor version update + hosts: "{{ cifmw_target_host | default('localhost') }}" + gather_facts: false + tasks: + - name: Set cifmw_basedir if not defined + ansible.builtin.set_fact: + cifmw_basedir: "{{ cifmw_basedir | default(ansible_user_dir ~ '/ci-framework-data') }}" + + - name: Load parameters files + ansible.builtin.include_vars: + dir: "{{ cifmw_basedir }}/artifacts/parameters" + + - 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' + ignore_errors: true # Continue even if cleanup fails + + - 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: 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: 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: 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: 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: Run make openstack_update_run + vars: + make_openstack_update_run_env: "{{ cifmw_minor_update_env }}" + make_openstack_update_run_params: + 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: 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: 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 }} diff --git a/ci/playbooks/edpm_baremetal_update/run.yml b/ci/playbooks/edpm_baremetal_update/run.yml new file mode 100644 index 0000000000..b44757f705 --- /dev/null +++ b/ci/playbooks/edpm_baremetal_update/run.yml @@ -0,0 +1,174 @@ +--- +- name: "Run ci/playbooks/edpm_baremetal_update/run.yml" + hosts: "{{ cifmw_zuul_target_host | default('all') }}" + gather_facts: true + tasks: + - name: Filter out host if needed + when: + - cifmw_zuul_target_host is defined + - cifmw_zuul_target_host != 'all' + - inventory_hostname != cifmw_zuul_target_host + ansible.builtin.meta: end_host + + - name: Check for edpm-ansible.yml file + ansible.builtin.stat: + path: "{{ ansible_user_dir }}/ci-framework-data/artifacts/edpm-ansible.yml" + register: edpm_file + + - name: Check if new ssh keypair exists + ansible.builtin.include_role: + name: recognize_ssh_keypair + + - name: Add crc node in local inventory + ansible.builtin.add_host: + name: crc + ansible_ssh_private_key_file: "{{ ansible_user_dir }}/.crc/machines/crc/{{ crc_ssh_keypair }}" + ansible_ssh_user: core + ansible_host: api.crc.testing + + - name: Ensure we know ssh hosts + ansible.builtin.shell: + cmd: "ssh-keyscan {{ hostvars[item].ansible_host }} >> ~/.ssh/known_hosts" + loop: "{{ hostvars.keys() | reject('equalto', 'localhost') }}" + + - name: Inject CRC in zuul_inventory + block: + - name: Load zuul_inventory + register: _inventory + ansible.builtin.slurp: + path: "{{ ansible_user_dir }}/ci-framework-data/artifacts/zuul_inventory.yml" + + - name: Inject CRC in zuul_inventory.yml + vars: + _crc: + all: + hosts: + crc: "{{ dict(hostvars.crc) }}" + _updated: >- + {{ + _inventory.content | b64decode | from_yaml | combine(_crc, recursive=true) + }} + ansible.builtin.copy: + dest: "{{ ansible_user_dir }}/ci-framework-data/artifacts/zuul_inventory.yml" + content: "{{ _updated | to_nice_yaml }}" + mode: "0644" + + - name: Set default pre-update tag if not provided + ansible.builtin.set_fact: + cifmw_minor_update_pre_update_tag: "{{ cifmw_minor_update_pre_update_tag | default('18.0-fr4-latest') }}" + + - name: Get pre-update index image digest from tag + ansible.builtin.shell: >- + skopeo inspect + docker://quay.io/openstack-k8s-operators/openstack-operator-index:{{ cifmw_minor_update_pre_update_tag }} + | jq -r '.Digest' + register: fr4_digest_result + changed_when: false + failed_when: fr4_digest_result.rc != 0 + + - name: Set FR4 index image using digest from tag + ansible.builtin.set_fact: + cifmw_minor_update_fr4_index_image: >- + quay.io/openstack-k8s-operators/openstack-operator-index@{{ fr4_digest_result.stdout | trim }} + + - name: Get minor update index image from content provider or use default + ansible.builtin.set_fact: + cifmw_minor_update_index_image: >- + {{ + cifmw_operator_build_output.operators['openstack-operator'].image_catalog + if (cifmw_operator_build_output is defined and + cifmw_operator_build_output.operators is defined and + 'openstack-operator' in cifmw_operator_build_output.operators) + else cifmw_minor_update_fr4_index_image + }} + + - name: Override operator build output with FR4 index image for Phase 1 + ansible.builtin.set_fact: + cifmw_operator_build_output_fr4: >- + {{ + { + 'cifmw_operator_build_output': { + 'operators': { + 'openstack-operator': { + 'image_catalog': cifmw_minor_update_fr4_index_image + } + } + } + } + }} + + - name: Phase 1 - Deploy with FR4 index image using deploy-edpm.yml + block: + - name: Write FR4 operator build output to temporary file + ansible.builtin.copy: + dest: "{{ ansible_user_dir }}/ci-framework-data/artifacts/operator_build_output_fr4.yml" + content: "{{ cifmw_operator_build_output_fr4 | to_nice_yaml }}" + mode: "0644" + + - name: Perform Podified and EDPM deployment on compute nodes with virtual baremetal (FR4) + 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_fr4.yml" + -e "cifmw_prepare_openstackversion=false" + + # Load install_yamls environment from parameters file created by deploy-edpm.yml bootstrap + # deploy-edpm.yml runs on target host, so files are on target host + # Use slurp to read from target host, then parse with from_yaml + - name: Read install-yamls-params.yml file from target host + ansible.builtin.slurp: + src: "{{ ansible_user_dir }}/ci-framework-data/artifacts/parameters/install-yamls-params.yml" + register: install_yamls_params_content + when: cifmw_install_yamls_environment is not defined + + - name: Load install_yamls environment from parameters file + ansible.builtin.set_fact: + cifmw_install_yamls_environment: "{{ (install_yamls_params_content.content | b64decode | from_yaml)['cifmw_install_yamls_environment'] | default({}) }}" + cifmw_install_yamls_defaults: "{{ (install_yamls_params_content.content | b64decode | from_yaml)['cifmw_install_yamls_defaults'] | default({}) }}" + when: + - cifmw_install_yamls_environment is not defined + - install_yamls_params_content.content is defined + + - 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}) + }} + + # Phase 2: Run update playbook in same execution context as deploy-edpm.yml + # This allows it to use install_yamls_makes role that was generated during Phase 1 bootstrap + - name: Phase 2 - Update with index image for minor update + block: + - name: Write minor update environment to temporary file + ansible.builtin.copy: + dest: "{{ ansible_user_dir }}/ci-framework-data/artifacts/parameters/minor_update_env.yml" + content: "{{ {'cifmw_minor_update_env': cifmw_minor_update_env} | to_nice_yaml }}" + mode: "0644" + + - name: Run Phase 2 update playbook for minor update + ansible.builtin.command: + chdir: "{{ ansible_user_dir }}/src/github.com/openstack-k8s-operators/ci-framework" + cmd: >- + ansible-playbook ci/playbooks/edpm_baremetal_update/minor-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" + -e "@{{ ansible_user_dir }}/ci-framework-data/artifacts/parameters/minor_update_env.yml" diff --git a/roles/edpm_prepare/tasks/kustomize_and_deploy.yml b/roles/edpm_prepare/tasks/kustomize_and_deploy.yml index 0a65a20397..89c685a863 100644 --- a/roles/edpm_prepare/tasks/kustomize_and_deploy.yml +++ b/roles/edpm_prepare/tasks/kustomize_and_deploy.yml @@ -26,18 +26,19 @@ 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 + cifmw_update_containers_openstack: "{{ cifmw_edpm_prepare_update_containers | default(true) }}" - name: Prepare OpenStackVersion CR when: >- - (cifmw_update_containers_edpm_image_url is defined and + (cifmw_prepare_openstackversion | default(true) | bool) and + ((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) + cifmw_update_containers_watcher | bool)) vars: cifmw_update_containers_metadata: "{{ _ctlplane_name }}" ansible.builtin.include_role: diff --git a/zuul.d/edpm.yaml b/zuul.d/edpm.yaml index dcd9cf514d..425bb8969d 100644 --- a/zuul.d/edpm.yaml +++ b/zuul.d/edpm.yaml @@ -39,6 +39,21 @@ cifmw_edpm_deploy_baremetal_bootc: true cifmw_update_containers: true +# Virtual Baremetal job with CRC for minor update testing. +# First deploys with FR4 index image, then updates with PR index image. +- job: + name: cifmw-crc-podified-edpm-baremetal-minor-update + nodeset: centos-9-crc-2-48-0-6xlarge + parent: cifmw-base-crc-openstack + run: ci/playbooks/edpm_baremetal_update/run.yml + dependencies: + - openstack-k8s-operators-content-provider + vars: + crc_parameters: "--memory 32000 --disk-size 240 --cpus 12" + cifmw_manage_secrets_pullsecret_content: '{}' + cifmw_rhol_crc_binary_folder: "/usr/local/bin" + cifmw_minor_update_pre_update_tag: "18.0-fr3-latest" + # Podified galera job - job: name: cifmw-crc-podified-galera-deployment diff --git a/zuul.d/project-templates.yaml b/zuul.d/project-templates.yaml index 6fe9ae944e..1e141b98cc 100644 --- a/zuul.d/project-templates.yaml +++ b/zuul.d/project-templates.yaml @@ -59,6 +59,7 @@ - cifmw-molecule - podified-multinode-edpm-deployment-crc: *content_provider - cifmw-crc-podified-edpm-baremetal: *content_provider + - cifmw-crc-podified-edpm-baremetal-minor-update: *content_provider - podified-multinode-hci-deployment-crc: *content_provider - cifmw-multinode-tempest: *content_provider - cifmw-pod-zuul-files