apiVersion: v1
data:
  functions: |
    #!/bin//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.

    # Configs are obtained from ENV variables.
    OVNBridge=${OVNBridge:-"br-int"}
    OVNRemote=${OVNRemote:-"tcp:localhost:6642"}
    OVNEncapType=${OVNEncapType:-"geneve"}
    OVNAvailabilityZones=${OVNAvailabilityZones:-""}
    EnableChassisAsGateway=${EnableChassisAsGateway:-true}
    PhysicalNetworks=${PhysicalNetworks:-""}
    OVNHostName=${OVNHostName:-""}
    DB_FILE=/etc/openvswitch/conf.db

    ovs_dir=/var/lib/openvswitch
    FLOWS_RESTORE_SCRIPT=$ovs_dir/flows-script
    FLOWS_RESTORE_DIR=$ovs_dir/saved-flows
    SAFE_TO_STOP_OVSDB_SERVER_SEMAPHORE=$ovs_dir/is_safe_to_stop_ovsdb_server

    function cleanup_ovsdb_server_semaphore() {
        rm -f $SAFE_TO_STOP_OVSDB_SERVER_SEMAPHORE 2>&1 > /dev/null
    }

    function cleanup_flows_backup() {
        rm -f $FLOWS_RESTORE_SCRIPT 2>&1 > /dev/null
        rm -rf $FLOWS_RESTORE_DIR 2>&1 > /dev/null
    }

    function wait_for_ovsdb_server {
        while true; do
            /usr/bin/ovs-vsctl show
            if [ $? -eq 0 ]; then
                break
            else
                echo "ovsdb-server seems not be ready yet. Waiting..."
                sleep 1
            fi
        done
    }

    # configure external-ids in OVS
    function configure_external_ids {
        ovs-vsctl set open . external-ids:ovn-bridge=${OVNBridge}
        ovs-vsctl set open . external-ids:ovn-remote=${OVNRemote}
        ovs-vsctl set open . external-ids:ovn-encap-type=${OVNEncapType}
        if [ -n "$OVNHostName" ]; then
            ovs-vsctl set open . external-ids:hostname=${OVNHostName}
        fi
        local cms_options=""
        if [ "$EnableChassisAsGateway" == "true" ]; then
            cms_options="enable-chassis-as-gw"
        fi
        if [ -n "$OVNAvailabilityZones" ]; then
            cms_options+=",availability-zones="$OVNAvailabilityZones
        fi
        if [ -n "${cms_options}" ]; then
            ovs-vsctl set open . external-ids:ovn-cms-options=${cms_options#,}
        else
            ovs-vsctl --if-exists remove open . external_ids ovn-cms-options
        fi
    }

    # Returns the set difference between $1 and $2
    function set_difference {
        echo "$(comm -23 <(sort <(echo $1 | xargs -n1)) <(sort <(echo $2 | xargs -n1)))"
    }

    # Configure bridge mappings and physical bridges
    function configure_physical_networks {
        local OVNBridgeMappings=""
        local br_new=""
        for physicalNetwork in ${PhysicalNetworks}; do
            br_name="br-${physicalNetwork}"
            bridgeMapping="${physicalNetwork}:${br_name}"
            if [ -z "$OVNBridgeMappings" ]; then
                OVNBridgeMappings=$bridgeMapping
                br_new=$br_name
            else
                OVNBridgeMappings="${OVNBridgeMappings},${bridgeMapping}"
                br_new="${br_new} ${br_name}"
            fi
        done

        # Current configured bridges.
        ovn_bms=$(ovs-vsctl --if-exists get open . external_ids:ovn-bridge-mappings|tr -d '"')
        local br_current=""
        for bm in ${ovn_bms/,/ }; do
            if [ -z "$br_current"]; then
                br_current=${bm##*:}
            else
                br_current="${br_current} ${bm##*:}"
            fi
        done

        # Bridges to add and delete.
        local br_to_delete=""
        local br_to_add=""
        br_to_delete=$(set_difference "$br_current" "$br_new")
        br_to_add=$(set_difference "$br_new" "$br_current")

        # Add the new bridges.
        for br_name in ${br_to_add}; do
            ovs-vsctl --may-exist add-br ${br_name}
            ovs-vsctl --may-exist add-port ${br_name} ${br_name#*-}
        done

        # Delete the old bridges not longer present in "OVNBridgeMappings" and the
        # patch ports in "br-int".
        for br_name in ${br_to_delete}; do
            # List all ports "type=patch", retrieve the "options:peer" parameter
            # and delete the peer port. The "$port" will be deleted during the
            # bridge deletion.
            #   $ ovs-vsctl --column=options --bare find interface name=patch-provnet1-to-br-int type=patch
            #     peer=patch-br-int-to-provnet1

            if ovs-vsctl br-exists ${br_name}; then
                for iface in $(ovs-vsctl list-ifaces ${br_name}); do
                    port_type=$(ovs-vsctl --column=type --bare list interface ${iface})
                    if [ "$port_type" == "patch" ]; then
                        peer=$(ovs-vsctl get interface ${iface} options:peer)
                        ovs-vsctl --if-exists del-port ${OVNBridge} ${peer}
                    fi
                done
                ovs-vsctl --if-exists del-br ${br_name}
            fi
        done

        # Set or remove the local OVS Open vSwitch "external-ids:ovn-bridge-mappings"
        if [ -n "$OVNBridgeMappings" ]; then
            ovs-vsctl set open . external-ids:ovn-bridge-mappings=${OVNBridgeMappings}
        else
            ovs-vsctl --if-exists remove open . external_ids ovn-bridge-mappings
        fi

    }

    function wait_for_db_creation {
        while [ ! -s ${DB_FILE} ]; do
            echo "${DB_FILE} does not exist yet or is empty. Waiting..."
            sleep 1
        done
    }
  init-ovsdb-server.sh: |
    #!/bin/sh
    #
    # Copyright 2023 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
    trap wait_for_db_creation EXIT

    # 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
        rm -f ${DB_FILE}
    fi

    # Compact the Database file if it exists
    if [ -f ${DB_FILE} ]; then
        ovsdb-tool compact ${DB_FILE}
    fi

    # Initialize or upgrade database if needed
    CTL_ARGS="--system-id=random --no-ovs-vswitchd"
    /usr/share/openvswitch/scripts/ovs-ctl start $CTL_ARGS
    /usr/share/openvswitch/scripts/ovs-ctl stop $CTL_ARGS

    wait_for_db_creation
    trap - EXIT
  init.sh: |
    #!/bin//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.

    source $(dirname $0)/functions

    wait_for_ovsdb_server

    # From now on, we should exit immediatelly when any command exits with non-zero status
    set -ex

    configure_external_ids
    configure_physical_networks
  ovn_controller_liveness.sh: |
    #!/bin/bash

    set -e

    error_exit() {
        echo "$1" >&2
        exit 1
    }

    # Check if ovn-controller is running
    check_ovn_controller_pid() {
        if ! pidof -q ovn-controller; then
            error_exit "ERROR - ovn-controller is not running"
        fi
    }

    # Function to check the running status of ovn-controller
    check_ovn_controller_status() {
        # Capture output and check exit status
        if ! output=$(ovn-appctl -t ovn-controller debug/status 2>&1); then
            error_exit "ERROR - Failed to get status from ovn-controller, ovn-appctl exit status: $?"
        fi

        if [ "$output" != "running" ]; then
            error_exit "ERROR - ovn-controller status is '$output', expecting 'running' status"
        fi
    }


    check_ovn_controller_pid
    check_ovn_controller_status
  ovn_controller_readiness.sh: |
    #!/bin/bash

    set -e

    error_exit() {
        echo "$1" >&2
        exit 1
    }

    # Check if ovn-controller is connected to the OVN SB database
    check_ovn_controller_connection() {
        if ! output=$(ovn-appctl -t ovn-controller connection-status 2>&1); then
            error_exit "ERROR - Failed to get connection status from ovn-controller, ovn-appctl exit status: $?"
        fi

        if [ "$output" != "connected" ]; then
            error_exit "ERROR - ovn-controller connection status is '$output', expecting 'connected' status"
        fi
    }


    check_ovn_controller_connection
  ovsdb_server_liveness.sh: |
    #!/bin/bash

    set -e

    error_exit() {
        echo "$1" >&2
        exit 1
    }

    # Check if ovsdb-server is running
    check_ovsdb_server_pid() {
        if ! pidof -q ovsdb-server; then
            error_exit "ERROR - ovsdb-server is not running"
        fi
    }

    # Function to check the running status of ovsdb-server
    check_ovsdb_server_status() {
        if ! /usr/bin/ovs-vsctl show 2>&1; then
            error_exit "ERROR - Failed to get output from ovsdb-server, ovs-vsctl exit status: $?"
        fi
    }


    check_ovsdb_server_pid
    check_ovsdb_server_status
  ovsdb_server_readiness.sh: |
    #!/bin/bash

    set -e

    error_exit() {
        echo "$1" >&2
        exit 1
    }

    # Check ovsdb-server status
    check_ovsdb_server_status() {

        if ! pid=$(cat /var/run/openvswitch/ovsdb-server.pid); then
            error_exit "ERROR - Failed to get pid for ovsdb-server, exit status: $?"
        fi

        if ! output=$(ovs-appctl -t /var/run/openvswitch/ovsdb-server."$pid".ctl ovsdb-server/list-dbs); then
            error_exit "ERROR - Failed retrieving list of databases from ovsdb-server"
        fi

        if [[ "$output" != *"Open_vSwitch"* ]]; then
            error_exit "ERROR - 'Open_vSwitch' not found on databases"
        fi
    }

    check_ovsdb_server_status
  start-ovsdb-server.sh: |
    #!/bin/sh
    #
    # Copyright 2023 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

    # Remove the obsolete semaphore file in case it still exists.
    cleanup_ovsdb_server_semaphore

    # Start the service
    ovsdb-server ${DB_FILE} \
        --pidfile \
        --remote=punix:/var/run/openvswitch/db.sock \
        --private-key=db:Open_vSwitch,SSL,private_key \
        --certificate=db:Open_vSwitch,SSL,certificate \
        --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert
  start-vswitchd.sh: |
    #!/bin/sh
    #
    # 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.

    source $(dirname $0)/functions
    wait_for_ovsdb_server

    # The order - first wait for db server, then set -ex - is important. Otherwise,
    # wait_for_ovsdb_server interrim check would make the script exit.
    set -ex

    # Configure encap IP.
    OVNEncapIP=$(ip -o addr show dev tenant scope global | awk '{print $4}' | cut -d/ -f1)
    ovs-vsctl --no-wait set open . external-ids:ovn-encap-ip=${OVNEncapIP}

    # Before starting vswitchd, block it from flushing existing datapath flows.
    ovs-vsctl --no-wait set open_vswitch . other_config:flow-restore-wait=true

    # It's safe to start vswitchd now. Do it.
    # --detach to allow the execution to continue to restoring the flows.
    # We need to use --log-file since --detach disables all logging explicitly.
    # Once https://issues.redhat.com/browse/FDP-1292 is fixed we will be able to
    # use system logs only.
    /usr/sbin/ovs-vswitchd --pidfile --mlockall --detach --log-file

    # Restore saved flows.
    if [ -f $FLOWS_RESTORE_SCRIPT ]; then
        # It's unsafe to leave these files in place if they fail once. Make sure we
        # remove them if the eval fails.
        trap cleanup_flows_backup EXIT
        eval "$(cat $FLOWS_RESTORE_SCRIPT)"
        trap - EXIT
    fi

    # It's also unsafe to leave these files after flow-restore-wait flag is removed
    # because the backup will become stale and if a container later crashes, it may
    # mistakenly try to restore from this old backup.
    cleanup_flows_backup

    # Now, inform vswitchd that we are done.
    ovs-vsctl remove open_vswitch . other_config flow-restore-wait

    # This is container command script. Block it from exiting, otherwise k8s will
    # restart the container again.
    tail -f /var/log/openvswitch/ovs-vswitchd.log
  stop-ovsdb-server.sh: |
    #!/bin/sh
    #
    # 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.

    set -ex
    source $(dirname $0)/functions

    # The ovs_vswitchd container has to terminate before ovsdb-server because it
    # needs access to db in its preStop script. The preStop script backs up flows
    # for restoration during the next startup. This semaphore ensures the vswitchd
    # container is not torn down before flows are saved.
    while [ ! -f $SAFE_TO_STOP_OVSDB_SERVER_SEMAPHORE ]; do
        sleep 0.5
    done
    cleanup_ovsdb_server_semaphore

    # Now it's safe to stop db server. Do it.
    /usr/share/openvswitch/scripts/ovs-ctl stop --no-ovs-vswitchd
  stop-vswitchd.sh: |
    #!/bin/sh
    #
    # 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.

    set -ex
    source $(dirname $0)/functions

    # Clean up any previously created flow backups to avoid conflict with newly
    # generated backup.
    cleanup_flows_backup

    # Passing --real to mimic what upstream startup scripts do; maybe redundant.
    bridges=$(ovs-vsctl -- --real list-br)

    # Saving flows to avoid disrupting gateway datapath.
    mkdir $FLOWS_RESTORE_DIR
    TMPDIR=$FLOWS_RESTORE_DIR /usr/share/openvswitch/scripts/ovs-save save-flows $bridges > $FLOWS_RESTORE_SCRIPT

    # Once save-flows logic is complete it no longer needs ovsdb-server, this file
    # unlocks the db preStop script, working as a semaphore
    touch $SAFE_TO_STOP_OVSDB_SERVER_SEMAPHORE

    # Finally, stop vswitchd.
    /usr/share/openvswitch/scripts/ovs-ctl stop --no-ovsdb-server
  vswitchd_liveness.sh: |
    #!/bin/bash

    set -e

    error_exit() {
        echo "$1" >&2
        exit 1
    }

    # Check if ovs-vswitchd is running
    check_ovs_vswitchd_pid() {
        if ! pidof -q ovs-vswitchd; then
            error_exit "ERROR - ovs-vswitchd is not running"
        fi
    }

    # Function to check the running status of ovs-vswitchd
    check_ovs_vswitchd_status() {
        if ! /usr/bin/ovs-appctl bond/show 2>&1; then
            error_exit "ERROR - Failed to get output from ovs-vswitchd, ovs-appctl exit status: $?"
        fi
    }


    check_ovs_vswitchd_pid
    check_ovs_vswitchd_status
  vswitchd_readiness.sh: |
    #!/bin/bash

    set -e

    error_exit() {
        echo "$1" >&2
        exit 1
    }

    # Check ovs-vswitchd status
    check_ovs_vswitchd_status() {

        if ! pid=$(cat /var/run/openvswitch/ovs-vswitchd.pid); then
            error_exit "ERROR - Failed to get pid for ovs-vswitchd, exit status: $?"
        fi

        if ! output=$(ovs-appctl -t /var/run/openvswitch/ovs-vswitchd."$pid".ctl ofproto/list); then
            error_exit "ERROR - Failed retrieving ofproto/list from ovs-vswitchd"
        fi

        if [ -z "$output" ]; then
            error_exit "ERROR - No bridges on ofproto/list output"
        fi
    }

    check_ovs_vswitchd_status
kind: ConfigMap
metadata:
  creationTimestamp: '2026-04-04T02:20:06Z'
  labels:
    ovn-controller.openstack.org/name: ovncontroller
    ovn-controller.openstack.org/namespace: openstack
    ovn-controller.openstack.org/uid: 5a20e094-b6ab-45ac-b57a-3bc1e9ad81d6
  name: ovncontroller-scripts
  namespace: openstack
  ownerReferences:
  - apiVersion: ovn.openstack.org/v1beta1
    blockOwnerDeletion: true
    controller: true
    kind: OVNController
    name: ovncontroller
    uid: 5a20e094-b6ab-45ac-b57a-3bc1e9ad81d6
  resourceVersion: '43217'
  uid: c3624828-64e7-4b5e-855c-b38fd17b4187
