- name: set shell vars for edpm adoption no_log: "{{ use_no_log }}" when: - ('ceph' in [nova_libvirt_backend]) ansible.builtin.set_fact: ceph_backend_configuration_fsid_shell_vars: | CEPH_FSID=$(oc get secret ceph-conf-files -o json | jq -r '.data."{{ ceph_conf_secret_key }}"' | base64 -d | grep fsid | sed -e 's/fsid = //') # FIXME: missing docs coverage? - name: Patch openstackversion to use image built from source or latest if none is defined when: not skip_patching_ansibleee_csv | bool no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} oc patch openstackversion openstack \ --type='json' -p='[{ "op":"replace", "path":"/spec/customContainerImages/ansibleeeImage", "value": "{{ ansibleee_runner_img | default('quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest')}}"}]' - name: Include RHEV vars ansible.builtin.include_vars: file: rhev.yaml when: platform_rhev|default(false) - name: Include OSPdO vars ansible.builtin.include_vars: file: ospdo.yaml when: ospdo_src| bool - name: Pre process netconfig_networks for mtu to be an integer ansible.builtin.set_fact: netconfig_networks_converted: >- {% set new_list = [] -%} {% for net in netconfig_networks -%} {% set mtu_value = net.mtu | default(None) -%} {% if mtu_value is not none -%} {% set _ = net.update({'mtu': mtu_value | int}) -%} {% endif -%} {% set _ = new_list.append(net) -%} {% endfor -%} {{ new_list }} when: configure_ipam | bool - name: ensure IPAM is configured no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} oc apply -f - < 0 - name: create a configuration map which should become common for all cells (local storage back end) when: - compute_adoption|bool - ('ceph' not in [nova_libvirt_backend]) no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} oc apply -f - < 0 no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} {% for cluster in nova_dcn_clusters %} FSID_{{ cluster.name }}=$(oc get secret ceph-conf-{{ nova_dcn_clusters[0].name }} -o json | jq -r '.data."{{ cluster.name }}.conf"' | base64 -d | awk '/fsid/{print $3}') {% endfor %} {% for cluster in nova_dcn_clusters %} oc apply -f - < 0 no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} {{ cells_env }} {% for cluster in nova_dcn_clusters %} oc apply -f - <> computes-$CELL << EOF ${compute}: hostName: $compute ansible: ansibleHost: $compute networks: - defaultRoute: true fixedIP: ${!ip} name: ctlplane subnetName: subnet1 - name: internalapi subnetName: subnet1 fixedIP: ${!ip_api} - name: storage subnetName: subnet1 - name: tenant subnetName: subnet1 EOF ind=$(( ind + 1 )) done test -f computes-$CELL || continue cat > nodeset-${CELL}.yaml <> nodeset-${CELL}.yaml done # NOTE(bogdando): omit computes-$CELL insertion as that is a manual operation only needed by docs. # Those files are created here only to provide testing coverage of the commands provided in docs. # Their contents is irrelevant as the real values come from edpm_nodes, by the below task. # NOTE(bogdando): Assume cell1 must always have at least an only compute node. That is for backwards compatibility with scenarios not aware of multiple cells. - name: update EDPM nodes data in nodes sets of cells no_log: "{{ use_no_log }}" when: - compute_adoption|bool ansible.builtin.shell: | {{ shell_header }} {{ cells_env }} {% if 'cell1' not in edpm_nodes %} {% set edpm_nodes_real = {'cell1': edpm_nodes} %} {% else %} {% set edpm_nodes_real = edpm_nodes %} {% endif %} {% for cell in renamed_cells %} {% if cell in edpm_nodes_real %} cat > computes-real-{{ cell }} << EOF {% filter indent(width=4) %} {{ edpm_nodes_real[cell] | default([]) | to_yaml(indent=2) }} {% endfilter %} EOF cat computes-real-{{ cell }} >> nodeset-{{ cell }}.yaml {% endif %} {% endfor %} - name: Get OVN SB internalapi IPs for DCN nodesets when: edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} # Get internalapi IPs from OVN SB pods OVN_SB_IPS="" for pod in ovsdbserver-sb-0 ovsdbserver-sb-1 ovsdbserver-sb-2; do IP=$(oc get pod -n openstack $pod -o jsonpath='{.metadata.annotations.k8s\.v1\.cni\.cncf\.io/network-status}' | \ python3 -c "import sys, json; data=json.load(sys.stdin); print([n for n in data if 'internalapi' in n.get('name','')][0]['ips'][0])") if [ -z "$OVN_SB_IPS" ]; then OVN_SB_IPS="\"$IP\"" else OVN_SB_IPS="$OVN_SB_IPS, \"$IP\"" fi done echo "[$OVN_SB_IPS]" register: ovn_sb_ips_result - name: Set OVN SB IPs fact for DCN nodesets when: edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined ansible.builtin.set_fact: edpm_ovn_dbs_dcn: "{{ ovn_sb_ips_result.stdout | trim | from_json }}" - name: Create DCN OVN controller ConfigMap with direct IPs when: edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} # Build ovn-remote connection string from internalapi IPs OVN_REMOTE="{% for ip in edpm_ovn_dbs_dcn %}tcp:{{ ip }}:6642{% if not loop.last %},{% endif %}{% endfor %}" # Create ConfigMap for DCN nodes with direct IPs oc apply -f - < nodeset-cell1-${NODESET}.yaml < nodeset-cell1-${NODESET}.yaml < edpm-crd-networker.yaml {{ networker_cr }} EOF # FIXME: this is different in docs, need to align with tests # FIXME(bogdando): get ovs_external_ids.json data for multiple node sets - name: check ovs external-ids with os-diff before deployment failed_when: false tags: pull_openstack_configuration no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ cells_env }} for CELL in $(echo $RENAMED_CELLS); do test -f nodeset-${CELL}.yaml || continue {{ os_diff_dir }}/os-diff diff {{ os_diff_data_dir }}/tripleo/ovs_external_ids/standalone/ovs_external_ids.json nodeset-${CELL}.yaml --crd --service ovs_external_ids -f ${PWD}/{{ os_diff_dir }}/config.yaml done - name: deploy the OpenStackDataPlaneNodeSet CRs for each Nova compute cell ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} {{ cells_env }} for CELL in $(echo $RENAMED_CELLS); do test -f nodeset-${CELL}.yaml || continue oc apply -f nodeset-${CELL}.yaml done {%+ if edpm_nodes_networker is defined or edpm_networker_deploy +%} cat edpm-crd-networker.yaml | oc apply -f - {%+ endif +%} {%+ if edpm_nodes_dcn1 is defined +%} cat nodeset-cell1-dcn1.yaml | oc apply -f - {%+ endif +%} {%+ if edpm_nodes_dcn2 is defined +%} cat nodeset-cell1-dcn2.yaml | oc apply -f - {%+ endif +%} - name: Patch DCN nodesets to use ovn-dcn service instead of ovn when: edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} # Patch dcn1 nodeset if it exists {% if edpm_nodes_dcn1 is defined %} if oc get openstackdataplanenodeset dcn1 -n openstack &>/dev/null; then # Get current services list and replace 'ovn' with 'ovn-dcn' SERVICES=$(oc get openstackdataplanenodeset dcn1 -n openstack -o jsonpath='{.spec.services}' | \ sed 's/"ovn"/"ovn-dcn"/g') # Apply the patch oc patch openstackdataplanenodeset dcn1 -n openstack --type=merge --patch " spec: services: $SERVICES " echo "Patched dcn1 nodeset to use ovn-dcn service" fi {% endif %} # Patch dcn2 nodeset if it exists {% if edpm_nodes_dcn2 is defined %} if oc get openstackdataplanenodeset dcn2 -n openstack &>/dev/null; then # Get current services list and replace 'ovn' with 'ovn-dcn' SERVICES=$(oc get openstackdataplanenodeset dcn2 -n openstack -o jsonpath='{.spec.services}' | \ sed 's/"ovn"/"ovn-dcn"/g') # Apply the patch oc patch openstackdataplanenodeset dcn2 -n openstack --type=merge --patch " spec: services: $SERVICES " echo "Patched dcn2 nodeset to use ovn-dcn service" fi {% endif %} # TODO(bogdando): Apply the ceph backend config for Cinder in the original openstack CR, via kustomize perhaps? - name: prepare the adopted data plane workloads to use Ceph backend for Cinder, if configured so no_log: "{{ use_no_log }}" when: - compute_adoption|bool - cinder_volume_backend|default('') == "ceph" or cinder_backup_backend|default('') == "ceph" or ('ceph' in [nova_libvirt_backend]) - nova_dcn_clusters | length == 0 ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} {{ cells_env }} for CELL in $(echo $RENAMED_CELLS); do test -f nodeset-${CELL}.yaml || continue oc patch osdpns/openstack-$CELL --type=merge --patch " spec: services: - bootstrap - download-cache - configure-network - validate-network - install-os - configure-os - ssh-known-hosts - run-os - reboot-os - install-certs - ceph-client - ovn - neutron-metadata - libvirt - nova-$CELL {% if telemetry_adoption|bool +%} - telemetry {%+ endif +%} nodeTemplate: extraMounts: - extraVolType: Ceph volumes: - name: ceph secret: secretName: ceph-conf-files mounts: - name: ceph mountPath: "/etc/ceph" readOnly: true " done - name: prepare DCN central nodeset to use per-site Ceph backend no_log: "{{ use_no_log }}" when: - compute_adoption|bool - nova_dcn_clusters | length > 0 ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} {{ cells_env }} for CELL in $(echo $RENAMED_CELLS); do test -f nodeset-${CELL}.yaml || continue oc patch osdpns/openstack-$CELL --type=merge --patch " spec: services: - bootstrap - download-cache - configure-network - validate-network - install-os - configure-os - ssh-known-hosts - run-os - reboot-os - install-certs - ceph-client - ovn - neutron-metadata - libvirt - nova-custom-ceph-{{ nova_dcn_clusters[0].name }} {% if telemetry_adoption|bool +%} - telemetry {%+ endif +%} nodeTemplate: extraMounts: - extraVolType: Ceph volumes: - name: ceph secret: secretName: ceph-conf-{{ nova_dcn_clusters[0].name }} mounts: - name: ceph mountPath: "/etc/ceph" readOnly: true " done - name: prepare DCN edge nodesets to use per-site Ceph backend no_log: "{{ use_no_log }}" when: - compute_adoption|bool - nova_dcn_clusters | length > 0 - edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} {% for cluster in nova_dcn_clusters[1:] %} if oc get openstackdataplanenodeset {{ cluster.name }} -n openstack &>/dev/null; then SERVICES=$(oc get openstackdataplanenodeset {{ cluster.name }} -n openstack -o jsonpath='{.spec.services}' | \ sed 's/"nova-cell1"/"nova-custom-ceph-{{ cluster.name }}"/g' | \ sed 's/"install-certs"/"install-certs","ceph-client"/g') oc patch openstackdataplanenodeset {{ cluster.name }} -n openstack --type=merge --patch " spec: services: $SERVICES nodeTemplate: extraMounts: - extraVolType: Ceph volumes: - name: ceph secret: secretName: ceph-conf-{{ cluster.name }} mounts: - name: ceph mountPath: "/etc/ceph" readOnly: true " echo "Patched {{ cluster.name }} nodeset to use nova-custom-ceph-{{ cluster.name }} service" fi {% endfor %} - name: enable neutron-sriov-nic-agent in the OpenStackDataPlaneNodeSet CR no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} {{ cells_env }} for CELL in $(echo $RENAMED_CELLS); do test -f nodeset-${CELL}.yaml || continue oc patch openstackdataplanenodeset openstack-$CELL --type='json' --patch='[ { "op": "add", "path": "/spec/services/-", "value": "neutron-sriov" }, { "op": "add", "path": "/spec/nodeTemplate/ansible/ansibleVars/edpm_neutron_sriov_agent_SRIOV_NIC_physical_device_mappings", "value": "dummy_sriov_net:dummy-dev" }, { "op": "add", "path": "/spec/nodeTemplate/ansible/ansibleVars/edpm_neutron_sriov_agent_SRIOV_NIC_resource_provider_bandwidths", "value": "" }, { "op": "add", "path": "/spec/nodeTemplate/ansible/ansibleVars/edpm_neutron_sriov_agent_SRIOV_NIC_resource_provider_hypervisors", "value": "" }]' done when: - edpm_neutron_sriov_agent_enabled|bool - compute_adoption|bool - name: enable neutron-dhcp in the OpenStackDataPlaneNodeSet CR no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} {{ cells_env }} for CELL in $(echo $RENAMED_CELLS); do test -f nodeset-${CELL}.yaml || continue NODESETS="openstack-${CELL}" if [ "$CELL" == "cell1" ]; then test -f nodeset-cell1-dcn1.yaml && NODESETS="${NODESETS} dcn1" test -f nodeset-cell1-dcn2.yaml && NODESETS="${NODESETS} dcn2" fi for NODESET in $NODESETS; do oc patch openstackdataplanenodeset $NODESET --type='json' --patch='[ { "op": "add", "path": "/spec/services/-", "value": "neutron-dhcp" }]' done done when: edpm_neutron_dhcp_agent_enabled|bool - name: enable neutron-dhcp in the OpenStackDataPlaneNodeSet CR Networker no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} oc patch openstackdataplanenodeset openstack-networker --type='json' --patch='[ { "op": "add", "path": "/spec/services/-", "value": "neutron-dhcp" }]' when: - edpm_networker_neutron_dhcp_agent_enabled | default(false) | bool - edpm_nodes_networker is defined - name: Run the pre-adoption validation when: run_pre_adoption_validation|bool block: - name: create the validation service no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ oc_header }} oc apply -f - < /tmp/tripleo_config.yaml.tmp mv /tmp/tripleo_config.yaml.tmp /etc/os-net-config/tripleo_config.yaml os-net-config -c /etc/os-net-config/tripleo_config.yaml --provider ifcfg --debug EOF loop: "{{ edpm_nodes | combine(edpm_nodes_networker | default({})) | dict2items }}" - name: When the clean-up is finished, deploy the OpenStackDataPlaneDeployment CR no_log: "{{ use_no_log }}" ansible.builtin.shell: | {{ shell_header }} {{ nodesets_env_oc }} {%+ if edpm_nodes_networker is defined or edpm_networker_deploy +%} NODESETS="${NODESETS%]*},openstack-networker]" {%+ endif +%} {%+ if edpm_nodes_dcn1 is defined +%} NODESETS="${NODESETS%]*},dcn1]" {%+ endif +%} {%+ if edpm_nodes_dcn2 is defined +%} NODESETS="${NODESETS%]*},dcn2]" {%+ endif +%} oc apply -f - <Antelope FFU when: compute_adoption|bool ansible.builtin.include_tasks: file: nova_ffu.yaml - name: Cleanup non-adopted Neutron and OVN agents ansible.builtin.include_tasks: file: neutron_agents_cleanup.yaml - name: Adopted Neutron and OVN agents post-checks ansible.builtin.include_tasks: file: neutron_verify.yaml - name: Adopted Nova FFU post-checks when: compute_adoption|bool ansible.builtin.include_tasks: file: nova_verify.yaml - name: Adopted Octavia post-checks when: octavia_adoption|bool ansible.builtin.include_tasks: file: octavia_post.yaml - name: Adopted Cinder post-checks ansible.builtin.include_tasks: file: cinder_verify.yaml