#!/bin/sh

set -eu

log() {
  logpriority=$1
  logmessage=$2
  logger -p "$logpriority" -s -t puavo-update-client "$logmessage"
}

on_persistent_overlay() {
  grep -q "puavo.image.overlay=" /proc/cmdline
}

usage_error() {
  log err "error: $1 (try '$0 --help' for more information)"
  exit 1
}

hosttype=$(puavo-conf puavo.hosttype)

if [    "$hosttype" != 'bootserver' \
     -a "$hosttype" != 'laptop'     \
     -a "$hosttype" != 'wirelessaccesspoint' ]; then
  msg='this script should be run only for bootserver, laptops' \
  msg="${msg} and wirelessaccesspoints"
  log err "$msg"
  exit 1
fi

automatically_triggered=false
force_image_update=false
no_image_update=false
use_rate_limit=false
wait_for_image_update=false

while [ "$#" -gt 0 ]; do
  case "$1" in
    -h|--help)
      shift
      echo "Usage: $0"
      echo
      echo "Update device configuration and images."
      echo
      echo "Options:"
      echo "    --auto                 automatically scheduled update"
      echo "    --force-image-update   update image, no matter what"
      echo "                           (overrides --no-image-update)"
      echo "    --no-image-update      do not update images, only configurations"
      echo "    --use-rate-limit       limit the image download rate"
      echo "    -h, --help             print help and exit"
      echo
      exit 0
      ;;
    --auto)
      shift
      automatically_triggered=true
      ;;
    --force-image-update)
      shift
      force_image_update=true
      ;;
    --no-image-update)
      shift
      no_image_update=true
      ;;
    --use-rate-limit)
      shift
      use_rate_limit=true
      ;;
    --wait-for-image-update)
      shift
      wait_for_image_update=true
      ;;
    --)
      shift
      break
      ;;
    -*)
      usage_error "invalid argument '$1'"
      ;;
    *)
      break
      ;;
  esac
done

if [ "$#" -ne 0 ]; then
  usage_error "invalid number of arguments ($#), expected 0"
fi

if [ "$(puavo-conf puavo.admin.personally_administered)" = 'true' ]; then
  personally_administered=true
else
  personally_administered=false
fi

# figure out the value of do_image_update
if $force_image_update; then
  do_image_update=true
elif $no_image_update; then
  log notice 'not doing an image update, requested to not to'
  do_image_update=false
elif on_persistent_overlay; then
  # we are on persistent overlay (development mode),
  # do not do an image update
  log notice 'not doing an image update, we are on persistent overlay'
  do_image_update=false
else
  automatic_image_updates=$(puavo-conf puavo.image.automatic_updates)
  if [ "$automatic_image_updates" = 'false' ]; then
    log notice 'not doing an image update, automatic updates are off'
    do_image_update=false
  else
    # empty/missing or nonsensical value for $automatic_image_updates
    #   --> default to true
    do_image_update=true
  fi
fi

# If automatically triggered (with --auto from upstart script), use rate
# limit for image downloads but not on personally administered hosts (because
# the primary user may block automatic updates or interrupt them at any time).
if $automatically_triggered && ! $personally_administered; then
  use_rate_limit=true
fi

run_dbus() {
  dbus-send --dest=org.puavo.client.Daemon \
            --print-reply=literal          \
            --reply-timeout=30000          \
            --system                       \
            "$@" > /dev/null
}

do_puavo_pkg_update=true
case "$(puavo-conf puavo.pkgs.update)" in
  manual)
    log notice 'not updating puavo-pkgs as updates should be manual'
    do_puavo_pkg_update=false
    ;;
  nightly)
    hour=$(date +%H)
    if [ "$hour" -ge 6 ] && [ "$hour" -lt 22 ]; then
      log notice 'not updating puavo-pkgs, updates should happen only at night'
      do_puavo_pkg_update=false
    fi
    ;;
  *)
    ;;
esac

if $do_puavo_pkg_update; then
  if run_dbus /pkgupdater org.puavo.client.pkgupdater.StartUpdate; then
    log notice 'triggered puavo-pkg updates'
  else
    log err 'error in triggering puavo-pkg updates'
  fi
fi

if ! $do_image_update; then
  # do only the configuration update
  if run_dbus /updater org.puavo.client.update.UpdateConfiguration; then
    log notice 'configuration update started'
  else
    log err 'starting configuration update failed'
    exit 1
  fi
else
  if $use_rate_limit; then
    log notice 'using rate limit on image update'
  else
    log notice 'NOT using rate limit on image update'
  fi

  # do the whole update (configuration update + image update)
  if run_dbus /updater org.puavo.client.update.Update \
              "boolean:${use_rate_limit}"; then
    log notice 'system update started'
  else
    log notice 'starting system update failed'
    exit 1
  fi

  if $wait_for_image_update; then
    (
      dbus-monitor --profile --system \
        "type='signal',interface='org.puavo.client.update'" & \
      { while sleep 1; do echo quit on sigpipe; done }
    ) | awk '
            $1 == "sig" && $6 == "/updater" && $7 == "org.puavo.client.update" {
              if ($8 == "UpdateCancelled" || $8 == "UpdateFailed")     { exit 1 }
              if ($8 == "UpdateCompleted" || $8 == "UpdateIsUpToDate") { exit 0 }
            }
          '
  fi
fi
