ci: almost done cleanup
diff --git a/.github/workflows/ceph.yml b/.github/workflows/ceph.yml
index 65f2331..93f7b64 100644
--- a/.github/workflows/ceph.yml
+++ b/.github/workflows/ceph.yml
@@ -28,76 +28,15 @@
         default: false
 
 jobs:
-  # ovs-debug:
-  #   runs-on: ubuntu-20.04-16-cores
-  #   if: github.event_name == 'workflow_dispatch' && inputs.debug_enabled
-  #   steps:
-  #     - name: Checkout project
-  #       uses: actions/checkout@v3
-
-  #     - name: Install Poetry
-  #       run: pipx install poetry
-
-  #     - name: Setup Python
-  #       uses: actions/setup-python@v4
-  #       with:
-  #         cache: poetry
-
-  #     - name: Install dependencies
-  #       run: poetry install --no-interaction --with dev
-
-  #     # NOTE(mnaser): LVM commands take a long time if there are any existing
-  #     #               loop devices created by "snapd", so we uninstall it.
-  #     - name: Uninstall "snapd"
-  #       run: sudo apt-get purge -y snapd
-
-  #     - name: Turn off swap
-  #       run: sudo swapoff -a
-
-  #     - name: Run Molecule Converge
-  #       run: poetry run molecule converge -s ceph
-
-  #     # Enable tmate debugging of manually-triggered workflows if the input option was provided
-  #     - name: Setup tmate session
-  #       if: ${{ failure() }}
-  #       uses: mxschmitt/action-tmate@v3
-  #       timeout-minutes: 60
-
-  #     - name: Run Molecule Destroy
-  #       run: poetry run molecule destroy -s ceph
-
-  # ovs:
-  #   runs-on: ubuntu-20.04-16-cores
-  #   if: github.event_name != 'workflow_dispatch' || !inputs.debug_enabled
-  #   steps:
-  #     - name: Checkout project
-  #       uses: actions/checkout@v3
-
-  #     - name: Install Poetry
-  #       run: pipx install poetry
-
-  #     - name: Setup Python
-  #       uses: actions/setup-python@v4
-  #       with:
-  #         cache: poetry
-
-  #     - name: Install dependencies
-  #       run: poetry install --no-interaction --with dev
-
-  #     # NOTE(mnaser): LVM commands take a long time if there are any existing
-  #     #               loop devices created by "snapd", so we uninstall it.
-  #     - name: Uninstall "snapd"
-  #       run: sudo apt-get purge -y snapd
-
-  #     - name: Turn off swap
-  #       run: sudo swapoff -a
-
-  #     - name: Run Molecule
-  #       run: poetry run molecule test -s ceph
-
-  ovn-debug:
+  debug:
     runs-on: ubuntu-20.04-16-cores
-    # if: github.event_name == 'workflow_dispatch' && inputs.debug_enabled
+    if: github.event_name == 'workflow_dispatch' && inputs.debug_enabled
+    strategy:
+      fail-fast: false
+      matrix:
+        network_backend:
+          - openvswitch
+          - ovn
     steps:
       - name: Checkout project
         uses: actions/checkout@v3
@@ -123,45 +62,49 @@
 
       - name: Run Molecule Converge
         run: poetry run molecule converge -s ceph
-        env:
-          OVN_ENABLED: true
 
       # Enable tmate debugging of manually-triggered workflows if the input option was provided
       - name: Setup tmate session
         if: ${{ failure() }}
         uses: mxschmitt/action-tmate@v3
-        timeout-minutes: 180
+        timeout-minutes: 60
 
       - name: Run Molecule Destroy
         run: poetry run molecule destroy -s ceph
 
-  # ovn:
-  #   runs-on: ubuntu-20.04-16-cores
-  #   if: github.event_name != 'workflow_dispatch' || !inputs.debug_enabled
-  #   steps:
-  #     - name: Checkout project
-  #       uses: actions/checkout@v3
+  test:
+    runs-on: ubuntu-20.04-16-cores
+    if: github.event_name != 'workflow_dispatch' || !inputs.debug_enabled
+    strategy:
+      fail-fast: false
+      matrix:
+        network_backend:
+          - openvswitch
+          - ovn
+    steps:
+      - name: Checkout project
+        uses: actions/checkout@v3
 
-  #     - name: Install Poetry
-  #       run: pipx install poetry
+      - name: Install Poetry
+        run: pipx install poetry
 
-  #     - name: Setup Python
-  #       uses: actions/setup-python@v4
-  #       with:
-  #         cache: poetry
+      - name: Setup Python
+        uses: actions/setup-python@v4
+        with:
+          cache: poetry
 
-  #     - name: Install dependencies
-  #       run: poetry install --no-interaction --with dev
+      - name: Install dependencies
+        run: poetry install --no-interaction --with dev
 
-  #     # NOTE(mnaser): LVM commands take a long time if there are any existing
-  #     #               loop devices created by "snapd", so we uninstall it.
-  #     - name: Uninstall "snapd"
-  #       run: sudo apt-get purge -y snapd
+      # NOTE(mnaser): LVM commands take a long time if there are any existing
+      #               loop devices created by "snapd", so we uninstall it.
+      - name: Uninstall "snapd"
+        run: sudo apt-get purge -y snapd
 
-  #     - name: Turn off swap
-  #       run: sudo swapoff -a
+      - name: Turn off swap
+        run: sudo swapoff -a
 
-  #     - name: Run Molecule
-  #       run: poetry run molecule test -s ceph
-  #       env:
-  #         OVN_ENABLED: true
+      - name: Run Molecule
+        run: poetry run molecule test -s ceph
+        env:
+          ATMOSPHERE_NETWORK_BACKEND: ${{ matrix.network_backend }}
diff --git a/charts/neutron/templates/configmap-etc.yaml b/charts/neutron/templates/configmap-etc.yaml
index 046c02b..e88a333 100644
--- a/charts/neutron/templates/configmap-etc.yaml
+++ b/charts/neutron/templates/configmap-etc.yaml
@@ -142,13 +142,13 @@
 {{- end -}}
 
 {{- if empty $envAll.Values.conf.ovn_metadata_agent.DEFAULT.nova_metadata_host -}}
-{{- $_ := tuple "compute_metadata" "internal" . | include "helm-toolkit.endpoints.hostname_fqdn_endpoint_lookup" | set $envAll.Values.conf.metadata_agent.DEFAULT "nova_metadata_host" -}}
+{{- $_ := tuple "compute_metadata" "internal" . | include "helm-toolkit.endpoints.hostname_fqdn_endpoint_lookup" | set $envAll.Values.conf.ovn_metadata_agent.DEFAULT "nova_metadata_host" -}}
 {{- end -}}
 {{- if empty $envAll.Values.conf.ovn_metadata_agent.cache.memcache_servers -}}
-{{- $_ := tuple "oslo_cache" "internal" "memcache" . | include "helm-toolkit.endpoints.host_and_port_endpoint_uri_lookup" | set $envAll.Values.conf.metadata_agent.cache "memcache_servers" -}}
+{{- $_ := tuple "oslo_cache" "internal" "memcache" . | include "helm-toolkit.endpoints.host_and_port_endpoint_uri_lookup" | set $envAll.Values.conf.ovn_metadata_agent.cache "memcache_servers" -}}
 {{- end -}}
 {{- if empty $envAll.Values.conf.ovn_metadata_agent.DEFAULT.nova_metadata_port -}}
-{{- $_ := tuple "compute_metadata" "internal" "metadata" . | include "helm-toolkit.endpoints.endpoint_port_lookup" | set $envAll.Values.conf.metadata_agent.DEFAULT "nova_metadata_port" }}
+{{- $_ := tuple "compute_metadata" "internal" "metadata" . | include "helm-toolkit.endpoints.endpoint_port_lookup" | set $envAll.Values.conf.ovn_metadata_agent.DEFAULT "nova_metadata_port" }}
 {{- end -}}
 
 {{- if empty $envAll.Values.conf.neutron.DEFAULT.interface_driver -}}
diff --git a/charts/nova/templates/bin/_health-probe.py.tpl b/charts/nova/templates/bin/_health-probe.py.tpl
index 4034df7..9b06f40 100644
--- a/charts/nova/templates/bin/_health-probe.py.tpl
+++ b/charts/nova/templates/bin/_health-probe.py.tpl
@@ -137,7 +137,7 @@
     try:
         with open(sys.argv[2]) as conf_file:
             for line in conf_file:
-                if "connection =" in line:
+                if line.startswith("connection ="):
                     service = line.split(':', 3)[3].split('/')[1].rstrip('\n')
                     if service == "nova":
                         database_ports.add(
diff --git a/charts/ovn/templates/bin/_ovn-controller-init.sh.tpl b/charts/ovn/templates/bin/_ovn-controller-init.sh.tpl
index aa3ff6d..54b7417 100644
--- a/charts/ovn/templates/bin/_ovn-controller-init.sh.tpl
+++ b/charts/ovn/templates/bin/_ovn-controller-init.sh.tpl
@@ -23,6 +23,58 @@
   echo ${ip}
 }
 
+function get_ip_prefix_from_interface {
+  local interface=$1
+  local prefix=$(ip -4 -o addr s "${interface}" | awk '{ print $4; exit }' | awk -F '/' '{print $2}')
+  if [ -z "${prefix}" ] ; then
+    exit 1
+  fi
+  echo ${prefix}
+}
+
+function migrate_ip_from_nic {
+  src_nic=$1
+  bridge_name=$2
+
+  # Enabling explicit error handling: We must avoid to lose the IP
+  # address in the migration process. Hence, on every error, we
+  # attempt to assign the IP back to the original NIC and exit.
+  set +e
+
+  ip=$(get_ip_address_from_interface ${src_nic})
+  prefix=$(get_ip_prefix_from_interface ${src_nic})
+
+  bridge_ip=$(get_ip_address_from_interface "${bridge_name}")
+  bridge_prefix=$(get_ip_prefix_from_interface "${bridge_name}")
+
+  ip link set ${bridge_name} up
+
+  if [[ -n "${ip}" && -n "${prefix}" ]]; then
+    ip addr flush dev ${src_nic}
+    if [ $? -ne 0 ] ; then
+      ip addr add ${ip}/${prefix} dev ${src_nic}
+      echo "Error while flushing IP from ${src_nic}."
+      exit 1
+    fi
+
+    ip addr add ${ip}/${prefix} dev "${bridge_name}"
+    if [ $? -ne 0 ] ; then
+      echo "Error assigning IP to bridge "${bridge_name}"."
+      ip addr add ${ip}/${prefix} dev ${src_nic}
+      exit 1
+    fi
+  elif [[ -n "${bridge_ip}" && -n "${bridge_prefix}" ]]; then
+    echo "Bridge '${bridge_name}' already has IP assigned. Keeping the same:: IP:[${bridge_ip}]; Prefix:[${bridge_prefix}]..."
+  elif [[ -z "${bridge_ip}" && -z "${ip}" ]]; then
+    echo "Interface and bridge have no ips configured. Leaving as is."
+  else
+    echo "Interface ${name} has invalid IP address. IP:[${ip}]; Prefix:[${prefix}]..."
+    exit 1
+  fi
+
+  set -e
+}
+
 # Detect tunnel interface
 tunnel_interface="{{- .Values.network.interface.tunnel -}}"
 if [ -z "${tunnel_interface}" ] ; then
@@ -85,5 +137,6 @@
   if [ -n "$iface" ] && [ "$iface" != "null" ]
   then
     ovs-vsctl --may-exist add-port $bridge $iface
+    migrate_ip_from_nic $iface $bridge
   fi
 done
diff --git a/charts/ovn/templates/daemonset-controller.yaml b/charts/ovn/templates/daemonset-controller.yaml
index 1c6596e..a07c5fa 100644
--- a/charts/ovn/templates/daemonset-controller.yaml
+++ b/charts/ovn/templates/daemonset-controller.yaml
@@ -50,6 +50,7 @@
 {{- tuple $envAll "ovn_controller" list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
         - name: controller-init
 {{ tuple $envAll "ovn_controller" | include "helm-toolkit.snippets.image" | indent 10 }}
+{{ dict "envAll" $envAll "application" "ovn_controller" "container" "controller_init" | include "helm-toolkit.snippets.kubernetes_container_security_context" | indent 10 }}
           command:
             - /tmp/ovn-controller-init.sh
           volumeMounts:
diff --git a/charts/ovn/templates/statefulset-nb-db.yaml b/charts/ovn/templates/statefulset-nb-db.yaml
deleted file mode 100644
index 78d7b56..0000000
--- a/charts/ovn/templates/statefulset-nb-db.yaml
+++ /dev/null
@@ -1,85 +0,0 @@
-{{/*
-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.
-*/}}
-
-{{- if .Values.manifests.statefulset_ovn_nb_db }}
-{{- $envAll := . }}
-
-{{- $serviceAccountName := "ovn-nb-db" }}
-{{ tuple $envAll "ovn_nb_db" $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
----
-apiVersion: apps/v1
-kind: StatefulSet
-metadata:
-  name: ovn-nb-db
-  annotations:
-    {{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
-  labels:
-{{ tuple $envAll "ovn" "ovn-nb-db" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
-spec:
-  serviceName: {{ tuple "ovn-nb-db" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }}
-  replicas: 1
-  selector:
-    matchLabels:
-{{ tuple $envAll "ovn" "ovn-nb-db" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 6 }}
-  template:
-    metadata:
-      labels:
-{{ tuple $envAll "ovn" "ovn-nb-db" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
-      annotations:
-{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" | indent 8 }}
-    spec:
-      serviceAccountName: {{ $serviceAccountName }}
-      affinity:
-{{- tuple $envAll "ovn" "ovn-nb-db" | include "helm-toolkit.snippets.kubernetes_pod_anti_affinity" | indent 8 }}
-      nodeSelector:
-        {{ .Values.labels.ovn_nb_db.node_selector_key }}: {{ .Values.labels.ovn_nb_db.node_selector_value }}
-      initContainers:
-{{- tuple $envAll "ovn_nb_db" list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
-      containers:
-        - name: ovn-nb-db
-{{ tuple $envAll "ovn_nb_db" | include "helm-toolkit.snippets.image" | indent 10 }}
-          ports:
-            - containerPort: {{ tuple "ovn-nb-db" "internal" "db" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
-          command:
-            - /tmp/start.sh
-            - nb-ovsdb
-{{ tuple $envAll $envAll.Values.pod.resources.server | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
-          volumeMounts:
-            - name: ovn-bin
-              mountPath: /tmp/start.sh
-              subPath: ovn.sh
-              readOnly: true
-            - name: ovn-nb-db-data
-              mountPath: /var/lib/ovn
-      volumes:
-        - name: ovn-bin
-          configMap:
-            name: ovn-bin
-            defaultMode: 0555
-{{- if not .Values.volume.ovn_nb_db.enabled }}
-        - name: ovn-nb-db-data
-          emptyDir: {}
-{{- else }}
-  volumeClaimTemplates:
-    - metadata:
-        name: ovn-nb-db-data
-      spec:
-        accessModes: ["ReadWriteOnce"]
-        resources:
-          requests:
-            storage: {{ $envAll.Values.volume.ovn_nb_db.size }}
-        storageClassName: {{ $envAll.Values.volume.ovn_nb_db.class_name }}
-{{- end }}
-
-{{- end }}
diff --git a/charts/ovn/templates/statefulset-ovsdb-nb.yaml b/charts/ovn/templates/statefulset-ovsdb-nb.yaml
new file mode 100644
index 0000000..bda1ab9
--- /dev/null
+++ b/charts/ovn/templates/statefulset-ovsdb-nb.yaml
@@ -0,0 +1,102 @@
+{{/*
+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.
+*/}}
+
+{{- if .Values.manifests.statefulset_ovn_ovsdb_nb }}
+{{- $envAll := . }}
+
+{{- $serviceAccountName := "ovn-ovsdb-nb" }}
+{{ tuple $envAll "ovn_ovsdb_nb" $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: ovn-ovsdb-nb
+  annotations:
+    {{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
+  labels:
+{{ tuple $envAll "ovn" "ovn-ovsdb-nb" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
+spec:
+  serviceName: {{ tuple "ovn-ovsdb-nb" "direct" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }}
+  replicas: {{ .Values.pod.replicas.ovn_ovsdb_nb }}
+  selector:
+    matchLabels:
+{{ tuple $envAll "ovn" "ovn-ovsdb-nb" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 6 }}
+  template:
+    metadata:
+      labels:
+{{ tuple $envAll "ovn" "ovn-ovsdb-nb" | 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" }}
+    spec:
+      serviceAccountName: {{ $serviceAccountName }}
+      affinity:
+{{- tuple $envAll "ovn" "ovn-ovsdb-nb" | include "helm-toolkit.snippets.kubernetes_pod_anti_affinity" | indent 8 }}
+      nodeSelector:
+        {{ .Values.labels.ovn_ovsdb_nb.node_selector_key }}: {{ .Values.labels.ovn_ovsdb_nb.node_selector_value }}
+      initContainers:
+{{- tuple $envAll "ovn_ovsdb_nb" list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
+      containers:
+        - name: ovsdb
+{{ tuple $envAll "ovn_ovsdb_nb" | include "helm-toolkit.snippets.image" | indent 10 }}
+{{ tuple $envAll $envAll.Values.pod.resources.server | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+          ports:
+            - containerPort: {{ tuple "ovn-ovsdb-nb" "internal" "ovsdb" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
+            - containerPort: {{ tuple "ovn-ovsdb-nb" "internal" "raft" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
+          env:
+            - name: OVS_DATABASE
+              value: nb
+            - name: OVS_PORT
+              value: "{{ tuple "ovn-ovsdb-nb" "internal" "ovsdb" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}"
+          command:
+            - /tmp/ovsdb-server.sh
+            - start
+          lifecycle:
+            preStop:
+              exec:
+                command:
+                  - /tmp/ovsdb-server.sh
+                  - stop
+          volumeMounts:
+            - name: ovn-bin
+              mountPath: /tmp/ovsdb-server.sh
+              subPath: ovsdb-server.sh
+              readOnly: true
+            - name: run-openvswitch
+              mountPath: /run/openvswitch
+            - name: data
+              mountPath: /var/lib/ovn
+      volumes:
+        - name: run-openvswitch
+          emptyDir: {}
+        - name: ovn-bin
+          configMap:
+            name: ovn-bin
+            defaultMode: 0555
+{{- if not .Values.volume.ovn_ovsdb_nb.enabled }}
+        - name: data
+          emptyDir: {}
+{{- else }}
+  volumeClaimTemplates:
+    - metadata:
+        name: data
+      spec:
+        accessModes: ["ReadWriteOnce"]
+        storageClassName: {{ $envAll.Values.volume.ovn_ovsdb_nb.class_name }}
+        resources:
+          requests:
+            storage: {{ $envAll.Values.volume.ovn_ovsdb_nb.size }}
+{{- end }}
+
+{{- end }}
diff --git a/charts/ovn/templates/statefulset-ovsdb-sb.yaml b/charts/ovn/templates/statefulset-ovsdb-sb.yaml
new file mode 100644
index 0000000..3f4c6b9
--- /dev/null
+++ b/charts/ovn/templates/statefulset-ovsdb-sb.yaml
@@ -0,0 +1,102 @@
+{{/*
+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.
+*/}}
+
+{{- if .Values.manifests.statefulset_ovn_ovsdb_sb }}
+{{- $envAll := . }}
+
+{{- $serviceAccountName := "ovn-ovsdb-sb" }}
+{{ tuple $envAll "ovn_ovsdb_sb" $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: ovn-ovsdb-sb
+  annotations:
+    {{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
+  labels:
+{{ tuple $envAll "ovn" "ovn-ovsdb-sb" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
+spec:
+  serviceName: {{ tuple "ovn-ovsdb-sb" "direct" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }}
+  replicas: {{ .Values.pod.replicas.ovn_ovsdb_sb }}
+  selector:
+    matchLabels:
+{{ tuple $envAll "ovn" "ovn-ovsdb-sb" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 6 }}
+  template:
+    metadata:
+      labels:
+{{ tuple $envAll "ovn" "ovn-ovsdb-sb" | 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" }}
+    spec:
+      serviceAccountName: {{ $serviceAccountName }}
+      affinity:
+{{- tuple $envAll "ovn" "ovn-ovsdb-sb" | include "helm-toolkit.snippets.kubernetes_pod_anti_affinity" | indent 8 }}
+      nodeSelector:
+        {{ .Values.labels.ovn_ovsdb_sb.node_selector_key }}: {{ .Values.labels.ovn_ovsdb_sb.node_selector_value }}
+      initContainers:
+{{- tuple $envAll "ovn_ovsdb_sb" list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
+      containers:
+        - name: ovsdb
+{{ tuple $envAll "ovn_ovsdb_sb" | include "helm-toolkit.snippets.image" | indent 10 }}
+{{ tuple $envAll $envAll.Values.pod.resources.server | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+          ports:
+            - containerPort: {{ tuple "ovn-ovsdb-sb" "internal" "ovsdb" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
+            - containerPort: {{ tuple "ovn-ovsdb-sb" "internal" "raft" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
+          env:
+            - name: OVS_DATABASE
+              value: sb
+            - name: OVS_PORT
+              value: "{{ tuple "ovn-ovsdb-sb" "internal" "ovsdb" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}"
+          command:
+            - /tmp/ovsdb-server.sh
+            - start
+          lifecycle:
+            preStop:
+              exec:
+                command:
+                  - /tmp/ovsdb-server.sh
+                  - stop
+          volumeMounts:
+            - name: ovn-bin
+              mountPath: /tmp/ovsdb-server.sh
+              subPath: ovsdb-server.sh
+              readOnly: true
+            - name: run-openvswitch
+              mountPath: /run/openvswitch
+            - name: data
+              mountPath: /var/lib/ovn
+      volumes:
+        - name: run-openvswitch
+          emptyDir: {}
+        - name: ovn-bin
+          configMap:
+            name: ovn-bin
+            defaultMode: 0555
+{{- if not .Values.volume.ovn_ovsdb_sb.enabled }}
+        - name: data
+          emptyDir: {}
+{{- else }}
+  volumeClaimTemplates:
+    - metadata:
+        name: data
+      spec:
+        accessModes: ["ReadWriteOnce"]
+        resources:
+          requests:
+            storage: {{ $envAll.Values.volume.ovn_ovsdb_sb.size }}
+        storageClassName: {{ $envAll.Values.volume.ovn_ovsdb_sb.class_name }}
+{{- end }}
+
+{{- end }}
diff --git a/charts/ovn/templates/statefulset-sb-db.yaml b/charts/ovn/templates/statefulset-sb-db.yaml
deleted file mode 100644
index 37c2ee0..0000000
--- a/charts/ovn/templates/statefulset-sb-db.yaml
+++ /dev/null
@@ -1,85 +0,0 @@
-{{/*
-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.
-*/}}
-
-{{- if .Values.manifests.statefulset_ovn_sb_db }}
-{{- $envAll := . }}
-
-{{- $serviceAccountName := "ovn-sb-db" }}
-{{ tuple $envAll "ovn_sb_db" $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
----
-apiVersion: apps/v1
-kind: StatefulSet
-metadata:
-  name: ovn-sb-db
-  annotations:
-    {{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
-  labels:
-{{ tuple $envAll "ovn" "ovn-sb-db" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
-spec:
-  serviceName: {{ tuple "ovn-sb-db" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }}
-  replicas: 1
-  selector:
-    matchLabels:
-{{ tuple $envAll "ovn" "ovn-sb-db" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 6 }}
-  template:
-    metadata:
-      labels:
-{{ tuple $envAll "ovn" "ovn-sb-db" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
-      annotations:
-{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" | indent 8 }}
-    spec:
-      serviceAccountName: {{ $serviceAccountName }}
-      affinity:
-{{- tuple $envAll "ovn" "ovn-sb-db" | include "helm-toolkit.snippets.kubernetes_pod_anti_affinity" | indent 8 }}
-      nodeSelector:
-        {{ .Values.labels.ovn_sb_db.node_selector_key }}: {{ .Values.labels.ovn_sb_db.node_selector_value }}
-      initContainers:
-{{- tuple $envAll "ovn_sb_db" list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
-      containers:
-        - name: ovn-sb-db
-{{ tuple $envAll "ovn_sb_db" | include "helm-toolkit.snippets.image" | indent 10 }}
-          ports:
-            - containerPort: {{ tuple "ovn-sb-db" "internal" "db" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
-          command:
-            - /tmp/start.sh
-            - sb-ovsdb
-{{ tuple $envAll $envAll.Values.pod.resources.server | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
-          volumeMounts:
-            - name: ovn-bin
-              mountPath: /tmp/start.sh
-              subPath: ovn.sh
-              readOnly: true
-            - name: ovn-sb-db-data
-              mountPath: /var/lib/ovn
-      volumes:
-        - name: ovn-bin
-          configMap:
-            name: ovn-bin
-            defaultMode: 0555
-{{- if not .Values.volume.ovn_sb_db.enabled }}
-        - name: ovn-sb-db-data
-          emptyDir: {}
-{{- else }}
-  volumeClaimTemplates:
-    - metadata:
-        name: ovn-sb-db-data
-      spec:
-        accessModes: ["ReadWriteOnce"]
-        resources:
-          requests:
-            storage: {{ $envAll.Values.volume.ovn_sb_db.size }}
-        storageClassName: {{ $envAll.Values.volume.ovn_sb_db.class_name }}
-{{- end }}
-
-{{- end }}
diff --git a/charts/ovn/values.yaml b/charts/ovn/values.yaml
index 3e3d69d..05408fa 100644
--- a/charts/ovn/values.yaml
+++ b/charts/ovn/values.yaml
@@ -90,6 +90,9 @@
               - SYS_NICE
     ovn_controller:
       container:
+        controller_init:
+          privileged: true
+          runAsUser: 0
         controller:
           capabilities:
             add:
diff --git a/molecule/ceph/group_vars/all/molecule.yml b/molecule/ceph/group_vars/all/molecule.yml
index 23d82d0..1a5f975 100644
--- a/molecule/ceph/group_vars/all/molecule.yml
+++ b/molecule/ceph/group_vars/all/molecule.yml
@@ -76,7 +76,7 @@
 coredns_helm_values:
   replicaCount: 1
 
-ovn_enabled: "{{ lookup('env', 'OVN_ENABLED') | default('false') | bool }}"
+atmosphere_network_backend: "{{ lookup('env', 'OVN_ENABLED') | default('false') | bool | ternary('ovn', 'openvswitch') }}"
 ovn_helm_values:
   conf:
     auto_bridge_add:
diff --git a/molecule/default/group_vars/all/molecule.yml b/molecule/default/group_vars/all/molecule.yml
index 5f2e4c6..f13f895 100644
--- a/molecule/default/group_vars/all/molecule.yml
+++ b/molecule/default/group_vars/all/molecule.yml
@@ -10,7 +10,7 @@
     container_format: bare

     is_public: true

 

-ovn_enabled: "{{ lookup('env', 'OVN_ENABLED') | default('false') | bool }}"

+atmosphere_network_backend: "{{ lookup('env', 'ATMOSPHERE_NETWORK_BACKEND') | default('openvswitch') }}"

 ovn_helm_values:

   conf:

     auto_bridge_add:

diff --git a/playbooks/openstack.yml b/playbooks/openstack.yml
index dbfd943..63bb237 100644
--- a/playbooks/openstack.yml
+++ b/playbooks/openstack.yml
@@ -148,7 +148,6 @@
         - nova
 
     - role: ovn
-      when: ovn_enabled | default(false)
       tags:
         - ovn
 
diff --git a/roles/defaults/defaults/main.yml b/roles/defaults/defaults/main.yml
index ec0988d..841fdb3 100644
--- a/roles/defaults/defaults/main.yml
+++ b/roles/defaults/defaults/main.yml
@@ -18,5 +18,8 @@
 atmosphere_ingress_class_name: atmosphere
 atmosphere_ingress_cluster_issuer: atmosphere
 
+# Network backend
+atmosphere_network_backend: openvswitch
+
 # This is for override values in atmosphere_images
 atmosphere_image_overrides: {}
diff --git a/roles/keepalived/defaults/main.yml b/roles/keepalived/defaults/main.yml
index ac9309e..dd1e135 100644
--- a/roles/keepalived/defaults/main.yml
+++ b/roles/keepalived/defaults/main.yml
@@ -42,3 +42,15 @@
 keepalived_vrid: 51
 
                                                                    # ]]]
+
+keepalived_pod_dependency:
+  openvswitch:
+    - requireSameNode: true
+      labels:
+        application: neutron
+        component: neutron-ovs-agent
+  ovn:
+    - requireSameNode: true
+      labels:
+        application: ovn
+        component: ovn-controller
diff --git a/roles/keepalived/tasks/main.yml b/roles/keepalived/tasks/main.yml
index 50eb9d3..4eff179 100644
--- a/roles/keepalived/tasks/main.yml
+++ b/roles/keepalived/tasks/main.yml
@@ -131,7 +131,7 @@
                           apiVersion: v1
                           fieldPath: metadata.name
                     - name: DEPENDENCY_POD_JSON
-                      value: '[{"labels":{"application":"neutron","component":"neutron-ovs-agent"},"requireSameNode":true}]'
+                      value: "{{ keepalived_pod_dependency[atmosphere_network_backend] | to_json }}"
                 - name: wait-for-ip
                   image: "{{ atmosphere_images['keepalived'] | vexxhost.kubernetes.docker_image('ref') }}"
                   command:
diff --git a/roles/neutron/defaults/main.yml b/roles/neutron/defaults/main.yml
index b82e0b6..c7d21b3 100644
--- a/roles/neutron/defaults/main.yml
+++ b/roles/neutron/defaults/main.yml
@@ -19,9 +19,6 @@
 neutron_helm_release_namespace: openstack
 neutron_helm_values: {}
 
-# OVN support
-neutron_ovn_enabled: "{{ ovn_enabled | default(false) | bool }}"
-
 # List of networks to provision inside OpenStack
 neutron_networks: []
 
diff --git a/roles/neutron/tasks/main.yml b/roles/neutron/tasks/main.yml
index 5853b31..f37f6a5 100644
--- a/roles/neutron/tasks/main.yml
+++ b/roles/neutron/tasks/main.yml
@@ -40,30 +40,10 @@
   ansible.builtin.set_fact:
     _neutron_helm_values: "{{ __neutron_helm_values }}"
 
-- name: Add OVN configuration
-  when: neutron_ovn_enabled | bool
-  block:
-    - name: Retrieve OVN Northbound service IP
-      kubernetes.core.k8s_info:
-        api_version: v1
-        kind: Service
-        name: ovn-ovsdb-nb
-        namespace: "{{ neutron_helm_release_namespace }}"
-      register: neutron_ovn_nb_svc
-      failed_when: neutron_ovn_nb_svc.resources | length == 0
-
-    - name: Retrieve OVN Southbound service IP
-      kubernetes.core.k8s_info:
-        api_version: v1
-        kind: Service
-        name: ovn-ovsdb-sb
-        namespace: "{{ neutron_helm_release_namespace }}"
-      register: neutron_ovn_sb_svc
-      failed_when: neutron_ovn_sb_svc.resources | length == 0
-
-    - name: Append Helm values
-      ansible.builtin.set_fact:
-        _neutron_helm_values: "{{ _neutron_helm_values | combine(__neutron_ovn_helm_values, recursive=True) }}"
+- name: Append Helm values
+  when: atmosphere_network_backend == 'ovn'
+  ansible.builtin.set_fact:
+    _neutron_helm_values: "{{ _neutron_helm_values | combine(__neutron_ovn_helm_values, recursive=True) }}"
 
 - name: Deploy Helm chart
   run_once: true
diff --git a/roles/neutron/vars/main.yml b/roles/neutron/vars/main.yml
index 6352a03..acae3fc 100644
--- a/roles/neutron/vars/main.yml
+++ b/roles/neutron/vars/main.yml
@@ -16,6 +16,9 @@
   endpoints: "{{ openstack_helm_endpoints }}"
   images:
     tags: "{{ atmosphere_images | vexxhost.atmosphere.openstack_helm_image_tags('neutron') }}"
+  network:
+    backend:
+      - "{{ atmosphere_network_backend }}"
   pod:
     replicas:
       server: 3
@@ -67,9 +70,6 @@
     service_ingress_server: false
 
 __neutron_ovn_helm_values:
-  network:
-    backend:
-      - ovn
   conf:
     neutron:
       DEFAULT:
diff --git a/roles/ovn/tasks/main.yml b/roles/ovn/tasks/main.yml
index 307c50e..8c9eb37 100644
--- a/roles/ovn/tasks/main.yml
+++ b/roles/ovn/tasks/main.yml
@@ -14,6 +14,7 @@
 
 - name: Deploy Helm chart
   run_once: true
+  when: atmosphere_network_backend == 'ovn'
   kubernetes.core.helm:
     name: "{{ ovn_helm_release_name }}"
     chart_ref: "{{ ovn_helm_chart_ref }}"
diff --git a/roles/tempest/tasks/main.yml b/roles/tempest/tasks/main.yml
index 3a46f9e..254691a 100644
--- a/roles/tempest/tasks/main.yml
+++ b/roles/tempest/tasks/main.yml
@@ -85,7 +85,7 @@
     chart_ref: "{{ tempest_helm_chart_ref }}"
     release_namespace: "{{ tempest_helm_release_namespace }}"
     kubeconfig: /etc/kubernetes/admin.conf
-    values: "{{ _tempest_helm_values | combine(tempest_helm_values, recursive=True) }}"
+    values: "{{ _tempest_helm_values | combine(_tempest_network_backend_settings[atmosphere_network_backend], recursive=True) | combine(tempest_helm_values, recursive=True) }}"
     wait: true
     wait_timeout: 20m
 
diff --git a/roles/tempest/vars/main.yml b/roles/tempest/vars/main.yml
index c8ab79c..944f021 100644
--- a/roles/tempest/vars/main.yml
+++ b/roles/tempest/vars/main.yml
@@ -63,3 +63,48 @@
       # NOTE(mnaser): Heat uses the catalog and blindly adds a /v3 to the end of
       #               the endpoint.  This is a workaround to make it work.
       default: /v3
+
+_tempest_network_backend_settings:
+  openvswitch: {}
+  ovn:
+    conf:
+      tempest:
+        network-feature-enabled:
+          api_extensions:
+            - default-subnetpools
+            - network-ip-availability
+            - network_availability_zone
+            - auto-allocated-topology
+            - ext-gw-mode
+            - binding
+            - agent
+            - subnet_allocation
+            - tag
+            - external-net
+            - flavors
+            - net-mtu
+            - availability_zone
+            - quotas
+            - l3-ha
+            - provider
+            - multi-provider
+            - address-scope
+            - extraroute
+            - subnet-service-types
+            - standard-attr-timestamp
+            - service-type
+            - l3-flavors
+            - port-security
+            - extra_dhcp_opt
+            - standard-attr-revisions
+            - pagination
+            - sorting
+            - security-group
+            - dhcp_agent_scheduler
+            - router_availability_zone
+            - rbac-policies
+            - standard-attr-description
+            - router
+            - allowed-address-pairs
+            - project-id
+            - dvr