#!/bin/bash
#
# Script to start docker daemon
#
# June 2016, Lokheshvar Balakumar
# Copyright (c) 2016-2017, 2019-2021 by Cisco Systems, Inc.
# All rights reserved.
#

# Check $VMTYPE and $VIRT_METHOD;
# if in xr-vm and VIRT_METHOD is vm or
# if in host-os and VIR_METHOD is lxc; execute this script
# else exit

XR_DOCKER_LOG_FILE="/var/log/docker.log"
VMTYPE=`cat /proc/cmdline | sed 's/^.*vmtype=//' | cut -d" " -f1`
VIRT_METHOD=$(grep VIRT_METHOD /etc/init.d/calvados_bootstrap.cfg | awk -F '=' '{print $2}')

if [[ ! (("$VIRT_METHOD" == "lxc" && "$VMTYPE" == "hostos") ||
        ("$VIRT_METHOD" == "vm" && "$VMTYPE" == "xr-vm")) ]]; then
    echo "Virt_method: $VIRT_METHOD, VM_type: $VMTYPE - Script doesn't need to run" >> ${XR_DOCKER_LOG_FILE}
    exit 1
fi

if [[ "$app_hosting_cisco_docker_sourced" != true ]]; then
    app_hosting_cisco_docker_sourced=true

    if [[ -f /etc/rc.d/init.d/spirit_log.sh ]]; then
        source /etc/rc.d/init.d/spirit_log.sh
    fi

    if [[ -f /etc/sysconfig/docker ]]; then
        source /etc/sysconfig/docker
    fi

    if [[ -f /etc/sysconfig/cisco_docker ]]; then
        source /etc/sysconfig/cisco_docker
    fi

    if [[ -f /etc/init.d/operns-functions ]]; then
        source /etc/init.d/operns-functions
    fi
fi

XR_DOCKER_CE=0
if rpm -q docker-ce 1> /dev/null; then
    XR_DOCKER_CE=1
fi

XR_DOCKER_DAEMON_ALIVE_POLL_DELAY=10
if [[ "${XR_DOCKER_CE}" -eq 1 ]]; then
    XR_DOCKER_DAEMON_PID_PATTERN="[d]ockerd"
    DOCKER_DAEMON_LAUNCH="dockerd ${CISCO_DOCKER_OPTS}"
else
    XR_DOCKER_DAEMON_PID_PATTERN="[d]ocker daemon -D"
    DOCKER_DAEMON_LAUNCH="docker daemon ${CISCO_DOCKER_OPTS}"
fi
XR_DOCKER_PID=

if [[ -z "${DOCKER_VRF}" ]]; then
    DOCKER_VRF="global-vrf"
fi

function xr_docker_log
{
    local DATE=`date`
    echo "$DATE ($0): $*" >> ${XR_DOCKER_LOG_FILE}
}

function xr_docker_log_exec
{
    xr_docker_log "exec: $*"
    xr_docker_log "    : in cwd" `pwd`

    local PREFIX="`date -u`: -- "
    $* 2>&1 | sed "s/^/${PREFIX}/g" >>${XR_DOCKER_LOG_FILE} 2>&1

    return ${PIPESTATUS[0]}
}

#
# rm function to remove files
#
function safe_rm_file()
{
    if [[ "$*" = "" ]]; then
        return
    fi

    /bin/rm -f $*
}

#
# Remove the mounts used by system LXCs from docker daemon's
# mount namespace
#
function docker_daemon_cleanup_bind_mounts()
{
    local check_lxcs=""

    #
    # Clean up is not required in platforms which run xr in a vm
    # Docker will run in the XR VM and will be shutdown on xr vm
    # shutdown
    #
    if [[ "$VIRT_METHOD" == "vm" ]]; then
        return
    fi

    check_lxcs=$(virsh -c lxc:/// list --name 2>/dev/null | egrep -w 'sysadmin|default-sdr--*')

    xr_docker_log "Remove mounts used by system LXCs from docker daemon's mount namespace"
    declare -F app_hosting_docker_daemon_cleanup_bind_mounts &>/dev/null &&
    app_hosting_docker_daemon_cleanup_bind_mounts "$check_lxcs"

    if [[ $? -ne 0 ]]; then
        xr_docker_log "Removal of one or more mounts may have failed. Check /var/log/platform.log"
        false
        return
    fi

    true
    return
}

function create_docker_mount()
{
    xr_docker_log_exec mkdir -p ${DOCKER_STORAGE_VOLUME}
    xr_docker_log_exec mkdir -p ${DOCKER_STORAGE_MOUNT}
    if [[ `grep -c $DOCKER_STORAGE_VOLUME /proc/mounts` -eq 0 ]]; then
        xr_docker_log_exec mount --bind ${DOCKER_STORAGE_MOUNT} ${DOCKER_STORAGE_VOLUME}
    fi
}

function docker_daemon_wait_initial_conditions()
{
    xr_docker_log "Docker daemon is waiting on initial conditions"

    while true
    do
        sleep $XR_DOCKER_DAEMON_ALIVE_POLL_DELAY

        ip netns exec ${DOCKER_VRF} ifconfig lo0 | grep -q "UP LOOPBACK RUNNING"
        if [[ $? -eq 0 ]]; then
            break
        fi
    done
}

function docker_daemon_launch()
{
    xr_docker_log "Starting the docker daemon"
    safe_rm_file ${DOCKER_DAEMON_PID_FILE}

    (exec ip netns exec ${DOCKER_VRF} ${DOCKER_DAEMON_LAUNCH}  $DOCKER_OPTS &>> ${XR_DOCKER_LOG_FILE}) &
}

function docker_daemon_get_pid()
{
    while true
    do
        docker_daemon_launch

        sleep $XR_DOCKER_DAEMON_ALIVE_POLL_DELAY

        XR_DOCKER_PID=$(ps aux | grep "$XR_DOCKER_DAEMON_PID_PATTERN" | awk "{print \$2}")
        if [[ $XR_DOCKER_PID != "" ]]; then
            xr_docker_log "Docker daemon pid $XR_DOCKER_PID is running"
            docker_daemon_cleanup_bind_mounts
            break
        fi
    done
}

function docker_daemon_wait_pid()
{
    local first_time=true

    while true
    do
        sleep $XR_DOCKER_DAEMON_ALIVE_POLL_DELAY

        ps p $XR_DOCKER_PID | grep -q "$XR_DOCKER_DAEMON_PID_PATTERN"
        if [[ $? -eq 0 ]]; then
            if [[ $first_time == true ]]; then
                first_time=false
                xr_docker_log "Verified the docker daemon is running"
            fi

            continue
        fi

        break
    done

    xr_docker_log "Docker daemon pid $XR_DOCKER_PID is no longer running"
}

function start_docker_daemon()
{
    xr_docker_log "Preparing to start the docker daemon"

    while true
    do
        docker_daemon_wait_initial_conditions
        docker_daemon_get_pid
        docker_daemon_wait_pid
    done
}

function main()
{
    create_docker_mount

    start_docker_daemon $@
}

main $@
