diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 350da42..3011638 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -11,4 +11,4 @@ jobs: - name: Run ShellCheck uses: ludeeus/action-shellcheck@master env: - SHELLCHECK_OPTS: -x -e SC2001 -e SC2002 -e SC2223 -e SC2034 -e SC2064 -e SC2317 + SHELLCHECK_OPTS: -x -e SC2001 -e SC2002 -e SC2223 -e SC2034 -e SC2064 -e SC2317 -e SC2028 diff --git a/Dockerfile b/Dockerfile index b4a1b26..0aaec57 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,8 +27,8 @@ RUN apt-get update && apt-get -y upgrade && \ net-tools \ btrfs-progs \ ca-certificates \ - netcat-openbsd \ qemu-system-x86 \ + netcat-traditional \ && apt-get clean COPY run/*.sh /run/ @@ -65,6 +65,6 @@ LABEL org.opencontainers.image.version=${VERSION_ARG} LABEL org.opencontainers.image.source=https://github.com/kroese/virtual-dsm/ LABEL org.opencontainers.image.url=https://hub.docker.com/r/kroese/virtual-dsm/ -HEALTHCHECK --interval=30s --retries=3 CMD /run/check.sh +HEALTHCHECK --interval=30s --retries=2 CMD /run/check.sh ENTRYPOINT ["/run/run.sh"] diff --git a/run/check.sh b/run/check.sh index 0b74eb7..b9024f3 100644 --- a/run/check.sh +++ b/run/check.sh @@ -1,16 +1,47 @@ #!/usr/bin/env bash set -u -# Docker Healthcheck +# Retrieve guest info for Docker healthcheck +RESPONSE=$(curl -s -m 6 -S http://127.0.0.1:2210/read?command=10 2>&1) -: ${DHCP:='N'} +if [[ ! "${RESPONSE}" =~ "\"success\"" ]] ; then + echo "Failed to connect to guest: $RESPONSE" + exit 1 +fi -if [[ "${DHCP}" == [Yy1]* ]]; then - PORT=5555 - IP="127.0.0.1" -else - PORT=5000 - IP="20.20.20.21" +# Retrieve the HTTP port number + +if [[ ! "${RESPONSE}" =~ "\"http_port\"" ]] ; then + echo "Failed to parse response from guest: $RESPONSE" + exit 1 +fi + +rest=${RESPONSE#*http_port} +rest=${rest#*:} +rest=${rest%%,*} +PORT=${rest%%\"*} + +if [ -z "${PORT}" ]; then + echo "Guest has not set a portnumber yet.." + exit 1 +fi + +# Retrieve the IP address + +if [[ ! "${RESPONSE}" =~ "eth0" ]] ; then + echo "Failed to parse response from guest: $RESPONSE" + exit 1 +fi + +rest=${RESPONSE#*eth0} +rest=${rest#*ip} +rest=${rest#*:} +rest=${rest#*\"} +IP=${rest%%\"*} + +if [ -z "${IP}" ]; then + echo "Guest has not received an IP yet.." + exit 1 fi if ! curl -m 3 -ILfSs "http://${IP}:${PORT}/" > /dev/null; then diff --git a/run/install.sh b/run/install.sh index c153507..7d42c51 100644 --- a/run/install.sh +++ b/run/install.sh @@ -5,9 +5,10 @@ set -Eeuo pipefail HTML="Please wait while Virtual DSM is installing..." -pkill -f server.sh || true -/run/server.sh 80 "${HTML}" > /dev/null & -/run/server.sh 5000 "${HTML}" > /dev/null & +{ pkill -f server.sh || true; } 2>/dev/null + +/run/server.sh 80 "${HTML}" & +/run/server.sh 5000 "${HTML}" & # Download the required files from the Synology website DL="https://global.synologydownload.com/download/DSM" diff --git a/run/network.sh b/run/network.sh index dda5d96..473d48c 100644 --- a/run/network.sh +++ b/run/network.sh @@ -31,8 +31,8 @@ configureDHCP() { { ip link add link "${VM_NET_DEV}" "${VM_NET_VLAN}" type macvlan mode bridge ; rc=$?; } || : if (( rc != 0 )); then - echo -n "ERROR: Cannot create macvlan interface. Please make sure the network type is 'macvlan' and not 'ipvlan'." - echo " And that the NET_ADMIN capability has been added to the container config: --cap-add NET_ADMIN" && exit 15 + echo "ERROR: Cannot create macvlan interface. Please make sure the network type is 'macvlan' and not 'ipvlan'," + echo "ERROR: and that the NET_ADMIN capability has been added to the container config: --cap-add NET_ADMIN" && exit 15 fi ip address add "${IP}" dev "${VM_NET_VLAN}" @@ -226,14 +226,26 @@ if [[ "${DHCP}" == [Yy1]* ]]; then # Configuration for DHCP IP configureDHCP - # Display the received IP on port 5000 - HTML="DSM is using another IP address.

Check the Docker logfile to see which one was
assigned, or download the\ - \ - Synology Assistant utility." + { pkill -f server.sh || true; } 2>/dev/null - pkill -f server.sh || true - /run/server.sh 80 "${HTML}" > /dev/null & - /run/server.sh 5000 "${HTML}" > /dev/null & + SH_SCRIPT="/run/ipinfo.sh" + + { echo "#!/bin/bash" + echo "INFO=\$(curl -s -m 5 -S http://127.0.0.1:2210/read?command=10 2>/dev/null)" + echo "rest=\${INFO#*http_port}; rest=\${rest#*:}; rest=\${rest%%,*}; PORT=\${rest%%\\\"*}" + echo "rest=\${INFO#*eth0}; rest=\${rest#*ip}; rest=\${rest#*:}; rest=\${rest#*\\\"}; IP=\${rest%%\\\"*}" + echo "BODY=\"The location of DSM is http://\${IP}:\${PORT}\"" + echo "HTML=\"VirtualDSM

\$BODY

\"" + echo "LENGTH=\"\${#HTML}\"; RESPONSE=\"HTTP/1.1 200 OK\\nContent-Length: \${LENGTH}\\nConnection: close\\n\\n\$HTML\\n\\n\"" + echo "echo -e \"\$RESPONSE\"" + } > "$SH_SCRIPT" + + chmod +x "$SH_SCRIPT" + + /run/server.sh 80 "$SH_SCRIPT" & + /run/server.sh 5000 "$SH_SCRIPT" & else @@ -244,17 +256,6 @@ fi NET_OPTS="${NET_OPTS} -device virtio-net-pci,romfile=,netdev=hostnet0,mac=${VM_NET_MAC},id=net0" -if [[ "${DHCP}" == [Yy1]* ]]; then - - # Add extra LAN interface for Docker Healthcheck script - - : ${MAC2:='02:11:32:CC:BB:AA'} - - NET_OPTS="${NET_OPTS} -netdev user,id=hostnet1,restrict=y,hostfwd=tcp::5555-:5000" - NET_OPTS="${NET_OPTS} -device virtio-net-pci,romfile=,netdev=hostnet1,mac=${MAC2},id=net1" - -fi - [[ "${DEBUG}" == [Yy1]* ]] && echo && echo "Finished network setup.." && echo return 0 diff --git a/run/power.sh b/run/power.sh index 08cfd03..817f167 100644 --- a/run/power.sh +++ b/run/power.sh @@ -33,7 +33,7 @@ _graceful_shutdown() { # echo 'system_powerdown' | nc -q 1 -w 1 localhost "${QEMU_MONPORT}" > /dev/null # Send shutdown command to guest agent via serial port - RESPONSE=$(curl -s -m 2 -S http://127.0.0.1:2210/write?command=6 2>&1) + RESPONSE=$(curl -s -m 5 -S http://127.0.0.1:2210/read?command=6 2>&1) if [[ ! "${RESPONSE}" =~ "\"success\"" ]] ; then @@ -47,9 +47,13 @@ _graceful_shutdown() { if ((AGENT_VERSION > 1)); then # Send a NMI interrupt which will be detected by the kernel - echo 'nmi' | nc -q 1 -w 1 localhost "${QEMU_MONPORT}" > /dev/null - - else + if ! echo 'nmi' | nc -q 1 -w 1 localhost "${QEMU_MONPORT}" > /dev/null ; then + AGENT_VERSION=0 + fi + + fi + + if ((AGENT_VERSION < 2)); then echo && echo "Please update the VirtualDSM Agent to allow for gracefull shutdowns..." @@ -65,7 +69,7 @@ _graceful_shutdown() { echo $(($(cat ${_QEMU_SHUTDOWN_COUNTER})+1)) > ${_QEMU_SHUTDOWN_COUNTER} # Try to connect to qemu - if echo 'info version'| nc -q 1 -w 1 localhost "${QEMU_MONPORT}" > /dev/null; then + if echo 'info version'| nc -q 1 -w 1 localhost "${QEMU_MONPORT}" >/dev/null 2>&1 ; then sleep 1 #echo "Shutting down, waiting... ($(cat ${_QEMU_SHUTDOWN_COUNTER})/${QEMU_POWERDOWN_TIMEOUT})" @@ -75,7 +79,7 @@ _graceful_shutdown() { done echo && echo "Quitting..." - echo 'quit' | nc -q 1 -w 1 localhost "${QEMU_MONPORT}" > /dev/null || true + echo 'quit' | nc -q 1 -w 1 localhost "${QEMU_MONPORT}" >/dev/null 2>&1 || true return } diff --git a/run/server.sh b/run/server.sh index ae3c6ae..b6a8a4e 100644 --- a/run/server.sh +++ b/run/server.sh @@ -1,17 +1,29 @@ #!/usr/bin/env bash set -eu -trap 'kill 0' EXIT -trap exit SIGINT SIGTERM +stop() { + trap - SIGINT EXIT + { pkill -f nc || true; } 2>/dev/null +} -# Serve the page -HTML="VirtualDSM

$2

" +trap 'stop' EXIT SIGINT SIGTERM SIGHUP -LENGTH="${#HTML}" +if [[ "$2" == "/"* ]]; then -RESPONSE="HTTP/1.1 200 OK\nContent-Length: ${LENGTH}\nConnection: close\n\n$HTML\n\n" + while true ; do + nc -lp "${1:-5000}" -e "$2" & wait $! + done -while true; do - echo -en "$RESPONSE" | nc -lp "${1:-5000}" & wait $! -done +else + + HTML="VirtualDSM

$2

" + + LENGTH="${#HTML}" + RESPONSE="HTTP/1.1 200 OK\nContent-Length: ${LENGTH}\nConnection: close\n\n$HTML\n\n" + + while true; do + echo -en "$RESPONSE" | nc -lp "${1:-5000}" & wait $! + done + +fi