#!/bin/bash

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="automatic eaddress configuration"
NAME="ngcp-eaddress"

# exit if either ngcpcfg or ngcp-network aren't available
[ -x "/usr/sbin/ngcpcfg" ] || exit 0
[ -x "/usr/sbin/ngcp-network" ] || exit 0

# Read configuration variable file if it is present
# shellcheck disable=SC1090
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
# shellcheck disable=SC1091
[ -r /lib/init/vars.sh ] && . /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
# shellcheck disable=SC1091
. /lib/lsb/init-functions

adjust_ec2_ip() {
  if ! [ -x /usr/bin/facter ] ; then
    return 0
  fi

  if [ -z "$IFACE" ] ; then
    log_warning_msg "Interface variable IFACE is unset."
    return 1
  fi

  log_action_begin_msg "Checking for public EC2 IPv4 address using facter."
  local PUBLIC_IP
  PUBLIC_IP="$(facter ec2_public_ipv4 2>/dev/null)"
  log_end_msg 0

  # ec2_public_ipv4 might be empty when using VPC with elastic IP
  if [ -z "$PUBLIC_IP" ] ; then
    local PUBLIC_IP
    PUBLIC_IP="$(wget --timeout=3 --wait=3 --tries=1 -O- http://169.254.169.254/latest/meta-data/public-ipv4 2>/dev/null)"
  fi

  if [ -z "$PUBLIC_IP" ] ; then
    log_warning_msg "Could not retrieve IPv4 address for EC2, not running ngcp-network to adjust advertised IP address."
  else
    log_action_begin_msg "Setting $PUBLIC_IP as advertised IP address on $IFACE"
    # get rid of any pre-existing entries
    ngcp-network --set-interface="$IFACE" --advertised-ip=delete
    ngcp-network --set-interface="$IFACE" --advertised-ip="$PUBLIC_IP"
    log_end_msg $?
  fi
}

do_start() {
  if [ -e "/run/ngcpcfg-services.running" ]; then
    log_warning_msg "Skipping ngcp-eaddress as we are running from within ngcpcfg"
    exit 0
  fi

  # Looking for network interface to be used
  if [ -z "$IFACE" ]; then
    declare -a IFACES
    read -r -a IFACES < <(
      cd /proc/sys/net/ipv4/conf/ &&
      for f in *; do
        printf "%s" "$f" | grep -vE "all|default|lo";
      done
    )
    if [ "${#IFACES[@]}" = "1" ]; then
      IFACE=${IFACES[0]}
    else
      log_warning_msg "Skipping ngcp-eaddress as more than one network interface found: ${IFACES[*]}"
      exit 0
    fi
  fi

  # Make sure the device actually exists
  if ! [ -d "/proc/sys/net/ipv4/conf/${IFACE}" ] ; then
    log_warning_msg "Network device $IFACE doesn't seem to exist."
    exit 0
  fi

  # User doesn't want us to run it
  if [ -r /etc/.ngcp_skip_network_autoconfig ] ; then
    log_warning_msg "Ignoring autoconfiguration as /etc/.ngcp_skip_network_autoconfig is present."
    exit 0
  fi

  # Do not mess with multiple NICs
  orig_dir="$(pwd)"
  if ! cd /proc/sys/net/ipv4/conf; then
    log_warning_msg "Cannot change directory to /proc/sys/net/ipv4/conf"
    exit 0
  fi
  for dev in * ; do
    case $dev in
      all|default|"${IFACE}"|lo) ;;
      *)
        log_action_begin_msg "Multiple network interfaces found (${dev}), ignoring eaddress autoconfig."
        log_end_msg 0
        exit 0
        ;;
    esac
  done
  if ! cd "$orig_dir"; then
    log_warning_msg "Cannot change directory back to $orig_dir"
    exit 0
  fi

  # check for IP address
  IP=$(ip addr show dev "$IFACE" | awk '/inet / {print $2}' | sed 's;/.*;;')
  if [ -z "$IP" ] ; then
    exit 0
  fi

  # adjust advertized IP when running on EC2
  adjust_ec2_ip

  if service mysql status &>/dev/null ; then
    MYSQL=true
  else
    # give mysql up to one minute
    MYSQL=""
    counter=12
    while [ -z "$MYSQL" ] && [ "$counter" != 0 ] ; do
      counter=$(( counter-1 ))
      echo "Waiting for mysql service... $counter retries tries"
      sleep 5
      if service mysql status &>/dev/null ; then
        MYSQL=true
      fi
    done
  fi

  if [ -z "$MYSQL" ] ; then
    log_failure_msg "MySQL service not available, skipping execution of ngcp-network/ngcpcfg"
    log_end_msg 1
    exit 1
  fi

  # Everything ok, so adjust
  ngcp-network --set-interface="$IFACE" --ip=auto --netmask=auto --hwaddr=auto
  ngcp-network --move-from=lo --move-to="$IFACE" --type=web_ext --type=sip_ext --type=rtp_ext --type=web_int
  ngcp-network --set-interface="$IFACE" --type=ssh_ext

  # Adjust configuration files
  export HOME=/ # required for ngcpcfg
  if ngcpcfg status | grep -q "ACTION_NEEDED: configuration files have been" ; then
    log_action_begin_msg "Applying NGCP network configuration changes."
    ngcpcfg apply "applying ngcp-network changes via ngcp-eaddress"
    log_end_msg $?
  else
    log_action_begin_msg "Nothing changed regarding network setup, skipping ngcp-network/ngcpcfg execution."
    log_end_msg 0
  fi
}

do_stop() {
  # nothing to do
  return 0
}

status_check() {
  if ngcpcfg status | grep -q "ACTION_NEEDED: configuration files have been" ; then
    log_action_begin_msg 'Configuration files have been modified, please (re)start init script.'
    log_end_msg 0
    return 1
  else
    log_action_begin_msg "No configuration files have been modified, nothing to do."
    log_end_msg 0
    return 0
  fi
}

case "$1" in
  start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
        do_start
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  status)
        status_check && exit 0 || exit $?
        ;;
  restart|force-reload)
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
          0|1)
                do_start
                case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
          *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
        exit 3
        ;;
esac

:
