#!/bin/bash
#
# functions - OpenDaylight driver utility functions

function _odl_nexus_path {
    local ODL_URL_PREFIX=$1
    echo "${NEXUSPATH:-${ODL_URL_PREFIX}/${ODL_URL_SNAPSHOT_REPOSITORY_PATH}/${ODL_URL_DISTRIBUTION_KARAF_PATH}}"
}

function _wget {
    local MAVENMETAFILE=$1
    local URL=$2
    local $OFFLINE=$3
    local ALLOW_MISSING=${4:-False}

    if [[ "$OFFLINE" == "True" ]]; then
        if [[ ! -r $MAVENMETAFILE && "$ALLOW_MISSING" != "True" ]]; then
            echo "$MAVENMETAFILE doesn't exist. Please try with OFFLINE=False to download $URL"
            exit 1
        fi
        return
    fi

    # Remove stale MAVENMETAFILE for cases where you switch releases
    rm -f $MAVENMETAFILE

    # Acquire the timestamp information from maven-metadata.xml
    wget -O $MAVENMETAFILE $URL
    if [[ ! -r $MAVENMETAFILE && "$ALLOW_MISSING" != "True" ]]; then
        echo "can't download $URL. Please check intenet connection, site availability or directory permision to create file $MAVENMETAFILE"
        exit 1
    fi
}

function _xpath {
    local XPATH=$1
    local MAVENMETAFILE=$2
    local result=""
    if is_ubuntu; then
        result=`xpath -e "$XPATH" $MAVENMETAFILE 2>/dev/null`
    elif [ "$os_VENDOR" = "Fedora" ]; then
        result=`xpath -e "$XPATH" $MAVENMETAFILE 2>/dev/null`
    else
        result=`xpath $MAVENMETAFILE "$XPATH" 2>/dev/null`
    fi
    if [[ -z "$result" ]]; then
        echo "xpath can't find matching xpath $XPATH" 1>&2
        cat $MAVENMETAFILE 1>&2
        exit 1
    fi
    echo $result
}

function odl_artifact_id {
    local ODL_DIR=$1
    local ODL_URL_PREFIX=$2
    local BUNDLEVERSION=$3
    local OFFLINE=$4

    local MAVENMETAFILE=$ODL_DIR/maven-metadata-artifact-id.xml
    local _NEXUSPATH
    _NEXUSPATH=$(_odl_nexus_path $ODL_URL_PREFIX)
    _wget $MAVENMETAFILE ${_NEXUSPATH}/${BUNDLEVERSION}/maven-metadata.xml $OFFLINE True
    if [[ -f "$MAVENMETAFILE" ]]; then
        # In auto release case, metadata file exists only in parent directly.
        # e.g. https://nexus.opendaylight.org/content/repositories/autorelease-1929/org/opendaylight/integration/distribution-karaf/maven-metadata.xml
        _wget $MAVENMETAFILE ${_NEXUSPATH}/maven-metadata.xml $OFFLINE
    fi
    local result
    result=$(_xpath "//artifactId/text()" $MAVENMETAFILE)
    echo $result
}

# get snapshot version <major>.<minor> -> <major>.<minor>.<reivision>
function odl_snapshot_full_version {
    local ODL_DIR=$1
    local ODL_URL_PREFIX=$2
    local MAJOR_MINOR=$3
    local OFFLINE=$4

    local MAVENMETAFILE=$ODL_DIR/maven-metadata-snapshot.xml
    local _NEXUSPATH
    _NEXUSPATH=$(_odl_nexus_path $ODL_URL_PREFIX)
    _wget $MAVENMETAFILE ${_NEXUSPATH}/maven-metadata.xml $OFFLINE

    if [[ "$MAJOR_MINOR" == "latest" ]]; then
        local ODL_FULL_VERSION
        ODL_FULL_VERSION=$(_xpath "//latest/text()" $MAVENMETAFILE)
    else
        local ODL_FULL_VERSION
        ODL_FULL_VERSION=$(_xpath "//version[starts-with(text(), '$MAJOR_MINOR')][last()]/text()" $MAVENMETAFILE)
    fi
    ODL_FULL_VERSION=${ODL_FULL_VERSION/-SNAPSHOT/}
    echo $ODL_FULL_VERSION
}

function _odl_export_snapshot_url_pkg {
    local ODL_DIR=$1
    local ODL_URL_PREFIX=$2
    local BUNDLEVERSION=$3
    local OFFLINE=$4
    local BUNDLE_TIMESTAMP=$5

    local MAVENMETAFILE=$ODL_DIR/maven-metadata.xml
    local _NEXUSPATH
    _NEXUSPATH=$(_odl_nexus_path $ODL_URL_PREFIX)

    if [ "$BUNDLE_TIMESTAMP" == "latest" ]; then
        # Get build information
        _wget $MAVENMETAFILE ${_NEXUSPATH}/${BUNDLEVERSION}/maven-metadata.xml $OFFLINE
        BUNDLE_TIMESTAMP=$(_xpath "//snapshotVersion[extension='zip'][1]/value/text()" $MAVENMETAFILE)
    fi

    export ODL_URL=${_NEXUSPATH}/${BUNDLEVERSION}
    export ODL_PKG=${ODL_ARTIFACT_ID}-${BUNDLE_TIMESTAMP}.zip
}

# get release bundle version <Name> -> <major>.<minor>.<reivision>-<Name>[-SR<N>]
function odl_release_bundleversion {
    local ODL_DIR=$1
    local ODL_URL_PREFIX=$2
    local RELEASE_NAME=$3
    local OFFLINE=$4

    local MAVENMETAFILE=$ODL_DIR/maven-metadata-release.xml
    local _NEXUSPATH
    local _NEXUSPATH="${NEXUSPATH:-${ODL_URL_PREFIX}/${ODL_URL_RELEASE_REPOSITORY_PATH}/${ODL_URL_DISTRIBUTION_KARAF_PATH}}"

    _wget $MAVENMETAFILE ${_NEXUSPATH}/maven-metadata.xml $OFFLINE
    local _ODL_BUNDLEVERSION
    if [[ "$RELEASE_NAME" == "latest" ]]; then
        _ODL_BUNDLEVERSION=$(_xpath "//release/text()" $MAVENMETAFILE)
    else
        # until carbon, karaf is named as <major>.<minor>.<revision>-<name>
        # from Nitrogen, it's named as <major>.<minor>.<revision>
        local _ODL_MAJOR_MINOR=${ODL_NAME_TO_MAJOR_MINOR["$RELEASE_NAME"]}
        _ODL_BUNDLEVERSION=$(_xpath "//version[starts-with(text(), '$_ODL_MAJOR_MINOR')][last()]/text()" $MAVENMETAFILE)
    fi
    echo $_ODL_BUNDLEVERSION
}

function _odl_export_release_url_pkg {
    local ODL_URL_PREFIX=$1
    local BUNDLEVERSION=$2
    local _NEXUSPATH="${NEXUSPATH:-${ODL_URL_PREFIX}/${ODL_URL_RELEASE_REPOSITORY_PATH}/${ODL_URL_DISTRIBUTION_KARAF_PATH}}"

    export ODL_URL=${_NEXUSPATH}/${BUNDLEVERSION}
    export ODL_PKG=${ODL_ARTIFACT_ID}-${BUNDLEVERSION}.zip
}

function setup_opendaylight_package {
    if [[ -n "$ODL_SNAPSHOT_VERSION" ]]; then
        _odl_export_snapshot_url_pkg ${ODL_DIR} ${ODL_URL_PREFIX} ${ODL_BUNDLEVERSION} ${OFFLINE} ${ODL_SNAPSHOT_VERSION}
    else
        _odl_export_release_url_pkg ${ODL_URL_PREFIX} ${ODL_BUNDLEVERSION}
    fi
}

# Test if OpenDaylight is enabled
function is_opendaylight_enabled {
    [[ ,${ENABLED_SERVICES} =~ ,"odl-" ]] && return 0
    return 1
}


# Check that the bridge is up and running
function wait_for_active_bridge {
    local BRIDGE=$1
    local SLEEP_INTERVAL=$2
    local MAX_WAIT=$3

    echo "Waiting for bridge $BRIDGE to be available..."
    local testcmd="sudo ovs-vsctl list Bridge | grep $BRIDGE"
    test_with_retry "$testcmd" \
        "$BRIDGE did not become available in $MAX_WAIT seconds." \
        $MAX_WAIT $SLEEP_INTERVAL
    echo "Bridge $BRIDGE is available."
}

# Move the public IP addresses to the OVS bridge on startup,
# or back to the public interface on cleanup
function move_interface_addresses {
    local direction=$1

    if [[ -n "$ODL_PROVIDER_MAPPINGS" ]]; then
        local VETH_INTERFACE
        VETH_INTERFACE=$(echo $ODL_PROVIDER_MAPPINGS | cut -d ':' -f1)
        local PHYSICAL_INTERFACE
        PHYSICAL_INTERFACE=$(echo $ODL_PROVIDER_MAPPINGS | cut -d ':' -f2)

        if [[ "$direction" == "into_bridge" ]]; then
            _move_neutron_addresses_route "$PHYSICAL_INTERFACE" "$VETH_INTERFACE" True False "inet"
            if _has_public_ipv6_address "$PHYSICAL_INTERFACE"; then
                _move_neutron_addresses_route "$PHYSICAL_INTERFACE" "$VETH_INTERFACE" False False "inet6"
            fi
        elif [[ "$direction" == "outof_bridge" ]]; then
            _move_neutron_addresses_route "$VETH_INTERFACE" "$PHYSICAL_INTERFACE" False True "inet"
            if _has_public_ipv6_address "$VETH_INTERFACE"; then
                _move_neutron_addresses_route "$VETH_INTERFACE" "$PHYSICAL_INTERFACE" False False "inet6"
            fi
        fi
    fi
}

# Check that the interface has an IP v6 address which
# is routable on external network
function _has_public_ipv6_address {
    local interface=$1
    local interface_public_ipv6_addresses
    interface_public_ipv6_addresses=$(ip -f inet6 a s dev "$interface" | grep -c 'global')
    echo "$interface public IPv6 address count: $interface_public_ipv6_addresses"
    if [[ "$interface_public_ipv6_addresses" != 0 ]]; then
        return 0
    else
        return 1
    fi
}


# NOTE(manjeets) br-ex is not up when neutron initial networks are created so this workaround
# is done to bring up the br-ex.
# TODO delete this workaround once br-ex bringup is fixed.
function purge_and_recreate_initial_networks {
    DEVSTACK_DIR=$1
    if [ -z "$DEVSTACK_DIR" ]; then
        echo "Please specify devstack directory"
        exit 1
    fi

    cat <<EOF >> $DEVSTACK_DIR/local.sh
#!/usr/bin/env bash
sudo ifconfig br-ex 172.24.5.1/24 up
source $DEVSTACK_DIR/openrc admin
openstack router unset --external-gateway router1
openstack port list --router router1 -c ID -f value | xargs -I {} openstack router remove port router1 {}
openstack router delete router1
openstack subnet list | grep -e public -e private | cut -f2 -d'|' | xargs openstack subnet delete
openstack network list | grep -e public -e private | cut -f2 -d'|' | xargs openstack network delete
openstack network create public --external --provider-network-type=flat --provider-physical-network=public
openstack subnet create --network=public --subnet-range=172.24.5.0/24 --gateway 172.24.5.1 public-subnet
EOF
    chmod 755 $DEVSTACK_DIR/local.sh
}


function populate_odl_ml2_config {
    section=$1
    param=$2
    value=$3
    if is_neutron_legacy_enabled; then
        populate_ml2_config /$Q_PLUGIN_CONF_FILE $section $param=$value
    else
        iniset $NEUTRON_CORE_PLUGIN_CONF $section $param $value
    fi
}


function neutron_plugin_create_nova_conf {
    :
}
