apiVersion: v1
data:
  cleanup.sh: |
    #!/usr/bin/env bash
    #
    # Copyright 2022 Red Hat Inc.
    #
    # 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 -ex
    source $(dirname $0)/functions

    DB_NAME="OVN_Northbound"
    if [[ "${DB_TYPE}" == "sb" ]]; then
        DB_NAME="OVN_Southbound"
    fi

    # There is nothing special about -0 pod, except that it's always guaranteed to
    # exist, assuming any replicas are ordered.
    if [[ "$(hostname)" != "ovsdbserver-nb-0" ]]; then
        ovs-appctl -t /tmp/ovn${DB_TYPE}_db.ctl cluster/leave ${DB_NAME}

        # wait for when the leader confirms we left the cluster
        while true; do
            # TODO: is there a better way to detect the cluster left state?..
            STATUS=$(ovs-appctl -t /tmp/ovn${DB_TYPE}_db.ctl cluster/status ${DB_NAME} | grep Status: | awk -e '{print $2}')
            if [ -z "$STATUS" -o "x$STATUS" = "xleft cluster" ]; then
                break
            fi
            sleep 1
        done
    fi

    # If replicas are 0 and *all* pods are removed, we still want to retain the
    # database with its cid/sid for when the cluster is scaled back to > 0, so
    # leaving the database file intact for -0 pod.
    if [[ "$(hostname)" != "ovsdbserver-nb-0" ]]; then
        # now that we left, the database file is no longer valid
        cleanup_db_file
    fi

    # Stop the DB server gracefully; this will also end the pod running script.
    # By executing the stop command in the background, we guarantee to exit
    # this script and not fail with "FailedPreStopHook", while the database is
    # stopped.
    /usr/share/ovn/scripts/ovn-ctl stop_${DB_TYPE}_ovsdb &
  functions: |
    # Copyright 2024 Red Hat Inc.
    #
    # 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.

    DB_TYPE="nb"
    DB_FILE=/etc/ovn/ovn${DB_TYPE}_db.db

    function cleanup_db_file() {
        rm -f $DB_FILE
    }

    function wait_for_ovsdb_tool {
        while pgrep -a ovsdb-tool; do
            echo "ovsdb-tool still working. Waiting..."
            sleep 1
        done
    }
  setup.sh: |
    #!/usr/bin/env bash
    #
    # Copyright 2022 Red Hat Inc.
    #
    # 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 -ex
    source $(dirname $0)/functions

    DB_PORT="6641"
    DB_SCHEME="pssl"
    RAFT_PORT="6643"
    NAMESPACE="openstack"
    OPTS=""
    DB_NAME="OVN_Northbound"
    if [[ "${DB_TYPE}" == "sb" ]]; then
        DB_NAME="OVN_Southbound"
    fi

    # [::] Works for both IPv4 and IPv6
    DB_ADDR="[::]"

    # The --cluster-remote-addr / --cluster-local-addr options will have effect
    # only on bootstrap, when we assume the leadership role for the first pod.
    # Later, cli arguments are still passed, but raft membership hints are already
    # stored in the databases, and hence the arguments are of no effect.
    if [[ "$(hostname)" != "ovsdbserver-nb-0" ]]; then
        #ovsdb-tool join-cluster /etc/ovn/ovn${DB_TYPE}_db.db ${DB_NAME} tcp:$(hostname).ovsdbserver-nb.${NAMESPACE}.svc.cluster.local:${RAFT_PORT} tcp:ovsdbserver-nb-0.ovsdbserver-nb.${NAMESPACE}.svc.cluster.local:${RAFT_PORT}
        OPTS="--db-${DB_TYPE}-cluster-remote-addr=ovsdbserver-nb-0.ovsdbserver-nb.${NAMESPACE}.svc.cluster.local --db-${DB_TYPE}-cluster-remote-port=${RAFT_PORT}"
    fi


    # call to ovn-ctl directly instead of start-${DB_TYPE}-db-server to pass
    # extra_args after --
    set /usr/share/ovn/scripts/ovn-ctl --no-monitor

    set "$@" --db-${DB_TYPE}-election-timer=10000
    set "$@" --db-${DB_TYPE}-cluster-local-addr=$(hostname).ovsdbserver-nb.${NAMESPACE}.svc.cluster.local
    set "$@" --db-${DB_TYPE}-cluster-local-port=${RAFT_PORT}
    set "$@" --db-${DB_TYPE}-probe-interval-to-active=60000
    set "$@" --db-${DB_TYPE}-addr=${DB_ADDR}
    set "$@" --db-${DB_TYPE}-port=${DB_PORT}
    set "$@" --ovn-${DB_TYPE}-db-ssl-key=/etc/pki/tls/private/ovndb.key
    set "$@" --ovn-${DB_TYPE}-db-ssl-cert=/etc/pki/tls/certs/ovndb.crt
    set "$@" --ovn-${DB_TYPE}-db-ssl-ca-cert=/etc/pki/tls/certs/ovndbca.crt
    set "$@" --db-${DB_TYPE}-cluster-local-proto=ssl
    set "$@" --db-${DB_TYPE}-cluster-remote-proto=ssl
    set "$@" --db-${DB_TYPE}-create-insecure-remote=no

    # log to console
    set "$@" --ovn-${DB_TYPE}-log=-vconsole:info

    # if server attempts to log to file, ignore
    #
    # note: even with -vfile:off (see below), the server sometimes attempts to
    # create a log file -> this argument makes sure it doesn't polute OVN_LOGDIR
    # with a nearly empty log file
    set "$@" --ovn-${DB_TYPE}-logfile=/dev/null

    # If db file is empty, remove it; otherwise service won't start.
    # See https://issues.redhat.com/browse/FDP-689 for more details.
    if ! [ -s $DB_FILE ]; then
        cleanup_db_file
    fi

    # Must remove a cluster member to change protocol, replicas 1/2 will have
    # left the cluster when terminating the pod, but cannot remove final member from
    # a cluster (replica 0).
    # Convert db to standalone mode on this member instead.
    # Cluster then gets recreated by ovnctl run_*b_ovsdb using the new local address.
    if [ "$(hostname)" == "ovsdbserver-nb-0" ]; then
        DB_LOCAL_ADDR=ssl:$(hostname).ovsdbserver-nb.${NAMESPACE}.svc.cluster.local:${RAFT_PORT}
        if [ -e ${DB_FILE} ] && \
           ovsdb-tool db-is-clustered ${DB_FILE} && \
           ACTUAL_DB_LOCAL_ADDR="$(ovsdb-tool db-local-address ${DB_FILE})" && \
           [ "${ACTUAL_DB_LOCAL_ADDR}" != "${DB_LOCAL_ADDR}" ] \
           ; \
        then
            rm -f "${DB_FILE%.db}_standalone.db"
            if ovsdb-tool cluster-to-standalone "${DB_FILE%.db}_standalone.db" "${DB_FILE}"; then
                mv -f "${DB_FILE%.db}_standalone.db" "${DB_FILE}"
            fi
        fi
    fi

    # Wait until the ovsdb-tool finishes.
    trap wait_for_ovsdb_tool EXIT

    # don't log to file (we already log to console)
    $@ ${OPTS} run_${DB_TYPE}_ovsdb -- -vfile:off &

    # Once the database is running, we will attempt to configure db options
    CTLCMD="ovn-${DB_TYPE}ctl --no-leader-only"

    # Nothing special about the first pod, we just know that it always exists with
    # replicas > 0 and use it for configuration. In theory, this could be executed
    # in any other pod.
    if [[ "$(hostname)" == "ovsdbserver-nb-0" ]]; then
        # The command will wait until the daemon is connected and the DB is available
        # All following ctl invocation will use the local DB replica in the daemon
        export OVN_${DB_TYPE^^}_DAEMON=$(${CTLCMD} --pidfile --detach)
        ${CTLCMD} set-ssl /etc/pki/tls/private/ovndb.key /etc/pki/tls/certs/ovndb.crt /etc/pki/tls/certs/ovndbca.crt
        ${CTLCMD} set-connection ${DB_SCHEME}:${DB_PORT}:${DB_ADDR}

        # OVN does not support setting inactivity-probe through --remote cli arg so
        # we have to set it after database is up.
        #
        # In theory, ovsdb.local-config(5) could be used to configure inactivity
        # probe using a local ovsdb-server. But the future of this database is
        # unclear, and it was largely abandoned by the community in mid-flight, so
        # no tools exist to configure connections using this database. It may even
        # be that this scheme will be abandoned in the future, because its features
        # are covered by ovs text config file support added in latest ovs releases.
        #
        # TODO: Consider migrating inactivity probe setting  to config files when
        # we update to ovs 3.3. See --config-file in ovsdb-server(1) for more
        # details.
        while [ "$(${CTLCMD} get connection . inactivity_probe)" != "60000" ]; do
            ${CTLCMD} --inactivity-probe=60000 set-connection ${DB_SCHEME}:${DB_PORT}:${DB_ADDR}
        done
        ${CTLCMD} list connection

        # The daemon is no longer needed, kill it
        kill $(cat $OVN_RUNDIR/ovn-${DB_TYPE}ctl.pid)
        unset OVN_${DB_TYPE^^}_DAEMON
    fi

    wait_for_ovsdb_tool
    trap - EXIT

    wait
kind: ConfigMap
metadata:
  creationTimestamp: '2026-04-04T02:20:06Z'
  labels:
    ovsdbserver-nb.openstack.org/name: ovndbcluster-nb
    ovsdbserver-nb.openstack.org/namespace: openstack
    ovsdbserver-nb.openstack.org/uid: c58ec8dd-deaf-4f0c-bbeb-ed7060102128
  name: ovndbcluster-nb-scripts
  namespace: openstack
  ownerReferences:
  - apiVersion: ovn.openstack.org/v1beta1
    blockOwnerDeletion: true
    controller: true
    kind: OVNDBCluster
    name: ovndbcluster-nb
    uid: c58ec8dd-deaf-4f0c-bbeb-ed7060102128
  resourceVersion: '43262'
  uid: 6c05f790-139c-4c49-95ae-0222991ce59e
