#!/bin/bash

function getMountPoint()
{
    echo $1 | python -c "import sys, json, os; mnts = [x for x in json.load(sys.stdin)[0]['Mounts'] if x['Destination'] == '/usr/share/sonic/hwsku']; print '' if len(mnts) == 0 else os.path.basename(mnts[0]['Source'])" 2>/dev/null
}

function updateHostName()
{
    HOSTS=/etc/hosts
    HOSTS_TMP=/etc/hosts.tmp

    EXEC="docker exec -i {{docker_container_name}} bash -c"

    NEW_HOSTNAME="$1"
    HOSTNAME=`$EXEC "hostname"`
    if ! [[ $HOSTNAME =~ ^[a-zA-Z0-9.\-]*$ ]]; then
        HOSTNAME=`hostname`
    fi

    # copy HOSTS to HOSTS_TMP
    $EXEC "cp $HOSTS $HOSTS_TMP"
    # remove entry with hostname
    $EXEC "sed -i \"/$HOSTNAME$/d\" $HOSTS_TMP"
    # add entry with new hostname
    $EXEC "echo -e \"127.0.0.1\t$NEW_HOSTNAME\" >> $HOSTS_TMP"

    echo "Set hostname in {{docker_container_name}} container"
    $EXEC "hostname '$NEW_HOSTNAME'"
    $EXEC "cat $HOSTS_TMP > $HOSTS"
    $EXEC "rm -f $HOSTS_TMP"
}

function getBootType()
{
    # same code snippet in files/scripts/syncd.sh
    case "$(cat /proc/cmdline)" in
    *SONIC_BOOT_TYPE=warm*)
        TYPE='warm'
        ;;
    *SONIC_BOOT_TYPE=fastfast*)
        TYPE='fastfast'
        ;;
    *SONIC_BOOT_TYPE=fast*|*fast-reboot*)
        TYPE='fast'
        ;;
    *)
        TYPE='cold'
    esac
    echo "${TYPE}"
}

function preStartAction()
{
{%- if docker_container_name == "database" %}
    WARM_DIR=/host/warmboot
    if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast")  && -f $WARM_DIR/dump.rdb ]]; then
        # Load redis content from /host/warmboot/dump.rdb
        docker cp $WARM_DIR/dump.rdb database:/var/lib/redis/dump.rdb
    else
        # Create an emtpy file and overwrite any RDB if already there
        echo -n > /tmp/dump.rdb
        docker cp /tmp/dump.rdb database:/var/lib/redis/
    fi
{%- elif docker_container_name == "snmp" %}
    docker exec -i database redis-cli -n 6 HSET 'DEVICE_METADATA|localhost' chassis_serial_number $(decode-syseeprom -s)
    vrfenabled=`/usr/bin/redis-cli -n 4 hget "MGMT_VRF_CONFIG|vrf_global" mgmtVrfEnabled`
    v1SnmpTrapIp=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v1TrapDest" DestIp`
    v1SnmpTrapPort=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v1TrapDest" DestPort`
    v1Vrf=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v1TrapDest" vrf`
    v1Comm=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v1TrapDest" Community`
    v2SnmpTrapIp=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v2TrapDest" DestIp`
    v2SnmpTrapPort=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v2TrapDest" DestPort`
    v2Vrf=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v2TrapDest" vrf`
    v2Comm=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v2TrapDest" Community`
    v3SnmpTrapIp=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v3TrapDest" DestIp`
    v3SnmpTrapPort=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v3TrapDest" DestPort`
    v3Vrf=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v3TrapDest" vrf`
    v3Comm=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v3TrapDest" Community`

    if [ "${v1SnmpTrapIp}" != "" ]
    then
        if [ "${v1Vrf}" != "None" ]
        then
            sed -i "s/v1_trap_dest:.*/v1_trap_dest: ${v1SnmpTrapIp}:${v1SnmpTrapPort}%${v1Vrf} ${v1Comm}/" "/etc/sonic/snmp.yml"
        else
            sed -i "s/v1_trap_dest:.*/v1_trap_dest: ${v1SnmpTrapIp}:${v1SnmpTrapPort} ${v1Comm}/" "/etc/sonic/snmp.yml"
        fi
    else
        sed -i "s/v1_trap_dest:.*/v1_trap_dest: NotConfigured/" "/etc/sonic/snmp.yml"
    fi
    if [ "${v2SnmpTrapIp}" != "" ]
    then
        if [ "${v2Vrf}" != "None" ]
        then
            sed -i "s/v2_trap_dest:.*/v2_trap_dest: ${v2SnmpTrapIp}:${v2SnmpTrapPort}%${v2Vrf} ${v2Comm}/" "/etc/sonic/snmp.yml"
        else
            sed -i "s/v2_trap_dest:.*/v2_trap_dest: ${v2SnmpTrapIp}:${v2SnmpTrapPort} ${v2Comm}/" "/etc/sonic/snmp.yml"
        fi
    else
        sed -i "s/v2_trap_dest:.*/v2_trap_dest: NotConfigured/" "/etc/sonic/snmp.yml"
    fi
    if [ "${v3SnmpTrapIp}" != "" ]
    then
        if [ "${v3Vrf}" != "None" ]
        then
            sed -i "s/v3_trap_dest:.*/v3_trap_dest: ${v3SnmpTrapIp}:${v3SnmpTrapPort}%${v3Vrf} ${v3Comm}/" "/etc/sonic/snmp.yml"
        else
            sed -i "s/v3_trap_dest:.*/v3_trap_dest: ${v3SnmpTrapIp}:${v3SnmpTrapPort} ${v3Comm}/" "/etc/sonic/snmp.yml"
        fi
    else
        sed -i "s/v3_trap_dest:.*/v3_trap_dest: NotConfigured/" "/etc/sonic/snmp.yml"
    fi

    echo -n "" > /tmp/snmpagentaddr.yml
    keys=`/usr/bin/redis-cli -n 4 keys "SNMP_AGENT_ADDRESS_CONFIG|*"`
    count=1
    for key in $keys;do
        ip=`echo $key|cut -d "|" -f2`
        echo -n "snmp_agent_address_$count: $ip" >> /tmp/snmpagentaddr.yml
        port=`echo $key|cut -d "|" -f3`
        if [ -n "$port" ]; then
            echo -n ":$port" >> /tmp/snmpagentaddr.yml
        fi
        vrf=`echo $key|cut -d "|" -f4`
        if [ -n "$vrf" ]; then
            echo -n "%$vrf" >> /tmp/snmpagentaddr.yml
        fi
        echo "" >> /tmp/snmpagentaddr.yml
        count=$((count+1))
    done
    sed -i '/snmp_agent_address_*/d' /etc/sonic/snmp.yml
    cat /tmp/snmpagentaddr.yml >> /etc/sonic/snmp.yml
{%- else %}
    : # nothing
{%- endif %}
}

function postStartAction()
{
{%- if docker_container_name == "database" %}
    # Wait until redis starts
    /usr/bin/docker exec database ping_pong_db_insts
    if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast") && -f $WARM_DIR/dump.rdb ]]; then
        rm -f $WARM_DIR/dump.rdb
    else
        # If there is a config db dump file, load it
        if [ -r /etc/sonic/config_db.json ]; then
            sonic-cfggen -j /etc/sonic/config_db.json --write-to-db
        fi

        if [[ "$BOOT_TYPE" == "fast" ]]; then
            # set the key to expire in 3 minutes
            redis-cli -n 6 SET "FAST_REBOOT|system" "1" "EX" "180"
        fi

        redis-cli -n 4 SET "CONFIG_DB_INITIALIZED" "1"
    fi

    if [[ -x /usr/bin/db_migrator.py ]]; then
        # Migrate the DB to the latest schema version if needed
        /usr/bin/db_migrator.py -o migrate
    fi
{%- elif docker_container_name == "swss" %}
    docker exec swss rm -f /ready   # remove cruft
    if [[ "$BOOT_TYPE" == "fast" ]] && [[ -d /host/fast-reboot ]]; then
        test -e /host/fast-reboot/fdb.json && docker cp /host/fast-reboot/fdb.json swss:/
        test -e /host/fast-reboot/arp.json && docker cp /host/fast-reboot/arp.json swss:/
        test -e /host/fast-reboot/default_routes.json && docker cp /host/fast-reboot/default_routes.json swss:/
        rm -fr /host/fast-reboot
    fi
    docker exec swss touch /ready   # signal swssconfig.sh to go
{%- elif docker_container_name == "pmon" %}

    DEVPATH="/usr/share/sonic/device"
    REBOOT="platform_reboot"
    PSENSOR="/usr/local/bin/platform_sensors.py"
    if [ -d ${DEVPATH}/${PLATFORM} ] && [ -f $PSENSOR ]; then
        exist=`docker exec -i pmon ls /usr/bin/platform_sensors.py "$@" 2>/dev/null`
        if [ -z "$exist" ]; then
            docker cp $PSENSOR pmon:/usr/bin/
        fi
    fi
{%- else %}
    : # nothing
{%- endif %}
}

start() {
    # Obtain boot type from kernel arguments
    BOOT_TYPE=`getBootType`

    # Obtain our platform as we will mount directories with these names in each docker
    PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`

    {%- if docker_container_name == "database" %}
    # Don't mount HWSKU in {{docker_container_name}} container.
    HWSKU=""
    {%- else %}
    # Obtain our HWSKU as we will mount directories with these names in each docker
    HWSKU=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'`
    HOSTNAME=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hostname"]'`
    {%- endif %}
    if [ -z "$HOSTNAME" ] || ! [[ $HOSTNAME =~ ^[a-zA-Z0-9.\-]*$ ]]; then
        HOSTNAME=`hostname`
    fi

    DOCKERCHECK=`docker inspect --type container {{docker_container_name}} 2>/dev/null`
    if [ "$?" -eq "0" ]; then
        {%- if docker_container_name == "database" %}
        DOCKERMOUNT=""
        {%- else %}
        DOCKERMOUNT=`getMountPoint "$DOCKERCHECK"`
        {%- endif %}
        if [ x"$DOCKERMOUNT" == x"$HWSKU" ]; then
            {%- if docker_container_name == "database" %}
            echo "Starting existing {{docker_container_name}} container"
            {%- else %}
            echo "Starting existing {{docker_container_name}} container with HWSKU $HWSKU"
            {%- endif %}
            preStartAction
            docker start {{docker_container_name}}
            CURRENT_HOSTNAME="$(docker exec {{docker_container_name}} hostname)"
            if [ x"$HOSTNAME" != x"$CURRENT_HOSTNAME" ]; then
                updateHostName "$HOSTNAME"
            fi
            postStartAction
            exit $?
        fi

        # docker created with a different HWSKU, remove and recreate
        echo "Removing obsolete {{docker_container_name}} container with HWSKU $DOCKERMOUNT"
        docker rm -f {{docker_container_name}}
    fi

{%- if docker_container_name == "database" %}
    echo "Creating new {{docker_container_name}} container"
    # if database_config exists in old_config, use it; otherwise use the default one in new image
    if [ -f /etc/sonic/old_config/database_config.json ]; then
        echo "Use database_config.json from old system..."
        mv /etc/sonic/old_config/database_config.json /etc/sonic/
    fi
{%- else %}
    echo "Creating new {{docker_container_name}} container with HWSKU $HWSKU"
{%- endif %}
{%- if sonic_asic_platform == "mellanox" %}
    # TODO: Mellanox will remove the --tmpfs exception after SDK socket path changed in new SDK version
{%- endif %}
    docker create {{docker_image_run_opt}} \
{%- if install_debug_image == "y" %}
        -v /src:/src:ro -v /debug:/debug:rw \
{%- endif %}
{%- if '--log-driver=json-file' in docker_image_run_opt or '--log-driver' not in docker_image_run_opt %}
        --log-opt max-size=2M --log-opt max-file=5 \
{%- endif %}
{%- if sonic_asic_platform == "mellanox" %}
{%- if docker_container_name == "syncd" %}
        -v /var/log/mellanox/sniffer:/var/log/mellanox/sniffer:rw \
        -v mlnx_sdk_socket:/tmp \
        -v /dev/shm:/dev/shm:rw \
{%- elif docker_container_name == "pmon" %}
        -v /var/run/hw-management:/var/run/hw-management:rw \
        -v mlnx_sdk_socket:/tmp \
        -v /dev/shm:/dev/shm:rw \
{%- else %}
        --tmpfs /tmp \
{%- endif %}
{%- endif %}
        -v /var/run/redis:/var/run/redis:rw \
        -v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \
{%- if docker_container_name != "database" %}
        -v /usr/share/sonic/device/$PLATFORM/$HWSKU:/usr/share/sonic/hwsku:ro \
{%- endif %}
{%- if sonic_asic_platform != "mellanox" %}
        --tmpfs /tmp \
{%- endif %}
        --tmpfs /var/tmp \
        --hostname "$HOSTNAME" \
        --name={{docker_container_name}} {{docker_image_name}}:latest || {
            echo "Failed to docker run" >&1
            exit 4
    }

    preStartAction
    docker start {{docker_container_name}}
    postStartAction
}

wait() {
    docker wait {{docker_container_name}}
}

stop() {
    docker stop {{docker_container_name}}
}

case "$1" in
    start|wait|stop|updateHostName)
        cmd=$1
        shift
        $cmd $@
        ;;
    *)
        echo "Usage: $0 {start|wait|stop|updateHostName new_hostname}"
        exit 1
        ;;
esac