Compare commits

..

3 Commits
v4.40 ... v4.42

Author SHA1 Message Date
Kroese
8fa900335a feat: Add qcow2 disk format (#440)
* feat: Add qcow2 disk format
2023-12-09 02:55:39 +01:00
Kroese
a527080ccd feat: Print curl error (#438)
* feat: Print curl error
2023-12-07 23:36:57 +01:00
Kroese
ce6d60c611 Parse JSON with JQ (#437)
* feat: Parse JSON with JQ
2023-12-07 23:18:47 +01:00
8 changed files with 300 additions and 166 deletions

View File

@@ -28,6 +28,7 @@ RUN apt-get update && apt-get -y upgrade && \
iproute2 \ iproute2 \
dnsmasq \ dnsmasq \
net-tools \ net-tools \
qemu-utils \
ca-certificates \ ca-certificates \
netcat-openbsd \ netcat-openbsd \
qemu-system-x86 \ qemu-system-x86 \

View File

@@ -87,16 +87,16 @@ docker run -it --rm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-ti
- /mnt/data/example:/storage3 - /mnt/data/example:/storage3
``` ```
* ### How do I change the space reserved by the virtual disk? * ### How do I create a growable disk?
By default, the entire disk space is reserved in advance. To create a growable disk that only reserves the space that is actually used, add the following environment variable: By default, the entire disk space is reserved in advance. To create a growable disk that only allocates space that is actually used, add the following environment variable:
```yaml ```yaml
environment: environment:
ALLOCATE: "N" DISK_FMT: "qcow2"
``` ```
Keep in mind that this will not affect any of your existing disks, it only applies to newly created disks. This can also be used to convert any existing disks to the ```qcow2``` format.
* ### How do I increase the amount of CPU or RAM? * ### How do I increase the amount of CPU or RAM?

View File

@@ -9,53 +9,40 @@ file="/run/dsm.url"
if [ ! -f "$file" ]; then if [ ! -f "$file" ]; then
# Retrieve IP from guest VM for Docker healthcheck # Retrieve IP from guest VM for Docker healthcheck
RESPONSE=$(curl -s -m 30 -S http://127.0.0.1:2210/read?command=10 2>&1)
if [[ ! "${RESPONSE}" =~ "\"success\"" ]] ; then { json=$(curl -m 30 -sk http://127.0.0.1:2210/read?command=10); rc=$?; } || :
echo "Failed to connect to guest: $RESPONSE" && exit 1 (( rc != 0 )) && echo "Failed to connect to guest: curl error $rc" && exit 1
{ result=$(echo "$json" | jq -r '.status'); rc=$?; } || :
(( rc != 0 )) && echo "Failed to parse response from guest: jq error $rc ( $json )" && exit 1
[[ "$result" == "null" ]] && echo "Guest returned invalid response: $json" && exit 1
if [[ "$result" != "success" ]] ; then
{ msg=$(echo "$json" | jq -r '.message'); rc=$?; } || :
echo "Guest replied ${result}: $msg" && exit 1
fi fi
# Retrieve the HTTP port number { port=$(echo "$json" | jq -r '.data.data.dsm_setting.data.http_port'); rc=$?; } || :
if [[ ! "${RESPONSE}" =~ "\"http_port\"" ]] ; then (( rc != 0 )) && echo "Failed to parse response from guest: jq error $rc ( $json )" && exit 1
echo "Failed to parse response from guest: $RESPONSE" && exit 1 [[ "$port" == "null" ]] && echo "Guest has not set a portnumber yet.." && exit 1
fi [ -z "${port}" ] && echo "Guest has not set a portnumber yet.." && exit 1
rest=${RESPONSE#*http_port} { ip=$(echo "$json" | jq -r '.data.data.ip.data[] | select((.name=="eth0") and has("ip")).ip'); rc=$?; } || :
rest=${rest#*:} (( rc != 0 )) && echo "Failed to parse response from guest: jq error $rc ( $json )" && exit 1
rest=${rest%%,*} [[ "$ip" == "null" ]] && echo "Guest returned invalid response: $json" && exit 1
PORT=${rest%%\"*} [ -z "${ip}" ] && echo "Guest has not received an IP yet.." && exit 1
[ -z "${PORT}" ] && echo "Guest has not set a portnumber yet.." && exit 1 echo "${ip}:${port}" > $file
# 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%%\"*}
[ -z "${IP}" ] && echo "Guest has not received an IP yet.." && exit 1
echo "${IP}:${PORT}" > $file
fi fi
LOCATION=$(cat "$file") location=$(cat "$file")
if ! curl -m 20 -ILfSs "http://${LOCATION}/" > /dev/null; then if ! curl -m 20 -ILfSs "http://${location}/" > /dev/null; then
rm -f $file rm -f $file
echo "Failed to reach http://${LOCATION}" echo "Failed to reach http://${location}"
exit 1 exit 1
fi fi
if [[ "$LOCATION" == "20.20"* ]]; then echo "Healthcheck OK"
echo "Healthcheck OK"
else
echo "Healthcheck OK ( ${LOCATION%:*} )"
fi
exit 0 exit 0

View File

@@ -4,6 +4,7 @@ set -Eeuo pipefail
# Docker environment variables # Docker environment variables
: ${DISK_IO:='native'} # I/O Mode, can be set to 'native', 'threads' or 'io_turing' : ${DISK_IO:='native'} # I/O Mode, can be set to 'native', 'threads' or 'io_turing'
: ${DISK_FMT:='raw'} # Disk file format, 'raw' by default for best performance
: ${DISK_CACHE:='none'} # Caching mode, can be set to 'writeback' for better performance : ${DISK_CACHE:='none'} # Caching mode, can be set to 'writeback' for better performance
: ${DISK_DISCARD:='on'} # Controls whether unmap (TRIM) commands are passed to the host. : ${DISK_DISCARD:='on'} # Controls whether unmap (TRIM) commands are passed to the host.
: ${DISK_ROTATION:='1'} # Rotation rate, set to 1 for SSD storage and increase for HDD : ${DISK_ROTATION:='1'} # Rotation rate, set to 1 for SSD storage and increase for HDD
@@ -22,48 +23,77 @@ DISK_OPTS="\
-drive file=${SYSTEM},if=none,id=drive-synosys,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \ -drive file=${SYSTEM},if=none,id=drive-synosys,format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
-device scsi-hd,bus=hw-synosys.0,channel=0,scsi-id=0,lun=0,drive=drive-synosys,id=synosys0,rotation_rate=${DISK_ROTATION},bootindex=2" -device scsi-hd,bus=hw-synosys.0,channel=0,scsi-id=0,lun=0,drive=drive-synosys,id=synosys0,rotation_rate=${DISK_ROTATION},bootindex=2"
addDisk () { fmt2ext() {
local DISK_FMT=$1
case "${DISK_FMT,,}" in
qcow2)
echo "qcow2"
;;
raw)
echo "img"
;;
*)
error "Unrecognized disk format: ${DISK_FMT}" && exit 88
;;
esac
}
ext2fmt() {
local DISK_EXT=$1
case "${DISK_EXT,,}" in
qcow2)
echo "qcow2"
;;
img)
echo "raw"
;;
*)
error "Unrecognized file extension: .${DISK_EXT}" && exit 90
;;
esac
}
getSize() {
local DISK_FILE=$1
local DISK_EXT
local DISK_FMT
DISK_EXT="$(echo "${DISK_FILE//*./}" | sed 's/^.*\.//')"
DISK_FMT="$(ext2fmt "${DISK_EXT}")"
case "${DISK_FMT,,}" in
raw)
stat -c%s "${DISK_FILE}"
;;
qcow2)
qemu-img info "${DISK_FILE}" -f "${DISK_FMT}" | grep '^virtual size: ' | sed 's/.*(\(.*\) bytes)/\1/'
;;
*)
error "Unrecognized disk format: ${DISK_FMT}" && exit 88
;;
esac
}
resizeDisk() {
local FS
local GB local GB
local DIR
local REQ local REQ
local SPACE local SPACE
local CUR_SIZE local SPACE_GB
local DATA_SIZE local DISK_FILE=$1
local DISK_ID=$1 local CUR_SIZE=$2
local DISK_FILE=$2 local DATA_SIZE=$3
local DISK_DESC=$3
local DISK_SPACE=$4 local DISK_SPACE=$4
local DISK_INDEX=$5 local DISK_DESC=$5
local DISK_ADDRESS=$6 local DISK_FMT=$6
DIR=$(dirname "${DISK_FILE}")
[ ! -d "${DIR}" ] && return 0
FS=$(stat -f -c %T "$DIR")
if [[ "$FS" == "overlay"* ]]; then
info "Warning: the filesystem of ${DIR} is OverlayFS, this usually means it was binded to an invalid path!"
fi
[ -z "$DISK_SPACE" ] && DISK_SPACE="16G"
DISK_SPACE=$(echo "${DISK_SPACE}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
DATA_SIZE=$(numfmt --from=iec "${DISK_SPACE}")
if (( DATA_SIZE < 6442450944 )); then
error "Please increase ${DISK_DESC^^}_SIZE to at least 6 GB." && exit 83
fi
if [ -f "${DISK_FILE}" ]; then
CUR_SIZE=$(stat -c%s "${DISK_FILE}")
if [ "$DATA_SIZE" -gt "$CUR_SIZE" ]; then
GB=$(( (CUR_SIZE + 1073741823)/1073741824 )) GB=$(( (CUR_SIZE + 1073741823)/1073741824 ))
info "Resizing ${DISK_DESC} from ${GB}G to ${DISK_SPACE} .." info "Resizing ${DISK_DESC} from ${GB}G to ${DISK_SPACE} .."
case "${DISK_FMT,,}" in
raw)
if [[ "${ALLOCATE}" == [Nn]* ]]; then if [[ "${ALLOCATE}" == [Nn]* ]]; then
# Resize file by changing its length # Resize file by changing its length
@@ -81,7 +111,7 @@ addDisk () {
if (( REQ > SPACE )); then if (( REQ > SPACE )); then
error "Not enough free space to resize ${DISK_DESC} to ${DISK_SPACE} in ${DIR}, it has only ${SPACE_GB} GB available.." error "Not enough free space to resize ${DISK_DESC} to ${DISK_SPACE} in ${DIR}, it has only ${SPACE_GB} GB available.."
error "Specify a smaller ${DISK_DESC^^}_SIZE or disable preallocation with ALLOCATE=N." && exit 84 error "Specify a smaller ${DISK_DESC^^}_SIZE or switch to a growable disk with DISK_FMT=qcow2." && exit 84
fi fi
# Resize file by allocating more space # Resize file by allocating more space
@@ -92,17 +122,51 @@ addDisk () {
fi fi
fi fi
;;
qcow2)
if ! qemu-img resize -f "${DISK_FMT}" "${DISK_FILE}" "${DISK_SPACE}" ; then
error "Could not resize ${DISK_DESC} file (${DISK_FILE}) to ${DISK_SPACE}" && exit 85
fi fi
fi ;;
esac
}
if [ ! -f "${DISK_FILE}" ]; then convertDisk() {
local CONV_FLAGS=""
local SOURCE_FILE=$1
local SOURCE_FMT=$2
local DST_FILE=$3
local DST_FMT=$4
case "${DST_FMT}" in
qcow2)
CONV_FLAGS="${CONV_FLAGS} -c"
;;
esac
# shellcheck disable=SC2086
qemu-img convert ${CONV_FLAGS} -f "${SOURCE_FMT}" -O "${DST_FMT}" -- "${SOURCE_FILE}" "${DST_FILE}"
}
createDisk() {
local GB
local SPACE
local SPACE_GB
local DISK_FILE=$1
local DISK_SPACE=$2
local DISK_DESC=$3
local DISK_FMT=$4
case "${DISK_FMT,,}" in
raw)
if [[ "${ALLOCATE}" == [Nn]* ]]; then if [[ "${ALLOCATE}" == [Nn]* ]]; then
# Create an empty file # Create an empty file
if ! truncate -s "${DISK_SPACE}" "${DISK_FILE}"; then if ! truncate -s "${DISK_SPACE}" "${DISK_FILE}"; then
rm -f "${DISK_FILE}" rm -f "${DISK_FILE}"
error "Could not create a ${DISK_SPACE} file for ${DISK_DESC} (${DISK_FILE})" && exit 87 error "Could not create a ${DISK_SPACE} ${DISK_FMT} file for ${DISK_DESC} (${DISK_FILE})" && exit 87
fi fi
else else
@@ -113,66 +177,147 @@ addDisk () {
if (( DATA_SIZE > SPACE )); then if (( DATA_SIZE > SPACE )); then
error "Not enough free space to create ${DISK_DESC} of ${DISK_SPACE} in ${DIR}, it has only ${SPACE_GB} GB available.." error "Not enough free space to create ${DISK_DESC} of ${DISK_SPACE} in ${DIR}, it has only ${SPACE_GB} GB available.."
error "Specify a smaller ${DISK_DESC^^}_SIZE or disable preallocation with ALLOCATE=N." && exit 86 error "Specify a smaller ${DISK_DESC^^}_SIZE or switch to a growable disk with DISK_FMT=qcow2." && exit 86
fi fi
# Create an empty file # Create an empty file
if ! fallocate -l "${DISK_SPACE}" "${DISK_FILE}"; then if ! fallocate -l "${DISK_SPACE}" "${DISK_FILE}"; then
if ! truncate -s "${DISK_SPACE}" "${DISK_FILE}"; then if ! truncate -s "${DISK_SPACE}" "${DISK_FILE}"; then
rm -f "${DISK_FILE}" rm -f "${DISK_FILE}"
error "Could not create a ${DISK_SPACE} file for ${DISK_DESC} (${DISK_FILE})" && exit 87 error "Could not create a ${DISK_SPACE} ${DISK_FMT} file for ${DISK_DESC} (${DISK_FILE})" && exit 87
fi fi
fi fi
fi fi
;;
qcow2)
if ! qemu-img create -f "$DISK_FMT" -- "${DISK_FILE}" "${DISK_SPACE}" ; then
error "Could not create a ${DISK_SPACE} ${DISK_FMT} file for ${DISK_DESC} (${DISK_FILE})" && exit 89
fi
;;
esac
}
addDisk () {
local FS
local DIR
local CUR_SIZE
local DATA_SIZE
local DISK_FILE
local DISK_ID=$1
local DISK_BASE=$2
local DISK_EXT=$3
local DISK_DESC=$4
local DISK_SPACE=$5
local DISK_INDEX=$6
local DISK_ADDRESS=$7
local DISK_FMT=$8
DISK_FILE="${DISK_BASE}.${DISK_EXT}"
DIR=$(dirname "${DISK_FILE}")
[ ! -d "${DIR}" ] && return 0
FS=$(stat -f -c %T "$DIR")
if [[ "$FS" == "overlay"* ]]; then
info "Warning: the filesystem of ${DIR} is OverlayFS, this usually means it was binded to an invalid path!"
fi
if ! [ -f "${DISK_FILE}" ] ; then
local PREV_EXT
local PREV_FMT
local PREV_FILE
if [[ "${DISK_FMT,,}" != "raw" ]]; then
PREV_FMT="raw"
else
PREV_FMT="qcow2"
fi
PREV_EXT="$(fmt2ext "${PREV_FMT}")"
PREV_FILE="${DISK_BASE}.${PREV_EXT}"
if [ -f "${PREV_FILE}" ] ; then
info "Disk format change detected for ${DISK_DESC} (${PREV_FMT} to ${DISK_FMT}), converting ${PREV_FILE} ..."
if ! convertDisk "${PREV_FILE}" "${PREV_FMT}" "${DISK_FILE}" "${DISK_FMT}" ; then
info "Disk conversion failed, creating new disk image as fallback."
rm -f "${DISK_FILE}"
else
info "Disk conversion completed succesfully, removing ${PREV_FILE} ..."
rm -f "${PREV_FILE}"
fi
fi
fi
[ -z "$DISK_SPACE" ] && DISK_SPACE="16G"
DISK_SPACE=$(echo "${DISK_SPACE}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
DATA_SIZE=$(numfmt --from=iec "${DISK_SPACE}")
if (( DATA_SIZE < 6442450944 )); then
error "Please increase ${DISK_DESC^^}_SIZE to at least 6 GB." && exit 83
fi
if [ -f "${DISK_FILE}" ]; then
CUR_SIZE=$(getSize "${DISK_FILE}")
if [ "$DATA_SIZE" -gt "$CUR_SIZE" ]; then
resizeDisk "${DISK_FILE}" "${CUR_SIZE}" "${DATA_SIZE}" "${DISK_SPACE}" "${DISK_DESC}" "${DISK_FMT}" || exit $?
fi
else
createDisk "${DISK_FILE}" "${DISK_SPACE}" "${DISK_DESC}" "${DISK_FMT}" || exit $?
fi fi
DISK_OPTS="${DISK_OPTS} \ DISK_OPTS="${DISK_OPTS} \
-device virtio-scsi-pci,id=hw-${DISK_ID},bus=pcie.0,addr=${DISK_ADDRESS} \ -device virtio-scsi-pci,id=hw-${DISK_ID},bus=pcie.0,addr=${DISK_ADDRESS} \
-drive file=${DISK_FILE},if=none,id=drive-${DISK_ID},format=raw,cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \ -drive file=${DISK_FILE},if=none,id=drive-${DISK_ID},format=${DISK_FMT},cache=${DISK_CACHE},aio=${DISK_IO},discard=${DISK_DISCARD},detect-zeroes=on \
-device scsi-hd,bus=hw-${DISK_ID}.0,channel=0,scsi-id=0,lun=0,drive=drive-${DISK_ID},id=${DISK_ID},rotation_rate=${DISK_ROTATION},bootindex=${DISK_INDEX}" -device scsi-hd,bus=hw-${DISK_ID}.0,channel=0,scsi-id=0,lun=0,drive=drive-${DISK_ID},id=${DISK_ID},rotation_rate=${DISK_ROTATION},bootindex=${DISK_INDEX}"
return 0 return 0
} }
DISK1_FILE="${STORAGE}/data.img" DISK_EXT="$(fmt2ext "${DISK_FMT}")" || exit $?
if [[ ! -f "${DISK1_FILE}" ]] && [[ -f "${STORAGE}/data${DISK_SIZE}.img" ]]; then DISK1_FILE="${STORAGE}/data"
if [[ ! -f "${DISK1_FILE}.img" ]] && [[ -f "${STORAGE}/data${DISK_SIZE}.img" ]]; then
# Fallback for legacy installs # Fallback for legacy installs
mv "${STORAGE}/data${DISK_SIZE}.img" "${DISK1_FILE}" mv "${STORAGE}/data${DISK_SIZE}.img" "${DISK1_FILE}.img"
fi fi
DISK2_FILE="/storage2/data2.img" DISK2_FILE="/storage2/data2"
if [ ! -f "${DISK2_FILE}.img" ]; then
if [ ! -f "${DISK2_FILE}" ]; then
# Fallback for legacy installs # Fallback for legacy installs
FALLBACK="/storage2/data.img" FALLBACK="/storage2/data.img"
if [[ -f "${DISK1_FILE}" ]] && [[ -f "${FALLBACK}" ]]; then if [[ -f "${DISK1_FILE}.img" ]] && [[ -f "${FALLBACK}" ]]; then
SIZE1=$(stat -c%s "${FALLBACK}") SIZE1=$(stat -c%s "${FALLBACK}")
SIZE2=$(stat -c%s "${DISK1_FILE}") SIZE2=$(stat -c%s "${DISK1_FILE}.img")
if [[ SIZE1 -ne SIZE2 ]]; then if [[ SIZE1 -ne SIZE2 ]]; then
mv "${FALLBACK}" "${DISK2_FILE}" mv "${FALLBACK}" "${DISK2_FILE}.img"
fi fi
fi fi
fi fi
DISK3_FILE="/storage3/data3.img" DISK3_FILE="/storage3/data3"
if [ ! -f "${DISK3_FILE}.img" ]; then
if [ ! -f "${DISK3_FILE}" ]; then
# Fallback for legacy installs # Fallback for legacy installs
FALLBACK="/storage3/data.img" FALLBACK="/storage3/data.img"
if [[ -f "${DISK1_FILE}" ]] && [[ -f "${FALLBACK}" ]]; then if [[ -f "${DISK1_FILE}.img" ]] && [[ -f "${FALLBACK}" ]]; then
SIZE1=$(stat -c%s "${FALLBACK}") SIZE1=$(stat -c%s "${FALLBACK}")
SIZE2=$(stat -c%s "${DISK1_FILE}") SIZE2=$(stat -c%s "${DISK1_FILE}.img")
if [[ SIZE1 -ne SIZE2 ]]; then if [[ SIZE1 -ne SIZE2 ]]; then
mv "${FALLBACK}" "${DISK3_FILE}" mv "${FALLBACK}" "${DISK3_FILE}.img"
fi fi
fi fi
fi fi
DISK4_FILE="/storage4/data4.img" DISK4_FILE="/storage4/data4"
DISK5_FILE="/storage5/data5.img" DISK5_FILE="/storage5/data5"
DISK6_FILE="/storage6/data6.img" DISK6_FILE="/storage6/data6"
: ${DISK2_SIZE:=''} : ${DISK2_SIZE:=''}
: ${DISK3_SIZE:=''} : ${DISK3_SIZE:=''}
@@ -180,12 +325,12 @@ DISK6_FILE="/storage6/data6.img"
: ${DISK5_SIZE:=''} : ${DISK5_SIZE:=''}
: ${DISK6_SIZE:=''} : ${DISK6_SIZE:=''}
addDisk "userdata" "${DISK1_FILE}" "disk" "${DISK_SIZE}" "3" "0xc" addDisk "userdata" "${DISK1_FILE}" "${DISK_EXT}" "disk" "${DISK_SIZE}" "3" "0xc" "${DISK_FMT}"
addDisk "userdata2" "${DISK2_FILE}" "disk2" "${DISK2_SIZE}" "4" "0xd" addDisk "userdata2" "${DISK2_FILE}" "${DISK_EXT}" "disk2" "${DISK2_SIZE}" "4" "0xd" "${DISK_FMT}"
addDisk "userdata3" "${DISK3_FILE}" "disk3" "${DISK3_SIZE}" "5" "0xe" addDisk "userdata3" "${DISK3_FILE}" "${DISK_EXT}" "disk3" "${DISK3_SIZE}" "5" "0xe" "${DISK_FMT}"
addDisk "userdata4" "${DISK4_FILE}" "disk4" "${DISK4_SIZE}" "9" "0x7" addDisk "userdata4" "${DISK4_FILE}" "${DISK_EXT}" "disk4" "${DISK4_SIZE}" "9" "0x7" "${DISK_FMT}"
addDisk "userdata5" "${DISK5_FILE}" "disk5" "${DISK5_SIZE}" "10" "0x8" addDisk "userdata5" "${DISK5_FILE}" "${DISK_EXT}" "disk5" "${DISK5_SIZE}" "10" "0x8" "${DISK_FMT}"
addDisk "userdata6" "${DISK6_FILE}" "disk6" "${DISK6_SIZE}" "11" "0x9" addDisk "userdata6" "${DISK6_FILE}" "${DISK_EXT}" "disk6" "${DISK6_SIZE}" "11" "0x9" "${DISK_FMT}"
addDevice () { addDevice () {

View File

@@ -109,7 +109,7 @@ if [ ! -f "${RDC}" ]; then
VERIFY="b4215a4b213ff5154db0488f92c87864" VERIFY="b4215a4b213ff5154db0488f92c87864"
LOC="$DL/release/7.0.1/42218/DSM_VirtualDSM_42218.pat" LOC="$DL/release/7.0.1/42218/DSM_VirtualDSM_42218.pat"
{ curl -r "$POS" -sfk -o "$RD" "$LOC"; rc=$?; } || : { curl -r "$POS" -sfk -S -o "$RD" "$LOC"; rc=$?; } || :
(( rc != 0 )) && error "Failed to download $LOC, reason: $rc" && exit 60 (( rc != 0 )) && error "Failed to download $LOC, reason: $rc" && exit 60
SUM=$(md5sum "$RD" | cut -f 1 -d " ") SUM=$(md5sum "$RD" | cut -f 1 -d " ")

View File

@@ -32,7 +32,7 @@ _graceful_shutdown() {
# echo 'system_powerdown' | nc -q 1 -w 1 localhost "${QEMU_PORT}" > /dev/null # echo 'system_powerdown' | nc -q 1 -w 1 localhost "${QEMU_PORT}" > /dev/null
# Send shutdown command to guest agent via serial port # Send shutdown command to guest agent via serial port
RESPONSE=$(curl -s -m 30 -S http://127.0.0.1:2210/read?command=6 2>&1) RESPONSE=$(curl -sk -m 30 -S http://127.0.0.1:2210/read?command=6 2>&1)
if [[ ! "${RESPONSE}" =~ "\"success\"" ]]; then if [[ ! "${RESPONSE}" =~ "\"success\"" ]]; then

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -Eeuo pipefail set -Eeuo pipefail
info () { echo -e >&2 "\E[1;34m\E[1;36m $1\E[0m" ; } info () { printf "%b%s%b" "\E[1;34m \E[1;36m" "$1" "\E[0m\n" >&2; }
error () { echo -e >&2 "\E[1;31m ERROR: $1\E[0m" ; } error () { printf "%b%s%b" "\E[1;31m " "ERROR: $1" "\E[0m\n" >&2; }
file="/run/dsm.url" file="/run/dsm.url"
@@ -14,53 +14,53 @@ do
# Retrieve IP from guest VM # Retrieve IP from guest VM
set +e { json=$(curl -m 30 -sk http://127.0.0.1:2210/read?command=10); rc=$?; } || :
RESPONSE=$(curl -s -m 30 -S http://127.0.0.1:2210/read?command=10 2>&1) (( rc != 0 )) && error "Failed to connect to guest: curl error $rc" && continue
set -e
if [[ ! "${RESPONSE}" =~ "\"success\"" ]] ; then { result=$(echo "$json" | jq -r '.status'); rc=$?; } || :
error "Failed to connect to guest: $RESPONSE" && continue (( rc != 0 )) && error "Failed to parse response from guest: jq error $rc ( $json )" && continue
[[ "$result" == "null" ]] && error "Guest returned invalid response: $json" && continue
if [[ "$result" != "success" ]] ; then
{ msg=$(echo "$json" | jq -r '.message'); rc=$?; } || :
error "Guest replied ${result}: $msg" && continue
fi fi
# Retrieve the HTTP port number { port=$(echo "$json" | jq -r '.data.data.dsm_setting.data.http_port'); rc=$?; } || :
if [[ ! "${RESPONSE}" =~ "\"http_port\"" ]] ; then (( rc != 0 )) && error "Failed to parse response from guest: jq error $rc ( $json )" && continue
error "Failed to parse response from guest: $RESPONSE" && continue [[ "$port" == "null" ]] && error "Guest returned invalid response: $json" && continue
fi [ -z "${port}" ] && continue
rest=${RESPONSE#*http_port} { ip=$(echo "$json" | jq -r '.data.data.ip.data[] | select((.name=="eth0") and has("ip")).ip'); rc=$?; } || :
rest=${rest#*:} (( rc != 0 )) && error "Failed to parse response from guest: jq error $rc ( $json )" && continue
rest=${rest%%,*} [[ "$ip" == "null" ]] && error "Guest returned invalid response: $json" && continue
PORT=${rest%%\"*} [ -z "${ip}" ] && continue
[ -z "${PORT}" ] && continue echo "${ip}:${port}" > $file
# Retrieve the IP address
if [[ ! "${RESPONSE}" =~ "eth0" ]] ; then
error "Failed to parse response from guest: $RESPONSE" && continue
fi
rest=${RESPONSE#*eth0}
rest=${rest#*ip}
rest=${rest#*:}
rest=${rest#*\"}
IP=${rest%%\"*}
[ -z "${IP}" ] && continue
echo "${IP}:${PORT}" > $file
done done
LOCATION=$(cat "$file") location=$(cat "$file")
if [[ "$location" != "20.20"* ]]; then
msg="http://${location}"
if [[ "$LOCATION" == "20.20"* ]]; then
MSG="port ${LOCATION##*:}"
else else
MSG="http://${LOCATION}"
ip=$(ip address show dev eth0 | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/)
port="${location##*:}"
if [[ "$ip" == "172."* ]]; then
msg="port ${port}"
else
msg="http://${ip}:${port}"
fi
fi fi
echo "" >&2 echo "" >&2
info "--------------------------------------------------------" info "--------------------------------------------------------"
info " You can now login to DSM at ${MSG}" info " You can now login to DSM at ${msg}"
info "--------------------------------------------------------" info "--------------------------------------------------------"
echo "" >&2 echo "" >&2

View File

@@ -1,8 +1,9 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -Eeuo pipefail set -Eeuo pipefail
info () { echo -e "\E[1;34m \E[1;36m$1\E[0m" ; } info () { printf "%b%s%b" "\E[1;34m \E[1;36m" "$1" "\E[0m\n"; }
error () { echo -e >&2 "\E[1;31m ERROR: $1\E[0m" ; } error () { printf "%b%s%b" "\E[1;31m " "ERROR: $1" "\E[0m\n" >&2; }
trap 'error "Status $? while: ${BASH_COMMAND} (line $LINENO/$BASH_LINENO)"' ERR trap 'error "Status $? while: ${BASH_COMMAND} (line $LINENO/$BASH_LINENO)"' ERR
[ ! -f "/run/entry.sh" ] && error "Script must run inside Docker container!" && exit 11 [ ! -f "/run/entry.sh" ] && error "Script must run inside Docker container!" && exit 11