#!/bin/sh

# We should be run by puavo-install-and-update-ltspimages when the
# new image is downloaded but not yet set as default.
# Care must be taken to not break old images (because we might still
# be booted to those), yet we should help the system move forward to this
# new image.
#
# This script will be run for all device types that boot from local
# hard drive.  You should be able to read the device type from
# "/etc/puavo/hosttype".  If this script fails, new image will *not* be
# set as default.
#
# This script should be written so that it might be run once or many times,
# and always should do the right thing.
#
# The old image/system should now be mounted at /, and this new image
# should be mounted at /images/mnt.
#
# Note that grub-install and maybe some scripts should be run under chroot
# of the new system, or otherwise there may be missing dynamic libraries,
# or segfaults may occur in case system versions mismatch.

set -eu

new_mnt=/images/mnt

bind_paths='/dev /images /proc /run /sys'

cleanup() {
  for path in $bind_paths; do
    { mountpoint -q "${new_mnt}${path}" && umount "${new_mnt}${path}"; } \
      || true
  done
}

trap cleanup 0 INT TERM

block_interrupts() {
  if ! which systemd-inhibit >/dev/null; then
    # In case we are on a system that lacks systemd-inhibit, we just try
    # without it.  (This can happen with updates from Ubuntu Trusty
    # to Debian Buster, and even though that should not happen much,
    # we do not want to break those either).
    "$@"
  else
    inhibit_list='shutdown:sleep:idle:handle-power-key:handle-suspend-key:handle-hibernate-key:handle-lid-switch'

    # XXX We use "block" to ensure safe(r) updates from Stretch to Buster.
    # XXX Using "delay" is problematic with Stretch, because Stretch has
    # XXX logind.conf InhibitDelayMaxSec=5 and this may be too short for
    # XXX grub updates.  Our Buster has InhibitDelayMaxSec=60 and we thus
    # XXX we could change --mode=delay for Bullseye, that would probably
    # XXX be better (note that $inhibit_list should also change).
    systemd-inhibit "--what=${inhibit_list}"  \
                    --who=puavo-image-preinst \
                    '--why=Updating Grub'     \
                    --mode=block              \
                    "$@"
  fi
}

update_grub() {
  # puavo-install-grub updates /images/boot/grub/version
  old_grub_version="$(cat /images/boot/grub/version 2>/dev/null || true)"
  new_grub_version="$(chroot "$new_mnt" /usr/sbin/grub-install --version \
                        | awk '{ print $3 }')"
  if [ -z "$new_grub_version" ]; then
    echo 'Can not determine the new grub version' >&2
    return 1
  fi

  if [ -z "$old_grub_version" ] \
    || dpkg --compare-versions "$old_grub_version" lt "$new_grub_version"; then
      block_interrupts chroot "$new_mnt" /usr/sbin/puavo-install-grub "$@"
  else
    block_interrupts chroot "$new_mnt" \
      /usr/sbin/puavo-install-grub --only-update-config "$@"
  fi
}

hosttype=

# This should not fail even if we get parameters we do not understand.
# The arguments should be simple: in format "--option value" only.  The point
# is that this might be called from an image that is far in the past or far in
# the future, and we should do our best and just ignore whatever we do not
# understand.
while [ $# -ge 2 ]; do
  case "$1" in
    --hosttype) hosttype=$2; shift; shift ;;
    --*)                     shift; shift ;;
    *)                       shift        ;;
  esac
done

if [ -z "$hosttype" ]; then
  hosttype=$(cat /etc/puavo/hosttype 2>/dev/null || true)
  if [ -z "$hosttype" ]; then
    echo 'Could not determine hosttype for grub update' >&2
    exit 1
  fi
fi


# Duplicate /images (and other $bind_paths) mount under $new_mnt
# so that grub installation can access it.
for path in $bind_paths; do
  if ! mount -o bind "$path" "${new_mnt}${path}"; then
    echo "Could not mount bind ${path} under ${new_mnt}${path}" >&2
    exit 1
  fi
done

# update grub configuration from the new image
update_grub --hosttype "$hosttype"

exit 0
