#!/bin/bash

# TT#97950 Ensure presence of proper /etc/udev/rules.d/70-persistent-net.rules,
#          because it is not created by default by the base Debian
#          system but we still want to use this method
#
# Based on mr5.5/check_persistent_net_devices, but forcing the creation
# (upgrade since mr9.5 installs in new partition, the file never exists),
# or if already present but using the old MAC based layout, then re-create
# it, to use PCIID approach

set -e
set -u

# === HELPER FUNCTIONS =========================================================

die() {
  local message="$*"

  echo "ERROR: ${message}" >&2
  exit 1
}

fatal_missing_var() {
  local var_name="$1"
  if [[ ! -v "${var_name}" ]] ; then
    die "Missing mandatory environment variable '\$${var_name}', exiting."
  fi

  local var_value="${!var_name}"
  if [[ -z "${var_value}" ]] ; then
    die "Empty mandatory environment variable '\$${var_name}', exiting."
  fi
}

request_confirmation() {
  if [[ "${FORCE_UPGRADE}" = "true" ]] ; then
    echo "Warning: Forcing to CONTINUE, as FORCE_UPGRADE is set"
    return
  fi

  while true; do
    echo -n "Should we continue with the upgrade? (yes/no): "
    read -r answer
    case "${answer,,}" in
      yes)
        echo "Continue as requested."
        break
        ;;
      no)
        die "Aborted as requested."
        ;;
      *)
        echo "Please answer 'yes' or 'no'."
        ;;
    esac
    unset answer
  done
}


# ==============================================================================

fatal_missing_var FORCE_UPGRADE

UDEV_PERSISTENT_NET_RULES="/etc/udev/rules.d/70-persistent-net.rules"

if [[ -f "${UDEV_PERSISTENT_NET_RULES}" ]]; then
  echo "INFO: The file '${UDEV_PERSISTENT_NET_RULES}' already exists, the content is:"
  echo "----------------------------------------"
  cat "${UDEV_PERSISTENT_NET_RULES}"
  echo "----------------------------------------"
  if ! grep -q 'ATTR{address}==".*ATTR{dev_id}' "${UDEV_PERSISTENT_NET_RULES}" ; then
    echo "INFO: Exiting as there is no need to modify the file."
    exit 0
  else
    echo "WARNING: it looks like file '${UDEV_PERSISTENT_NET_RULES}' was deployed before mr9.5.6.1"
    renamed_file="/root/upgrade_leftover_70-persistent-net.rules.$(date -u +%Y%m%d%H%M%S)"
    mv "${UDEV_PERSISTENT_NET_RULES}" "${renamed_file}"
    echo "NOTE:    renamed '${UDEV_PERSISTENT_NET_RULES}' to '${renamed_file}'"
    echo "NOTE:    continuing execution to re-create '${UDEV_PERSISTENT_NET_RULES}' with PCIID layout"
  fi
fi

echo "INFO: Generating udev persistent net rules: ${UDEV_PERSISTENT_NET_RULES}"
echo "# Generated by ngcp-upgrade ${OLD_VERSION}->${UPGRADE_VERSION}" > "${UDEV_PERSISTENT_NET_RULES}"
ERRORS_FOUND=0
declare -a NETWORK_DEVICES
mapfile -t NETWORK_DEVICES < <(find /sys/class/net -type l -printf '%P\n' | grep -vE '^(bond|docker|lo|tun|usb|vboxnet|vlan|vmnet)' | sort -u)
for dev in "${NETWORK_DEVICES[@]}"; do
  pciid=$(ethtool -i "${dev}" | awk '/^bus-info: / {print $2}')
  if [[ "${pciid}" =~ ^([0-9a-fA-F:.-])+$ ]]; then
    echo "INFO: Adding device '${dev}' with PCIID '${pciid}'"
    cat >> "${UDEV_PERSISTENT_NET_RULES}" <<EOL
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", KERNELS=="${pciid}", NAME="${dev}"
EOL
  else
    echo "ERROR: could not find valid PCIID '${pciid}' for device '${dev}'"
    (( ERRORS_FOUND += 1 ))
  fi
  unset pciid
done
unset NETWORK_DEVICES

echo "INFO: Contents of '${UDEV_PERSISTENT_NET_RULES}' after generating it:"
echo "----------------------------------------"
cat "${UDEV_PERSISTENT_NET_RULES}"
echo "----------------------------------------"

if [[ "${ERRORS_FOUND}" -ne 0 ]] ; then
  echo "WARNING: There were errors trying to pin network devices to fix names"
  echo "         across reboots, see previous warnings/errors."
  echo
  echo "         These errors are potentially fatal if after reboot the network"
  echo "         devices are reshuffled at boot time, this might lead to loss"
  echo "         of connectivity to those nodes even during the upgrade"
  echo "         procedure."
  echo
  echo "         One way to work around the problem of undetected PCIID is to"
  echo "         map by MAC address, although it is less reliable, for example"
  echo "         for 'eth0' with the following result:"
  echo
  echo "           ip addr show eth0 | awk '/link.ether / {print \$2}'"
  echo "           cc:00:ff:ee:g0:0d"
  echo
  echo "         add the following line to '${UDEV_PERSISTENT_NET_RULES}':"
  echo
  echo "           SUBSYSTEM==\"net\", ACTION==\"add\", DRIVERS==\"?*\", ATTR{address}==\"cc:00:ff:ee:g0:0d\", ATTR{dev_id}==\"0x0\", ATTR{type}==\"1\", KERNEL==\"eth*\", NAME=\"eth0\""
  echo
  echo "         Please check if the detected problems are relevant before"
  echo "         continuing, or ensure that you have means to access the nodes"
  echo "         (e.g. the main interface for ssh-ext was detected"
  echo "         successfully, or we have access through serial console or"
  echo "         similar methods, that the system is not for production or that"
  echo "         we always have quick access to local admins that can fix"
  echo "         things if the worst happens)."
  echo

  # ask admins/ops if the upgrade should continue or not
  request_confirmation
fi

unset UDEV_PERSISTENT_NET_RULES
unset ERRORS_FOUND
