From fb88dd9b05fe5aecc123001a0a6e61c2bf4366a0 Mon Sep 17 00:00:00 2001
From: Karl Kloppenborg <k@rl.ag>
Date: Tue, 12 Sep 2023 06:33:56 +0000
Subject: [PATCH] feat: BGP-Dragent for Neutron

Change-Id: Ibf4ce793f0e8d4d03b9e2bd5cd1163b52fcad4f1
---
 neutron/Chart.yaml                            |   2 +-
 .../templates/bin/_neutron-bgp-dragent.sh.tpl |  21 +++
 neutron/templates/configmap-bin.yaml          |   2 +
 neutron/templates/configmap-etc.yaml          |   1 +
 neutron/templates/daemonset-bgp-dragent.yaml  | 167 ++++++++++++++++++
 neutron/values.yaml                           |  35 ++++
 releasenotes/notes/neutron.yaml               |   1 +
 7 files changed, 228 insertions(+), 1 deletion(-)
 create mode 100644 neutron/templates/bin/_neutron-bgp-dragent.sh.tpl
 create mode 100644 neutron/templates/daemonset-bgp-dragent.yaml

diff --git a/neutron/Chart.yaml b/neutron/Chart.yaml
index 536005e306..befe1ec0c8 100644
--- a/neutron/Chart.yaml
+++ b/neutron/Chart.yaml
@@ -14,7 +14,7 @@ apiVersion: v1
 appVersion: v1.0.0
 description: OpenStack-Helm Neutron
 name: neutron
-version: 0.3.21
+version: 0.3.22
 home: https://docs.openstack.org/neutron/latest/
 icon: https://www.openstack.org/themes/openstack/images/project-mascots/Neutron/OpenStack_Project_Neutron_vertical.png
 sources:
diff --git a/neutron/templates/bin/_neutron-bgp-dragent.sh.tpl b/neutron/templates/bin/_neutron-bgp-dragent.sh.tpl
new file mode 100644
index 0000000000..c78bbc8f8b
--- /dev/null
+++ b/neutron/templates/bin/_neutron-bgp-dragent.sh.tpl
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+{{/*
+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.
+*/}}
+
+set -x
+exec neutron-bgp-dragent \
+      --config-file /etc/neutron/neutron.conf \
+      --config-file /etc/neutron/bgp_dragent.ini \
+      --debug
diff --git a/neutron/templates/configmap-bin.yaml b/neutron/templates/configmap-bin.yaml
index b509721ff7..9a934e0720 100644
--- a/neutron/templates/configmap-bin.yaml
+++ b/neutron/templates/configmap-bin.yaml
@@ -83,6 +83,8 @@ data:
 {{ tuple "bin/_neutron-bagpipe-bgp.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
   neutron-bagpipe-bgp-init.sh: |
 {{ tuple "bin/_neutron-bagpipe-bgp-init.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
+  neutron-bgp-dragent.sh: |
+{{ tuple "bin/_neutron-bgp-dragent.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
 {{- if .Values.manifests.certificates }}
   nginx.sh: |
 {{ tuple "bin/_nginx.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
diff --git a/neutron/templates/configmap-etc.yaml b/neutron/templates/configmap-etc.yaml
index 0a3b718067..87058363bf 100644
--- a/neutron/templates/configmap-etc.yaml
+++ b/neutron/templates/configmap-etc.yaml
@@ -308,6 +308,7 @@ data:
   sriov_agent.ini: {{ include "helm-toolkit.utils.to_oslo_conf" $envAll.Values.conf.plugins.sriov_agent | b64enc }}
   l2gw_agent.ini: {{ default "\"\"" (include "helm-toolkit.utils.to_oslo_conf" .Values.conf.l2gateway_agent | b64enc) }}
   bagpipe_bgp.conf: {{ default "\"\"" (include "helm-toolkit.utils.to_oslo_conf" .Values.conf.bagpipe_bgp | b64enc) }}
+  bgp_dragent.ini: {{ default "\"\"" (include "helm-toolkit.utils.to_oslo_conf" .Values.conf.bgp_dragent | b64enc) }}
   tf_plugin.ini: {{ default "\"\"" (include "helm-toolkit.utils.to_oslo_conf" $envAll.Values.conf.plugins.tungstenfabric | b64enc) }}
   vnc_api_lib.ini: {{ default "\"\"" (include "helm-toolkit.utils.to_oslo_conf" $envAll.Values.conf.plugins.tf_vnc_api_lib | b64enc) }}
   dnsmasq.conf: "{{ $envAll.Values.conf.dnsmasq | b64enc }}"
diff --git a/neutron/templates/daemonset-bgp-dragent.yaml b/neutron/templates/daemonset-bgp-dragent.yaml
new file mode 100644
index 0000000000..ca8a3d144b
--- /dev/null
+++ b/neutron/templates/daemonset-bgp-dragent.yaml
@@ -0,0 +1,167 @@
+{{/*
+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.
+*/}}
+
+{{- define "bgp_dragentLivenessProbeTemplate" }}
+exec:
+  command:
+    - bash
+    - -c
+    - pidof -x /var/lib/openstack/bin/neutron-bgp-dragent
+{{- end }}
+
+
+{{- define "neutron.bgp_dragent.daemonset" }}
+{{- $daemonset := index . 0 }}
+{{- $configMapName := index . 1 }}
+{{- $serviceAccountName := index . 2 }}
+{{- $envAll := index . 3 }}
+{{- with $envAll }}
+
+{{- $mounts_neutron_bgp_dragent := .Values.pod.mounts.bgp_dragent.bgp_dragent }}
+{{- $mounts_neutron_bgp_dragent_init := .Values.pod.mounts.bgp_dragent.init_container }}
+
+---
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  name: bgp-dragent
+  annotations:
+    {{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
+  labels:
+{{ tuple $envAll "neutron" "bgp-dragent" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
+spec:
+  selector:
+    matchLabels:
+{{ tuple $envAll "neutron" "bgp-dragent" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 6 }}
+{{ tuple $envAll "bgp_dragent" | include "helm-toolkit.snippets.kubernetes_upgrades_daemonset" | indent 2 }}
+  template:
+    metadata:
+      labels:
+{{ tuple $envAll "neutron" "bgp-dragent" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
+      annotations:
+{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" | indent 8 }}
+        configmap-bin-hash: {{ tuple "configmap-bin.yaml" . | include "helm-toolkit.utils.hash" }}
+        configmap-etc-hash: {{ tuple "configmap-etc.yaml" . | include "helm-toolkit.utils.hash" }}
+    spec:
+{{ dict "envAll" $envAll "application" "neutron_bgp_dragent" | include "helm-toolkit.snippets.kubernetes_pod_security_context" | indent 6 }}
+      serviceAccountName: {{ $serviceAccountName }}
+{{ if $envAll.Values.pod.tolerations.neutron.enabled }}
+{{ tuple $envAll "neutron" | include "helm-toolkit.snippets.kubernetes_tolerations" | indent 6 }}
+{{ end }}
+      nodeSelector:
+        {{ .Values.labels.bgp_dragent.node_selector_key }}: {{ .Values.labels.bgp_dragent.node_selector_value }}
+      dnsPolicy: ClusterFirstWithHostNet
+      hostNetwork: true
+      {{- if or ( gt .Capabilities.KubeVersion.Major "1" ) ( ge .Capabilities.KubeVersion.Minor "10" ) }}
+      shareProcessNamespace: true
+      {{- else }}
+      hostPID: true
+      {{- end }}
+      containers:
+        - name: neutron-bgp-dragent
+{{ tuple $envAll "neutron_bgp_dragent" | include "helm-toolkit.snippets.image" | indent 10 }}
+{{ tuple $envAll $envAll.Values.pod.resources.agent.bgp_dragent | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+{{ dict "envAll" $envAll "application" "neutron_bgp_dragent" "container" "neutron_bgp_dragent" | include "helm-toolkit.snippets.kubernetes_container_security_context" | indent 10 }}
+{{ dict "envAll" $envAll "component" "bgp_dragent" "container" "bgp_dragent" "type" "liveness" "probeTemplate" (include "bgp_dragentLivenessProbeTemplate" $envAll | fromYaml) | include "helm-toolkit.snippets.kubernetes_probe" | indent 10 }}
+          command:
+            - /tmp/neutron-bgp-dragent.sh
+          volumeMounts:
+            - name: pod-tmp
+              mountPath: /tmp
+            - name: pod-var-neutron
+              mountPath: {{ .Values.conf.neutron.DEFAULT.state_path }}
+            - name: neutron-bin
+              mountPath: /tmp/neutron-bgp-dragent.sh
+              subPath: neutron-bgp-dragent.sh
+              readOnly: true
+            - name: neutron-bin
+              mountPath: /tmp/health-probe.py
+              subPath: health-probe.py
+              readOnly: true
+            - name: neutron-etc
+              mountPath: /etc/neutron/neutron.conf
+              subPath: neutron.conf
+              readOnly: true
+            {{- if .Values.conf.neutron.DEFAULT.log_config_append }}
+            - name: neutron-etc
+              mountPath: {{ .Values.conf.neutron.DEFAULT.log_config_append }}
+              subPath: {{ base .Values.conf.neutron.DEFAULT.log_config_append }}
+              readOnly: true
+            {{- end }}
+            - name: neutron-etc
+              mountPath: /etc/neutron/bgp_dragent.ini
+              subPath: bgp_dragent.ini
+              readOnly: true
+            - name: neutron-etc
+              # NOTE (Portdirect): We mount here to override Kollas
+              # custom sudoers file when using Kolla images, this
+              # location will also work fine for other images.
+              mountPath: /etc/sudoers.d/kolla_neutron_sudoers
+              subPath: neutron_sudoers
+              readOnly: true
+            - name: neutron-etc
+              mountPath: /etc/neutron/rootwrap.conf
+              subPath: rootwrap.conf
+              readOnly: true
+            {{- range $key, $value := $envAll.Values.conf.rootwrap_filters }}
+            {{- if ( has "bgp_dragent" $value.pods ) }}
+            {{- $filePrefix := replace "_" "-"  $key }}
+            {{- $rootwrapFile := printf "/etc/neutron/rootwrap.d/%s.filters" $filePrefix }}
+            - name: neutron-etc
+              mountPath: {{ $rootwrapFile }}
+              subPath: {{ base $rootwrapFile }}
+              readOnly: true
+            {{- end }}
+            {{- end }}
+            - name: libmodules
+              mountPath: /lib/modules
+              readOnly: true
+            - name: run
+              mountPath: /run
+{{ if $mounts_neutron_bgp_dragent.volumeMounts }}{{ toYaml $mounts_neutron_bgp_dragent.volumeMounts | indent 12 }}{{ end }}
+      volumes:
+        - name: pod-tmp
+          emptyDir: {}
+        - name: pod-var-neutron
+          emptyDir: {}
+        - name: neutron-bin
+          configMap:
+            name: neutron-bin
+            defaultMode: 0555
+        - name: neutron-etc
+          secret:
+            secretName: {{ $configMapName }}
+            defaultMode: 0444
+        - name: libmodules
+          hostPath:
+            path: /lib/modules
+        - name: run
+          hostPath:
+            path: /run
+{{ if $mounts_neutron_bgp_dragent.volumes }}{{ toYaml $mounts_neutron_bgp_dragent.volumes | indent 8 }}{{ end }}
+{{- end }}
+{{- end }}
+
+{{- if .Values.manifests.daemonset_bgp_dragent }}
+{{- $envAll := . }}
+{{- $daemonset := "bgp-dragent" }}
+{{- $configMapName := "neutron-etc" }}
+{{- $serviceAccountName := "neutron-bgp-dragent" }}
+{{- $dependencyOpts := dict "envAll" $envAll "dependencyMixinParam" $envAll.Values.network.backend "dependencyKey" "bgp_dragent" -}}
+{{- $_ := include "helm-toolkit.utils.dependency_resolver" $dependencyOpts | toString | fromYaml }}
+{{ tuple $envAll "pod_dependency" $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
+{{- $daemonset_yaml := list $daemonset $configMapName $serviceAccountName . | include "neutron.bgp_dragent.daemonset" | toString | fromYaml }}
+{{- $configmap_yaml := "neutron.configmap.etc" }}
+{{- list $daemonset $daemonset_yaml $configmap_yaml $configMapName . | include "helm-toolkit.utils.daemonset_overrides" }}
+{{- end }}
diff --git a/neutron/values.yaml b/neutron/values.yaml
index 70f808fb41..a7ba61b928 100644
--- a/neutron/values.yaml
+++ b/neutron/values.yaml
@@ -42,6 +42,7 @@ images:
     neutron_sriov_agent: docker.io/openstackhelm/neutron:stein-18.04-sriov
     neutron_sriov_agent_init: docker.io/openstackhelm/neutron:stein-18.04-sriov
     neutron_bagpipe_bgp: docker.io/openstackhelm/neutron:stein-ubuntu_bionic
+    neutron_bgp_dragent: docker.io/openstackhelm/neutron:stein-ubuntu_bionic
     neutron_ironic_agent: docker.io/openstackhelm/neutron:stein-ubuntu_bionic
     neutron_netns_cleanup_cron: docker.io/openstackhelm/neutron:stein-ubuntu_bionic
     dep_check: quay.io/airshipit/kubernetes-entrypoint:v1.0.0
@@ -86,6 +87,9 @@ labels:
   bagpipe_bgp:
     node_selector_key: openstack-compute-node
     node_selector_value: enabled
+  bgp_dragent:
+    node_selector_key: openstack-compute-node
+    node_selector_value: enabled
   server:
     node_selector_key: openstack-control-plane
     node_selector_value: enabled
@@ -159,6 +163,7 @@ dependencies:
       l2gateway: {}
       bagpipe_bgp: {}
       ovn: {}
+      bgp_dragent: {}
       openvswitch:
         dhcp:
           pod:
@@ -440,6 +445,15 @@ pod:
           enabled: true
           params:
             initialDelaySeconds: 60
+    bgp_dragent:
+      bgp_dragent:
+        readiness:
+          enabled: false
+          params:
+        liveness:
+          enabled: true
+          params:
+            initialDelaySeconds: 60
     l2gw_agent:
       l2gw_agent:
         readiness:
@@ -489,6 +503,13 @@ pod:
         neutron_bagpipe_bgp:
           readOnlyRootFilesystem: true
           privileged: true
+    neutron_bgp_dragent:
+      pod:
+        runAsUser: 42424
+      container:
+        neutron_bgp_dragent:
+          readOnlyRootFilesystem: true
+          privileged: true
     neutron_l3_agent:
       pod:
         runAsUser: 42424
@@ -654,6 +675,11 @@ pod:
       bagpipe_bgp:
         volumeMounts:
         volumes:
+    bgp_dragent:
+      init_container: null
+      bgp_dragent:
+        volumeMounts:
+        volumes:
     neutron_ironic_agent:
       init_container: null
       neutron_ironic_agent:
@@ -801,6 +827,13 @@ pod:
         limits:
           memory: "1024Mi"
           cpu: "2000m"
+      bgp_dragent:
+        requests:
+          memory: "128Mi"
+          cpu: "100m"
+        limits:
+          memory: "1024Mi"
+          cpu: "2000m"
     server:
       requests:
         memory: "128Mi"
@@ -2000,6 +2033,7 @@ conf:
       backend: dogpile.cache.memcached
     ovs:
       ovsdb_connection: unix:/run/openvswitch/db.sock
+  bgp_dragent: {}
 
   rabbitmq:
     # NOTE(rk760n): adding rmq policy to mirror messages from notification queues and set expiration time for the ones
@@ -2481,6 +2515,7 @@ manifests:
   daemonset_sriov_agent: true
   daemonset_l2gw_agent: false
   daemonset_bagpipe_bgp: false
+  daemonset_bgp_dragent: false
   daemonset_netns_cleanup_cron: true
   deployment_ironic_agent: false
   deployment_server: true
diff --git a/releasenotes/notes/neutron.yaml b/releasenotes/notes/neutron.yaml
index 58227d63bd..9aee23157b 100644
--- a/releasenotes/notes/neutron.yaml
+++ b/releasenotes/notes/neutron.yaml
@@ -63,4 +63,5 @@ neutron:
   - 0.3.19 Fix getting IP for interface when there are multiple IPs assigned
   - 0.3.20 Add Ubuntu Jammy overrides
   - 0.3.21 Run native netns cleanup
+  - 0.3.22 Add BGP Dragent support for running dragent agents as daemonsets
 ...