From f72bad3d6678c682e8918161acdcfdb0bad98d8c Mon Sep 17 00:00:00 2001 From: Oliver Walsh Date: Wed, 17 Dec 2025 15:02:26 +0000 Subject: [PATCH 1/3] Add DCN adoption support Adds support for deploying DCN with local storage (which is essentially multi-stack plus spine & leaf networking) to the adoption_osp_deploy role. Signed-off-by: Oliver Walsh --- .../tasks/config_files.yml | 26 ++- .../tasks/prepare_overcloud.yml | 91 +++++++++- .../templates/adoption_vars.yaml.j2 | 143 ++++++++++++---- .../templates/os_net_config_overcloud.yml.j2 | 2 +- .../templates/resolv.conf.j2 | 3 + .../tripleo-ansible-inventory.yaml.j2 | 29 ++-- scenarios/adoption/dcn_nostorage.yml | 160 ++++++++++++++++++ scenarios/reproducers/dt-dcn.yml | 33 ++-- 8 files changed, 407 insertions(+), 80 deletions(-) create mode 100644 roles/adoption_osp_deploy/templates/resolv.conf.j2 create mode 100644 scenarios/adoption/dcn_nostorage.yml diff --git a/roles/adoption_osp_deploy/tasks/config_files.yml b/roles/adoption_osp_deploy/tasks/config_files.yml index 28eab22e97..ce3674a691 100644 --- a/roles/adoption_osp_deploy/tasks/config_files.yml +++ b/roles/adoption_osp_deploy/tasks/config_files.yml @@ -34,9 +34,18 @@ register: _original_config_download delegate_to: "localhost" +- name: Reset facts + ansible.builtin.set_fact: + _tripleo_nodes: [] + _hostname_map: {} + _deployedserverport_map: {} + _nodeport_map: {} + _ctlplanenet_attributes: {} + - name: Generate config download file vars: - _ctlplane_net: "{{ cifmw_networking_env_definition.networks.ctlplane }}" + _ctlplane_net1: "{{ cifmw_networking_env_definition.networks['ctlplane'] }}" + _ctlplane_net: "{{ cifmw_networking_env_definition.networks[_stack.ctlplanenet|default('ctlplane')] }}" _hostname_map_translation: >- {{ cifmw_adoption_osp_deploy_scenario.hostname_groups_map | @@ -77,13 +86,13 @@ dns_version: dns_v6 gw_version: gw_v6 prefix_length_version: prefix_length_v6 - when: cifmw_networking_env_definition.networks.ctlplane.network_v6 is defined + when: cifmw_networking_env_definition.networks[_stack.ctlplanenet|default('ctlplane')].network_v6 is defined - name: Generate DeployedServerPortMap field vars: _node_instance_net: "{{ cifmw_networking_env_definition.instances[node] }}" _key_name: "{{ node }}-ctlplane" - _ctlplane_ip: "{{ _node_instance_net.networks.ctlplane[ip_version|default('ip_v4')] }}" + _ctlplane_ip: "{{ _node_instance_net.networks[_stack.ctlplanenet|default('ctlplane')][ip_version|default('ip_v4')] }}" _server_port: >- {%- set port = {_key_name: {}} -%} {%- set _ = port[_key_name].update({ @@ -115,7 +124,8 @@ {%- set nodeport = {node: {}} -%} {% for network, net_info in _node_instance_net.networks.items() if network != 'ocpbm' %} {%- set subnet = cifmw_networking_env_definition.networks[network][network_version|default("network_v4")] -%} - {%- set network_name = network.replace('storagemgmt', 'storage_mgmt') -%} + {%- set network_name = cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[network] | default(network) -%} + {%- set network_name = network_name.replace('storagemgmt', 'storage_mgmt') -%} {%- set network_name = network_name.replace('internalapi', 'internal_api') -%} {%- set _ = nodeport[node].update( { @@ -144,18 +154,18 @@ _cloud_domain: "{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}" _dns_server: >- {{ - (_ctlplane_net[dns_version|default("dns_v4")] | length > 0) | - ternary(_ctlplane_net[dns_version|default("dns_v4")], _ctlplane_net[gw_version|default("gw_v4")]) + (_ctlplane_net1[dns_version|default("dns_v4")] | length > 0) | + ternary(_ctlplane_net1[dns_version|default("dns_v4")], _ctlplane_net1[gw_version|default("gw_v4")]) }} ansible.builtin.set_fact: _ctlplanenet_attributes: network: dns_domain: "{{ _cloud_domain }}" - mtu: "{{ _ctlplane_net.mtu }}" + mtu: "{{ _ctlplane_net1.mtu }}" subnets: ctlplane-subnet: dns_nameservers: "{{ _dns_server }}" - gateway_ip: "{{ _ctlplane_net[gw_version|default('gw_v4')] }}" + gateway_ip: "{{ _ctlplane_net1[gw_version|default('gw_v4')] }}" - name: Create new config download file vars: diff --git a/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml b/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml index d259b8c866..ecbd7c9905 100644 --- a/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml +++ b/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml @@ -21,7 +21,51 @@ - user_id - user_dir +- name: Reset facts + ansible.builtin.set_fact: + _tripleo_nodes_stack: {} + - name: Prepare enviornment for 17.1 overcloud deployment + vars: + _overcloud_name: >- + {{ + _stack.stackname | + default('overcloud') + }} + _hostname_map_translation: >- + {{ + cifmw_adoption_osp_deploy_scenario.hostname_groups_map | + ansible.utils.keep_keys(target=_stack.stack_nodes) + }} + _network_data_file: >- + {{ + [cifmw_adoption_source_scenario_path, + _stack.network_data_file + ] | path_join + }} + _network_data_file_dest: >- + {{ + [ansible_user_dir, + 'network_data_' ~ _overcloud_name ~'.yaml' + ] | path_join + }} + _network_data_extension: "{{ _network_data_file | splitext | last }}" + _vips_data_file: >- + {{ + [cifmw_adoption_source_scenario_path, + _stack.vips_data_file + ] | path_join + }} + _vips_data_file_dest: >- + {{ + [ansible_user_dir, + 'vips_data_' ~ _overcloud_name ~ '.yaml' + ] | path_join + }} + _source_cmd: "source {{ ansible_user_dir }}/stackrc" + _network_provision_output: "network_provision_{{ _overcloud_name }}_out.yaml" + _vips_provision_output: "vips_provision_{{ _overcloud_name }}_out.yaml" + _ctlplane: "{{ _stack.ctlplanenet|default('ctlplane') }}" block: - name: Gather stack nodes and facts ansible.builtin.include_tasks: gather_stack_nodes.yml @@ -51,6 +95,43 @@ apply: delegate_to: "{{ cifmw_target_host | default('localhost') }}" + - name: Configure NetworkManager to not override /etc/resolv.conf + become: true + delegate_to: "{{ overcloud_vm }}" + community.general.ini_file: + path: "/etc/NetworkManager/NetworkManager.conf" + option: dns + section: main + value: none + mode: "0644" + loop: "{{ _tripleo_nodes_stack[_overcloud_name] }}" + loop_control: + loop_var: overcloud_vm + + - name: Restart NetworkManager to ensure we apply new configuration + become: true + delegate_to: "{{ overcloud_vm }}" + ansible.builtin.service: + name: NetworkManager + state: restarted + loop: "{{ _tripleo_nodes_stack[_overcloud_name] }}" + loop_control: + loop_var: overcloud_vm + + - name: Inject custom nameservers in /etc/resolv.conf + become: true + delegate_to: "{{ overcloud_vm }}" + vars: + _ctlplane_net: "{{ cifmw_networking_env_definition.networks[_ctlplane] }}" + _dns_server: "{{ _ctlplane_net[dns_version|default('dns_v4')] }}" + ansible.builtin.template: + src: "resolv.conf.j2" + dest: "/etc/resolv.conf" + mode: "0644" + loop: "{{ _tripleo_nodes_stack[_overcloud_name] }}" + loop_control: + loop_var: overcloud_vm + - name: Ensure needed logins ansible.builtin.include_tasks: login_registries.yml args: @@ -171,12 +252,12 @@ delegate_to: "{{ overcloud_vm }}" vars: _node_net: "{{ cifmw_networking_env_definition.instances[overcloud_vm] }}" - _ctlplane_ip: "{{ _node_net.networks.ctlplane[ip_version|default('ip_v4')] }}" - _ctlplane_net: "{{ cifmw_networking_env_definition.networks.ctlplane }}" - _dns_server: "{{ _ctlplane_net.[dns_version|default('dns_v4')] }}" + _ctlplane_ip: "{{ _node_net.networks[_ctlplane][ip_version|default('ip_v4')] }}" + _ctlplane_net: "{{ cifmw_networking_env_definition.networks[_ctlplane] }}" + _dns_server: "{{ _ctlplane_net[dns_version|default('dns_v4')] }}" _gateway_ip: "{{ _ctlplane_net[gw_version|default('gw_v4')] }}" - _interface_mtu: "{{ _node_net.networks.ctlplane.mtu }}" - _ctlplane_cidr: "{{ _node_net.networks.ctlplane[prefix_length_version|default('prefix_length_v4')] }}" + _interface_mtu: "{{ _node_net.networks[_ctlplane].mtu }}" + _ctlplane_cidr: "{{ _node_net.networks[_ctlplane][prefix_length_version|default('prefix_length_v4')] }}" ansible.builtin.template: src: "os_net_config_overcloud.yml.j2" dest: /etc/os-net-config/tripleo_config.yaml diff --git a/roles/adoption_osp_deploy/templates/adoption_vars.yaml.j2 b/roles/adoption_osp_deploy/templates/adoption_vars.yaml.j2 index 143104dff8..774d3fb2e6 100644 --- a/roles/adoption_osp_deploy/templates/adoption_vars.yaml.j2 +++ b/roles/adoption_osp_deploy/templates/adoption_vars.yaml.j2 @@ -18,6 +18,31 @@ source_mariadb_ip: {{ _controller_1_internalapi_ip }} source_ovndb_ip: {{ _controller_1_internalapi_ip }} edpm_node_hostname: {{ _compute_1_name }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} edpm_node_ip: {{ _compute_1_ip }} + +{% if _vm_groups['osp-computes'] | default([]) | length > 0 %} +edpm_computes: | + {% for compute in _vm_groups['osp-computes'] %} + {% set node_nets = cifmw_networking_env_definition.instances[compute] %} + ["{{ compute }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="{{ node_nets.networks.ctlplane[ip_version|default('ip_v4')] }}" + {% endfor %} +{% endif %} + +{% if _vm_groups['osp-dcn1-compute-az1s'] | default([]) | length > 0 %} +edpm_computes_dcn1: | + {% for compute in _vm_groups['osp-dcn1-compute-az1s'] %} + {% set node_nets = cifmw_networking_env_definition.instances[compute] %} + ["{{ compute }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="{{ node_nets.networks.ctlplanedcn1[ip_version|default('ip_v4')] }}" + {% endfor %} +{% endif %} + +{% if _vm_groups['osp-dcn2-compute-az2s'] | default([]) | length > 0 %} +edpm_computes_dcn2: | + {% for compute in _vm_groups['osp-dcn2-compute-az2s'] %} + {% set node_nets = cifmw_networking_env_definition.instances[compute] %} + ["{{ compute }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="{{ node_nets.networks.ctlplanedcn2[ip_version|default('ip_v4')] }}" + {% endfor %} +{% endif %} + {% if _vm_groups['osp-networkers'] | default([]) | length > 0 %} edpm_networkers: | {% for networker in _vm_groups['osp-networkers'] | default([]) %} @@ -51,35 +76,75 @@ source_galera_members: | {% endfor %} {%+ endif +%} +{% if _vm_groups['osp-computes'] | default([]) | length > 0 %} edpm_nodes: -{% for stack in _stack_names %} - {% if stack == 'overcloud' %} - {% set cell = _default_cell_name %} - {% set prefix = '' %} - {% else %} - {% set cell = stack %} - {% set prefix = stack ~ '-' %} - {% endif %} - {% if _vm_groups[prefix ~ 'osp-computes'] | default([]) | length > 0 %} - {{ cell }}: - {% for compute in _vm_groups[prefix ~ 'osp-computes'] %} - {% set node_nets = cifmw_networking_env_definition.instances[compute] %} - {{ compute }}: - hostName: {{ compute }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} - ansible: - ansibleHost: {{ node_nets.networks.ctlplane[ip_version|default('ip_v4')] }} - networks: - {% for net in node_nets.networks.keys() if net not in cifmw_adoption_osp_deploy_adoption_vars_exclude_nets %} - - fixedIP: {{ node_nets.networks[net][ip_version|default('ip_v4')] }} - name: {{ net }} - subnetName: subnet1 - {% if net == 'ctlplane' %} - defaultRoute: true - {% endif %} - {% endfor %} + {% for compute in _vm_groups['osp-computes'] %} + {% set node_nets = cifmw_networking_env_definition.instances[compute] %} + {{ compute }}: + hostName: {{ compute }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + {% for net in node_nets.networks.keys() if cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[net]|default(net) == "ctlplane" %} + ansible: + ansibleHost: {{ node_nets.networks[net][ip_version|default('ip_v4')] }} + {% endfor %} + networks: + {% for net in node_nets.networks.keys() if net not in cifmw_adoption_osp_deploy_adoption_vars_exclude_nets %} +{% set net_name = cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[net]|default(net) %} + - fixedIP: {{ node_nets.networks[net][ip_version|default('ip_v4')] }} + name: {{ net_name }} + subnetName: {{ "subnet1" if net_name == net else net}} +{% if net_name == 'ctlplane' %} + defaultRoute: true +{% endif %} + {% endfor %} + {% endfor %} +{% endif %} + +{% if _vm_groups['osp-dcn1-compute-az1s'] | default([]) | length > 0 %} +edpm_nodes_dcn1: + {% for compute in _vm_groups['osp-dcn1-compute-az1s'] %} + {% set node_nets = cifmw_networking_env_definition.instances[compute] %} + {{ compute }}: + hostName: {{ compute }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + {% for net in node_nets.networks.keys() if cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[net]|default(net) == "ctlplane" %} + ansible: + ansibleHost: {{ node_nets.networks[net][ip_version|default('ip_v4')] }} + {% endfor %} + networks: + {% for net in node_nets.networks.keys() if net not in cifmw_adoption_osp_deploy_adoption_vars_exclude_nets %} +{% set net_name = cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[net]|default(net) %} + - fixedIP: {{ node_nets.networks[net][ip_version|default('ip_v4')] }} + name: {{ net_name }} + subnetName: {{ "subnet1" if net_name == net else net}} +{% if net_name == 'ctlplane' %} + defaultRoute: true +{% endif %} + {% endfor %} {% endfor %} - {%+ endif +%} -{% endfor %} +{% endif %} + +{% if _vm_groups['osp-dcn2-compute-az2s'] | default([]) | length > 0 %} +edpm_nodes_dcn2: + {% for compute in _vm_groups['osp-dcn2-compute-az2s'] %} + {% set node_nets = cifmw_networking_env_definition.instances[compute] %} + {{ compute }}: + hostName: {{ compute }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + {% for net in node_nets.networks.keys() if cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[net]|default(net) == "ctlplane" %} + ansible: + ansibleHost: {{ node_nets.networks[net][ip_version|default('ip_v4')] }} + {% endfor %} + networks: + {% for net in node_nets.networks.keys() if net not in cifmw_adoption_osp_deploy_adoption_vars_exclude_nets %} +{% set net_name = cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[net]|default(net) %} + - fixedIP: {{ node_nets.networks[net][ip_version|default('ip_v4')] }} + name: {{ net_name }} + subnetName: {{ "subnet1" if net_name == net else net}} +{% if net_name == 'ctlplane' %} + defaultRoute: true +{% endif %} + {% endfor %} + {% endfor %} +{% endif %} + edpm_nodes_networker: {% if _vm_groups['osp-networkers'] | default([]) | length > 0 %} @@ -87,14 +152,17 @@ edpm_nodes_networker: {% set node_nets = cifmw_networking_env_definition.instances[networker] %} {{ networker }}: hostName: {{ networker }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + {% for net in node_nets.networks.keys() if cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[net]|default(net) == "ctlplane" %} ansible: - ansibleHost: {{ node_nets.networks.ctlplane[ip_version|default('ip_v4')] }} + ansibleHost: {{ node_nets.networks[net][ip_version|default('ip_v4')] }} + {% endfor %} networks: {% for net in node_nets.networks.keys() if net not in cifmw_adoption_osp_deploy_adoption_vars_exclude_nets %} +{% set net_name = cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[net]|default(net) %} - fixedIP: {{ node_nets.networks[net][ip_version|default('ip_v4')] }} - name: {{ net }} - subnetName: subnet1 -{% if net == 'ctlplane' %} + name: {{ net_name }} + subnetName: {{ "subnet1" if net_name == net else net}} +{% if net_name == 'ctlplane' %} defaultRoute: true {% endif %} {% endfor %} @@ -104,14 +172,17 @@ edpm_nodes_networker: {% set node_nets = cifmw_networking_env_definition.instances[controller] %} {{ controller }}: hostName: {{ controller }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + {% for net in node_nets.networks.keys() if cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[net]|default(net) == "ctlplane" %} ansible: - ansibleHost: {{ node_nets.networks.ctlplane[ip_version|default('ip_v4')] }} + ansibleHost: {{ node_nets.networks[net][ip_version|default('ip_v4')] }} + {% endfor %} networks: {% for net in node_nets.networks.keys() if net not in cifmw_adoption_osp_deploy_adoption_vars_exclude_nets %} +{% set net_name = cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[net]|default(net) %} - fixedIP: {{ node_nets.networks[net][ip_version|default('ip_v4')] }} - name: {{ net }} - subnetName: subnet1 -{% if net == 'ctlplane' %} + name: {{ net_name }} + subnetName: {{ "subnet1" if net_name == net else net}} +{% if net_name == 'ctlplane' %} defaultRoute: true {% endif %} {% endfor %} @@ -119,5 +190,5 @@ edpm_nodes_networker: upstream_dns: {{ cifmw_networking_env_definition.networks.ctlplane[dns_version|default('dns_v4')] | first }} -os_cloud_name: {{ _stack_names[0] }} +os_cloud_name: {{ cifmw_adoption_osp_deploy_scenario.stacks[0].stackname }} standalone_ip: {{ _undercloud_ip }} diff --git a/roles/adoption_osp_deploy/templates/os_net_config_overcloud.yml.j2 b/roles/adoption_osp_deploy/templates/os_net_config_overcloud.yml.j2 index 7cd90787a7..22341ceec7 100644 --- a/roles/adoption_osp_deploy/templates/os_net_config_overcloud.yml.j2 +++ b/roles/adoption_osp_deploy/templates/os_net_config_overcloud.yml.j2 @@ -5,7 +5,7 @@ network_config: mtu: {{ _interface_mtu }} use_dhcp: false dns_servers: - {% for dns_ip in dns_server | default([]) %} + {% for _dns_ip in _dns_server | default([]) %} - {{ _dns_ip }} {% endfor %} - {{ _gateway_ip }} diff --git a/roles/adoption_osp_deploy/templates/resolv.conf.j2 b/roles/adoption_osp_deploy/templates/resolv.conf.j2 new file mode 100644 index 0000000000..5b9f928b5e --- /dev/null +++ b/roles/adoption_osp_deploy/templates/resolv.conf.j2 @@ -0,0 +1,3 @@ +{% for _dns_ip in _dns_server | default([]) %} +nameserver {{ _dns_ip }} +{% endfor %} diff --git a/roles/adoption_osp_deploy/templates/tripleo-ansible-inventory.yaml.j2 b/roles/adoption_osp_deploy/templates/tripleo-ansible-inventory.yaml.j2 index 9cf21bd78d..adc5cb4fbb 100644 --- a/roles/adoption_osp_deploy/templates/tripleo-ansible-inventory.yaml.j2 +++ b/roles/adoption_osp_deploy/templates/tripleo-ansible-inventory.yaml.j2 @@ -1,18 +1,20 @@ #jinja2: trim_blocks:True, lstrip_blocks:True -{% for group, role in cifmw_adoption_osp_deploy_scenario.roles_groups_map.items() %} +{% for group in _stack.stack_nodes %} + {% set role = cifmw_adoption_osp_deploy_scenario.roles_groups_map[group] %} {{ role }}: hosts: {% for node in _vm_groups[group] %} {% set node_nets = cifmw_networking_env_definition.instances[node] %} {{ node }}: - ansible_host: {{ node_nets.networks.ctlplane[ip_version|default('ip_v4')] }} + ansible_host: {{ node_nets.networks[_ctlplane][ip_version|default('ip_v4')] }} canonical_hostname: {{ node }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} - ctlplane_ip: {{ node_nets.networks.ctlplane[ip_version|default('ip_v4')] }} + ctlplane_ip: {{ node_nets.networks[_ctlplane][ip_version|default('ip_v4')] }} {% for network_name, net in node_nets.networks.items() %} + {% set network_name = cifmw_adoption_osp_deploy_scenario.network_tripleo_network_map[network_name]|default(network_name) %} {% if 'vlan_id' in net %} - {% set net_name = ['storage_mgmt'] if network_name == 'storagemgmt' else [network_name] %} - {% set net_name = ['internal_api'] if network_name == 'internalapi' else [network_name] %} - {{ net_name[0] }}_ip: {{ net[ip_version|default('ip_v4')] }} + {% set network_name = 'storage_mgmt' if network_name == 'storagemgmt' else network_name %} + {% set network_name = 'internal_api' if network_name == 'internalapi' else network_name %} + {{ network_name }}_ip: {{ net[ip_version|default('ip_v4')] }} {% endif %} {% endfor %} {% endfor %} @@ -33,19 +35,18 @@ allovercloud: {% endfor %} computes: children: -{% if _role_map_translation['osp-computes'] | default([]) | length > 0 %} - {{ _role_map_translation['osp-computes'] }}: {} -{% endif %} -{% if _role_map_translation[_overcloud_name ~ '-osp-computes'] | default([]) | length > 0 %} - {{ _role_map_translation[_overcloud_name ~ '-osp-computes'] }}: {} -{% endif %} + {% for group in _stack.stack_nodes %} + {% if 'computes' in group %} + {{ cifmw_adoption_osp_deploy_scenario.roles_groups_map[group] }}: {} + {% endif %} + {% endfor %} {{ _overcloud_name }}: hosts: - {% for group in _role_map_translation.keys() %} + {% for group in _stack.stack_nodes %} {% for node in _vm_groups[group] %} {% set node_nets = cifmw_networking_env_definition.instances[node] %} {{ node }}: ansible_user: tripleo-admin - ansible_host: {{ node_nets.networks.ctlplane[ip_version|default('ip_v4')] }} + ansible_host: {{ node_nets.networks[_ctlplane][ip_version|default('ip_v4')] }} {% endfor %} {% endfor %} diff --git a/scenarios/adoption/dcn_nostorage.yml b/scenarios/adoption/dcn_nostorage.yml new file mode 100644 index 0000000000..70eb9e5d86 --- /dev/null +++ b/scenarios/adoption/dcn_nostorage.yml @@ -0,0 +1,160 @@ +_osp_img_data: &osp_base_conf + image_local_dir: "{{ cifmw_basedir }}/images/" + disk_file_name: osp-base.qcow2 + image_url: "{{ osp_base_img_url | default(cifmw_discovered_image_url) }}" + sha256_image_name: >- + {{ osp_base_img_sha256 | default(cifmw_discovered_hash) }} + +libvirt_manager_patch_layout: + vms: + osp-undercloud: + <<: *osp_base_conf + amount: 1 + memory: 16 + cpus: 8 + disksize: 80 + nets: + - ocpbm + - osp_trunk + osp-controller: + <<: *osp_base_conf + amount: 1 + disksize: 50 + memory: 8 + cpus: 4 + nets: + - ocpbm + - osp_trunk + # Let's remove the default computes, since we want to adopt the + # OSP ones + compute: + amount: 0 + osp-compute: + <<: *osp_base_conf + amount: "{{ [cifmw_libvirt_manager_compute_amount|int, 3] | max }}" + extra_disks_num: 3 + extra_disks_size: 15G + disksize: "{{ [cifmw_libvirt_manager_compute_disksize|int, 50] | max }}" + memory: "{{ [cifmw_libvirt_manager_compute_memory|int, 8] | max }}" + cpus: "{{ [cifmw_libvirt_manager_compute_cpus|int, 4] | max }}" + nets: + - ocpbm + - osp_trunk + dcn1-compute-az1: + amount: 0 + osp-dcn1-compute-az1: + <<: *osp_base_conf + amount: "{{ [cifmw_libvirt_manager_compute_amount|int, 3] | max }}" + extra_disks_num: 3 + extra_disks_size: 15G + disksize: "{{ [cifmw_libvirt_manager_compute_disksize|int, 50] | max }}" + memory: "{{ [cifmw_libvirt_manager_compute_memory|int, 8] | max }}" + cpus: "{{ [cifmw_libvirt_manager_compute_cpus|int, 4] | max }}" + nets: + - dcn1_pb + - dcn1_tr + dcn2-compute-az2: + amount: 0 + osp-dcn2-compute-az2: + <<: *osp_base_conf + amount: "{{ [cifmw_libvirt_manager_compute_amount|int, 3] | max }}" + extra_disks_num: 3 + extra_disks_size: 15G + disksize: "{{ [cifmw_libvirt_manager_compute_disksize|int, 50] | max }}" + memory: "{{ [cifmw_libvirt_manager_compute_memory|int, 8] | max }}" + cpus: "{{ [cifmw_libvirt_manager_compute_cpus|int, 4] | max }}" + nets: + - dcn2_pb + - dcn2_tr + +networking_mapper_definition_patch: + networks: + external: + network: "10.0.0.0/24" + vlan: 44 + mtu: 1496 + + group-templates: + osp-controllers: + network-template: + range: + start: 103 + length: 3 + networks: &osp_nets + ctlplane: {} + external: + trunk-parent: ctlplane + internalapi: + trunk-parent: ctlplane + tenant: + trunk-parent: ctlplane + storage: + trunk-parent: ctlplane + storagemgmt: + trunk-parent: ctlplane + osp-underclouds: + network-template: + range: + start: 100 + length: 1 + networks: *osp_nets + computes: + network-template: + range: + start: 200 + length: 1 + osp-computes: + network-template: + range: + start: 106 + length: 3 + networks: + ctlplane: {} + internalapi: + trunk-parent: ctlplane + tenant: + trunk-parent: ctlplane + storage: + trunk-parent: ctlplane + storagemgmt: + trunk-parent: ctlplane + dcn1-compute-az1s: + network-template: + range: + start: 201 + length: 1 + osp-dcn1-compute-az1s: + network-template: + range: + start: 111 + length: 10 + networks: + ctlplanedcn1: {} + internalapidcn1: + trunk-parent: ctlplanedcn1 + tenantdcn1: + trunk-parent: ctlplanedcn1 + storagedcn1: + trunk-parent: ctlplanedcn1 + storagemgmtdcn1: + trunk-parent: ctlplanedcn1 + dcn2-compute-az2s: + network-template: + range: + start: 202 + length: 1 + osp-dcn2-compute-az2s: + network-template: + range: + start: 121 + length: 10 + networks: + ctlplanedcn2: {} + internalapidcn2: + trunk-parent: ctlplanedcn2 + tenantdcn2: + trunk-parent: ctlplanedcn2 + storagedcn2: + trunk-parent: ctlplanedcn2 + storagemgmtdcn2: + trunk-parent: ctlplanedcn2 diff --git a/scenarios/reproducers/dt-dcn.yml b/scenarios/reproducers/dt-dcn.yml index 74f60cb89b..e689985b38 100644 --- a/scenarios/reproducers/dt-dcn.yml +++ b/scenarios/reproducers/dt-dcn.yml @@ -68,34 +68,34 @@ cifmw_libvirt_manager_configuration: dcn1_pb: | dcn1_pb - - - - + + + + dcn1_tr: | dcn1_tr - - - - + + + + dcn2_pb: | dcn2_pb - - - - + + + + dcn2_tr: | dcn2_tr - - - - + + + + vms: ocp: @@ -114,6 +114,7 @@ cifmw_libvirt_manager_configuration: - ocppr - ocpbm - osp_trunk + - osp_trunk compute: uefi: "{{ cifmw_use_uefi }}" root_part_id: "{{ cifmw_root_partition_id }}" From 5b51be13152216556ddc09db3ac1fdd6ee63f055 Mon Sep 17 00:00:00 2001 From: John Fulton Date: Wed, 17 Dec 2025 15:03:30 +0000 Subject: [PATCH 2/3] Render network-specific routes in os-net-config for DCN deployments Modify os_net_config_overcloud.yml.j2 template to render per-network routes from stack configuration instead of hardcoded empty routes. Problem: - Template had hardcoded "routes: []" for all VLAN networks (line 40) - DCN compute nodes need routes to reach central site services - Routes defined in data-plane-adoption's network_data.yaml.j2 were being ignored because ci-framework pre-generates os-net-config files before TripleO Heat deployment runs Solution: - Check if _stack.network_routes is defined and contains routes for the current network - If routes exist, render them with ip_netmask and next_hop - Otherwise, fall back to empty routes array This enables DCN scenarios to configure cross-site routes via the network_routes field in stack definitions (dcn_nostorage.yaml). Example usage in stack config: network_routes: internalapidcn1: - ip_netmask: 172.17.0.0/24 next_hop: 172.17.10.1 Related: Requires corresponding data-plane-adoption change to add network_routes to dcn1/dcn2 stack definitions. Co-Authored-By: Claude Signed-off-by: John Fulton --- .../templates/os_net_config_overcloud.yml.j2 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/roles/adoption_osp_deploy/templates/os_net_config_overcloud.yml.j2 b/roles/adoption_osp_deploy/templates/os_net_config_overcloud.yml.j2 index 22341ceec7..bd4badcb6c 100644 --- a/roles/adoption_osp_deploy/templates/os_net_config_overcloud.yml.j2 +++ b/roles/adoption_osp_deploy/templates/os_net_config_overcloud.yml.j2 @@ -37,8 +37,16 @@ network_config: vlan_id: {{ net.vlan_id }} addresses: - ip_netmask: {{ net[ip_version|default('ip_v4')] }}/{{ net[prefix_length_version|default('prefix_length_v4')] }} + {% if _stack.network_routes is defined and network_name in _stack.network_routes %} + routes: + {% for route in _stack.network_routes[network_name] %} + - ip_netmask: {{ route.ip_netmask }} + next_hop: {{ route.next_hop }} + {% endfor %} + {% else %} routes: [] {% endif %} + {% endif %} {% endfor %} {% if 'ironic' in _node_net.networks.keys () %} {% set net = _node_net.networks.ironic %} From 65cdb65e1ab2a942f4f1477dbf8654f98ad6c746 Mon Sep 17 00:00:00 2001 From: John Fulton Date: Wed, 17 Dec 2025 15:03:39 +0000 Subject: [PATCH 3/3] Extract DCN network routes from TripleO scenario into adoption vars Add edpm_dcn1_routes and edpm_dcn2_routes variables to adoption_vars.yaml template. These variables extract network routes defined in the TripleO scenario file (dcn_nostorage.yaml) and make them available for EDPM ansible configuration. Routes are extracted from stack.network_routes for dcn1 and dcn2 stacks, with each route containing destination (ip_netmask) and nexthop fields. This enables proper inter-site connectivity in DCN deployments where compute nodes in edge sites need routes to reach control plane services in the central site. Co-Authored-By: Claude Signed-off-by: John Fulton --- .../templates/adoption_vars.yaml.j2 | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/roles/adoption_osp_deploy/templates/adoption_vars.yaml.j2 b/roles/adoption_osp_deploy/templates/adoption_vars.yaml.j2 index 774d3fb2e6..341cef117c 100644 --- a/roles/adoption_osp_deploy/templates/adoption_vars.yaml.j2 +++ b/roles/adoption_osp_deploy/templates/adoption_vars.yaml.j2 @@ -192,3 +192,28 @@ edpm_nodes_networker: upstream_dns: {{ cifmw_networking_env_definition.networks.ctlplane[dns_version|default('dns_v4')] | first }} os_cloud_name: {{ cifmw_adoption_osp_deploy_scenario.stacks[0].stackname }} standalone_ip: {{ _undercloud_ip }} + +# DCN network routes extracted from TripleO scenario +{% set _dcn1_stack = cifmw_adoption_osp_deploy_scenario.stacks | selectattr('stackname', 'equalto', 'dcn1') | first | default({}) %} +{% if _dcn1_stack.network_routes is defined %} +edpm_dcn1_routes: + {% for subnet_name, routes in _dcn1_stack.network_routes.items() %} + {{ subnet_name }}: + {% for route in routes %} + - destination: {{ route.ip_netmask }} + nexthop: {{ route.next_hop }} + {% endfor %} + {% endfor %} +{% endif %} + +{% set _dcn2_stack = cifmw_adoption_osp_deploy_scenario.stacks | selectattr('stackname', 'equalto', 'dcn2') | first | default({}) %} +{% if _dcn2_stack.network_routes is defined %} +edpm_dcn2_routes: + {% for subnet_name, routes in _dcn2_stack.network_routes.items() %} + {{ subnet_name }}: + {% for route in routes %} + - destination: {{ route.ip_netmask }} + nexthop: {{ route.next_hop }} + {% endfor %} + {% endfor %} +{% endif %}