#!/bin/bash


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

    # Remove existing logfiles
    rm -f "/opt/stack/logs/$ONOS_KARAF_LOG_BASE*"
    unbind_onos_controller
}


# configure_onos() - Set config files, create data dirs, etc
function configure_onos {
    echo "Configuring ONOS"
    # The logging config file in ONOS
    local ONOS_LOGGING_CONFIG=${ONOS_DIR}/${ONOS_NAME}/${ONOS_KARAF_DIR}/etc/org.ops4j.pax.logging.cfg

    # Move Jetty to $ONOS_PORT
    if [[ ! -f "$ONOS_DIR/$ONOS_NAME/${ONOS_KARAF_DIR}/etc/jetty.xml" ]]; then
        cp $NETWORKING_ONOS_DIR/devstack/onos-releases/$ONOS_RELEASE-jetty.xml \
        $ONOS_DIR/$ONOS_NAME/${ONOS_KARAF_DIR}/etc/jetty.xml
    fi
    local _ONOSPORT=$(cat $ONOS_DIR/$ONOS_NAME/${ONOS_KARAF_DIR}/etc/jetty.xml | grep $ONOS_PORT)
    if [ "$_ONOSPORT" == "" ]; then
        sed -i "/\<Property name\=\"jetty\.port/ s/8.../$ONOS_PORT/" \
               $ONOS_DIR/$ONOS_NAME/${ONOS_KARAF_DIR}/etc/jetty.xml
    fi

    # Remove existing logfiles
    rm -f "/opt/stack/logs/$ONOS_KARAF_LOG_BASE*"
    # Log karaf output to a file
    _LF=/opt/stack/logs/$ONOS_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/" \
    $ONOS_DIR/$ONOS_NAME/${ONOS_KARAF_DIR}/etc/org.ops4j.pax.logging.cfg

    # Configure DEBUG logs for network virtualization in onos, if the user wants it
    if [ "${ONOS_VTN_DEBUG_LOGS}" == "True" ]; then
        sed -i "/^log4j\.rootLogger\=/ s/INFO/DEBUG/" \
            $ONOS_DIR/$ONOS_NAME/${ONOS_KARAF_DIR}/etc/org.ops4j.pax.logging.cfg
    fi
    if [[ "$ONOS_EXTERNAL_VETH" == "True" ]]; then
        sudo ip link add ${ONOS_EXTERNAL_NIC} type veth peer name ${ONOS_EXTERNAL_NIC}out
    fi
}

# configure_neutron_onos() - Set Neutron config files according to ONOS settings
function configure_neutron_onos {
    echo "Configuring ML2 for ONOS"
    populate_ml2_config /$Q_PLUGIN_CONF_FILE onos url_path=$ONOS_ENDPOINT
    populate_ml2_config /$Q_PLUGIN_CONF_FILE onos username=$ONOS_USERNAME
    populate_ml2_config /$Q_PLUGIN_CONF_FILE onos password=$ONOS_PASSWORD
}


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


# install_onos() - Collect source and prepare
function install_onos {
    echo "Installing ONOS and dependent packages"
    if [[ "$ONOS_USING_EXISTING_JAVA" != "True" ]]
    then
        if ! setup_java "${ONOS_REQUIRED_JAVA_VERSION:-8}"; then
            exit 1
        fi
    fi

    install_onos_neutron_thin_ml2_driver

    cd $ONOS_DIR

    unzip -u -o $ONOS_PKG
}


# install_onos_neutron_thin_ml2_driver() - Install the ML2 driver
function install_onos_neutron_thin_ml2_driver {
    cd $NETWORKING_ONOS_DIR
    echo "Installing the Networking-ONOS driver for ONOS"
    sudo python setup.py install
}


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


# start_onos() - Start running processes, including screen
function start_onos {
    echo "Starting ONOS"

    # Wipe out the data and journal directories ... grumble grumble grumble
    rm -rf $ONOS_DIR/$ONOS_NAME/data
    rm -rf $ONOS_DIR/$ONOS_NAME/${ONOS_KARAF_DIR}/data

    # The following variables are needed by the running karaf process.
    # See the "bin/setenv" file in the ONOS distribution for
    # their individual meaning.
    setup_java_env
    export JAVA_MIN_MEM=$ONOS_JAVA_MIN_MEM
    export JAVA_MAX_MEM=$ONOS_JAVA_MAX_MEM
    export JAVA_MAX_PERM_MEM=$ONOS_JAVA_MAX_PERM_MEM
    run_process onos-server "$ONOS_DIR/$ONOS_NAME/bin/onos-service apps-clean server"

    if [ -n "$ONOS_BOOT_WAIT_URL" ]; then
        echo "Waiting for ONOS to start via $ONOS_BOOT_WAIT_URL ..."
        # Probe ONOS networks for vtn until it is operational
        local testcmd="curl -o /dev/null --fail --silent --head -u \
              ${ONOS_USERNAME}:${ONOS_PASSWORD} http://${ONOS_MGR_IP}:${ONOS_PORT}/${ONOS_BOOT_WAIT_URL}"
        test_with_retry "$testcmd" "ONOS vtn did not start after $ONOS_BOOT_WAIT" \
              $ONOS_BOOT_WAIT $ONOS_RETRY_SLEEP_INTERVAL
    else
        echo "Waiting for ONOS to start ..."
        # Sleep a bit to let ONOS finish starting up
        sleep $ONOS_BOOT_WAIT
    fi
    echo "Setting ONOS external nic $ONOS_EXTERNAL_NIC"
    if [[ "$ONOS_VETH" == "True" ]]; then
        sudo ip link add ${ONOS_EXTERNAL_NIC} type veth peer name ${ONOS_EXTERNAL_NIC}out
    fi
    $ONOS_DIR/$ONOS_NAME/${ONOS_KARAF_DIR}/bin/client -u karaf "onos:externalportname-set -n $ONOS_EXTERNAL_NIC"
}


# stop_onos() - Stop running processes (non-screen)
function stop_onos {
    # Stop the karaf container
    $ONOS_DIR/$ONOS_NAME/${ONOS_KARAF_DIR}/bin/stop
    stop_process onos-server
}


# cleanup_onos_compute() - Remove all OVS ports, bridges and disconnects
# controller from switch
function cleanup_onos_compute {
    # Remove the patch ports
    for port in $(sudo ovs-vsctl show | grep Port | awk '{print $2}'  | cut -d '"' -f 2 | grep patch); do
        sudo ovs-vsctl del-port ${port}
    done

    # 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 the vxlan ports
    for port in $(sudo ovs-vsctl list port | grep name | grep vxlan | awk '{print $3}'  | cut -d '"' -f 2); do
        sudo ovs-vsctl del-port ${port}
    done

    # Disconnect controller from switch
    unbind_onos_controller

    # remove all OVS bridges created by ONOS
    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_onos_controller() - set control manager to OVS
function bind_onos_controller {
    echo_summary "Initializing ONOS"
    ONOS_LOCAL_IP=${ONOS_LOCAL_IP:-$HOST_IP}
    ONOS_MGR_PORT=${ONOS_MGR_PORT:-6640}
    ONOS_OVS_MANAGERS=${ONOS_OVS_MANAGERS:-$ONOS_MGR_IP}
    read ovstbl <<< $(sudo ovs-vsctl get Open_vSwitch . _uuid)
    local ONOS_MANAGERS_PARAM=()
    for manager in $(echo $ONOS_OVS_MANAGERS | tr "," "\n"); do
        ONOS_MANAGERS_PARAM=( "${ONOS_MANAGERS_PARAM[@]}" "tcp:$manager:$ONOS_MGR_PORT" )
    done
    sudo ovs-vsctl set-manager ${ONOS_MANAGERS_PARAM[@]}
    sudo ovs-vsctl set Open_vSwitch $ovstbl other_config:local_ip=$ONOS_LOCAL_IP
}


# unbind_onos_controller() - disconnect controller from switch and clear bridges
function unbind_onos_controller {
    sudo ovs-vsctl del-manager
    BRIDGES=$(sudo ovs-vsctl list-br)
    for bridge in $BRIDGES ; do
        sudo ovs-vsctl del-controller $bridge
    done
    local _ONOSEXTPORT=$(ip link | grep $ONOS_EXTERNAL_NIC)
    if [[ "$ONOS_EXTERNAL_VETH" == "True" && $_ONOSEXTPORT != "" ]]; then
        sudo ip link delete ${ONOS_EXTERNAL_NIC} type veth
    fi
}
