#!/bin/bash -xe

CHASSIS="ovn-chassis-"
CHASSIS1="ovn-chassis-1"
CHASSIS2="ovn-chassis-2"

test -t 1 && USE_TTY="t"

function container_exec() {
    container=$1
    args=$2
    podman exec "-i$USE_TTY" "$container" /bin/bash -c "$args"
}

function create_fake_vm() {
    container=$1
    name=$2
    mac=$3
    bridge=${4:-"br-int"}

    container_exec $container "ovs-vsctl \
          -- add-port $bridge $name \
          -- set interface $name type=internal"

    container_exec $container "ip netns add $name"
    container_exec $container "ip netns exec $name ip link set lo up"

    container_exec $container "ip link set $name netns $name"
    container_exec $container "ip netns exec $name ip link set $name address $mac"
    container_exec $container "ip netns exec $name ip link set $name up"

    if [ "$bridge" == "br-int" ]; then
        container_exec $container "ovs-vsctl set interface $name external_ids:iface-id=$name"
    fi
}

function set_vm_ip() {
    container=$1
    name=$2
    ip=$3
    gw=$4

    container_exec $container "ip netns exec $name ip addr add $ip dev $name"
    container_exec $container "ip netns exec $name ip route add default via $gw dev $name"
}

function ovn_setup_northd() {
    container=$1

    # Cleanup existing one
    container_exec $container "/usr/share/ovn/scripts/ovn-ctl stop_northd"
    container_exec $container "rm -f /etc/ovn/*.db"


    container_exec $container "/usr/share/ovn/scripts/ovn-ctl start_northd"
    container_exec $container "ovn-nbctl set-connection ptcp:6641"
    container_exec $container "ovn-sbctl set-connection ptcp:6642"
}

function ovn_setup_controller() {
    container=$1
    id=$2
    encap_ip=$3
    remote_ip=$4

    # Cleanup existing one
    container_exec $container "/usr/share/openvswitch/scripts/ovs-ctl stop"
    container_exec $container "/usr/share/ovn/scripts/ovn-ctl stop_controller"
    container_exec $container "rm -f /etc/ovn/*.db"

    container_exec $container "/usr/share/openvswitch/scripts/ovs-ctl start --system-id=$id"
    container_exec $container "/usr/share/ovn/scripts/ovn-ctl start_controller"

    container_exec $container "ovs-vsctl set open . external_ids:ovn-encap-ip=$encap_ip"
    container_exec $container "ovs-vsctl set open . external-ids:ovn-encap-type=geneve"
    container_exec $container "ovs-vsctl set open . external-ids:ovn-remote=tcp:$remote_ip:6642"
    container_exec $container "ovs-vsctl set open . external-ids:ovn-openflow-probe-interval=60"
    container_exec $container "ovs-vsctl set open . external-ids:ovn-remote-probe-interval=180000"
    container_exec $container "ovs-vsctl set open . external-ids:ovn-bridge-datapath-type=system"
}

for i in 1 2; do
    ip=$(( 3 + $i ))
    chassis=$CHASSIS$i
    echo $chassis
    container_exec $chassis "ovs-vsctl set open . external_ids:ovn-monitor-all=true"

    ovn_setup_northd $chassis
    ovn_setup_controller $chassis $chassis "170.168.0.$ip" "170.168.0.$ip"

    container_exec $chassis "ovn-nbctl ls-add ls"

    container_exec $chassis "ovn-nbctl lsp-add ls vm10"
    container_exec $chassis "ovn-nbctl lsp-set-addresses vm10 \"00:00:00:00:20:10 192.168.100.10\""

    container_exec $chassis "ovn-nbctl lsp-add ls vm20"
    container_exec $chassis "ovn-nbctl lsp-set-addresses vm20 \"00:00:00:00:20:20 192.168.100.20\""
done


container_exec $CHASSIS1 "ovn-sbctl chassis-add $CHASSIS2 geneve 170.168.0.5"
container_exec $CHASSIS1 "ovn-sbctl set chassis $CHASSIS2 other_config:is-remote=true"

container_exec $CHASSIS2 "ovn-sbctl chassis-add $CHASSIS1 geneve 170.168.0.4"
container_exec $CHASSIS2 "ovn-sbctl set chassis $CHASSIS1 other_config:is-remote=true"

container_exec $CHASSIS1 "ovn-nbctl lsp-set-type vm20 remote"
container_exec $CHASSIS1 "ovn-nbctl lsp-set-options vm10 requested-chassis=$CHASSIS1"
container_exec $CHASSIS1 "ovn-nbctl lsp-set-options vm20 requested-chassis=$CHASSIS2"

container_exec $CHASSIS2 "ovn-nbctl lsp-set-type vm10 remote"
container_exec $CHASSIS2 "ovn-nbctl lsp-set-options vm10 requested-chassis=$CHASSIS1"
container_exec $CHASSIS2 "ovn-nbctl lsp-set-options vm20 requested-chassis=$CHASSIS2"

create_fake_vm $CHASSIS1 vm10 00:00:00:00:20:10
set_vm_ip $CHASSIS1 vm10 192.168.100.10/24 192.168.100.1

create_fake_vm $CHASSIS2 vm10 00:00:00:00:20:10
set_vm_ip $CHASSIS2 vm10 192.168.100.10/24 192.168.100.1

create_fake_vm $CHASSIS2 vm20 00:00:00:00:20:20
set_vm_ip $CHASSIS2 vm20 192.168.100.20/24 192.168.100.1

container_exec $CHASSIS2 "ip netns exec vm20 ping -c5 192.168.100.10"

# Migration
container_exec $CHASSIS1 "ovn-nbctl lsp-set-options vm10 requested-chassis=$CHASSIS1,$CHASSIS2"

container_exec $CHASSIS2 "ovn-nbctl lsp-set-type vm10 \"\""
container_exec $CHASSIS2 "ovn-nbctl lsp-set-options vm10 requested-chassis=$CHASSIS1,$CHASSIS2"

container_exec $CHASSIS2 "ip netns exec vm20 ping -c5 192.168.100.10"

# After migration
container_exec $CHASSIS1 "ovn-nbctl lsp-set-type vm10 remote"
container_exec $CHASSIS1 "ovn-nbctl lsp-set-options vm10 requested-chassis=$CHASSIS2"

container_exec $CHASSIS2 "ovn-nbctl lsp-set-options vm10 requested-chassis=$CHASSIS2"

container_exec $CHASSIS2 "ip netns exec vm20 ping -c5 192.168.100.10"

