Skip to content

Commit 1a46652

Browse files
Merge pull request #1186 from fultonj/dcn_adoption_pr_ovn_sb
Configure OVN SB direct IPs for DCN nodesets
2 parents 201d175 + 1c8bf1d commit 1a46652

2 files changed

Lines changed: 195 additions & 0 deletions

File tree

tests/roles/dataplane_adoption/defaults/main.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,9 @@ dataplane_cr: |
397397
ovn_monitor_all: true
398398
edpm_ovn_remote_probe_interval: 60000
399399
edpm_ovn_ofctrl_wait_before_clear: 8000
400+
{% if edpm_ovn_dbs_nodeset is defined -%}
401+
edpm_ovn_dbs: {{ edpm_ovn_dbs_nodeset }}
402+
{%+ endif +%}
400403
nodes:
401404
402405
dpa_dir: "../.."

tests/roles/dataplane_adoption/tasks/main.yaml

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,69 @@
4343
EOF
4444
when: configure_ipam | bool
4545

46+
# DCN requires routes in the internalapi NAD so OVN SB pods can reach DCN compute nodes.
47+
# Macvlan pods don't inherit routes from the node interface, so we add them to the NAD.
48+
- name: Patch internalapi NAD with routes to DCN subnets
49+
when: edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined
50+
no_log: "{{ use_no_log }}"
51+
ansible.builtin.shell: |
52+
{{ shell_header }}
53+
{{ oc_header }}
54+
55+
# Get current NAD config
56+
CURRENT_CONFIG=$(oc get net-attach-def internalapi -n openstack -o jsonpath='{.spec.config}')
57+
58+
# Check if routes already exist
59+
if echo "$CURRENT_CONFIG" | grep -q '"routes"'; then
60+
echo "Routes already exist in internalapi NAD, skipping"
61+
exit 0
62+
fi
63+
64+
# Build routes array for DCN subnets
65+
# DCN1: 172.17.10.0/24, DCN2: 172.17.20.0/24, gateway: 172.17.0.1
66+
ROUTES='[{"dst":"172.17.10.0/24","gw":"172.17.0.1"},{"dst":"172.17.20.0/24","gw":"172.17.0.1"}]'
67+
68+
# Add routes to IPAM config
69+
NEW_CONFIG=$(echo "$CURRENT_CONFIG" | python3 -c "
70+
import json, sys
71+
config = json.load(sys.stdin)
72+
config['ipam']['routes'] = json.loads('$ROUTES')
73+
print(json.dumps(config))
74+
")
75+
76+
# Apply updated NAD
77+
oc apply -f - <<EOF
78+
apiVersion: k8s.cni.cncf.io/v1
79+
kind: NetworkAttachmentDefinition
80+
metadata:
81+
name: internalapi
82+
namespace: openstack
83+
labels:
84+
osp/net: internalapi
85+
osp/net-attach-def-type: standard
86+
spec:
87+
config: |
88+
$NEW_CONFIG
89+
EOF
90+
register: nad_patch_result
91+
92+
- name: Restart OVN SB pods to pick up new NAD routes
93+
when:
94+
- edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined
95+
- nad_patch_result.changed
96+
- "'skipping' not in nad_patch_result.stdout"
97+
no_log: "{{ use_no_log }}"
98+
ansible.builtin.shell: |
99+
{{ shell_header }}
100+
{{ oc_header }}
101+
102+
# Delete OVN SB pods so they restart with new routes
103+
oc delete pod -n openstack -l service=ovsdbserver-sb --wait=false
104+
105+
# Wait for pods to be ready again
106+
sleep 10
107+
oc wait --for=condition=Ready pod -n openstack -l service=ovsdbserver-sb --timeout=120s
108+
46109
- name: Slurp the private key
47110
no_log: "{{ use_no_log }}"
48111
ansible.builtin.slurp:
@@ -258,11 +321,100 @@
258321
{% endif %}
259322
{% endfor %}
260323
324+
- name: Get OVN SB internalapi IPs for DCN nodesets
325+
when: edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined
326+
no_log: "{{ use_no_log }}"
327+
ansible.builtin.shell: |
328+
{{ shell_header }}
329+
{{ oc_header }}
330+
331+
# Get internalapi IPs from OVN SB pods
332+
OVN_SB_IPS=""
333+
for pod in ovsdbserver-sb-0 ovsdbserver-sb-1 ovsdbserver-sb-2; do
334+
IP=$(oc get pod -n openstack $pod -o jsonpath='{.metadata.annotations.k8s\.v1\.cni\.cncf\.io/network-status}' | \
335+
python3 -c "import sys, json; data=json.load(sys.stdin); print([n for n in data if 'internalapi' in n.get('name','')][0]['ips'][0])")
336+
if [ -z "$OVN_SB_IPS" ]; then
337+
OVN_SB_IPS="\"$IP\""
338+
else
339+
OVN_SB_IPS="$OVN_SB_IPS, \"$IP\""
340+
fi
341+
done
342+
343+
echo "[$OVN_SB_IPS]"
344+
register: ovn_sb_ips_result
345+
346+
- name: Set OVN SB IPs fact for DCN nodesets
347+
when: edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined
348+
ansible.builtin.set_fact:
349+
edpm_ovn_dbs_dcn: "{{ ovn_sb_ips_result.stdout | trim | from_json }}"
350+
351+
- name: Create DCN OVN controller ConfigMap with direct IPs
352+
when: edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined
353+
no_log: "{{ use_no_log }}"
354+
ansible.builtin.shell: |
355+
{{ shell_header }}
356+
{{ oc_header }}
357+
358+
# Build ovn-remote connection string from internalapi IPs
359+
OVN_REMOTE="{% for ip in edpm_ovn_dbs_dcn %}tcp:{{ ip }}:6642{% if not loop.last %},{% endif %}{% endfor %}"
360+
361+
# Create ConfigMap for DCN nodes with direct IPs
362+
oc apply -f - <<EOF
363+
apiVersion: v1
364+
kind: ConfigMap
365+
metadata:
366+
name: ovncontroller-config-dcn
367+
namespace: openstack
368+
data:
369+
ovsdb-config: |
370+
ovn-remote: $OVN_REMOTE
371+
EOF
372+
373+
- name: Create DCN-specific OVN DataPlaneService
374+
when: edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined
375+
no_log: "{{ use_no_log }}"
376+
ansible.builtin.shell: |
377+
{{ shell_header }}
378+
{{ oc_header }}
379+
380+
# Create OpenStackDataPlaneService for DCN that uses the DCN ConfigMap
381+
oc apply -f - <<EOF
382+
apiVersion: dataplane.openstack.org/v1beta1
383+
kind: OpenStackDataPlaneService
384+
metadata:
385+
name: ovn-dcn
386+
namespace: openstack
387+
spec:
388+
addCertMounts: false
389+
caCerts: combined-ca-bundle
390+
containerImageFields:
391+
- OvnControllerImage
392+
dataSources:
393+
- configMapRef:
394+
name: ovncontroller-config-dcn
395+
edpmServiceType: ovn
396+
playbook: osp.edpm.ovn
397+
tlsCerts:
398+
default:
399+
contents:
400+
- dnsnames
401+
- ips
402+
issuer: osp-rootca-issuer-ovn
403+
keyUsages:
404+
- digital signature
405+
- key encipherment
406+
- server auth
407+
- client auth
408+
networks:
409+
- ctlplane
410+
EOF
411+
261412
- name: Create OpenStackDataPlaneNodeSet_dcn1
262413
when: edpm_nodes_dcn1 is defined
263414
no_log: "{{ use_no_log }}"
264415
vars:
265416
edpm_ovn_bridge_mappings_nodeset: "{{ edpm_ovn_bridge_mappings_dcn1|default(omit) }}"
417+
edpm_ovn_dbs_nodeset: "{{ edpm_ovn_dbs_dcn }}"
266418
ansible.builtin.shell: |
267419
{{ shell_header }}
268420
CELL=cell1
@@ -279,6 +431,7 @@
279431
no_log: "{{ use_no_log }}"
280432
vars:
281433
edpm_ovn_bridge_mappings_nodeset: "{{ edpm_ovn_bridge_mappings_dcn2|default(omit) }}"
434+
edpm_ovn_dbs_nodeset: "{{ edpm_ovn_dbs_dcn }}"
282435
ansible.builtin.shell: |
283436
{{ shell_header }}
284437
CELL=cell1
@@ -336,6 +489,45 @@
336489
cat nodeset-cell1-dcn2.yaml | oc apply -f -
337490
{%+ endif +%}
338491
492+
- name: Patch DCN nodesets to use ovn-dcn service instead of ovn
493+
when: edpm_nodes_dcn1 is defined or edpm_nodes_dcn2 is defined
494+
no_log: "{{ use_no_log }}"
495+
ansible.builtin.shell: |
496+
{{ shell_header }}
497+
{{ oc_header }}
498+
499+
# Patch dcn1 nodeset if it exists
500+
{% if edpm_nodes_dcn1 is defined %}
501+
if oc get openstackdataplanenodeset dcn1 -n openstack &>/dev/null; then
502+
# Get current services list and replace 'ovn' with 'ovn-dcn'
503+
SERVICES=$(oc get openstackdataplanenodeset dcn1 -n openstack -o jsonpath='{.spec.services}' | \
504+
sed 's/"ovn"/"ovn-dcn"/g')
505+
506+
# Apply the patch
507+
oc patch openstackdataplanenodeset dcn1 -n openstack --type=merge --patch "
508+
spec:
509+
services: $SERVICES
510+
"
511+
echo "Patched dcn1 nodeset to use ovn-dcn service"
512+
fi
513+
{% endif %}
514+
515+
# Patch dcn2 nodeset if it exists
516+
{% if edpm_nodes_dcn2 is defined %}
517+
if oc get openstackdataplanenodeset dcn2 -n openstack &>/dev/null; then
518+
# Get current services list and replace 'ovn' with 'ovn-dcn'
519+
SERVICES=$(oc get openstackdataplanenodeset dcn2 -n openstack -o jsonpath='{.spec.services}' | \
520+
sed 's/"ovn"/"ovn-dcn"/g')
521+
522+
# Apply the patch
523+
oc patch openstackdataplanenodeset dcn2 -n openstack --type=merge --patch "
524+
spec:
525+
services: $SERVICES
526+
"
527+
echo "Patched dcn2 nodeset to use ovn-dcn service"
528+
fi
529+
{% endif %}
530+
339531
# TODO(bogdando): Apply the ceph backend config for Cinder in the original openstack CR, via kustomize perhaps?
340532
- name: prepare the adopted data plane workloads to use Ceph backend for Cinder, if configured so
341533
no_log: "{{ use_no_log }}"

0 commit comments

Comments
 (0)