#!/bin/bash


# cleanup_opendaylight() - Remove residual data files, anything left over
# from previous runs that a clean run would need to clean up
function cleanup_opendaylight {
    # Wipe out the data and journal directories ... grumble grumble grumble
    rm -rf $ODL_DIR/$ODL_NAME/{data,journal}

    # Remove existing logfiles
    rm -f "/opt/stack/logs/$ODL_KARAF_LOG_BASE*"

    unbind_opendaylight_controller
}


# configure_opendaylight() - Set config files, create data dirs, etc
function configure_opendaylight {
    echo "Configuring OpenDaylight"

    # The logging config file in ODL
    local ODL_LOGGING_CONFIG=${ODL_DIR}/${ODL_NAME}/etc/org.ops4j.pax.logging.cfg

    # Add netvirt feature in Karaf, if it's not already there
    local ODLFEATUREMATCH=$(cat $ODL_DIR/$ODL_NAME/etc/org.apache.karaf.features.cfg | \
                            grep featuresBoot= | grep $ODL_NETVIRT_KARAF_FEATURE)
    if [ "$ODLFEATUREMATCH" == "" ]; then
        sed -i "/^featuresBoot=/ s/$/,$ODL_NETVIRT_KARAF_FEATURE/" \
               $ODL_DIR/$ODL_NAME/etc/org.apache.karaf.features.cfg
    fi

    if [[ "$ODL_RELEASE" =~ "helium" ]]; then
        # Move Tomcat to $ODL_PORT
        local _ODLPORT=$(cat $ODL_DIR/$ODL_NAME/configuration/tomcat-server.xml | \
                         grep $ODL_PORT)
        if [ "$_ODLPORT" == "" ]; then
            sed -i "/\<Connector port/ s/808./$ODL_PORT/" \
                   $ODL_DIR/$ODL_NAME/configuration/tomcat-server.xml
        fi
    else
        # Move Jetty to $ODL_PORT
        local _ODLPORT=$(cat $ODL_DIR/$ODL_NAME/etc/jetty.xml | grep $ODL_PORT)
        if [ "$_ODLPORT" == "" ]; then
            sed -i "/\<Property name\=\"jetty\.port/ s/808./$ODL_PORT/" \
                   $ODL_DIR/$ODL_NAME/etc/jetty.xml
        fi
    fi

    # Configure L3 if the user wants it
    if [ "${ODL_L3}" == "True" ]; then
        # Configure L3 FWD if it's not there
        local L3FWD=$(cat $ODL_DIR/$ODL_NAME/etc/custom.properties | \
                      grep ^ovsdb.l3.fwd.enabled)
        if [ "$L3FWD" == "" ]; then
            echo "ovsdb.l3.fwd.enabled=yes" >> $ODL_DIR/$ODL_NAME/etc/custom.properties
        fi

        # Configure L3 GW MAC if it's not there
        local L3GW_MAC=$(cat $ODL_DIR/$ODL_NAME/etc/custom.properties | \
                         grep ^ovsdb.l3gateway.mac)
        if [[ -z "$L3GW_MAC" && -n "$ODL_L3GW_MAC" ]]; then
            echo "ovsdb.l3gateway.mac=$ODL_L3GW_MAC" >> $ODL_DIR/$ODL_NAME/etc/custom.properties
        fi
    fi

    # Remove existing logfiles
    rm -f "/opt/stack/logs/$ODL_KARAF_LOG_BASE*"
    # Log karaf output to a file
    _LF=/opt/stack/logs/$ODL_KARAF_LOG_NAME
    LF=$(echo $_LF | sed 's/\//\\\//g')
    # Soft link for easy consumption
    ln -sf $_LF "/opt/stack/logs/screen-karaf.txt"

    # Change the karaf logfile
    sed -i "/^log4j\.appender\.out\.file/ s/.*/log4j\.appender\.out\.file\=$LF/" \
    $ODL_DIR/$ODL_NAME/etc/org.ops4j.pax.logging.cfg

    # Configure DEBUG logs for network virtualization in odl, if the user wants it
    if [ "${ODL_NETVIRT_DEBUG_LOGS}" == "True" ]; then
        local OVSDB_DEBUG_LOGS=$(cat $ODL_LOGGING_CONFIG | grep ^log4j.logger.org.opendaylight.ovsdb)
        if [ "${OVSDB_DEBUG_LOGS}" == "" ]; then
            echo 'log4j.logger.org.opendaylight.ovsdb = TRACE, out' >> $ODL_LOGGING_CONFIG
            echo 'log4j.logger.org.opendaylight.ovsdb.lib = INFO, out' >> $ODL_LOGGING_CONFIG
            echo 'log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.impl.NeutronL3Adapter = DEBUG, out' >> $ODL_LOGGING_CONFIG
            echo 'log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.impl.TenantNetworkManagerImpl = DEBUG, out' >> $ODL_LOGGING_CONFIG
            echo 'log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.arp.GatewayMacResolverService = DEBUG, out' >> $ODL_LOGGING_CONFIG
            echo 'log4j.logger.org.opendaylight.ovsdb.plugin.md.OvsdbInventoryManager = INFO, out' >> $ODL_LOGGING_CONFIG
        fi
        if [[ "$ODL_RELEASE" =~ "helium" ]]; then
            local ODL_NEUTRON_DEBUG_LOGS=$(cat $ODL_LOGGING_CONFIG | \
                        grep ^log4j.logger.org.opendaylight.controller.networkconfig.neutron)
            if [ "${ODL_NEUTRON_DEBUG_LOGS}" == "" ]; then
                echo 'log4j.logger.org.opendaylight.controller.networkconfig.neutron = TRACE, out' >> $ODL_LOGGING_CONFIG
            fi
        else
            local ODL_NEUTRON_DEBUG_LOGS=$(cat $ODL_LOGGING_CONFIG | \
                        grep ^log4j.logger.org.opendaylight.neutron)
            if [ "${ODL_NEUTRON_DEBUG_LOGS}" == "" ]; then
                echo 'log4j.logger.org.opendaylight.neutron = TRACE, out' >> $ODL_LOGGING_CONFIG
            fi
        fi
        # Bump up how man logfiles we save after rotation if debug is turned on
        sed -i "/^log4j.appender.out.maxBackupIndex=/ s/10/$ODL_LOGFILES_TO_SAVE/" $ODL_LOGGING_CONFIG
    fi
}

# configure_neutron_opendaylight() - Set Neutron config files according to ODL settings
function configure_neutron_odl {
    echo "Configuring ML2 for OpenDaylight"
    populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_odl url=$ODL_ENDPOINT
    populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_odl username=$ODL_USERNAME
    populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_odl password=$ODL_PASSWORD
}


# init_opendaylight() - Initialize databases, etc.
function init_opendaylight {
    # clean up from previous (possibly aborted) runs
    # create required data files
    :
}


# install_opendaylight() - Collect source and prepare
function install_opendaylight {
    echo "Installing OpenDaylight and dependent packages"

    if is_ubuntu; then
        install_package maven openjdk-7-jre openjdk-7-jdk
    else
        yum_install maven java-1.7.0-openjdk
    fi

    install_opendaylight_neutron_thin_ml2_driver

    # Download OpenDaylight
    cd $ODL_DIR

    if [[ "$OFFLINE" != "True" ]]; then
        wget -N $ODL_URL/$ODL_PKG
    fi
    unzip -u -o $ODL_PKG
}


# install_opendaylight_neutron_thin_ml2_driver() - Install the ML2 driver
function install_opendaylight_neutron_thin_ml2_driver {
    cd $NETWORKING_ODL_DIR
    echo "Installing the Networking-ODL driver for OpenDaylight"
    sudo python setup.py install
}


# install_opendaylight_compute() - Make sure OVS is installed
function install_opendaylight_compute {
    # packages are the same as for Neutron OVS agent
    _neutron_ovs_base_install_agent_packages
}


# start_opendaylight() - Start running processes, including screen
function start_opendaylight {
    echo "Starting OpenDaylight"
    if is_ubuntu; then
        JHOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64
    else
        JHOME=/usr/lib/jvm/java-1.7.0-openjdk
    fi

    # Wipe out the data and journal directories ... grumble grumble grumble
    rm -rf $ODL_DIR/$ODL_NAME/{data,journal}

    # The following variables are needed by the running karaf process.
    # See the "bin/setenv" file in the OpenDaylight distribution for
    # their individual meaning.
    export JAVA_HOME=$JHOME
    export JAVA_MIN_MEM=$ODL_JAVA_MIN_MEM
    export JAVA_MAX_MEM=$ODL_JAVA_MAX_MEM
    export JAVA_MAX_PERM_MEM=$ODL_JAVA_MAX_PERM_MEM
    run_process odl-server "$ODL_DIR/$ODL_NAME/bin/start"

    if [ -n "$ODL_BOOT_WAIT_URL" ]; then
        echo "Waiting for Opendaylight to start via $ODL_BOOT_WAIT_URL ..."
        # Probe ODL restconf for netvirt until it is operational
        local testcmd="curl -o /dev/null --fail --silent --head -u \
              ${ODL_USERNAME}:${ODL_PASSWORD} http://${ODL_MGR_IP}:${ODL_PORT}/${ODL_BOOT_WAIT_URL}"
        test_with_retry "$testcmd" "Opendaylight did not start after $ODL_BOOT_WAIT" \
              $ODL_BOOT_WAIT $ODL_RETRY_SLEEP_INTERVAL
    else
        echo "Waiting for Opendaylight to start ..."
        # Sleep a bit to let OpenDaylight finish starting up
        sleep $ODL_BOOT_WAIT
    fi
}


# stop_opendaylight() - Stop running processes (non-screen)
function stop_opendaylight {
    # Stop the karaf container
    $ODL_DIR/$ODL_NAME/bin/stop
    stop_process odl-server
}


# stop_opendaylight_compute() - Remove OVS bridges
function stop_opendaylight_compute {
    # remove all OVS ports that look like Neutron created ports
    for port in $(sudo ovs-vsctl list port | grep -o -e tap[0-9a-f\-]* -e q[rg]-[0-9a-f\-]*); do
        sudo ovs-vsctl del-port ${port}
    done

    # remove all OVS bridges created by ODL
    for bridge in $(sudo ovs-vsctl list-br | grep -o -e ${OVS_BR} -e ${PUBLIC_BRIDGE}); do
        sudo ovs-vsctl del-br ${bridge}
    done
}


# bind_opendaylight_controller() - set control manager to OVS
function bind_opendaylight_controller {
    echo_summary "Initializing OpenDaylight"
    ODL_LOCAL_IP=${ODL_LOCAL_IP:-$HOST_IP}
    ODL_MGR_PORT=${ODL_MGR_PORT:-6640}
    read ovstbl <<< $(sudo ovs-vsctl get Open_vSwitch . _uuid)
    sudo ovs-vsctl set-manager tcp:$ODL_MGR_IP:$ODL_MGR_PORT
    if [[ -n "$ODL_PROVIDER_MAPPINGS" ]] && [[ "$ENABLE_TENANT_VLANS" == "True" ]]; then
        sudo ovs-vsctl set Open_vSwitch $ovstbl \
            other_config:provider_mappings=$ODL_PROVIDER_MAPPINGS
    fi
    sudo ovs-vsctl set Open_vSwitch $ovstbl other_config:local_ip=$ODL_LOCAL_IP
}


# unbind_opendaylight_controller() - disconnect controller from switch and clear bridges
function unbind_opendaylight_controller {
    sudo ovs-vsctl del-manager
    BRIDGES=$(sudo ovs-vsctl list-br)
    for bridge in $BRIDGES ; do
        sudo ovs-vsctl del-controller $bridge
     done
}


# configure_opendaylight_l3() - configure bridges for OpenDaylight L3 forwarding
function configure_opendaylight_l3 {
    wait_for_active_bridge $PUBLIC_BRIDGE $ODL_RETRY_SLEEP_INTERVAL $ODL_BOOT_WAIT

    # Add public interface to public bridge, if needed
    if [ -n "$PUBLIC_INTERFACE" ]; then
        echo "Adding $PUBLIC_INTERFACE to $PUBLIC_BRIDGE"
        sudo ovs-vsctl --no-wait -- --may-exist add-port $PUBLIC_BRIDGE $PUBLIC_INTERFACE
        sudo ip link set $PUBLIC_INTERFACE up
    fi
}
