#!/bin/bash

# Idempotent script to apply heat configuration to the running network
# environment.
#
# If a public_interface_raw_device is defined in metadata and public_interface
# does not exist, the public_interface is used to derived a vlan id and a vlan
# interface is configured.
#
# If a bootstrap public_interface_ip is defined in metadata and not attached to
# any device then it will be added to the public_interface device if one is
# defined.
#
# An integration bridge for neutron-ovs-agent is created.
#
# If no physical bridge is defined in metadata, the script will have no
# further effect.
#
# If a physical bridge is defined then ensure-bridge is called to set it up.
#
# If there is configuration (tag + IP) for an access port, one is created on
# top of the bridge, again by ensure-bridge.

set -eux

PATH=/usr/local/bin:$PATH

EXTERNAL_BRIDGE=$(os-apply-config --key neutron.ovs.physical_bridge --type raw --key-default '')
PHYSICAL_INTERFACE=$(os-apply-config --key neutron.ovs.public_interface --type raw  --key-default '')
PHYSICAL_INTERFACE_IP=$(os-apply-config --key bootstack.public_interface_ip --type netaddress  --key-default '')
PHYSICAL_INTERFACE_RAW_DEVICE=$(os-apply-config --key neutron.ovs.public_interface_raw_device --type raw --key-default '')
PUBLIC_INTERFACE_ROUTE=$(os-apply-config --key neutron.ovs.public_interface_route --type netaddress --key-default '')
# TAG is type raw because we can't do an absent key as a default in Heat, and '' is not an int.
PUBLIC_INTERFACE_TAG=$(os-apply-config --key neutron.ovs.public_interface_tag --type raw --key-default '')
PUBLIC_INTERFACE_TAG_IP=$(os-apply-config --key neutron.ovs.public_interface_tag_ip --type netaddress --key-default '')
PHYSICAL_ROUTE_PREFIX=$(os-apply-config --key neutron.ovs.physical_bridge_route.prefix --type netaddress --key-default '')
PHYSICAL_ROUTE_VIA=$(os-apply-config --key neutron.ovs.physical_bridge_route.via --type netaddress --key-default '')


if [ -n "$PHYSICAL_INTERFACE_RAW_DEVICE" -a -n "$PUBLIC_INTERFACE_TAG" ]; then
    echo "ERROR: cannot specify a raw device and a tagged access port at the same time." >&2
    exit 1
fi

if [ -n "$PHYSICAL_INTERFACE_RAW_DEVICE" ]; then
    echo "DEPRECATED: please use neutron.ovs.public_interface_ip_tag instead." >&2
    if ! (ip link show dev $PHYSICAL_INTERFACE) ; then
        VLAN_ID=$(echo $PHYSICAL_INTERFACE | sed s/vlan//)
        vconfig set_name_type VLAN_PLUS_VID_NO_PAD
        vconfig add $PHYSICAL_INTERFACE_RAW_DEVICE $VLAN_ID
    fi
    ip link set $PHYSICAL_INTERFACE up
fi

# Hacky: ensure the switch is running : we should instead arrange for this
# script to not be run before it's started.
service openvswitch-switch restart || service openvswitch restart

ovs-vsctl --no-wait -- --may-exist add-br br-int
ovs-vsctl --no-wait br-set-external-id br-int bridge-id br-int

if [ -z "$EXTERNAL_BRIDGE" ] ; then
    exit 0
fi

ensure-bridge "$EXTERNAL_BRIDGE" "$PHYSICAL_INTERFACE" "$PHYSICAL_INTERFACE_IP" \
    "$PUBLIC_INTERFACE_ROUTE" --public-tag "$PUBLIC_INTERFACE_TAG" \
    --public-tag-ip "$PUBLIC_INTERFACE_TAG_IP" \
    ${PHYSICAL_ROUTE_PREFIX:+--bridge-route "${PHYSICAL_ROUTE_PREFIX} ${PHYSICAL_ROUTE_VIA}"}
