diff --git a/Dockerfile b/Dockerfile index b9b9574..627a47e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -52,8 +52,8 @@ ENV CPU_CORES 1 ENV DISK_SIZE 16G ENV RAM_SIZE 512M -ARG BUILD_ARG 0 -ARG VERSION_ARG "0.0" +ARG BUILD_ARG=0 +ARG VERSION_ARG="0.0" ENV BUILD=$BUILD_ARG ENV VERSION=$VERSION_ARG diff --git a/agent/agent.sh b/agent/agent.sh index 871f657..bcd844a 100644 --- a/agent/agent.sh +++ b/agent/agent.sh @@ -1,36 +1,101 @@ #!/usr/bin/env bash set -u +VERSION="4" +HEADER="VirtualDSM Agent" + # Functions +finish() { + + echo "$HEADER: Shutting down.." + exit + +} + function checkNMI { local nmi - nmi=$(awk '/NMI/ {for (i=2; i<=NF; i++) if ($i ~ /^[0-9]+$/) {sum+=$i}} END {print sum}' /proc/interrupts) + nmi=$(cat /proc/interrupts | grep NMI | sed 's/[^1-9]*//g') - if [ "$nmi" != "" ] && [ "$nmi" -ne "0" ]; then + if [ "$nmi" != "" ]; then - echo "Received shutdown request through NMI.." > /dev/ttyS0 + echo "$HEADER: Received shutdown request through NMI.." /usr/syno/sbin/synoshutdown -s > /dev/null - exit + finish fi - } -finish() { +function downloadUpdate { - echo "Shutting down Guest Agent.." > /dev/ttyS0 - exit + TMP="/tmp/agent.sh" + rm -f "${TMP}" + + # Auto update the agent + + URL="https://raw.githubusercontent.com/kroese/virtual-dsm/master/agent/agent.sh" + remote_size=$(curl -sIk -m 4 "${URL}" | grep -i "content-length:" | tr -d " \t" | cut -d ':' -f 2) + + [ "$remote_size" == "" ] && return + [ "$remote_size" == "0" ] && return + + SCRIPT=$(readlink -f ${BASH_SOURCE[0]}) + local_size=$(stat -c%s "$SCRIPT") + + [ "$remote_size" == "$local_size" ] && return + + if ! curl -sfk -m 10 -o "${TMP}" "${URL}"; then + echo "$HEADER: curl error" && return + fi + + if [ ! -f "${TMP}" ]; then + echo "$HEADER: update error, file not found.." && return + fi + + line=$(head -1 "${TMP}") + + if [ "$line" != "#!/usr/bin/env bash" ]; then + echo "$HEADER: update error, invalid header: $line" && return + fi + + if cmp --silent -- "${TMP}" "${SCRIPT}"; then + echo "$HEADER: update file is already equal?" && return + fi + + mv -f "${TMP}" "${SCRIPT}" + chmod +x "${SCRIPT}" + + echo "$HEADER: succesfully installed update, please reboot." + +} + +function installPackages { + + for filename in /usr/local/packages/*.spk; do + if [ -f "$filename" ]; then + + BASE=$(basename "$filename" .spk) + BASE="${BASE%%-*}" + + echo "$HEADER: Installing package ${BASE}.." + + /usr/syno/bin/synopkg install "$filename" > /dev/null + /usr/syno/bin/synopkg start "$BASE" > /dev/null & + + rm "$filename" + + fi + done } trap finish SIGINT SIGTERM -# Setup serialport +ts=$(date +%s%N) +echo "$HEADER v$VERSION" -chmod 666 /dev/ttyS0 checkNMI # Install packages @@ -44,36 +109,28 @@ for filename in /usr/local/packages/*.spk; do done if [ "$first_run" = true ]; then - for filename in /usr/local/packages/*.spk; do - if [ -f "$filename" ]; then - - BASE=$(basename "$filename" .spk) - BASE="${BASE%%-*}" - - echo "Installing package ${BASE}.." > /dev/ttyS0 - /usr/syno/bin/synopkg install "$filename" > /dev/null - - echo "Starting package ${BASE}.." > /dev/ttyS0 - /usr/syno/bin/synopkg start "$BASE" > /dev/null - - rm "$filename" - - fi - done -else - # TODO: Auto-update agent - echo "Checking for updates.." > /dev/ttyS0 + installPackages - sleep 5 +else + downloadUpdate + +fi + +delay=5000 +elapsed=$((($(date +%s%N) - ts)/1000000)) + +if (( delay > elapsed )); then + difference=$((delay-elapsed)) + sleep "$(echo | awk -v diff="${difference}" '{print diff * 0.001}')" fi # Display message in docker log output -echo "-------------------------------------------" > /dev/ttyS0 -echo " You can now login to DSM at port 5000 " > /dev/ttyS0 -echo "-------------------------------------------" > /dev/ttyS0 +echo "-------------------------------------------" +echo " You can now login to DSM at port 5000 " +echo "-------------------------------------------" # Wait for NMI interrupt as a shutdown signal @@ -83,3 +140,4 @@ while true; do sleep 2 done +. diff --git a/agent/service.sh b/agent/service.sh index 4bf057d..1fe2494 100644 --- a/agent/service.sh +++ b/agent/service.sh @@ -1,7 +1,6 @@ #!/bin/bash PIDFILE="/var/run/agent.pid" -LOGFILE="/var/log/agent.log" SCRIPT="/usr/local/bin/agent.sh" status() { @@ -17,7 +16,8 @@ start() { return 1 fi printf 'Starting agent service...' >&2 - "$SCRIPT" &> "$LOGFILE" & echo $! > "$PIDFILE" + chmod 666 /dev/ttyS0 + "$SCRIPT" &> /dev/ttyS0 & echo $! > "$PIDFILE" } stop() { diff --git a/run/disk.sh b/run/disk.sh index 3b73753..b4585ec 100644 --- a/run/disk.sh +++ b/run/disk.sh @@ -80,12 +80,12 @@ if [ ! -f "${DATA}" ]; then fi +AGENT_VERSION=1 AGENT="${STORAGE}/${BASE}.agent" -[ ! -f "$AGENT" ] && echo "1" > "$AGENT" -AGENT_VERSION=$(cat "${AGENT}") +[ -f "$AGENT" ] && AGENT_VERSION=$(cat "${AGENT}") -if ((AGENT_VERSION < 3)); then - echo "INFO: The installed Guest Agent in DSM is an outdated version, please upgrade it." +if ((AGENT_VERSION < 4)); then + echo "INFO: The installed VirtualDSM Agent is an outdated version, please upgrade it." fi KVM_DISK_OPTS="\ diff --git a/run/install.sh b/run/install.sh index d78c5ea..fb69e3b 100644 --- a/run/install.sh +++ b/run/install.sh @@ -28,12 +28,15 @@ RD="$TMP/rd.gz" rm -rf $TMP && mkdir -p $TMP LOC="$DL/release/7.0.1/42218/DSM_VirtualDSM_42218.pat" -curl -r 64493568-69886247 -s -k -o "$RD" "$LOC" + +if ! curl -r 64493568-69886247 -sfk -o "$RD" "$LOC"; then + echo "Failed to download extractor, code: $?" && exit 60 +fi SUM=$(md5sum $RD | cut -f 1 -d " ") if [ $SUM != "14fb88cb7cabddb5af1d0269bf032845" ]; then - echo "Invalid extractor, checksum failed." && exit 59 + echo "Invalid extractor, checksum failed." && exit 61 fi set +e @@ -160,7 +163,7 @@ cp /agent/service.sh $LOC/agent.sh chmod +x $LOC/agent.sh # Store agent version -echo "3" > "$STORAGE"/"$BASE".agent +echo "4" > "$STORAGE"/"$BASE".agent echo "Install: Installing system partition..." diff --git a/run/power.sh b/run/power.sh index b6556f0..b49cc8a 100644 --- a/run/power.sh +++ b/run/power.sh @@ -32,7 +32,7 @@ _graceful_shutdown(){ # Don't send the powerdown signal because vDSM ignores ACPI signals # echo 'system_powerdown' | nc -q 1 -w 1 localhost "${QEMU_MONPORT}" > /dev/null - # Send shutdown command to guest agent tools instead via serial port + # Send shutdown command to host via serial port RESPONSE=$(curl -s -m 2 -S http://127.0.0.1:2210/write?command=6 2>&1) if [[ ! "${RESPONSE}" =~ "\"success\"" ]] ; then @@ -40,14 +40,16 @@ _graceful_shutdown(){ echo echo "Could not send shutdown command to guest, error: $RESPONSE" + # If we cannot shutdown the usual way, fallback to the NMI method + + AGENT_VERSION=1 AGENT="${STORAGE}/${BASE}.agent" - [ ! -f "$AGENT" ] && echo "1" > "$AGENT" - AGENT_VERSION=$(cat "${AGENT}") + [ -f "$AGENT" ] && AGENT_VERSION=$(cat "${AGENT}") if ((AGENT_VERSION < 2)); then echo - echo "Please update the agent to allow gracefull shutdowns..." + echo "Please update the VirtualDSM Agent to allow gracefull shutdowns..." pkill -f qemu-system-x86_64 diff --git a/run/run.sh b/run/run.sh index 72194c1..3946cb5 100755 --- a/run/run.sh +++ b/run/run.sh @@ -52,7 +52,5 @@ set -m ) set +m -# Since we started the QEMU process with -m, we need to poll if it's still running -while [ -d "/proc/$(cat ${_QEMU_PID})" ]; do - sleep 1 -done +pidwait -F "${_QEMU_PID}" & +wait $! diff --git a/run/serial.sh b/run/serial.sh index 6985eb4..0d533a4 100644 --- a/run/serial.sh +++ b/run/serial.sh @@ -12,7 +12,7 @@ set -eu : ${GUEST_UUID:='ba13a19a-c0c1-4fef-9346-915ed3b98341'} if [ -z "$HOST_CPU" ]; then - HOST_CPU=$(lscpu | sed -nr '/Model name/ s/.*:\s*(.*) @ .*/\1/p' | sed ':a;s/ / /;ta' | sed 's/"(R)"//g' | sed 's/"-"/" "/g' | sed 's/[^[:alnum:] ]\+//g') + HOST_CPU=$(lscpu | sed -nr '/Model name/ s/.*:\s*(.*) @ .*/\1/p' | sed ':a;s/ / /;ta' | sed s/"(R)"//g | sed 's/[^[:alnum:] ]\+/ /g' | sed 's/ */ /g') fi if [ -n "$HOST_CPU" ]; then