#!/bin/bash
set -x -e
HOST_DIR="${HOST_DIR:-/host}"
RELEASE_FILE="${RELEASE_FILE:-/etc/os-release}"
CONF_FILE="${CONF_FILE:-/run/data/cloud-config}"
LOCK_TIMEOUT="${LOCK_TIMEOUT:-600}"
LOCK_FILE="${LOCK_FILE:-$HOST_DIR/run/cos/upgrade.lock}"
ACTIVE_FILE="${ACTIVE_FILE:-$HOST_DIR/run/cos/active_mode}"

function config()
{
    if [ ! -s $CONF_FILE ]; then
        if [ -e ${HOST_DIR}/oem/90_operator.yaml ]; then
            rm -f ${HOST_DIR}/oem/90_operator.yaml
        fi
        return 0
    fi

    if [ ! -e ${HOST_DIR}/oem/90_operator.yaml ] || ! diff $CONF_FILE ${HOST_DIR}/oem/90_operator.yaml >/dev/null; then
        cp -f $CONF_FILE ${HOST_DIR}/oem/90_operator.yaml
    fi
}

function isHigherVersion()
{
    local img_ver=$( . ${RELEASE_FILE} && printf '%s\n' "${IMAGE_TAG}" )
    local img_repo=$( . ${RELEASE_FILE} && printf '%s\n' "${IMAGE_REPO}" )
    local host_ver=$( . ${HOST_DIR}${RELEASE_FILE} && printf '%s\n' "${IMAGE_TAG}" )
    local host_repo=$( . ${HOST_DIR}${RELEASE_FILE} && printf '%s\n' "${IMAGE_REPO}" )
    local higher_ver

    # If images are from different repositories the version check is omitted
    # and proceeds with the upgrade
    [ "${host_repo}" != "${img_repo}" ] && return 0

    # Without knowing the version in the host, all img versions are
    # considered higher
    [ -z "${host_ver}" ] && return 0

    [ "${host_ver}" == "${img_ver}" ] && return 1

    # Note sort -V is a natural numbering sort, not semver
    higher_ver=$(printf '%s\n' "${img_ver}" "${host_ver}" | sort -rV | head -n1)
    [ "${higher_ver}" == "${img_ver}" ] && return 0
    return 1
}

function isEqualVersion() {
 if diff $RELEASE_FILE ${HOST_DIR}${RELEASE_FILE} >/dev/null; then
     return 0
 fi
 return 1
}

function isActiveSystem() {
  [ ! -f "${ACTIVE_FILE}" ] && return 1
  return 0
}

(
  flock -w $LOCK_TIMEOUT 200 || exit 1
  if ! nsenter -i -m -t 1 -- systemctl is-system-running; then
      # Exit if there is a shutdown process already going on
      exit 1
  fi

  if isEqualVersion; then
      echo "Upgrade already done with release:"
      cat ${HOST_DIR}${RELEASE_FILE}

      config
      exit 0
  fi

  if [ "$FORCE" != "true" ]; then
      if ! isHigherVersion; then
          echo "Current OS is in a higher version, use FORCE to downgrade. Current version:"
          cat ${HOST_DIR}${RELEASE_FILE}
          
          exit 0
      fi

      if ! isActiveSystem; then
          echo "Current OS is not booted in Active configuration, use FORCE to run upgrade."
          exit 0
      fi
  fi
  
  config
  mount --rbind $HOST_DIR/dev /dev
  mount --rbind $HOST_DIR/run /run
  elemental --debug upgrade --system.uri dir:/

  # After elemental upgrade we have to also copy
  # /etc/resolv.conf from /host filesystem, otherwise 
  # it will be taken from container context
  mount -o remount,rw /run/initramfs/cos-state
  LOOP_DEV=$(losetup -f)
  losetup $LOOP_DEV /run/initramfs/cos-state/cOS/active.img
  mkdir -p /tmp/cOS
  mount $LOOP_DEV /tmp/cOS
  rsync -av $HOST_DIR/etc/resolv.conf /tmp/cOS/etc/resolv.conf
  umount /tmp/cOS
  losetup -d $LOOP_DEV

  nsenter -i -m -t 1 -- reboot
  exit 1
) 200> $LOCK_FILE
