From 3282ac3cc9b6dcd3bd1e70dde70dfbffd08627b1 Mon Sep 17 00:00:00 2001 From: Eduardo Olivares Date: Fri, 10 Oct 2025 13:17:35 +0200 Subject: [PATCH 1/5] Add bgp-l3-xl-adoption job --- .../adoption_bgp_post_overcloud.yaml | 37 ++ .../playbooks/adoption_bgp_pre_overcloud.yaml | 36 ++ playbooks/bgp/prepare-bgp-spines-leaves.yaml | 56 ++ .../tasks/config_files.yml | 9 + .../tasks/generate_adoption_vars.yml | 20 + .../tasks/prepare_overcloud.yml | 81 +++ .../tasks/prepare_undercloud.yml | 65 +++ .../templates/adoption_vars_bgp.yaml.j2 | 209 ++++++++ .../os_net_config_overcloud_bgp.yml.j2 | 59 +++ .../os_net_config_undercloud_bgp.yml.j2 | 73 +++ .../tripleo-ansible-inventory_bgp.yaml.j2 | 68 +++ .../templates/bgp-l3-xl-adoption | 1 + scenarios/adoption/bgp-l3-xl.yml | 495 ++++++++++++++++++ scenarios/reproducers/bgp-l3-xl.yml | 138 ++++- .../reproducers/networking-definition-bgp.yml | 266 ++++++++++ 15 files changed, 1609 insertions(+), 4 deletions(-) create mode 100644 hooks/playbooks/adoption_bgp_post_overcloud.yaml create mode 100644 hooks/playbooks/adoption_bgp_pre_overcloud.yaml create mode 100644 roles/adoption_osp_deploy/templates/adoption_vars_bgp.yaml.j2 create mode 100644 roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 create mode 100644 roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 create mode 100644 roles/adoption_osp_deploy/templates/tripleo-ansible-inventory_bgp.yaml.j2 create mode 120000 roles/ci_gen_kustomize_values/templates/bgp-l3-xl-adoption create mode 100644 scenarios/adoption/bgp-l3-xl.yml create mode 100644 scenarios/reproducers/networking-definition-bgp.yml diff --git a/hooks/playbooks/adoption_bgp_post_overcloud.yaml b/hooks/playbooks/adoption_bgp_post_overcloud.yaml new file mode 100644 index 0000000000..39bec0fee2 --- /dev/null +++ b/hooks/playbooks/adoption_bgp_post_overcloud.yaml @@ -0,0 +1,37 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +- name: BGP post_overcloud hook + hosts: "{{ cifmw_target_host | default('localhost') }}" + gather_facts: false + tasks: + - name: Remove default route from OC nodes + delegate_to: "{{ _vm }}" + become: true + ansible.builtin.command: + cmd: ip route del default via 192.168.111.1 + failed_when: false + loop: >- + {{ + _vm_groups['osp-r0-computes'] | list + + _vm_groups['osp-r0-controllers'] | list + + _vm_groups['osp-r1-computes'] | list + + _vm_groups['osp-r1-controllers'] | list + + _vm_groups['osp-r2-computes'] | list + + _vm_groups['osp-r2-controllers'] | list + }} + loop_control: + loop_var: _vm diff --git a/hooks/playbooks/adoption_bgp_pre_overcloud.yaml b/hooks/playbooks/adoption_bgp_pre_overcloud.yaml new file mode 100644 index 0000000000..e4d561e469 --- /dev/null +++ b/hooks/playbooks/adoption_bgp_pre_overcloud.yaml @@ -0,0 +1,36 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +- name: BGP pre_overcloud hook + hosts: "{{ cifmw_target_host | default('localhost') }}" + gather_facts: false + tasks: + - name: Add default route to OC nodes + delegate_to: "{{ _vm }}" + become: true + ansible.builtin.command: + cmd: ip route add default via 192.168.111.1 + loop: >- + {{ + _vm_groups['osp-r0-computes'] | list + + _vm_groups['osp-r0-controllers'] | list + + _vm_groups['osp-r1-computes'] | list + + _vm_groups['osp-r1-controllers'] | list + + _vm_groups['osp-r2-computes'] | list + + _vm_groups['osp-r2-controllers'] | list + }} + loop_control: + loop_var: _vm diff --git a/playbooks/bgp/prepare-bgp-spines-leaves.yaml b/playbooks/bgp/prepare-bgp-spines-leaves.yaml index 02cc851648..31df9548ca 100644 --- a/playbooks/bgp/prepare-bgp-spines-leaves.yaml +++ b/playbooks/bgp/prepare-bgp-spines-leaves.yaml @@ -1,4 +1,60 @@ --- +- name: Start spines and leafs and add them to inventory + hosts: localhost + vars: + leafs_list: + - leaf-0 + - leaf-1 + - leaf-2 + - leaf-3 + - leaf-4 + - leaf-5 + spines_list: + - spine-0 + - spine-1 + routers_list: + - router-0 + fabric_list: "{{ leafs_list + spines_list + routers_list }}" + tasks: + - name: Start spine and leaf VMs + delegate_to: hypervisor + become: true + community.libvirt.virt: + name: "cifmw-{{ item }}" + state: running + loop: "{{ fabric_list }}" + + - name: Add leafs group to inventory + when: '"leafs" not in groups' + ansible.builtin.add_host: + name: "{{ item }}.utility" + group: leafs + loop: "{{ leafs_list }}" + + - name: Add spines group to inventory + when: '"spines" not in groups' + ansible.builtin.add_host: + name: "{{ item }}.utility" + group: spines + loop: "{{ spines_list }}" + + - name: Add routers group to inventory + when: '"routers" not in groups' + ansible.builtin.add_host: + name: "{{ item }}.utility" + group: routers + loop: "{{ routers_list }}" + + - name: Check SSH connectivity + delegate_to: hypervisor + ansible.builtin.wait_for: + port: 22 + host: "{{ item }}.utility" + search_regex: OpenSSH + delay: 10 + timeout: 120 + loop: "{{ fabric_list }}" + - name: Common spines and leaves configuration hosts: "spines,leafs{{ router_bool | default(false) | ternary(',routers', '') }}" tasks: diff --git a/roles/adoption_osp_deploy/tasks/config_files.yml b/roles/adoption_osp_deploy/tasks/config_files.yml index 28eab22e97..e217f9a725 100644 --- a/roles/adoption_osp_deploy/tasks/config_files.yml +++ b/roles/adoption_osp_deploy/tasks/config_files.yml @@ -34,7 +34,16 @@ register: _original_config_download delegate_to: "localhost" +- name: Copy config download file as is (bgp) + when: bgp + delegate_to: "osp-undercloud-0" + ansible.builtin.copy: + content: "{{ _original_config_download['content'] |b64decode | from_yaml | to_nice_yaml(indent=2, sort_keys=false) }}" + dest: "{{ ansible_user_dir }}/config_download_{{ _stack.stackname }}.yaml" + mode: "0644" + - name: Generate config download file + when: not bgp vars: _ctlplane_net: "{{ cifmw_networking_env_definition.networks.ctlplane }}" _hostname_map_translation: >- diff --git a/roles/adoption_osp_deploy/tasks/generate_adoption_vars.yml b/roles/adoption_osp_deploy/tasks/generate_adoption_vars.yml index a6913bc271..f23c060df6 100644 --- a/roles/adoption_osp_deploy/tasks/generate_adoption_vars.yml +++ b/roles/adoption_osp_deploy/tasks/generate_adoption_vars.yml @@ -22,6 +22,7 @@ - user_dir - name: Generate adoption vars file + when: not bgp delegate_to: "controller-0" vars: _undercloud_name: "{{ _vm_groups['osp-underclouds'] | first }}" @@ -44,3 +45,22 @@ src: "adoption_vars.yaml.j2" dest: "{{ ansible_user_dir }}/adoption_vars.yaml" mode: "0644" + + +- name: Generate adoption vars file (BGP) + when: bgp + delegate_to: "controller-0" + vars: + _undercloud_name: "{{ _vm_groups['osp-underclouds'] | first }}" + _undercloud_net: "{{ cifmw_networking_env_definition.instances[_undercloud_name] }}" + _undercloud_ip: "{{ _undercloud_net.networks.ctlplaner0[ip_version|default('ip_v4')] }}" + _controller_1_name: "{{ _vm_groups['osp-r0-controllers'] | first }}" + _controller_1_net: "{{ cifmw_networking_env_definition.instances[_controller_1_name] }}" + _controller_1_internalapi_ip: "99.99.0.29" + _compute_1_name: "{{ _vm_groups['osp-r0-computes'] | first }}" + _compute_1_net: "{{ cifmw_networking_env_definition.instances[_compute_1_name] }}" + _compute_1_ip: "{{ _compute_1_net.networks.ctlplaner0[ip_version|default('ip_v4')] }}" + ansible.builtin.template: + src: "adoption_vars_bgp.yaml.j2" + dest: "{{ ansible_user_dir }}/adoption_vars.yaml" + mode: "0644" diff --git a/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml b/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml index d259b8c866..969aeb1ad9 100644 --- a/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml +++ b/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml @@ -137,12 +137,21 @@ script: "{{ _source_cmd }}; {{ _vip_provision_cmd }}" - name: Create tripleo ansible inventory + when: not bgp delegate_to: "osp-undercloud-0" ansible.builtin.template: src: "tripleo-ansible-inventory.yaml.j2" dest: "{{ ansible_user_dir }}/overcloud-deploy/{{ _overcloud_name }}/tripleo-ansible-inventory.yaml" mode: "0644" + - name: Create tripleo ansible inventory (BGP) + when: bgp + delegate_to: "osp-undercloud-0" + ansible.builtin.template: + src: "tripleo-ansible-inventory_bgp.yaml.j2" + dest: "{{ ansible_user_dir }}/overcloud-deploy/{{ _overcloud_name }}/tripleo-ansible-inventory.yaml" + mode: "0644" + - name: Ensure os-net-config and openvswitch is installed in overcloud nodes become: true delegate_to: "{{ overcloud_vm }}" @@ -184,6 +193,78 @@ loop: "{{ _tripleo_nodes_stack[_overcloud_name] }}" loop_control: loop_var: overcloud_vm + when: not bgp + + - name: Generate os-net-config file for overcloud nodes (bgp) + become: true + delegate_to: "{{ overcloud_vm }}" + vars: + _node_net: "{{ cifmw_networking_env_definition.instances[overcloud_vm] }}" + _dns_server: "{{ _ctlplane_net.[dns_version|default('dns_v4')] }}" + _interface_mtu: 1500 + vms: + osp-r0-compute-0: + ctlplane: '192.168.122.100' + left: '100.64.0.2' + right: '100.65.0.2' + main: '99.99.0.2' + main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0004' + osp-r0-compute-1: + ctlplane: '192.168.122.101' + left: '100.64.0.6' + right: '100.65.0.6' + main: '99.99.0.6' + main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0005' + osp-r1-compute-0: + ctlplane: '192.168.123.105' + left: '100.64.1.2' + right: '100.65.1.2' + main: '99.99.1.2' + main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0006' + osp-r1-compute-1: + ctlplane: '192.168.123.106' + left: '100.64.1.6' + right: '100.65.1.6' + main: '99.99.1.6' + main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0007' + osp-r2-compute-0: + ctlplane: '192.168.124.110' + left: '100.64.2.2' + right: '100.65.2.2' + main: '99.99.2.2' + main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0008' + osp-r2-compute-1: + ctlplane: '192.168.124.111' + left: '100.64.2.6' + right: '100.65.2.6' + main: '99.99.2.6' + main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0009' + osp-r0-controller-0: + ctlplane: '192.168.122.140' + left: '100.64.0.30' + right: '100.65.0.30' + main: '99.99.0.29' + main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0001' + osp-r1-controller-0: + ctlplane: '192.168.123.142' + left: '100.64.1.30' + right: '100.65.1.30' + main: '99.99.1.29' + main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0002' + osp-r2-controller-0: + ctlplane: '192.168.124.144' + left: '100.64.2.30' + right: '100.65.2.30' + main: '99.99.2.29' + main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0003' + ansible.builtin.template: + src: "os_net_config_overcloud_bgp.yml.j2" + dest: /etc/os-net-config/tripleo_config.yaml + mode: "0644" + loop: "{{ _tripleo_nodes_stack[_overcloud_name] }}" + loop_control: + loop_var: overcloud_vm + when: bgp - name: Configure network interfaces for overcloud nodes become: true diff --git a/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml b/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml index 522fb5ed0a..12e564c075 100644 --- a/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml +++ b/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml @@ -106,6 +106,7 @@ mode: '0755' - name: Generate os-net-config file + when: not bgp become: true vars: _undercloud_name: "{{ _vm_groups['osp-underclouds'] | first }}" @@ -122,6 +123,42 @@ dest: /etc/os-net-config/tripleo_config.yaml mode: "0644" + - name: Obtain IPs whose routes need to be added to the undercloud (bgp) + when: bgp + ansible.builtin.shell: | + getent ahosts {{ item }} | grep STREAM | awk '{print $1}' | grep -v : + register: _ips_for_uc_routes_output + loop: + - registry.redhat.io + - cdn.redhat.com + - access.redhat.com + - cdn01.quay.io + + - name: Create list with the previous IPs + when: bgp + ansible.builtin.set_fact: + ips_for_uc_routes_list: "{{ (ips_for_uc_routes_list | default([]) + item.stdout_lines) | ansible.builtin.unique }}" + loop: "{{ _ips_for_uc_routes_output.results }}" + + - name: Generate os-net-config file (bgp) + when: bgp + become: true + vars: + _undercloud_name: "{{ _vm_groups['osp-underclouds'] | first }}" + _undercloud_net: "{{ cifmw_networking_env_definition.instances[_undercloud_name] }}" + _ctlplane_ip: "{{ _undercloud_net.networks.ctlplaner0[ip_version|default('ip_v4')] }}" + _ctlplane_vip: "{{ cifmw_adoption_osp_deploy_scenario.undercloud.ctlplane_vip }}" + _ctlplane_net: "{{ cifmw_networking_env_definition.networks.ctlplaner0}}" + _dns_server: "{{ _ctlplane_net[dns_version|default('dns_v4')] }}" + _gateway_ip: "{{ _ctlplane_net[gw_version|default('gw_v4')] }}" + _interface_mtu: "{{ _undercloud_net.networks.ctlplaner0.mtu }}" + _ctlplane_cidr: "{{ _undercloud_net.networks.ctlplaner0[prefix_length_version|default('prefix_length_v4')] }}" + _ips_for_uc_routes_list: "{{ ips_for_uc_routes_list }}" + ansible.builtin.template: + src: "os_net_config_undercloud_bgp.yml.j2" + dest: /etc/os-net-config/tripleo_config.yaml + mode: "0644" + - name: Copy undercloud.conf file to location to edit it ansible.builtin.copy: src: "/usr/share/python-tripleoclient/undercloud.conf.sample" @@ -130,6 +167,7 @@ mode: "0644" - name: Add environment specific vars for undercloud + when: not bgp vars: _undercloud_name: "{{ _vm_groups['osp-underclouds'] | first }}" _undercloud_net: "{{ cifmw_networking_env_definition.instances[_undercloud_name] }}" @@ -185,6 +223,33 @@ combine(_env_undercloud, recursive=true, list_merge="append_rp") }} +- name: Add environment specific vars for undercloud (bgp) + when: bgp + vars: + _undercloud_name: "{{ _vm_groups['osp-underclouds'] | first }}" + _undercloud_net: "{{ cifmw_networking_env_definition.instances[_undercloud_name] }}" + _undercloud_ip: "{{ _undercloud_net.networks.ctlplaner0[ip_version|default('ip_v4')] }}" + _undercloud_net_prefix: "{{ _undercloud_net.networks.ctlplaner0[prefix_length_version|default('prefix_length_v4')] }}" + _ctlplane_cidr: "{{ cifmw_networking_env_definition.networks.ctlplaner0[network_version|default('network_v4')] }}" + _interface_mtu: "{{ _undercloud_net.networks.ctlplaner0.mtu }}" + _env_undercloud: + config: + - section: DEFAULT + option: undercloud_ntp_servers + value: "{{ cifmw_adoption_osp_deploy_ntp_server }}" + - section: DEFAULT + option: container_images_file + value: "{{ ansible_user_dir }}/containers-prepare-parameters.yaml" + - section: DEFAULT + option: net_config_override + value: "/etc/os-net-config/tripleo_config.yaml" + ansible.builtin.set_fact: + _undercloud_conf: >- + {{ + cifmw_adoption_osp_deploy_scenario.undercloud | + combine(_env_undercloud, recursive=true, list_merge="append_rp") + }} + - name: Copy undercloud overrides file if present and amend undercloud conf when: cifmw_adoption_osp_deploy_scenario.undercloud.undercloud_parameters_override is defined vars: diff --git a/roles/adoption_osp_deploy/templates/adoption_vars_bgp.yaml.j2 b/roles/adoption_osp_deploy/templates/adoption_vars_bgp.yaml.j2 new file mode 100644 index 0000000000..77a769a59d --- /dev/null +++ b/roles/adoption_osp_deploy/templates/adoption_vars_bgp.yaml.j2 @@ -0,0 +1,209 @@ +#jinja2: trim_blocks:True, lstrip_blocks:True +source_mariadb_ip: 99.99.0.29 +source_ovndb_ip: 99.99.0.29 +edpm_node_hostname: {{ _compute_1_name }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} +edpm_node_ip: {{ _compute_1_ip }} + +edpm_computes: | + {% for compute in _vm_groups['osp-r0-computes'] %} + {% set node_nets = cifmw_networking_env_definition.instances[compute] %} + ["{{ compute }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="{{ node_nets.networks.ctlplaner0[ip_version|default('ip_v4')] }}" + {% endfor %} + {% for compute in _vm_groups['osp-r1-computes'] %} + {% set node_nets = cifmw_networking_env_definition.instances[compute] %} + ["{{ compute }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="{{ node_nets.networks.ctlplaner1[ip_version|default('ip_v4')] }}" + {% endfor %} + {% for compute in _vm_groups['osp-r2-computes'] %} + {% set node_nets = cifmw_networking_env_definition.instances[compute] %} + ["{{ compute }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="{{ node_nets.networks.ctlplaner2[ip_version|default('ip_v4')] }}" + {% endfor %} + + +{% if _vm_groups['osp-r0-networkers'] | default([]) | length > 0 %} +edpm_networkers: | + {% for networker in _vm_groups['osp-r0-networkers'] | default([]) %} + {% set node_nets = cifmw_networking_env_definition.instances[networker] %} + ["{{ networker }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="{{ node_nets.networks.ctlplaner0[ip_version|default('ip_v4')] }}" + {% endfor %} + {% for networker in _vm_groups['osp-r1-networkers'] | default([]) %} + {% set node_nets = cifmw_networking_env_definition.instances[networker] %} + ["{{ networker }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="{{ node_nets.networks.ctlplaner1[ip_version|default('ip_v4')] }}" + {% endfor %} + {% for networker in _vm_groups['osp-r2-networkers'] | default([]) %} + {% set node_nets = cifmw_networking_env_definition.instances[networker] %} + ["{{ networker }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="{{ node_nets.networks.ctlplaner2[ip_version|default('ip_v4')] }}" + {% endfor %} +{% endif %} + + +source_galera_members: | + {% for controller in _vm_groups['osp-r0-controllers'] %} + {% set node_nets = cifmw_networking_env_definition.instances[controller] %} + ["{{ controller }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="99.99.0.29" + {% endfor %} + {% for controller in _vm_groups['osp-r1-controllers'] %} + {% set node_nets = cifmw_networking_env_definition.instances[controller] %} + ["{{ controller }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="99.99.1.29" + {% endfor %} + {% for controller in _vm_groups['osp-r2-controllers'] %} + {% set node_nets = cifmw_networking_env_definition.instances[controller] %} + ["{{ controller }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }}"]="99.99.2.29" + {% endfor %} + + +{% if _vm_groups['osp-r0-computes'] | default([]) | length > 0 %} +edpm_nodes: + {% for compute in _vm_groups['osp-r0-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.ctlplaner0[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 == 'ctlplaner0' %} + defaultRoute: true +{% endif %} + {% endfor %} + {% endfor %} + {% for compute in _vm_groups['osp-r1-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.ctlplaner1[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 == 'ctlplaner1' %} + defaultRoute: true +{% endif %} + {% endfor %} + {% endfor %} + {% for compute in _vm_groups['osp-r2-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.ctlplaner2[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 == 'ctlplaner2' %} + defaultRoute: true +{% endif %} + {% endfor %} + {% endfor %} +{% endif %} + +edpm_nodes_networker: +{% if _vm_groups['osp-r0-networkers'] | default([]) | length > 0 %} + {% for networker in _vm_groups['osp-r0-networkers'] | default([]) %} + {% set node_nets = cifmw_networking_env_definition.instances[networker] %} + {{ networker }}: + hostName: {{ networker }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + ansible: + ansibleHost: {{ node_nets.networks.ctlplaner0[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 == 'ctlplaner0' %} + defaultRoute: true +{% endif %} + {% endfor %} + {% endfor %} + {% for networker in _vm_groups['osp-r1-networkers'] | default([]) %} + {% set node_nets = cifmw_networking_env_definition.instances[networker] %} + {{ networker }}: + hostName: {{ networker }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + ansible: + ansibleHost: {{ node_nets.networks.ctlplaner1[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 == 'ctlplaner1' %} + defaultRoute: true +{% endif %} + {% endfor %} + {% endfor %} + {% for networker in _vm_groups['osp-r2-networkers'] | default([]) %} + {% set node_nets = cifmw_networking_env_definition.instances[networker] %} + {{ networker }}: + hostName: {{ networker }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + ansible: + ansibleHost: {{ node_nets.networks.ctlplaner2[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 == 'ctlplaner2' %} + defaultRoute: true +{% endif %} + {% endfor %} + {% endfor %} +{% endif %} + {% for controller in _vm_groups['osp-r0-controllers'] %} + {% set node_nets = cifmw_networking_env_definition.instances[controller] %} + {{ controller }}: + hostName: {{ controller }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + ansible: + ansibleHost: {{ node_nets.networks.ctlplaner0[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 == 'ctlplaner0' %} + defaultRoute: true +{% endif %} + {% endfor %} + {% endfor %} + {% for controller in _vm_groups['osp-r1-controllers'] %} + {% set node_nets = cifmw_networking_env_definition.instances[controller] %} + {{ controller }}: + hostName: {{ controller }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + ansible: + ansibleHost: {{ node_nets.networks.ctlplaner1[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 == 'ctlplaner1' %} + defaultRoute: true +{% endif %} + {% endfor %} + {% endfor %} + {% for controller in _vm_groups['osp-r2-controllers'] %} + {% set node_nets = cifmw_networking_env_definition.instances[controller] %} + {{ controller }}: + hostName: {{ controller }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + ansible: + ansibleHost: {{ node_nets.networks.ctlplaner2[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 == 'ctlplaner2' %} + defaultRoute: true +{% endif %} + {% endfor %} + {% endfor %} + + +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 }} diff --git a/roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 b/roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 new file mode 100644 index 0000000000..37f7db1e05 --- /dev/null +++ b/roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 @@ -0,0 +1,59 @@ +#jinja2: trim_blocks:True, lstrip_blocks:True +network_config: +- type: interface + name: nic1 + mtu: {{ _interface_mtu }} + use_dhcp: true + defroute: false + routes: [] +- type: interface + name: nic2 + mtu: {{ _interface_mtu }} + dns_servers: ['192.168.122.1', '192.168.125.1'] + domain: [] + routes: +{% if 'r0' in overcloud_vm %} + - ip_netmask: 192.168.123.0/24 + next_hop: 192.168.122.1 + - ip_netmask: 192.168.124.0/24 + next_hop: 192.168.122.1 +{% elif 'r1' in overcloud_vm %} + - ip_netmask: 192.168.122.0/24 + next_hop: 192.168.123.1 + - ip_netmask: 192.168.124.0/24 + next_hop: 192.168.123.1 +{% else %} + - ip_netmask: 192.168.122.0/24 + next_hop: 192.168.124.1 + - ip_netmask: 192.168.123.0/24 + next_hop: 192.168.124.1 +{% endif %} + use_dhcp: false + addresses: + - ip_netmask: {{ vms[overcloud_vm].ctlplane }}/24 +- type: interface + name: nic3 + use_dhcp: false + addresses: + - ip_netmask: + {{ vms[overcloud_vm].left }}/30 +- type: interface + name: nic4 + use_dhcp: false + addresses: + - ip_netmask: + {{ vms[overcloud_vm].right }}/30 +- type: interface + name: lo + use_dhcp: false + addresses: + - ip_netmask: + {{ vms[overcloud_vm].main }}/32 + - ip_netmask: + {{ vms[overcloud_vm].main6 }}/128 +- type: ovs_bridge + name: br-ex + use_dhcp: false +- type: ovs_bridge + name: br-vlan + use_dhcp: false diff --git a/roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 b/roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 new file mode 100644 index 0000000000..29b95d30d1 --- /dev/null +++ b/roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 @@ -0,0 +1,73 @@ +#jinja2: trim_blocks:True, lstrip_blocks:True +{% if ':' in _ctlplane_ip %} +{% set _ctlplane_ip_cidr = 128 %} +{% else %} +{% set _ctlplane_ip_cidr = 32 %} +{% endif %} +{% if ':' in _ctlplane_vip %} +{% set _ctlplane_vip_cidr = 128 %} +{% else %} +{% set _ctlplane_vip_cidr = 32 %} +{% endif %} +network_config: +network_config: +- type: interface + name: nic1 + mtu: {{ _interface_mtu }} + use_dhcp: true + defroute: false + routes: + - ip_netmask: 10.0.0.0/8 + next_hop: 192.168.111.1 + - ip_netmask: 23.0.0.0/8 + next_hop: 192.168.111.1 +{% for _ip in _ips_for_uc_routes_list %} + - ip_netmask: {{ _ip }}/32 + next_hop: 192.168.111.1 +{% endfor %} +- type: ovs_bridge + name: br-ctlplane + mtu: {{ _interface_mtu }} + use_dhcp: false + dns_servers: + {% for _dns_ip in dns_server | default([]) %} + - {{ _dns_ip }} + {% endfor %} + - {{ _gateway_ip }} + domain: [] + addresses: + - ip_netmask: {{ _ctlplane_ip }}/{{ _ctlplane_cidr }} + - ip_netmask: {{ _ctlplane_ip }}/{{ _ctlplane_ip_cidr }} + - ip_netmask: {{ _ctlplane_vip }}/{{ _ctlplane_vip_cidr }} + routes: + - ip_netmask: 192.168.123.0/24 + next_hop: 192.168.122.1 + - ip_netmask: 192.168.124.0/24 + next_hop: 192.168.122.1 + members: + - type: interface + name: {{ cifmw_adoption_osp_deploy_scenario.undercloud.os_net_config_iface | + default('nic2') }} + mtu: {{ _interface_mtu }} + # force the MAC address of the bridge to this interface + primary: true +- type: interface + name: nic3 + use_dhcp: false + addresses: + - ip_netmask: + 100.64.0.34/30 +- type: interface + name: nic4 + use_dhcp: false + addresses: + - ip_netmask: + 100.65.0.34/30 +- type: interface + name: lo + use_dhcp: false + addresses: + - ip_netmask: + 99.99.0.33/32 + - ip_netmask: + f00d:f00d:f00d:f00d:f00d:f00d:f00d:25/128 diff --git a/roles/adoption_osp_deploy/templates/tripleo-ansible-inventory_bgp.yaml.j2 b/roles/adoption_osp_deploy/templates/tripleo-ansible-inventory_bgp.yaml.j2 new file mode 100644 index 0000000000..9e947009c4 --- /dev/null +++ b/roles/adoption_osp_deploy/templates/tripleo-ansible-inventory_bgp.yaml.j2 @@ -0,0 +1,68 @@ +#jinja2: trim_blocks:True, lstrip_blocks:True +{% for group, role in cifmw_adoption_osp_deploy_scenario.roles_groups_map.items() %} +{{ role }}: + hosts: + {% for node in _vm_groups[group] %} + {% set node_nets = cifmw_networking_env_definition.instances[node] %} + {{ node }}: + {% if 'ctlplaner0' in node_nets.networks %} + ansible_host: {{ node_nets.networks.ctlplaner0[ip_version|default('ip_v4')] }} + canonical_hostname: {{ node }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + ctlplane_ip: {{ node_nets.networks.ctlplaner0[ip_version|default('ip_v4')] }} + {% elif 'ctlplaner1' in node_nets.networks %} + ansible_host: {{ node_nets.networks.ctlplaner1[ip_version|default('ip_v4')] }} + canonical_hostname: {{ node }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + ctlplane_ip: {{ node_nets.networks.ctlplaner1[ip_version|default('ip_v4')] }} + {% else %} + ansible_host: {{ node_nets.networks.ctlplaner2[ip_version|default('ip_v4')] }} + canonical_hostname: {{ node }}.{{ cifmw_adoption_osp_deploy_scenario.cloud_domain }} + ctlplane_ip: {{ node_nets.networks.ctlplaner2[ip_version|default('ip_v4')] }} + {% endif %} + {% for network_name, net in node_nets.networks.items() %} + {% 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')] }} + {% endif %} + {% endfor %} + {% endfor %} + vars: + ansible_ssh_common_args: -o StrictHostKeyChecking=no + ansible_ssh_user: zuul +{% endfor %} +Undercloud: + hosts: + undercloud: {} + vars: + ansible_connection: local + ansible_host: localhost +allovercloud: + children: + {% for _, role in cifmw_adoption_osp_deploy_scenario.roles_groups_map.items() %} + {{ role }}: {} + {% endfor %} +computes: + children: + {% for group, role in cifmw_adoption_osp_deploy_scenario.roles_groups_map.items() %} + {% if 'osp' in group and 'compute' in group %} + {{ role }}: {} + {% endif %} + {% endfor %} +{{ _overcloud_name }}: + hosts: + {% for group, _ in cifmw_adoption_osp_deploy_scenario.roles_groups_map.items() %} + {% if 'osp' in group and ('compute' in group or 'controller' in group) %} + {% for node in _vm_groups[group] %} + {% set node_nets = cifmw_networking_env_definition.instances[node] %} + {{ node }}: + ansible_user: tripleo-admin + {% if 'ctlplaner0' in node_nets.networks %} + ansible_host: {{ node_nets.networks.ctlplaner0[ip_version|default('ip_v4')] }} + {% elif 'ctlplaner1' in node_nets.networks %} + ansible_host: {{ node_nets.networks.ctlplaner1[ip_version|default('ip_v4')] }} + {% else %} + ansible_host: {{ node_nets.networks.ctlplaner2[ip_version|default('ip_v4')] }} + {% endif %} + {% endfor %} + {% endif %} + {% endfor %} diff --git a/roles/ci_gen_kustomize_values/templates/bgp-l3-xl-adoption b/roles/ci_gen_kustomize_values/templates/bgp-l3-xl-adoption new file mode 120000 index 0000000000..43886fd2df --- /dev/null +++ b/roles/ci_gen_kustomize_values/templates/bgp-l3-xl-adoption @@ -0,0 +1 @@ +bgp-l3-xl \ No newline at end of file diff --git a/scenarios/adoption/bgp-l3-xl.yml b/scenarios/adoption/bgp-l3-xl.yml new file mode 100644 index 0000000000..7e455a30eb --- /dev/null +++ b/scenarios/adoption/bgp-l3-xl.yml @@ -0,0 +1,495 @@ +--- +# By default, the OSP VMs will run using a default image. +# In upstream, it's usually latest centos-stream-9 +# For downstream, it's usually rhel-9.4 image, depending on +# the job configuration. +# +# Since OSP infra must use an older RHEL image, you can override it +# by setting "osp_base_img_url" to point to the downstream QCOW2 image, +# and "osp_base_img_sha256" holding the SHA256SUM of the image. +# +# We can't automatically discover the image, the role/module sets the +# value globally, and it would clash with the needs for RHOSO images. + +# Use anchor to avoid repetitions. This block is common to all of OSP nodes. +_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) }} + +cifmw_architecture_scenario: bgp-adoption + + +libvirt_manager_patch_layout: + vms: + # Let's remove the default computes, since we want to adopt the + # OSP ones + compute: + <<: *osp_base_conf + amount: 0 + osp-undercloud: + <<: *osp_base_conf + amount: 1 + memory: 16 + cpus: 8 + disksize: 80 + nets: + - ocpbm + - r0_tr + spineleafnets: + - # rack0 - undercloud + - "l00-node4" + - "l01-node4" + osp-r0-controller: + <<: *osp_base_conf + amount: 1 + memory: 16 + cpus: 8 + disksize: 80 + nets: + - ocpbm + - r0_tr + spineleafnets: + - # rack0 - controller0 + - "l00-node3" + - "l01-node3" + osp-r1-controller: + <<: *osp_base_conf + amount: 1 + memory: 16 + cpus: 8 + disksize: 80 + nets: + - ocpbm + - r1_tr + spineleafnets: + - # rack1 - controller1 + - "l10-node3" + - "l11-node3" + osp-r2-controller: + <<: *osp_base_conf + amount: 1 + memory: 16 + cpus: 8 + disksize: 80 + nets: + - ocpbm + - r2_tr + spineleafnets: + - # rack2 - controller2 + - "l20-node3" + - "l21-node3" + osp-r0-compute: + <<: *osp_base_conf + amount: 2 + memory: 4 + cpus: 4 + disksize: 20 + nets: + - ocpbm + - r0_tr + spineleafnets: + - # rack0 - compute0 + - "l00-node0" + - "l01-node0" + - # rack0 - compute0 + - "l00-node1" + - "l01-node1" + osp-r1-compute: + <<: *osp_base_conf + amount: 2 + memory: 4 + cpus: 4 + disksize: 20 + nets: + - ocpbm + - r1_tr + spineleafnets: + - # rack1 - compute0 + - "l10-node0" + - "l11-node0" + - # rack1 - compute1 + - "l10-node1" + - "l11-node1" + osp-r2-compute: + <<: *osp_base_conf + amount: 2 + memory: 4 + cpus: 4 + disksize: 20 + nets: + - ocpbm + - r2_tr + spineleafnets: + - # rack2 - compute0 + - "l20-node0" + - "l21-node0" + - # rack2 - compute1 + - "l20-node1" + - "l21-node1" + + router: + root_part_id: >- + {{ + (cifmw_repo_setup_os_release is defined and cifmw_repo_setup_os_release == 'rhel') | + ternary(4, 1) + }} + image_url: "{{ cifmw_discovered_image_url }}" + sha256_image_name: "{{ cifmw_discovered_hash }}" + image_local_dir: "{{ cifmw_basedir }}/images/" + disk_file_name: "base-os.qcow2" + amount: 1 + disksize: 25 + memory: 4 + cpus: 2 + nets: # nets common to all the router nodes + - "ocpbm" + spineleafnets: + - # router - ocp_tester + - "s0-rtr" + - "s1-rtr" + - "rtr-ocp" + spine: + root_part_id: >- + {{ + (cifmw_repo_setup_os_release is defined and cifmw_repo_setup_os_release == 'rhel') | + ternary(4, 1) + }} + image_url: "{{ cifmw_discovered_image_url }}" + sha256_image_name: "{{ cifmw_discovered_hash }}" + image_local_dir: "{{ cifmw_basedir }}/images/" + disk_file_name: "base-os.qcow2" + amount: 2 + disksize: 25 + memory: 4 + cpus: 2 + nets: # nets common to all the spine nodes + - "ocpbm" + spineleafnets: + - # spine0 + - "l00-s0" + - "l01-s0" + - "l10-s0" + - "l11-s0" + - "l20-s0" + - "l21-s0" + - "s0-rtr" + - # spine1 + - "l00-s1" + - "l01-s1" + - "l10-s1" + - "l11-s1" + - "l20-s1" + - "l21-s1" + - "s1-rtr" + leaf: + root_part_id: >- + {{ + (cifmw_repo_setup_os_release is defined and cifmw_repo_setup_os_release == 'rhel') | + ternary(4, 1) + }} + image_url: "{{ cifmw_discovered_image_url }}" + sha256_image_name: "{{ cifmw_discovered_hash }}" + image_local_dir: "{{ cifmw_basedir }}/images/" + disk_file_name: "base-os.qcow2" + amount: 6 + disksize: 25 + memory: 4 + cpus: 2 + nets: # nets common to all the leaf nodes + - "ocpbm" + spineleafnets: + - # rack0 - leaf00 + - "l00-s0" + - "l00-s1" + - "l00-node0" + - "l00-node1" + - "l00-node2" + - "l00-ocp0" + - "l00-ocp1" + - "l00-ocp2" + - "l00-ocp3" + - "l00-node3" + - "l00-node4" + - # rack0 - leaf01 + - "l01-s0" + - "l01-s1" + - "l01-node0" + - "l01-node1" + - "l01-node2" + - "l01-ocp0" + - "l01-ocp1" + - "l01-ocp2" + - "l01-ocp3" + - "l01-node3" + - "l01-node4" + - # rack1 - leaf10 + - "l10-s0" + - "l10-s1" + - "l10-node0" + - "l10-node1" + - "l10-node2" + - "l10-ocp0" + - "l10-ocp1" + - "l10-ocp2" + - "l10-ocp3" + - "l10-node3" + - "l10-node4" + - # rack1 - leaf11 + - "l11-s0" + - "l11-s1" + - "l11-node0" + - "l11-node1" + - "l11-node2" + - "l11-ocp0" + - "l11-ocp1" + - "l11-ocp2" + - "l11-ocp3" + - "l11-node3" + - "l11-node4" + - # rack2 - leaf20 + - "l20-s0" + - "l20-s1" + - "l20-node0" + - "l20-node1" + - "l20-node2" + - "l20-ocp0" + - "l20-ocp1" + - "l20-ocp2" + - "l20-ocp3" + - "l20-node3" + - "l20-node4" + - # rack2 - leaf21 + - "l21-s0" + - "l21-s1" + - "l21-node0" + - "l21-node1" + - "l21-node2" + - "l21-ocp0" + - "l21-ocp1" + - "l21-ocp2" + - "l21-ocp3" + - "l21-node3" + - "l21-node4" + + + # set to zero + r0-compute: + amount: 0 + <<: *osp_base_conf + r1-compute: + amount: 0 + <<: *osp_base_conf + r2-compute: + amount: 0 + <<: *osp_base_conf + r0-networker: + amount: 0 + <<: *osp_base_conf + r1-networker: + amount: 0 + <<: *osp_base_conf + r2-networker: + amount: 0 + <<: *osp_base_conf + + +cifmw_libvirt_manager_default_gw_nets: + - ocpbm + - r0_tr + - r1_tr + - r2_tr +cifmw_networking_mapper_interfaces_info_translations: + osp_trunk: + - controlplane + - ctlplane + r0_tr: + - ctlplaner0 + r1_tr: + - ctlplaner1 + r2_tr: + - ctlplaner2 + +networking_mapper_definition_patch: + networks: + ctlplane: + network: "192.168.125.0/24" + gateway: "192.168.125.1" + dns: + - "192.168.122.1" + mtu: 1500 + + ctlplaner0: + network: "192.168.122.0/24" + gateway: "192.168.122.1" + dns: + - "192.168.122.1" + mtu: 1500 + + ctlplaner1: + network: "192.168.123.0/24" + gateway: "192.168.123.1" + dns: + - "192.168.123.1" + mtu: 1500 + + ctlplaner2: + network: "192.168.124.0/24" + gateway: "192.168.124.1" + dns: + - "192.168.124.1" + mtu: 1500 + + internalapi: + network: "172.17.0.0/24" + vlan: 20 + mtu: 1500 + + storage: + network: "172.18.0.0/24" + vlan: 21 + mtu: 1500 + + tenant: + network: "172.19.0.0/24" + vlan: 22 + mtu: 1500 + + octavia: + vlan: 23 + mtu: 1500 + network: "172.23.0.0/24" + + # Not really used, but required by architecture + # https://github.com/openstack-k8s-operators/architecture/blob/main/lib/networking/netconfig/kustomization.yaml#L28-L36 + external: + network: "192.168.32.0/20" + vlan: 99 + mtu: 1500 + + # ensure ranges do not collide even if we don't create these vms + group-templates: + r0-computes: + network-template: + range: + start: 200 + length: 5 + r1-computes: + network-template: + range: + start: 205 + length: 5 + r2-computes: + network-template: + range: + start: 210 + length: 5 + r0-networkers: + network-template: + range: + start: 215 + length: 5 + r1-networkers: + network-template: + range: + start: 220 + length: 5 + r2-networkers: + network-template: + range: + start: 225 + length: 5 + + osp-r0-controllers: + network-template: + range: + start: 140 + length: 2 + networks: + ctlplaner0: {} + external: + trunk-parent: ctlplaner0 + internalapi: + trunk-parent: ctlplaner0 + tenant: + trunk-parent: ctlplaner0 + storage: + trunk-parent: ctlplaner0 + osp-r1-controllers: + network-template: + range: + start: 142 + length: 2 + networks: + ctlplaner1: {} + external: + trunk-parent: ctlplaner1 + internalapi: + trunk-parent: ctlplaner1 + tenant: + trunk-parent: ctlplaner1 + storage: + trunk-parent: ctlplaner1 + osp-r2-controllers: + network-template: + range: + start: 144 + length: 2 + networks: + ctlplaner2: {} + external: + trunk-parent: ctlplaner2 + internalapi: + trunk-parent: ctlplaner2 + tenant: + trunk-parent: ctlplaner2 + storage: + trunk-parent: ctlplaner2 + osp-r0-computes: + network-template: + range: + start: 100 + length: 5 + networks: + ctlplaner0: {} + internalapi: + trunk-parent: ctlplaner0 + tenant: + trunk-parent: ctlplaner0 + storage: + trunk-parent: ctlplaner0 + osp-r1-computes: + network-template: + range: + start: 105 + length: 5 + networks: + ctlplaner1: {} + internalapi: + trunk-parent: ctlplaner1 + tenant: + trunk-parent: ctlplaner1 + storage: + trunk-parent: ctlplaner1 + osp-r2-computes: + network-template: + range: + start: 110 + length: 5 + networks: + ctlplaner2: {} + internalapi: + trunk-parent: ctlplaner2 + tenant: + trunk-parent: ctlplaner2 + storage: + trunk-parent: ctlplaner2 + osp-underclouds: + network-template: + range: + start: 95 + length: 1 + networks: + ctlplaner0: {} diff --git a/scenarios/reproducers/bgp-l3-xl.yml b/scenarios/reproducers/bgp-l3-xl.yml index e658f81ce8..85d37679fe 100644 --- a/scenarios/reproducers/bgp-l3-xl.yml +++ b/scenarios/reproducers/bgp-l3-xl.yml @@ -47,39 +47,57 @@ cifmw_libvirt_manager_network_interface_types: l00-node0: network l00-node1: network l00-node2: network + l00-node3: network + l00-node4: network l00-ocp0: network l00-ocp1: network l00-ocp2: network + l00-ocp3: network l01-node0: network l01-node1: network l01-node2: network + l01-node3: network + l01-node4: network l01-ocp0: network l01-ocp1: network l01-ocp2: network + l01-ocp3: network l10-node0: network l10-node1: network l10-node2: network + l10-node3: network + l10-node4: network l10-ocp0: network l10-ocp1: network l10-ocp2: network + l10-ocp3: network l11-node0: network l11-node1: network l11-node2: network + l11-node3: network + l11-node4: network l11-ocp0: network l11-ocp1: network l11-ocp2: network + l11-ocp3: network l20-node0: network l20-node1: network l20-node2: network + l20-node3: network + l20-node4: network l20-ocp0: network l20-ocp1: network l20-ocp2: network + l20-ocp3: network l21-node0: network l21-node1: network l21-node2: network + l21-node3: network + l21-node4: network l21-ocp0: network l21-ocp1: network l21-ocp2: network + l21-ocp3: network cifmw_libvirt_manager_configuration: networks: @@ -193,6 +211,16 @@ cifmw_libvirt_manager_configuration: l00-node2 + l00-node3: | + + l00-node3 + + + l00-node4: | + + l00-node4 + + l00-ocp0: | l00-ocp0 @@ -208,6 +236,11 @@ cifmw_libvirt_manager_configuration: l00-ocp2 + l00-ocp3: | + + l00-ocp3 + + l01-node0: | l01-node0 @@ -223,6 +256,16 @@ cifmw_libvirt_manager_configuration: l01-node2 + l01-node3: | + + l01-node3 + + + l01-node4: | + + l01-node4 + + l01-ocp0: | l01-ocp0 @@ -238,6 +281,11 @@ cifmw_libvirt_manager_configuration: l01-ocp2 + l01-ocp3: | + + l01-ocp3 + + ## rack1 l10-node0: | @@ -254,6 +302,16 @@ cifmw_libvirt_manager_configuration: l10-node2 + l10-node3: | + + l10-node3 + + + l10-node4: | + + l10-node4 + + l10-ocp0: | l10-ocp0 @@ -269,6 +327,11 @@ cifmw_libvirt_manager_configuration: l10-ocp2 + l10-ocp3: | + + l10-ocp3 + + l11-node0: | l11-node0 @@ -284,6 +347,16 @@ cifmw_libvirt_manager_configuration: l11-node2 + l11-node3: | + + l11-node3 + + + l11-node4: | + + l11-node4 + + l11-ocp0: | l11-ocp0 @@ -299,6 +372,11 @@ cifmw_libvirt_manager_configuration: l11-ocp2 + l11-ocp3: | + + l11-ocp3 + + ## rack2 l20-node0: | @@ -315,6 +393,16 @@ cifmw_libvirt_manager_configuration: l20-node2 + l20-node3: | + + l20-node3 + + + l20-node4: | + + l20-node4 + + l20-ocp0: | l20-ocp0 @@ -330,6 +418,11 @@ cifmw_libvirt_manager_configuration: l20-ocp2 + l20-ocp3: | + + l20-ocp3 + + l21-node0: | l21-node0 @@ -345,6 +438,16 @@ cifmw_libvirt_manager_configuration: l21-node2 + l21-node3: | + + l21-node3 + + + l21-node4: | + + l21-node4 + + l21-ocp0: | l21-ocp0 @@ -360,6 +463,11 @@ cifmw_libvirt_manager_configuration: l21-ocp2 + l21-ocp3: | + + l21-ocp3 + + ocpbm: | ocpbm @@ -430,7 +538,7 @@ cifmw_libvirt_manager_configuration: - ocpbm - osp_trunk r0-compute: &r0_compute_def - amount: 2 + amount: 0 root_part_id: >- {{ (cifmw_repo_setup_os_release is defined and cifmw_repo_setup_os_release == 'rhel') | @@ -454,7 +562,7 @@ cifmw_libvirt_manager_configuration: - "l00-node1" - "l01-node1" r1-compute: - amount: 2 + amount: 0 root_part_id: "{{ cifmw_root_partition_id }}" uefi: "{{ cifmw_use_uefi }}" image_url: "{{ cifmw_discovered_image_url }}" @@ -475,7 +583,7 @@ cifmw_libvirt_manager_configuration: - "l10-node1" - "l11-node1" r2-compute: - amount: 2 + amount: 0 root_part_id: "{{ cifmw_root_partition_id }}" uefi: "{{ cifmw_use_uefi }}" image_url: "{{ cifmw_discovered_image_url }}" @@ -704,6 +812,8 @@ cifmw_libvirt_manager_configuration: - "l00-ocp0" - "l00-ocp1" - "l00-ocp2" + - "l00-node3" + - "l00-node4" - # rack0 - leaf01 - "l01-s0" - "l01-s1" @@ -713,6 +823,8 @@ cifmw_libvirt_manager_configuration: - "l01-ocp0" - "l01-ocp1" - "l01-ocp2" + - "l01-node3" + - "l01-node4" - # rack1 - leaf10 - "l10-s0" - "l10-s1" @@ -722,6 +834,7 @@ cifmw_libvirt_manager_configuration: - "l10-ocp0" - "l10-ocp1" - "l10-ocp2" + - "l10-node3" - # rack1 - leaf11 - "l11-s0" - "l11-s1" @@ -731,6 +844,7 @@ cifmw_libvirt_manager_configuration: - "l11-ocp0" - "l11-ocp1" - "l11-ocp2" + - "l11-node3" - # rack2 - leaf20 - "l20-s0" - "l20-s1" @@ -740,6 +854,7 @@ cifmw_libvirt_manager_configuration: - "l20-ocp0" - "l20-ocp1" - "l20-ocp2" + - "l20-node3" - # rack2 - leaf21 - "l21-s0" - "l21-s1" @@ -749,6 +864,7 @@ cifmw_libvirt_manager_configuration: - "l21-ocp0" - "l21-ocp1" - "l21-ocp2" + - "l21-node3" ## devscript support for OCP deploy cifmw_devscripts_config_overrides: @@ -796,7 +912,7 @@ pre_deploy: num_racks: "{{ num_racks }}" router_bool: true edpm_nodes_per_rack: 3 - ocp_nodes_per_rack: 3 + ocp_nodes_per_rack: 4 router_uplink_ip: 100.64.10.1 # post_deploy: @@ -919,6 +1035,13 @@ cifmw_networking_definition: mtu: 1500 tools: multus: + ipv4_routes: + - destination: "172.31.0.0/24" + gateway: "172.17.0.1" + - destination: "192.168.188.0/24" + gateway: "172.17.0.1" + - destination: "99.99.0.0/16" + gateway: "172.17.0.1" ranges: - start: 30 end: 70 @@ -937,6 +1060,13 @@ cifmw_networking_definition: mtu: 1500 tools: multus: + ipv4_routes: + - destination: "172.31.0.0/24" + gateway: "172.18.0.1" + - destination: "192.168.188.0/24" + gateway: "172.18.0.1" + - destination: "99.99.0.0/16" + gateway: "172.18.0.1" ranges: - start: 30 end: 70 diff --git a/scenarios/reproducers/networking-definition-bgp.yml b/scenarios/reproducers/networking-definition-bgp.yml new file mode 100644 index 0000000000..0d9a11d358 --- /dev/null +++ b/scenarios/reproducers/networking-definition-bgp.yml @@ -0,0 +1,266 @@ +cifmw_networking_definition: + networks: + ctlplane: + network: "192.168.125.0/24" + gateway: "192.168.125.1" + dns: + - "192.168.122.1" + mtu: 1500 + tools: + multus: + ranges: + - start: 30 + end: 70 + metallb: + ranges: + - start: 80 + end: 90 + netconfig: + ranges: + - start: 100 + end: 120 + - start: 150 + end: 200 + + ctlplaner0: + network: "192.168.122.0/24" + gateway: "192.168.122.1" + dns: + - "192.168.122.1" + mtu: 1500 + tools: + multus: + ranges: + - start: 30 + end: 70 + metallb: + ranges: + - start: 80 + end: 90 + netconfig: + ranges: + - start: 100 + end: 130 + - start: 150 + end: 200 + + ctlplaner1: + network: "192.168.123.0/24" + gateway: "192.168.123.1" + dns: + - "192.168.123.1" + mtu: 1500 + tools: + multus: + ranges: + - start: 30 + end: 70 + netconfig: + ranges: + - start: 100 + end: 130 + - start: 150 + end: 170 + metallb: + ranges: + - start: 80 + end: 90 + ctlplaner2: + network: "192.168.124.0/24" + gateway: "192.168.124.1" + dns: + - "192.168.124.1" + mtu: 1500 + tools: + multus: + ranges: + - start: 30 + end: 70 + netconfig: + ranges: + - start: 100 + end: 130 + - start: 150 + end: 170 + metallb: + ranges: + - start: 80 + end: 90 + + internalapi: + network: "172.17.0.0/24" + vlan: 20 + mtu: 1500 + tools: + multus: + ranges: + - start: 30 + end: 70 + metallb: + ranges: + - start: 80 + end: 90 + netconfig: + ranges: + - start: 100 + end: 250 + + storage: + network: "172.18.0.0/24" + vlan: 21 + mtu: 1500 + tools: + multus: + ranges: + - start: 30 + end: 70 + metallb: + ranges: + - start: 80 + end: 90 + netconfig: + ranges: + - start: 100 + end: 250 + + tenant: + network: "172.19.0.0/24" + vlan: 22 + mtu: 1500 + tools: + multus: + ranges: + - start: 30 + end: 70 + metallb: + ranges: + - start: 80 + end: 90 + netconfig: + ranges: + - start: 100 + end: 250 + + octavia: + vlan: 23 + mtu: 1500 + network: "172.23.0.0/24" + tools: + multus: + ranges: + - start: 30 + end: 70 + netconfig: + ranges: + - start: 100 + end: 250 + + # Not really used, but required by architecture + # https://github.com/openstack-k8s-operators/architecture/blob/main/lib/networking/netconfig/kustomization.yaml#L28-L36 + external: + network: "192.168.32.0/20" + vlan: 99 + mtu: 1500 + tools: + netconfig: + ranges: + - start: 130 + end: 250 + + group-templates: + r0-computes: + network-template: + range: + start: 100 + length: 5 + networks: + ctlplaner0: {} + internalapi: + trunk-parent: ctlplaner0 + tenant: + trunk-parent: ctlplaner0 + storage: + trunk-parent: ctlplaner0 + r1-computes: + network-template: + range: + start: 110 + length: 5 + networks: + ctlplaner1: {} + internalapi: + trunk-parent: ctlplaner1 + tenant: + trunk-parent: ctlplaner1 + storage: + trunk-parent: ctlplaner1 + r2-computes: + network-template: + range: + start: 120 + length: 5 + networks: + ctlplaner2: {} + internalapi: + trunk-parent: ctlplaner2 + tenant: + trunk-parent: ctlplaner2 + storage: + trunk-parent: ctlplaner2 + r0-networkers: + network-template: + range: + start: 200 + length: 5 + networks: + ctlplaner0: {} + internalapi: + trunk-parent: ctlplaner0 + tenant: + trunk-parent: ctlplaner0 + storage: + trunk-parent: ctlplaner0 + r1-networkers: + network-template: + range: + start: 210 + length: 5 + networks: + ctlplaner1: {} + internalapi: + trunk-parent: ctlplaner1 + tenant: + trunk-parent: ctlplaner1 + storage: + trunk-parent: ctlplaner1 + r2-networkers: + network-template: + range: + start: 220 + length: 5 + networks: + ctlplaner2: {} + internalapi: + trunk-parent: ctlplaner2 + tenant: + trunk-parent: ctlplaner2 + storage: + trunk-parent: ctlplaner2 + ocps: + network-template: + range: + start: 10 + length: 10 + networks: {} + ocp_workers: + network-template: + range: + start: 20 + length: 10 + networks: {} + + instances: + controller-0: + networks: + ctlplane: + ip: "192.168.125.9" From f56a75329856887d87b48a49823c643e43b28b86 Mon Sep 17 00:00:00 2001 From: Eduardo Olivares Date: Fri, 31 Oct 2025 10:21:20 +0100 Subject: [PATCH 2/5] different DNS servers per rack --- playbooks/bgp/prepare-bgp-spines-leaves.yaml | 13 +++++++++ .../tasks/prepare_overcloud.yml | 24 ++++++++++++++++ .../tasks/prepare_undercloud.yml | 28 ++++++++++++------- .../os_net_config_overcloud_bgp.yml.j2 | 12 +++++++- scenarios/reproducers/bgp-l3-xl.yml | 12 ++++++-- 5 files changed, 76 insertions(+), 13 deletions(-) diff --git a/playbooks/bgp/prepare-bgp-spines-leaves.yaml b/playbooks/bgp/prepare-bgp-spines-leaves.yaml index 31df9548ca..53bea8643a 100644 --- a/playbooks/bgp/prepare-bgp-spines-leaves.yaml +++ b/playbooks/bgp/prepare-bgp-spines-leaves.yaml @@ -239,10 +239,13 @@ autoconnect: true conn_name: "{{ item }}" type: ethernet + ifname: "{{ router_downlink_ifs[loop_index | int] }}" method4: disabled method6: link-local state: present loop: "{{ router_downlink_conns }}" + loop_control: + index_var: loop_index # uplink router IPv4 is configured for both IPv4 and IPv6 jobs - name: Configure uplink router connections with nmcli when IPv4 @@ -509,6 +512,8 @@ autoconnect: true conn_name: "{{ item }}" ip4: "{{ leaf_ds_ip4 }}/30" + type: ethernet + ifname: "{{ downlink_ifs_rack3[loop_index | int] }}" method4: manual method6: link-local state: present @@ -526,6 +531,8 @@ autoconnect: true conn_name: "{{ item }}" ip4: "{{ leaf_ds_ip4 }}/30" + type: ethernet + ifname: "{{ leaf_downlink_ifs[loop_index | int] }}" method4: manual method6: link-local state: present @@ -569,6 +576,8 @@ conn_name: "{{ item }}" ip4: "{{ _leaf_ds_ip4 }}/30" ip6: "{{ _leaf_ds_ip6 }}/126" + type: ethernet + ifname: "{{ leaf_downlink_ifs[loop_index | int] }}" method4: manual method6: manual state: present @@ -605,8 +614,12 @@ conn_name: "{{ item }}" method4: disabled method6: link-local + type: ethernet + ifname: "{{ uplink_ifs[loop_index | int] }}" state: present loop: "{{ uplink_conns }}" + loop_control: + index_var: loop_index - name: Enable FRR Zebra daemon become: true diff --git a/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml b/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml index 969aeb1ad9..408a46acdf 100644 --- a/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml +++ b/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml @@ -195,6 +195,19 @@ loop_var: overcloud_vm when: not bgp + - name: Obtain IPs whose routes need to be added to the undercloud (bgp) + when: bgp + delegate_to: "{{ overcloud_vm }}" + ansible.builtin.getent: + database: ahosts + key: "{{ item }}" + register: _ips_for_oc_routes_getent + loop: + - registry.redhat.io + - cdn.redhat.com + - access.redhat.com + - cdn01.quay.io + - name: Generate os-net-config file for overcloud nodes (bgp) become: true delegate_to: "{{ overcloud_vm }}" @@ -202,6 +215,17 @@ _node_net: "{{ cifmw_networking_env_definition.instances[overcloud_vm] }}" _dns_server: "{{ _ctlplane_net.[dns_version|default('dns_v4')] }}" _interface_mtu: 1500 + _ips_for_oc_routes_list: >- + {{ + _ips_for_oc_routes_getent.results | + map(attribute='ansible_facts.getent_ahosts') | + map('dict2items') | + flatten | + map(attribute='key') | + reject('match', '.*:.*') | + list | + unique + }} vms: osp-r0-compute-0: ctlplane: '192.168.122.100' diff --git a/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml b/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml index 12e564c075..f7fc43722c 100644 --- a/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml +++ b/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml @@ -59,6 +59,9 @@ openstack tripleo container image prepare default --output-env-file {{ ansible_user_dir }}/containers-prepare-parameters.yaml + {% if cifmw_adoption_osp_deploy_scenario.container_prepare_local_push_dest | default(false) | bool %} + --local-push-destination + {% endif %} cifmw.general.ci_script: output_dir: "{{ cifmw_basedir }}/artifacts" script: "{{ _container_prepare_cmd }}" @@ -125,21 +128,16 @@ - name: Obtain IPs whose routes need to be added to the undercloud (bgp) when: bgp - ansible.builtin.shell: | - getent ahosts {{ item }} | grep STREAM | awk '{print $1}' | grep -v : - register: _ips_for_uc_routes_output + ansible.builtin.getent: + database: ahosts + key: "{{ item }}" + register: _ips_for_uc_routes_getent loop: - registry.redhat.io - cdn.redhat.com - access.redhat.com - cdn01.quay.io - - name: Create list with the previous IPs - when: bgp - ansible.builtin.set_fact: - ips_for_uc_routes_list: "{{ (ips_for_uc_routes_list | default([]) + item.stdout_lines) | ansible.builtin.unique }}" - loop: "{{ _ips_for_uc_routes_output.results }}" - - name: Generate os-net-config file (bgp) when: bgp become: true @@ -153,7 +151,17 @@ _gateway_ip: "{{ _ctlplane_net[gw_version|default('gw_v4')] }}" _interface_mtu: "{{ _undercloud_net.networks.ctlplaner0.mtu }}" _ctlplane_cidr: "{{ _undercloud_net.networks.ctlplaner0[prefix_length_version|default('prefix_length_v4')] }}" - _ips_for_uc_routes_list: "{{ ips_for_uc_routes_list }}" + _ips_for_uc_routes_list: >- + {{ + _ips_for_uc_routes_getent.results | + map(attribute='ansible_facts.getent_ahosts') | + map('dict2items') | + flatten | + map(attribute='key') | + reject('match', '.*:.*') | + list | + unique + }} ansible.builtin.template: src: "os_net_config_undercloud_bgp.yml.j2" dest: /etc/os-net-config/tripleo_config.yaml diff --git a/roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 b/roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 index 37f7db1e05..42d58a80aa 100644 --- a/roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 +++ b/roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 @@ -5,11 +5,21 @@ network_config: mtu: {{ _interface_mtu }} use_dhcp: true defroute: false - routes: [] + routes: +{% for _ip in _ips_for_oc_routes_list %} + - ip_netmask: {{ _ip }}/32 + next_hop: 192.168.111.1 +{% endfor %} - type: interface name: nic2 mtu: {{ _interface_mtu }} +{% if 'r0' in overcloud_vm %} dns_servers: ['192.168.122.1', '192.168.125.1'] +{% elif 'r1' in overcloud_vm %} + dns_servers: ['192.168.123.1', '192.168.125.1'] +{% else %} + dns_servers: ['192.168.124.1', '192.168.125.1'] +{% endif %} domain: [] routes: {% if 'r0' in overcloud_vm %} diff --git a/scenarios/reproducers/bgp-l3-xl.yml b/scenarios/reproducers/bgp-l3-xl.yml index 85d37679fe..b6b0b841ee 100644 --- a/scenarios/reproducers/bgp-l3-xl.yml +++ b/scenarios/reproducers/bgp-l3-xl.yml @@ -563,7 +563,11 @@ cifmw_libvirt_manager_configuration: - "l01-node1" r1-compute: amount: 0 - root_part_id: "{{ cifmw_root_partition_id }}" + root_part_id: >- + {{ + (cifmw_repo_setup_os_release is defined and cifmw_repo_setup_os_release == 'rhel') | + ternary(4, 1) + }} uefi: "{{ cifmw_use_uefi }}" image_url: "{{ cifmw_discovered_image_url }}" sha256_image_name: "{{ cifmw_discovered_hash }}" @@ -584,7 +588,11 @@ cifmw_libvirt_manager_configuration: - "l11-node1" r2-compute: amount: 0 - root_part_id: "{{ cifmw_root_partition_id }}" + root_part_id: >- + {{ + (cifmw_repo_setup_os_release is defined and cifmw_repo_setup_os_release == 'rhel') | + ternary(4, 1) + }} uefi: "{{ cifmw_use_uefi }}" image_url: "{{ cifmw_discovered_image_url }}" sha256_image_name: "{{ cifmw_discovered_hash }}" From 926a1e92c0d4dd8bdf3f2535c4d0e6bae96fb920 Mon Sep 17 00:00:00 2001 From: Eduardo Olivares Date: Fri, 7 Nov 2025 16:11:56 +0100 Subject: [PATCH 3/5] Fix BGP registry IP route collection for multi-datacenter deployments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original implementation attempted to run getent directly in the task with delegate_to using an undefined loop variable, causing task failures. This fix properly delegates getent execution to each overcloud VM and accumulates the resolved IPs across all VMs. This is necessary because VMs in different racks/datacenters may use different DNS servers, resulting in different IP resolutions for the same registry domains. Changes: - Extract getent logic into separate task file (getent_registry_ips_bgp.yml) - Run getent from each VM via include_tasks with proper delegation - Accumulate IPs using set_fact to preserve results across all VMs - Simplify IP list generation in both prepare_overcloud.yml and prepare_undercloud.yml to use the accumulated list The accumulated IP list ensures routes are added for all possible registry IPs as resolved from each datacenter's DNS server. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../tasks/getent_registry_ips_bgp.yml | 42 +++++++++++++++++++ .../tasks/prepare_overcloud.yml | 30 ++++--------- .../tasks/prepare_undercloud.yml | 22 +--------- .../os_net_config_overcloud_bgp.yml.j2 | 8 ++++ .../os_net_config_undercloud_bgp.yml.j2 | 4 ++ 5 files changed, 65 insertions(+), 41 deletions(-) create mode 100644 roles/adoption_osp_deploy/tasks/getent_registry_ips_bgp.yml diff --git a/roles/adoption_osp_deploy/tasks/getent_registry_ips_bgp.yml b/roles/adoption_osp_deploy/tasks/getent_registry_ips_bgp.yml new file mode 100644 index 0000000000..319ba86ddc --- /dev/null +++ b/roles/adoption_osp_deploy/tasks/getent_registry_ips_bgp.yml @@ -0,0 +1,42 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +- name: Obtain IPs whose routes need to be added to the undercloud (bgp) + ansible.builtin.getent: + database: ahosts + key: "{{ item }}" + register: _current_vm_getent + loop: + - registry.redhat.io + - cdn.redhat.com + - access.redhat.com + - cdn01.quay.io + +- name: Accumulate IPs from this VM + ansible.builtin.set_fact: + _accumulated_ips: >- + {{ + _accumulated_ips | default([]) + + ( + _current_vm_getent.results | + map(attribute='ansible_facts.getent_ahosts') | + map('dict2items') | + flatten | + map(attribute='key') | + reject('match', '.*:.*') | + list + ) + }} diff --git a/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml b/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml index 408a46acdf..fdb0444d21 100644 --- a/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml +++ b/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml @@ -197,16 +197,14 @@ - name: Obtain IPs whose routes need to be added to the undercloud (bgp) when: bgp - delegate_to: "{{ overcloud_vm }}" - ansible.builtin.getent: - database: ahosts - key: "{{ item }}" - register: _ips_for_oc_routes_getent - loop: - - registry.redhat.io - - cdn.redhat.com - - access.redhat.com - - cdn01.quay.io + ansible.builtin.include_tasks: getent_registry_ips_bgp.yml + args: + apply: + delegate_to: "{{ _vm }}" + loop: "{{ _tripleo_nodes_stack[_overcloud_name] }}" + loop_control: + loop_var: _vm + pause: 1 - name: Generate os-net-config file for overcloud nodes (bgp) become: true @@ -215,17 +213,7 @@ _node_net: "{{ cifmw_networking_env_definition.instances[overcloud_vm] }}" _dns_server: "{{ _ctlplane_net.[dns_version|default('dns_v4')] }}" _interface_mtu: 1500 - _ips_for_oc_routes_list: >- - {{ - _ips_for_oc_routes_getent.results | - map(attribute='ansible_facts.getent_ahosts') | - map('dict2items') | - flatten | - map(attribute='key') | - reject('match', '.*:.*') | - list | - unique - }} + _ips_for_oc_routes_list: "{{ _accumulated_ips | unique }}" vms: osp-r0-compute-0: ctlplane: '192.168.122.100' diff --git a/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml b/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml index f7fc43722c..70b8a7c7d7 100644 --- a/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml +++ b/roles/adoption_osp_deploy/tasks/prepare_undercloud.yml @@ -128,15 +128,7 @@ - name: Obtain IPs whose routes need to be added to the undercloud (bgp) when: bgp - ansible.builtin.getent: - database: ahosts - key: "{{ item }}" - register: _ips_for_uc_routes_getent - loop: - - registry.redhat.io - - cdn.redhat.com - - access.redhat.com - - cdn01.quay.io + ansible.builtin.include_tasks: getent_registry_ips_bgp.yml - name: Generate os-net-config file (bgp) when: bgp @@ -151,17 +143,7 @@ _gateway_ip: "{{ _ctlplane_net[gw_version|default('gw_v4')] }}" _interface_mtu: "{{ _undercloud_net.networks.ctlplaner0.mtu }}" _ctlplane_cidr: "{{ _undercloud_net.networks.ctlplaner0[prefix_length_version|default('prefix_length_v4')] }}" - _ips_for_uc_routes_list: >- - {{ - _ips_for_uc_routes_getent.results | - map(attribute='ansible_facts.getent_ahosts') | - map('dict2items') | - flatten | - map(attribute='key') | - reject('match', '.*:.*') | - list | - unique - }} + _ips_for_uc_routes_list: "{{ _accumulated_ips | unique }}" ansible.builtin.template: src: "os_net_config_undercloud_bgp.yml.j2" dest: /etc/os-net-config/tripleo_config.yaml diff --git a/roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 b/roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 index 42d58a80aa..5a057bb2c0 100644 --- a/roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 +++ b/roles/adoption_osp_deploy/templates/os_net_config_overcloud_bgp.yml.j2 @@ -6,6 +6,14 @@ network_config: use_dhcp: true defroute: false routes: + - ip_netmask: 10.0.0.0/8 + next_hop: 192.168.111.1 + - ip_netmask: 23.0.0.0/8 + next_hop: 192.168.111.1 + - ip_netmask: 104.0.0.0/8 + next_hop: 192.168.111.1 + - ip_netmask: 212.0.0.0/8 + next_hop: 192.168.111.1 {% for _ip in _ips_for_oc_routes_list %} - ip_netmask: {{ _ip }}/32 next_hop: 192.168.111.1 diff --git a/roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 b/roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 index 29b95d30d1..94eb7f08bc 100644 --- a/roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 +++ b/roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 @@ -21,6 +21,10 @@ network_config: next_hop: 192.168.111.1 - ip_netmask: 23.0.0.0/8 next_hop: 192.168.111.1 + - ip_netmask: 104.0.0.0/8 + next_hop: 192.168.111.1 + - ip_netmask: 212.0.0.0/8 + next_hop: 192.168.111.1 {% for _ip in _ips_for_uc_routes_list %} - ip_netmask: {{ _ip }}/32 next_hop: 192.168.111.1 From d6603d4d01e76d51db2f712785508db64b303ac5 Mon Sep 17 00:00:00 2001 From: Eduardo Olivares Date: Wed, 12 Nov 2025 11:35:23 +0100 Subject: [PATCH 4/5] get rid of _arch_repo --- scenarios/reproducers/bgp-l3-xl.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scenarios/reproducers/bgp-l3-xl.yml b/scenarios/reproducers/bgp-l3-xl.yml index b6b0b841ee..cd2fd5dcb5 100644 --- a/scenarios/reproducers/bgp-l3-xl.yml +++ b/scenarios/reproducers/bgp-l3-xl.yml @@ -887,13 +887,12 @@ cifmw_devscripts_enable_ocp_nodes_host_routing: true # 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 }}" cifmw_architecture_scenario: bgp-l3-xl cifmw_kustomize_deploy_architecture_examples_path: "examples/dt/" cifmw_arch_automation_file: "bgp-l3-xl.yaml" cifmw_architecture_automation_file: >- {{ - (_arch_repo, + (cifmw_architecture_repo, 'automation/vars', cifmw_arch_automation_file) | path_join @@ -901,7 +900,7 @@ cifmw_architecture_automation_file: >- cifmw_kustomize_deploy_metallb_source_files: >- {{ - (_arch_repo, + (cifmw_architecture_repo, 'examples/dt/bgp-l3-xl/metallb') | path_join }} @@ -919,9 +918,10 @@ pre_deploy: extra_vars: num_racks: "{{ num_racks }}" router_bool: true - edpm_nodes_per_rack: 3 + edpm_nodes_per_rack: 5 ocp_nodes_per_rack: 4 router_uplink_ip: 100.64.10.1 + cifmw_repo_setup_rhos_release_rpm: "{{ cifmw_repo_setup_rhos_release_rpm }}" # post_deploy: # - name: BGP computes configuration From 6ccd019d06cbc87ef9eb60e5fd11a924056a3fdf Mon Sep 17 00:00:00 2001 From: Eduardo Olivares Date: Thu, 13 Nov 2025 14:44:30 +0100 Subject: [PATCH 5/5] remove an ocp node per rack --- .../tasks/prepare_overcloud.yml | 12 ++-- .../os_net_config_undercloud_bgp.yml.j2 | 4 +- scenarios/adoption/bgp-l3-xl.yml | 6 -- scenarios/reproducers/bgp-l3-xl.yml | 59 +++---------------- 4 files changed, 15 insertions(+), 66 deletions(-) diff --git a/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml b/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml index fdb0444d21..64c772c581 100644 --- a/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml +++ b/roles/adoption_osp_deploy/tasks/prepare_overcloud.yml @@ -253,20 +253,20 @@ main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0009' osp-r0-controller-0: ctlplane: '192.168.122.140' - left: '100.64.0.30' - right: '100.65.0.30' + left: '100.64.0.26' + right: '100.65.0.26' main: '99.99.0.29' main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0001' osp-r1-controller-0: ctlplane: '192.168.123.142' - left: '100.64.1.30' - right: '100.65.1.30' + left: '100.64.1.26' + right: '100.65.1.26' main: '99.99.1.29' main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0002' osp-r2-controller-0: ctlplane: '192.168.124.144' - left: '100.64.2.30' - right: '100.65.2.30' + left: '100.64.2.26' + right: '100.65.2.26' main: '99.99.2.29' main6: 'f00d:f00d:f00d:f00d:f00d:f00d:f00d:0003' ansible.builtin.template: diff --git a/roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 b/roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 index 94eb7f08bc..917ad41a86 100644 --- a/roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 +++ b/roles/adoption_osp_deploy/templates/os_net_config_undercloud_bgp.yml.j2 @@ -60,13 +60,13 @@ network_config: use_dhcp: false addresses: - ip_netmask: - 100.64.0.34/30 + 100.64.0.30/30 - type: interface name: nic4 use_dhcp: false addresses: - ip_netmask: - 100.65.0.34/30 + 100.65.0.30/30 - type: interface name: lo use_dhcp: false diff --git a/scenarios/adoption/bgp-l3-xl.yml b/scenarios/adoption/bgp-l3-xl.yml index 7e455a30eb..53870d2a86 100644 --- a/scenarios/adoption/bgp-l3-xl.yml +++ b/scenarios/adoption/bgp-l3-xl.yml @@ -210,7 +210,6 @@ libvirt_manager_patch_layout: - "l00-ocp0" - "l00-ocp1" - "l00-ocp2" - - "l00-ocp3" - "l00-node3" - "l00-node4" - # rack0 - leaf01 @@ -222,7 +221,6 @@ libvirt_manager_patch_layout: - "l01-ocp0" - "l01-ocp1" - "l01-ocp2" - - "l01-ocp3" - "l01-node3" - "l01-node4" - # rack1 - leaf10 @@ -234,7 +232,6 @@ libvirt_manager_patch_layout: - "l10-ocp0" - "l10-ocp1" - "l10-ocp2" - - "l10-ocp3" - "l10-node3" - "l10-node4" - # rack1 - leaf11 @@ -246,7 +243,6 @@ libvirt_manager_patch_layout: - "l11-ocp0" - "l11-ocp1" - "l11-ocp2" - - "l11-ocp3" - "l11-node3" - "l11-node4" - # rack2 - leaf20 @@ -258,7 +254,6 @@ libvirt_manager_patch_layout: - "l20-ocp0" - "l20-ocp1" - "l20-ocp2" - - "l20-ocp3" - "l20-node3" - "l20-node4" - # rack2 - leaf21 @@ -270,7 +265,6 @@ libvirt_manager_patch_layout: - "l21-ocp0" - "l21-ocp1" - "l21-ocp2" - - "l21-ocp3" - "l21-node3" - "l21-node4" diff --git a/scenarios/reproducers/bgp-l3-xl.yml b/scenarios/reproducers/bgp-l3-xl.yml index cd2fd5dcb5..9d45b9e6ee 100644 --- a/scenarios/reproducers/bgp-l3-xl.yml +++ b/scenarios/reproducers/bgp-l3-xl.yml @@ -52,7 +52,6 @@ cifmw_libvirt_manager_network_interface_types: l00-ocp0: network l00-ocp1: network l00-ocp2: network - l00-ocp3: network l01-node0: network l01-node1: network l01-node2: network @@ -61,7 +60,6 @@ cifmw_libvirt_manager_network_interface_types: l01-ocp0: network l01-ocp1: network l01-ocp2: network - l01-ocp3: network l10-node0: network l10-node1: network l10-node2: network @@ -70,7 +68,6 @@ cifmw_libvirt_manager_network_interface_types: l10-ocp0: network l10-ocp1: network l10-ocp2: network - l10-ocp3: network l11-node0: network l11-node1: network l11-node2: network @@ -79,7 +76,6 @@ cifmw_libvirt_manager_network_interface_types: l11-ocp0: network l11-ocp1: network l11-ocp2: network - l11-ocp3: network l20-node0: network l20-node1: network l20-node2: network @@ -88,7 +84,6 @@ cifmw_libvirt_manager_network_interface_types: l20-ocp0: network l20-ocp1: network l20-ocp2: network - l20-ocp3: network l21-node0: network l21-node1: network l21-node2: network @@ -97,7 +92,6 @@ cifmw_libvirt_manager_network_interface_types: l21-ocp0: network l21-ocp1: network l21-ocp2: network - l21-ocp3: network cifmw_libvirt_manager_configuration: networks: @@ -236,11 +230,6 @@ cifmw_libvirt_manager_configuration: l00-ocp2 - l00-ocp3: | - - l00-ocp3 - - l01-node0: | l01-node0 @@ -281,11 +270,6 @@ cifmw_libvirt_manager_configuration: l01-ocp2 - l01-ocp3: | - - l01-ocp3 - - ## rack1 l10-node0: | @@ -327,11 +311,6 @@ cifmw_libvirt_manager_configuration: l10-ocp2 - l10-ocp3: | - - l10-ocp3 - - l11-node0: | l11-node0 @@ -372,11 +351,6 @@ cifmw_libvirt_manager_configuration: l11-ocp2 - l11-ocp3: | - - l11-ocp3 - - ## rack2 l20-node0: | @@ -418,11 +392,6 @@ cifmw_libvirt_manager_configuration: l20-ocp2 - l20-ocp3: | - - l20-ocp3 - - l21-node0: | l21-node0 @@ -463,11 +432,6 @@ cifmw_libvirt_manager_configuration: l21-ocp2 - l21-ocp3: | - - l21-ocp3 - - ocpbm: | ocpbm @@ -695,7 +659,7 @@ cifmw_libvirt_manager_configuration: - "ocpbm" - "osp_trunk" ocp_worker: - amount: 10 + amount: 7 uefi: true root_part_id: 4 admin_user: core @@ -717,28 +681,19 @@ cifmw_libvirt_manager_configuration: - # rack0 - ocp worker 1 - "l00-ocp1" - "l01-ocp1" - - # rack0 - ocp worker 2 - - "l00-ocp2" - - "l01-ocp2" - - # rack1 - ocp worker 3 + - # rack1 - ocp worker 2 - "l10-ocp0" - "l11-ocp0" - - # rack1 - ocp worker 4 + - # rack1 - ocp worker 3 - "l10-ocp1" - "l11-ocp1" - - # rack1 - ocp worker 5 - - "l10-ocp2" - - "l11-ocp2" - - # rack2 - ocp worker 6 + - # rack2 - ocp worker 4 - "l20-ocp0" - "l21-ocp0" - - # rack2 - ocp worker 7 + - # rack2 - ocp worker 5 - "l20-ocp1" - "l21-ocp1" - - # rack2 - ocp worker 8 - - "l20-ocp2" - - "l21-ocp2" - - # router - ocp_tester (worker 9) + - # router - ocp_tester (worker 6) - "rtr-ocp" router: amount: 1 @@ -919,7 +874,7 @@ pre_deploy: num_racks: "{{ num_racks }}" router_bool: true edpm_nodes_per_rack: 5 - ocp_nodes_per_rack: 4 + ocp_nodes_per_rack: 3 router_uplink_ip: 100.64.10.1 cifmw_repo_setup_rhos_release_rpm: "{{ cifmw_repo_setup_rhos_release_rpm }}"