From 90147d3e371e32ec43afd24d363726b72a23b3aa Mon Sep 17 00:00:00 2001 From: Miguel Angel Nieto Jimenez Date: Fri, 7 Nov 2025 10:37:12 +0100 Subject: [PATCH] [multiple] Added IPv6 scenarios for NFV with OVS-DPDK and SR-IOV Added two new IPv6 deployment scenarios: * OVS-DPDK SR-IOV with 1 nodeset (va-nfv-ovs-dpdk-sriov-ipv6.yml) * OVS-DPDK SR-IOV with 2 nodesets (dt-nfv-ovs-dpdk-sriov-ipv6-2nodesets.yml) [ci_gen_kustomize_values] Added IPv6 nodeset templates * Added edpm-nodeset-values template with IPv6 configuration * Added edpm-nodeset2-values template for dual nodeset deployments * Updated common network-values template for IPv6 support [libvirt_manager] Fixed IPv6 address formatting * Updated generate_networking_data.yml to properly handle IPv6 addresses * Prevented bracket corruption when IPv6 addresses are embedded in YAML Signed-off-by: Miguel Angel Nieto Jimenez --- .../common/network-values/values.yaml.j2 | 1 + .../edpm-nodeset-values/values.yaml.j2 | 58 ++++++++ .../edpm-nodeset2-values/values.yaml.j2 | 58 ++++++++ .../edpm-nodeset-values/values.yaml.j2 | 45 ++++++ .../tasks/generate_networking_data.yml | 20 +-- .../dt-nfv-ovs-dpdk-sriov-ipv6-2nodesets.yml | 128 ++++++++++++++++++ .../va-nfv-ovs-dpdk-sriov-ipv6.yml | 128 ++++++++++++++++++ 7 files changed, 428 insertions(+), 10 deletions(-) create mode 100644 roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6-2nodesets/edpm-nodeset-values/values.yaml.j2 create mode 100644 roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6-2nodesets/edpm-nodeset2-values/values.yaml.j2 create mode 100644 roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6/edpm-nodeset-values/values.yaml.j2 create mode 100644 scenarios/reproducers/dt-nfv-ovs-dpdk-sriov-ipv6-2nodesets.yml create mode 100644 scenarios/reproducers/va-nfv-ovs-dpdk-sriov-ipv6.yml 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 9530d5444f..1769515a96 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 @@ -19,6 +19,7 @@ data: node_{{ ns.ocp_index }}: {% set ns.ocp_index = ns.ocp_index+1 %} name: {{ cifmw_networking_env_definition.instances[host]['hostname'] }} + 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 | diff --git a/roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6-2nodesets/edpm-nodeset-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6-2nodesets/edpm-nodeset-values/values.yaml.j2 new file mode 100644 index 0000000000..62ec8dad00 --- /dev/null +++ b/roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6-2nodesets/edpm-nodeset-values/values.yaml.j2 @@ -0,0 +1,58 @@ +--- +# source: ovs-dpdk-sriov-ipv6-2nodesets/edpm-nodeset-values/values.yaml.j2 +{% set instances_names = [] %} +{% set _original_nodeset = (original_content.data | default({})).nodeset | default({}) %} +{% set _original_nodes = _original_nodeset.nodes | default({}) %} +{% set _original_services = _original_nodeset['services'] | default([]) %} +{% if cifmw_baremetal_hosts | default([]) | length > 0 %} +{% for _inst in cifmw_baremetal_hosts.keys() %} +{% if (('label' in cifmw_baremetal_hosts[_inst]) and + (cifmw_baremetal_hosts[_inst]['label'] == 'openstack')) %} +{% set _ = instances_names.append(_inst) %} +{% endif %} +{% endfor %} +{% else %} +# Needed for verification gate +{% set _vm_type = (_original_nodes.keys() | first).split('-')[1] %} +{% for _inst in cifmw_networking_env_definition.instances.keys() %} +{% if _inst.startswith(_vm_type) %} +{% set _ = instances_names.append(_inst) %} +{% endif %} +{% endfor %} +{% endif %} +data: + ssh_keys: + authorized: {{ cifmw_ci_gen_kustomize_values_ssh_authorizedkeys | b64encode }} + private: {{ cifmw_ci_gen_kustomize_values_ssh_private_key | b64encode }} + public: {{ cifmw_ci_gen_kustomize_values_ssh_public_key | b64encode }} + nova: + migration: + ssh_keys: + private: {{ cifmw_ci_gen_kustomize_values_migration_priv_key | b64encode }} + public: {{ cifmw_ci_gen_kustomize_values_migration_pub_key | b64encode }} + nodeset: + ansible: + ansibleVars: + edpm_fips_mode: "{{ 'enabled' if cifmw_fips_enabled|default(false)|bool else 'check' }}" + timesync_ntp_servers: + - hostname: "{{ cifmw_ci_gen_kustomize_values_ntp_srv | default('pool.ntp.org') }}" +{% if cifmw_ci_gen_kustomize_values_sshd_ranges | default([]) | length > 0 %} + edpm_sshd_allowed_ranges: +{% for range in cifmw_ci_gen_kustomize_values_sshd_ranges %} + - "{{ range }}" +{% endfor %} +{% endif %} + nodes: +{% for instance in instances_names %} + edpm-{{ instance }}: + hostName: {{ instance }} +{% endfor %} + +{% if ('repo-setup' not in (_original_nodeset['services'] | default([]))) and + ('repo-setup' in ci_gen_kustomize_edpm_nodeset_predeployed_services) %} + services: + - "repo-setup" +{% for svc in _original_services %} + - "{{ svc }}" +{% endfor %} +{% endif %} diff --git a/roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6-2nodesets/edpm-nodeset2-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6-2nodesets/edpm-nodeset2-values/values.yaml.j2 new file mode 100644 index 0000000000..80103686c3 --- /dev/null +++ b/roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6-2nodesets/edpm-nodeset2-values/values.yaml.j2 @@ -0,0 +1,58 @@ +--- +# source: ovs-dpdk-sriov-ipv6-2nodesets/edpm-nodeset2-values/values.yaml.j2 +{% set instances_names = [] %} +{% set _original_nodeset = (original_content.data | default({})).nodeset | default({}) %} +{% set _original_nodes = _original_nodeset.nodes | default({}) %} +{% set _original_services = _original_nodeset['services'] | default([]) %} +{% if cifmw_baremetal_hosts | default([]) | length > 0 %} +{% for _inst in cifmw_baremetal_hosts.keys() %} +{% if (('label' in cifmw_baremetal_hosts[_inst]) and + (cifmw_baremetal_hosts[_inst]['label'] == 'openstack-2')) %} +{% set _ = instances_names.append(_inst) %} +{% endif %} +{% endfor %} +{% else %} +# Needed for verification gate +{% set _vm_type = (_original_nodes.keys() | first).split('-')[1] %} +{% for _inst in cifmw_networking_env_definition.instances.keys() %} +{% if _inst.startswith(_vm_type) %} +{% set _ = instances_names.append(_inst) %} +{% endif %} +{% endfor %} +{% endif %} +data: + ssh_keys: + authorized: {{ cifmw_ci_gen_kustomize_values_ssh_authorizedkeys | b64encode }} + private: {{ cifmw_ci_gen_kustomize_values_ssh_private_key | b64encode }} + public: {{ cifmw_ci_gen_kustomize_values_ssh_public_key | b64encode }} + nova: + migration: + ssh_keys: + private: {{ cifmw_ci_gen_kustomize_values_migration_priv_key | b64encode }} + public: {{ cifmw_ci_gen_kustomize_values_migration_pub_key | b64encode }} + nodeset: + ansible: + ansibleVars: + edpm_fips_mode: "{{ 'enabled' if cifmw_fips_enabled|default(false)|bool else 'check' }}" + timesync_ntp_servers: + - hostname: "{{ cifmw_ci_gen_kustomize_values_ntp_srv | default('pool.ntp.org') }}" +{% if cifmw_ci_gen_kustomize_values_sshd_ranges | default([]) | length > 0 %} + edpm_sshd_allowed_ranges: +{% for range in cifmw_ci_gen_kustomize_values_sshd_ranges %} + - "{{ range }}" +{% endfor %} +{% endif %} + nodes: +{% for instance in instances_names %} + edpm-{{ instance }}: + hostName: {{ instance }} +{% endfor %} + +{% if ('repo-setup' not in (_original_nodeset['services'] | default([]))) and + ('repo-setup' in ci_gen_kustomize_edpm_nodeset_predeployed_services) %} + services: + - "repo-setup" +{% for svc in _original_services %} + - "{{ svc }}" +{% endfor %} +{% endif %} diff --git a/roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6/edpm-nodeset-values/values.yaml.j2 b/roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6/edpm-nodeset-values/values.yaml.j2 new file mode 100644 index 0000000000..cf1e9ce624 --- /dev/null +++ b/roles/ci_gen_kustomize_values/templates/ovs-dpdk-sriov-ipv6/edpm-nodeset-values/values.yaml.j2 @@ -0,0 +1,45 @@ +--- +# source: ovs-dpdk-sriov-ipv6/edpm-nodeset-values/values.yaml.j2 +{% set instances_names = [] %} +{% set _original_nodeset = (original_content.data | default({})).nodeset | default({}) %} +{% set _original_nodes = _original_nodeset.nodes | default({}) %} +{% set _original_services = _original_nodeset['services'] | default([]) %} +{% for _inst in cifmw_baremetal_hosts.keys() %} +{% set _ = instances_names.append(_inst) %} +{% endfor %} +data: + ssh_keys: + authorized: {{ cifmw_ci_gen_kustomize_values_ssh_authorizedkeys | b64encode }} + private: {{ cifmw_ci_gen_kustomize_values_ssh_private_key | b64encode }} + public: {{ cifmw_ci_gen_kustomize_values_ssh_public_key | b64encode }} + nova: + migration: + ssh_keys: + private: {{ cifmw_ci_gen_kustomize_values_migration_priv_key | b64encode }} + public: {{ cifmw_ci_gen_kustomize_values_migration_pub_key | b64encode }} + nodeset: + ansible: + ansibleVars: + edpm_fips_mode: "{{ 'enabled' if cifmw_fips_enabled|default(false)|bool else 'check' }}" + timesync_ntp_servers: + - hostname: "{{ cifmw_ci_gen_kustomize_values_ntp_srv | default('pool.ntp.org') }}" +{% if cifmw_ci_gen_kustomize_values_sshd_ranges | default([]) | length > 0 %} + edpm_sshd_allowed_ranges: +{% for range in cifmw_ci_gen_kustomize_values_sshd_ranges %} + - "{{ range }}" +{% endfor %} +{% endif %} + nodes: +{% for instance in instances_names %} + edpm-{{ instance }}: + hostName: {{ instance }} +{% endfor %} + +{% if ('repo-setup' not in (_original_nodeset['services'] | default([]))) and + ('repo-setup' in ci_gen_kustomize_edpm_nodeset_predeployed_services) %} + services: + - "repo-setup" +{% for svc in _original_services %} + - "{{ svc }}" +{% endfor %} +{% endif %} diff --git a/roles/libvirt_manager/tasks/generate_networking_data.yml b/roles/libvirt_manager/tasks/generate_networking_data.yml index c464a0867e..3f69c76cb1 100644 --- a/roles/libvirt_manager/tasks/generate_networking_data.yml +++ b/roles/libvirt_manager/tasks/generate_networking_data.yml @@ -182,12 +182,12 @@ networks: {{ _lnet_data.name | replace('cifmw_', '') }}: {% if _lnet_data.ranges[0].start_v4 is defined and _lnet_data.ranges[0].start_v4 %} - {% set net_4 = _lnet_data.ranges[0].start_v4 | ansible.utils.ipsubnet(_lnet_data.ranges[0].prefix_length_v4) %} - network-v4: {{ net_4}} + {%- set net_4 = _lnet_data.ranges[0].start_v4 | ansible.utils.ipsubnet(_lnet_data.ranges[0].prefix_length_v4) %} + network-v4: '{{ net_4 }}' {% endif %} {% if _lnet_data.ranges[0].start_v6 is defined and _lnet_data.ranges[0].start_v6 %} - {% set net_6 = _lnet_data.ranges[0].start_v6 | ansible.utils.ipsubnet(_lnet_data.ranges[0].prefix_length_v6) %} - network-v6: {{ net_6 }} + {%- set net_6 = _lnet_data.ranges[0].start_v6 | ansible.utils.ipsubnet(_lnet_data.ranges[0].prefix_length_v6) %} + network-v6: '{{ net_6 }}' {% endif %} group-templates: {% for group in _cifmw_libvirt_manager_layout.vms.keys() if group != 'controller' and @@ -202,12 +202,12 @@ {% if cifmw_networking_definition['group-templates'][_gr ~ 's']['network-template'] is undefined %} {% if net_4 is defined %} range-v4: - start: {{ net_4 | ansible.utils.nthhost(ns.ip_start | int ) }} + start: '{{ net_4 | ansible.utils.nthhost(ns.ip_start | int ) }}' length: {{ _cifmw_libvirt_manager_layout.vms[group].amount | default(1) }} {% endif %} {% if net_6 is defined %} range-v6: - start: {{ net_6 | ansible.utils.nthhost(ns.ip_start | int) }} + start: '{{ net_6 | ansible.utils.nthhost(ns.ip_start | int) }}' length: {{ _cifmw_libvirt_manager_layout.vms[group].amount | default(1) }} {% endif %} {% set ns.ip_start = ns.ip_start|int + (_cifmw_libvirt_manager_layout.vms[group].amount | default(1) | int ) + 1 %} @@ -220,12 +220,12 @@ {{ cifmw_libvirt_manager_pub_net }}: {% if net_4 is defined and cifmw_networking_definition['group-templates']['baremetals']['network-template'] is undefined %} range-v4: - start: {{ net_4 | ansible.utils.nthhost(ns.ip_start) }} + start: '{{ net_4 | ansible.utils.nthhost(ns.ip_start) }}' length: {{ cifmw_baremetal_hosts | length }} {% endif %} {% if net_6 is defined and cifmw_networking_definition['group-templates']['baremetals']['network-template'] is undefined %} range-v6: - start: {{ net_6 | ansible.utils.nthhost(ns.ip_start) }} + start: '{{ net_6 | ansible.utils.nthhost(ns.ip_start) }}' length: {{ cifmw_baremetal_hosts | length }} {% endif %} {% endif %} @@ -235,10 +235,10 @@ networks: {{ _lnet_data.name | replace('cifmw_', '') }}: {% if net_4 is defined %} - ip-v4: "{{ net_4 | ansible.utils.nthhost(9) }}" + ip-v4: '{{ net_4 | ansible.utils.nthhost(9) }}' {% endif %} {% if net_6 is defined %} - ip-v6: "{{ net_6 | ansible.utils.nthhost(9) }}" + ip-v6: '{{ net_6 | ansible.utils.nthhost(9) }}' {% endif %} {% endif %} block: diff --git a/scenarios/reproducers/dt-nfv-ovs-dpdk-sriov-ipv6-2nodesets.yml b/scenarios/reproducers/dt-nfv-ovs-dpdk-sriov-ipv6-2nodesets.yml new file mode 100644 index 0000000000..8ccecadfa5 --- /dev/null +++ b/scenarios/reproducers/dt-nfv-ovs-dpdk-sriov-ipv6-2nodesets.yml @@ -0,0 +1,128 @@ +--- +# IPv6 variant of dt-nfv-ovs-dpdk-sriov-2nodesets +# This reproducer configures NFV OVS-DPDK SR-IOV with 2 different nodesets using IPv6 as primary IP + +cifmw_architecture_scenario: "ovs-dpdk-sriov-ipv6-2nodesets" + +# Automation section. Most of those parameters will be passed to the +# 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: "{{ cifmw_architecture_repo }}" + +# Enable IPv6 as primary IP version +cifmw_ci_gen_kustomize_values_primary_ip_version: 6 + +# Enable libvirt and NAT64 for IPv6-only deployment +cifmw_use_libvirt: true +cifmw_use_nat64: true + +# HERE if you want to override kustomization, you can uncomment this parameter +# and push the data structure you want to apply. +# cifmw_architecture_user_kustomize: +# stage_0: +# 'network-values': +# data: +# starwars: Obiwan + +# HERE, if you want to stop the deployment loop at any stage, you can uncomment +# the following parameter and update the value to match the stage you want to +# reach. Known stages are: +# pre_kustomize_stage_INDEX +# pre_apply_stage_INDEX +# post_apply_stage_INDEX +# +# cifmw_deploy_architecture_stopper: + +cifmw_libvirt_manager_net_prefix_add: false +cifmw_libvirt_manager_fixed_networks: + - ocpbm + - ocppr + - osp_external + - osp_trunk + +cifmw_libvirt_manager_configuration: + networks: + ocpbm: | + + ocpbm + + + + ocppr: | + + ocppr + + + + osp_external: | + + osp_external + + + + osp_trunk: | + + osp_trunk + + + + vms: + controller: + uefi: "{{ cifmw_use_uefi }}" + root_part_id: "{{ cifmw_root_partition_id }}" + image_url: "{{ cifmw_discovered_image_url }}" + sha256_image_name: "{{ cifmw_discovered_hash }}" + image_local_dir: "{{ cifmw_basedir }}/images/" + disk_file_name: "base-os.qcow2" + disksize: 50 + memory: 8 + cpus: 4 + nets: + - ocpbm + - osp_trunk + ocp: + amount: 3 + uefi: true + root_part_id: 4 + admin_user: core + image_local_dir: "{{ cifmw_basedir }}/images/" + disk_file_name: "ocp_master" + disksize: "100" + extra_disks_num: 3 + extra_disks_size: "50G" + cpus: 10 + memory: 32 + nets: + - ocppr + - ocpbm + - osp_trunk + - osp_external + +# Note: with that extra_network_names "osp_trunk", we instruct +# devscripts role to create a new network, and associate it to +# the OCP nodes. This one is a "private network", and will hold +# the VLANs used for network isolation. + +# Please create a custom env file to provide: +# cifmw_devscripts_ci_token: +# cifmw_devscripts_pull_secret: + +# Baremetal host configuration +cifmw_config_bmh: true + +# BMH are deployed in a different NS than the secret OSP BMO +# references in each BMH. Metal3 requires the referenced +# secrets to be in the same NS or be allowed to access them +cifmw_devscripts_config_overrides_patch_bmo_watch_all_namespaces: + bmo_watch_all_namespaces: true + +# Use EDPM image for computes +cifmw_update_containers_edpm_image_url: "{{ cifmw_update_containers_registry }}/{{ cifmw_update_containers_org }}/edpm-hardened-uefi:{{ cifmw_update_containers_tag }}" + +# Set Logical Volume Manager Storage by default for local storage +cifmw_use_lvms: true +cifmw_lvms_disk_list: + - /dev/vda + - /dev/vdb + - /dev/vdc diff --git a/scenarios/reproducers/va-nfv-ovs-dpdk-sriov-ipv6.yml b/scenarios/reproducers/va-nfv-ovs-dpdk-sriov-ipv6.yml new file mode 100644 index 0000000000..55573ce63a --- /dev/null +++ b/scenarios/reproducers/va-nfv-ovs-dpdk-sriov-ipv6.yml @@ -0,0 +1,128 @@ +--- +# IPv6 variant of va-nfv-ovs-dpdk-sriov +# This reproducer configures NFV OVS-DPDK SR-IOV with 1 nodeset using IPv6 as primary IP + +cifmw_architecture_scenario: "ovs-dpdk-sriov-ipv6" + +# Automation section. Most of those parameters will be passed to the +# 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: "{{ cifmw_architecture_repo }}" + +# Enable IPv6 as primary IP version +cifmw_ci_gen_kustomize_values_primary_ip_version: 6 + +# Enable libvirt and NAT64 for IPv6-only deployment +cifmw_use_libvirt: true +cifmw_use_nat64: true + +# HERE if you want to override kustomization, you can uncomment this parameter +# and push the data structure you want to apply. +# cifmw_architecture_user_kustomize: +# stage_0: +# 'network-values': +# data: +# starwars: Obiwan + +# HERE, if you want to stop the deployment loop at any stage, you can uncomment +# the following parameter and update the value to match the stage you want to +# reach. Known stages are: +# pre_kustomize_stage_INDEX +# pre_apply_stage_INDEX +# post_apply_stage_INDEX +# +# cifmw_deploy_architecture_stopper: + +cifmw_libvirt_manager_net_prefix_add: false +cifmw_libvirt_manager_fixed_networks: + - ocpbm + - ocppr + - osp_external + - osp_trunk + +cifmw_libvirt_manager_configuration: + networks: + ocpbm: | + + ocpbm + + + + ocppr: | + + ocppr + + + + osp_external: | + + osp_external + + + + osp_trunk: | + + osp_trunk + + + + vms: + controller: + uefi: "{{ cifmw_use_uefi }}" + root_part_id: "{{ cifmw_root_partition_id }}" + image_url: "{{ cifmw_discovered_image_url }}" + sha256_image_name: "{{ cifmw_discovered_hash }}" + image_local_dir: "{{ cifmw_basedir }}/images/" + disk_file_name: "base-os.qcow2" + disksize: 50 + memory: 8 + cpus: 4 + nets: + - ocpbm + - osp_trunk + ocp: + amount: 3 + uefi: true + root_part_id: 4 + admin_user: core + image_local_dir: "{{ cifmw_basedir }}/images/" + disk_file_name: "ocp_master" + disksize: "100" + extra_disks_num: 3 + extra_disks_size: "50G" + cpus: 10 + memory: 32 + nets: + - ocppr + - ocpbm + - osp_trunk + - osp_external + +# Note: with that extra_network_names "osp_trunk", we instruct +# devscripts role to create a new network, and associate it to +# the OCP nodes. This one is a "private network", and will hold +# the VLANs used for network isolation. + +# Please create a custom env file to provide: +# cifmw_devscripts_ci_token: +# cifmw_devscripts_pull_secret: + +# Baremetal host configuration +cifmw_config_bmh: true + +# BMH are deployed in a differnt NS than the secret OSP BMO +# references in each BMH. Metal3 requires the referenced +# secrets to be in the same NS or be allowed to access them +cifmw_devscripts_config_overrides_patch_bmo_watch_all_namespaces: + bmo_watch_all_namespaces: true + +# Use EDPM image for computes +cifmw_update_containers_edpm_image_url: "{{ cifmw_update_containers_registry }}/{{ cifmw_update_containers_org }}/edpm-hardened-uefi:{{ cifmw_update_containers_tag }}" + +# Set Logical Volume Manager Storage by default for local storage +cifmw_use_lvms: true +cifmw_lvms_disk_list: + - /dev/vda + - /dev/vdb + - /dev/vdc