Compare commits

...

63 Commits
v5.02 ... v5.10

Author SHA1 Message Date
Kroese
19aa313753 fix: Shellcheck (#509) 2023-12-28 08:35:51 +01:00
Kroese
9db12cd25f fix: Device detection
* fix: Device detection
2023-12-28 08:31:32 +01:00
Kroese
69e785e6ee fix: Shutdown message
* fix: Shutdown message
2023-12-28 05:26:53 +01:00
Kroese
159fce6839 fix: Detect device
* fix: Detect device
2023-12-28 05:04:40 +01:00
Kroese
08e4084458 feat: Daemonize QEMU
* feat: Daemonize QEMU
2023-12-28 03:42:06 +01:00
Kroese
06f210846c fix: KVM flag (#504) 2023-12-27 16:28:24 +01:00
Kroese
74629e4b55 fix: Installation (#501) 2023-12-27 04:07:45 +01:00
Kroese
6e8af6e52f fix: Host CPU (#500) 2023-12-27 03:23:39 +01:00
Kroese
38611a7af2 fix: Host CPU (#499) 2023-12-27 03:18:03 +01:00
Kroese
f089acc01a fix: CPU features (#496) 2023-12-25 05:58:14 +01:00
Kroese
5a7ecb48d6 fix: Error messages (#495) 2023-12-25 05:03:00 +01:00
Kroese
5b3880aa5e fix: Error messages (#494) 2023-12-25 04:48:18 +01:00
Kroese
4653aafbee docs: Readme (#493) 2023-12-25 04:21:50 +01:00
Kroese
281f2992ff fix: Close file descriptors
* fix: Close file descriptors
2023-12-25 04:04:01 +01:00
Kroese
4bdcf8bfe1 fix: Skip mknod errors (#491) 2023-12-24 14:39:37 +01:00
Kroese
62acaa95bf fix: Check attribute (#490) 2023-12-24 14:27:29 +01:00
Kroese
369bff339d fix: Update Dockerfile (#489) 2023-12-24 02:54:57 +01:00
Kroese
5332d387f4 fix: Set file attribute (#488)
* fix: Set file attribute
2023-12-24 02:41:44 +01:00
Kroese
f0d08ef263 fix: Remove flag (#487)
* fix: Remove flag
2023-12-23 22:58:45 +01:00
Kroese
e4334f9499 fix: Ignore mknod errors (#486) 2023-12-23 22:28:25 +01:00
Kroese
627ec56262 feat: LINUX_IMMUTABLE flag (#485)
* feat: LINUX_IMMUTABLE flag
2023-12-23 21:26:23 +01:00
Kroese
251cf8121e feat: Add LINUX_IMMUTABLE flag (#484)
To change directory attributes on COW filesystems
2023-12-23 20:35:06 +01:00
Kroese
87fad1b0e9 feat: Set directory attributes (#483)
* feat: Set directory attributes
2023-12-23 20:01:27 +01:00
Kroese
698516ac8c feat: Detect country from timezone (#482) 2023-12-23 18:46:14 +01:00
databreach
dae5d75674 feat: Improve support for unprivileged hosts (including LXC) (#479)
* * Add fakeroot to extract the dsm system without elevated permissions
* Remove obsolete docker variable "DEV" used to exclude extraction of device nodes

* feat: Detect unprivileged container

* fix: Use fakeroot for mke2fs

---------

Co-authored-by: Kroese <kroese@users.noreply.github.com>
2023-12-23 18:04:43 +01:00
Kroese
95facffa9b fix: Use specified LAN adaptor (#481)
* fix: Use specified LAN adaptor
2023-12-23 15:23:36 +01:00
Kroese
682e0a9952 feat: Check filesystem (#477)
* feat: Check filesystem
2023-12-22 15:00:22 +01:00
Kroese
9a97dfdc70 fix: Check filesystem (#476) 2023-12-22 06:15:33 +01:00
Kroese
2f383699f9 feat: Firewall info
feat: Firewall info
2023-12-22 05:20:44 +01:00
Kroese
8137a137b3 fix: Disable device nodes 2023-12-22 05:10:22 +01:00
Kroese
1339d51796 feat: Firewall info 2023-12-22 04:47:58 +01:00
Kroese
dce447c974 fix: Quit message 2023-12-22 04:24:48 +01:00
Kroese
ef5b650991 fix: Shutdown loop (#474) 2023-12-20 12:09:25 +01:00
Kroese
fd19c7b4f3 feat: Log creation info (#473) 2023-12-20 03:34:26 +01:00
Kroese
727297642c fix: Exit counter (#472) 2023-12-20 02:00:07 +01:00
Kroese
cd457801e7 fix: Set IP in bridge mode
* fix: Set IP in bridge mode
2023-12-20 01:52:55 +01:00
Kroese
392e7afdfe fix: Allocate after conversion
fix: Allocate after conversion
2023-12-19 08:54:43 +01:00
Kroese
b425e34907 fix: Allocate after conversion 2023-12-19 08:54:08 +01:00
Kroese
7c2e2fc7b1 feat: Enable IO threading
feat: Enable IO threading
2023-12-19 06:16:28 +01:00
Kroese
9bac0c94a8 feat: Detect COW on btrfs 2023-12-19 06:11:50 +01:00
Kroese
631568681e feat: Detect COW on BTRFS 2023-12-19 06:01:50 +01:00
Kroese
6599861dbb feat: Detect COW on BTRFS 2023-12-19 05:46:49 +01:00
Kroese
3bcd831531 fix: Display timeout 2023-12-19 04:30:01 +01:00
Kroese
fafd4a4fca feat: Enable IO threading 2023-12-19 03:59:19 +01:00
Kroese
5b69178f08 docs: Allocation 2023-12-19 03:33:41 +01:00
Kroese
479a30369d feat: Enable IO threading 2023-12-19 02:34:48 +01:00
Kroese
ba522a4acb feat: Increase clustersize for qcow2
* feat: Increase clustersize for qcow2
2023-12-18 17:34:40 +01:00
Kroese
3ab6d2c418 docs: Allocation 2023-12-18 16:48:01 +01:00
Kroese
b71b2245cb fix: Check diskspace
* fix: Check diskspace
2023-12-18 16:44:26 +01:00
Kroese
bbea0eb429 docs: Readme 2023-12-18 12:39:11 +01:00
Kroese
c28c5cfbaa docs: Allocation 2023-12-18 12:36:03 +01:00
Kroese
be3fd30cb2 feat: Honor allocation flag for qcow2
* feat: Honor allocation flag for qcow2
2023-12-18 12:18:28 +01:00
Kroese
e3942da906 feat: Set NOCOW flag for btrfs
feat: Set NOCOW flag for btrfs
2023-12-17 11:42:08 +01:00
Kroese
d66be1a228 fix: Do not set flags on resize 2023-12-17 11:25:42 +01:00
Kroese
72085d3711 fix: Set qcow2 flags 2023-12-17 11:17:26 +01:00
Kroese
e7cdbb1db5 feat: Optimize qcow2 flags 2023-12-17 10:51:30 +01:00
Kroese
7a592e0cea docs: DHCP mode 2023-12-17 10:08:55 +01:00
Kroese
107a4b87d5 fix: Quotes 2023-12-17 10:04:00 +01:00
Kroese
8b0ec3bef7 fix: Remove healthcheck exception 2023-12-17 09:57:50 +01:00
Kroese
aaded40a4f fix: Cleanup server files 2023-12-17 09:54:07 +01:00
Kroese
7f77bb88ab fix: Grammar 2023-12-17 09:50:07 +01:00
Kroese
95c3b2caad fix: Default folder 2023-12-17 09:39:19 +01:00
Kroese
150c450bf6 docs: Default folder 2023-12-17 09:37:36 +01:00
14 changed files with 568 additions and 266 deletions

View File

@@ -29,6 +29,7 @@ RUN apt-get update && apt-get -y upgrade \
iptables \ iptables \
iproute2 \ iproute2 \
dnsmasq \ dnsmasq \
fakeroot \
net-tools \ net-tools \
qemu-utils \ qemu-utils \
ca-certificates \ ca-certificates \

View File

@@ -14,10 +14,10 @@ services:
device_cgroup_rules: device_cgroup_rules:
- 'c *:* rwm' - 'c *:* rwm'
cap_add: cap_add:
- NET_ADMIN - NET_ADMIN
ports: ports:
- 5000:5000 - 5000:5000
volumes: volumes:
- /opt/dsm:/storage - /var/dsm:/storage
restart: on-failure restart: on-failure
stop_grace_period: 2m stop_grace_period: 2m

View File

@@ -39,7 +39,7 @@ services:
ports: ports:
- 5000:5000 - 5000:5000
volumes: volumes:
- /opt/dsm:/storage - /var/dsm:/storage
restart: on-failure restart: on-failure
stop_grace_period: 2m stop_grace_period: 2m
``` ```
@@ -65,14 +65,14 @@ docker run -it --rm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-ti
* ### How do I change the location of the virtual disk? * ### How do I change the location of the virtual disk?
To change the virtual disk's location from the default Docker volume, include the following bind mount in your compose file: To change the location of the virtual disk, include the following bind mount in your compose file:
```yaml ```yaml
volumes: volumes:
- /home/user/data:/storage - /var/dsm:/storage
``` ```
Replace the example path `/home/user/data` with the desired storage folder. Replace the example path `/var/dsm` with the desired storage folder.
* ### How do I add multiple disks? * ### How do I add multiple disks?
@@ -89,18 +89,23 @@ docker run -it --rm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-ti
* ### How do I create a growable disk? * ### How do I create a growable disk?
By default, the entire capacity of the disk is reserved in advance. To create a growable disk that only allocates space that is actually used, add the following environment variable: By default, the entire capacity of the disk is reserved in advance.
To create a growable disk that only allocates space that is actually used, add the following environment variables:
```yaml ```yaml
environment: environment:
ALLOCATE: "N"
DISK_FMT: "qcow2" DISK_FMT: "qcow2"
``` ```
This can also be used to convert any existing disks to the ```qcow2``` format. Please note that this may reduce the write performance of the disk.
* ### How do I increase the amount of CPU or RAM? * ### How do I increase the amount of CPU or RAM?
By default, a single core and 1 GB of RAM are allocated to the container. To increase this, add the following environment variables: By default, a single core and 1 GB of RAM are allocated to the container.
To increase this, add the following environment variables:
```yaml ```yaml
environment: environment:
@@ -164,13 +169,11 @@ docker run -it --rm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-ti
```yaml ```yaml
environment: environment:
DHCP: "Y" DHCP: "Y"
devices:
- /dev/vhost-net
device_cgroup_rules: device_cgroup_rules:
- 'c *:* rwm' - 'c *:* rwm'
``` ```
Please note that even if you don't need DHCP, it's still recommended to enable this feature as it prevents NAT issues and increases performance by using a `macvtap` interface. Please note that even if you don't want DHCP, it's still recommended to enable this feature as it prevents NAT issues and increases performance by using a `macvtap` interface. In that case just set a static IP from the DSM control panel after you enabled this mode.
* ### How do I passthrough the GPU? * ### How do I passthrough the GPU?

View File

@@ -1,8 +1,10 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -Eeuo pipefail set -Eeuo pipefail
[ ! -f "/run/qemu.pid" ] && echo "QEMU not running yet.." && exit 0 : ${VM_NET_DEV:='eth0'}
[ -f "/run/qemu.count" ] && echo "QEMU is shutting down.." && exit 1 [ -f "/run/qemu.count" ] && echo "QEMU is shutting down.." && exit 1
[ ! -f "/run/qemu.pid" ] && echo "QEMU not running yet.." && exit 0
file="/run/dsm.url" file="/run/dsm.url"
[ ! -f "$file" ] && echo "DSM has not enabled networking yet.." && exit 1 [ ! -f "$file" ] && echo "DSM has not enabled networking yet.." && exit 1
@@ -10,7 +12,18 @@ file="/run/dsm.url"
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
echo "Failed to reach page at http://$location" && exit 1
if [[ "$location" == "20.20"* ]]; then
ip="20.20.20.1"
port="${location##*:}"
echo "Failed to reach DSM at port $port"
else
echo "Failed to reach DSM at http://$location"
ip=$(ip address show dev "$VM_NET_DEV" | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/)
fi
echo "You might need to whitelist IP $ip in the DSM firewall." && exit 1
fi fi
echo "Healthcheck OK" echo "Healthcheck OK"

View File

@@ -7,10 +7,11 @@ set -Eeuo pipefail
: ${CPU_MODEL:='host'} : ${CPU_MODEL:='host'}
: ${CPU_FEATURES:='+ssse3,+sse4.1,+sse4.2'} : ${CPU_FEATURES:='+ssse3,+sse4.1,+sse4.2'}
KVM_ERR="" [ "$ARCH" != "amd64" ] && KVM="N"
KVM_OPTS=""
if [[ "$ARCH" == "amd64" && "$KVM" != [Nn]* ]]; then if [[ "$KVM" != [Nn]* ]]; then
KVM_ERR=""
if [ -e /dev/kvm ] && sh -c 'echo -n > /dev/kvm' &> /dev/null; then if [ -e /dev/kvm ] && sh -c 'echo -n > /dev/kvm' &> /dev/null; then
if ! grep -q -e vmx -e svm /proc/cpuinfo; then if ! grep -q -e vmx -e svm /proc/cpuinfo; then
@@ -21,25 +22,35 @@ if [[ "$ARCH" == "amd64" && "$KVM" != [Nn]* ]]; then
fi fi
if [ -n "$KVM_ERR" ]; then if [ -n "$KVM_ERR" ]; then
KVM="N"
error "KVM acceleration not detected $KVM_ERR, this will cause a major loss of performance." error "KVM acceleration not detected $KVM_ERR, this will cause a major loss of performance."
error "See the FAQ on how to enable it, or skip this error by setting KVM=N (not recommended)." error "See the FAQ on how to enable it, or continue without KVM by setting KVM=N (not recommended)."
[[ "$DEBUG" != [Yy1]* ]] && exit 88 [[ "$DEBUG" != [Yy1]* ]] && exit 88
[[ "$CPU_MODEL" == "host"* ]] && CPU_MODEL="max,$CPU_FEATURES"
else
KVM_OPTS=",accel=kvm -enable-kvm"
fi fi
if [ -n "$KVM_OPTS" ]; then fi
if ! grep -qE '^flags.* (sse4_2)' /proc/cpuinfo; then
error "Your host CPU does not has the SSE4.2 instruction set that Virtual DSM requires to boot." if [[ "$KVM" != [Nn]* ]]; then
error "Disable KVM by setting KVM=N to emulate a compatible CPU, at the cost of performance."
[[ "$DEBUG" != [Yy1]* ]] && exit 89 KVM_OPTS=",accel=kvm -enable-kvm"
fi
if ! grep -qE '^flags.* (sse4_2)' /proc/cpuinfo; then
error "Your host CPU does not have the SSE4.2 instruction set that Virtual DSM requires to boot."
error "Disable KVM by setting KVM=N to emulate a compatible CPU, at the cost of performance."
[[ "$DEBUG" != [Yy1]* ]] && exit 89
fi fi
else else
[[ "$CPU_MODEL" == "host"* ]] && CPU_MODEL="max,$CPU_FEATURES" KVM_OPTS=""
if [[ "$CPU_MODEL" == "host"* ]]; then
if [[ "$ARCH" == "amd64" ]]; then
CPU_MODEL="max,$CPU_FEATURES"
else
CPU_MODEL="qemu64,$CPU_FEATURES"
fi
fi
fi fi

View File

@@ -3,11 +3,12 @@ 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_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
: ${DISK_FLAGS:=''} # Specifies the options for use with the qcow2 disk format
BOOT="$STORAGE/$BASE.boot.img" BOOT="$STORAGE/$BASE.boot.img"
SYSTEM="$STORAGE/$BASE.system.img" SYSTEM="$STORAGE/$BASE.system.img"
@@ -16,10 +17,11 @@ SYSTEM="$STORAGE/$BASE.system.img"
[ ! -f "$SYSTEM" ] && error "Virtual DSM system-image does not exist ($SYSTEM)" && exit 82 [ ! -f "$SYSTEM" ] && error "Virtual DSM system-image does not exist ($SYSTEM)" && exit 82
DISK_OPTS="\ DISK_OPTS="\
-device virtio-scsi-pci,id=hw-synoboot,bus=pcie.0,addr=0xa \ -object iothread,id=io1 -object iothread,id=io2 \
-device virtio-scsi-pci,id=hw-synoboot,iothread=io1,bus=pcie.0,addr=0xa \
-drive file=$BOOT,if=none,id=drive-synoboot,format=raw,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on \ -drive file=$BOOT,if=none,id=drive-synoboot,format=raw,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on \
-device scsi-hd,bus=hw-synoboot.0,channel=0,scsi-id=0,lun=0,drive=drive-synoboot,id=synoboot0,rotation_rate=$DISK_ROTATION,bootindex=1 \ -device scsi-hd,bus=hw-synoboot.0,channel=0,scsi-id=0,lun=0,drive=drive-synoboot,id=synoboot0,rotation_rate=$DISK_ROTATION,bootindex=1 \
-device virtio-scsi-pci,id=hw-synosys,bus=pcie.0,addr=0xb \ -device virtio-scsi-pci,id=hw-synosys,iothread=io1,bus=pcie.0,addr=0xb \
-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"
@@ -75,74 +77,14 @@ getSize() {
esac esac
} }
resizeDisk() { isCow() {
local DISK_FILE=$1 local FS=$1
local CUR_SIZE=$2
local DATA_SIZE=$3
local DISK_SPACE=$4
local DISK_DESC=$5
local DISK_FMT=$6
local GB REQ FAIL SPACE SPACE_GB
GB=$(( (CUR_SIZE + 1073741823)/1073741824 )) if [[ "${FS,,}" == "xfs" || "${FS,,}" == "zfs" || "${FS,,}" == "btrfs" || "${FS,,}" == "bcachefs" ]]; then
info "Resizing $DISK_DESC from ${GB}G to $DISK_SPACE .." return 0
FAIL="Could not resize $DISK_FMT file of $DISK_DESC ($DISK_FILE) from ${GB}G to $DISK_SPACE .." fi
REQ=$((DATA_SIZE-CUR_SIZE)) return 1
(( REQ < 1 )) && error "Shrinking disks is not supported!" && exit 71
case "${DISK_FMT,,}" in
raw)
if [[ "$ALLOCATE" == [Nn]* ]]; then
# Resize file by changing its length
if ! truncate -s "$DISK_SPACE" "$DISK_FILE"; then
error "$FAIL" && exit 75
fi
else
# Check free diskspace
SPACE=$(df --output=avail -B 1 "$DIR" | tail -n 1)
SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))
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 "Please specify a smaller ${DISK_DESC^^}_SIZE or disable preallocation by setting DISK_FMT to \"qcow2\"." && exit 74
fi
# Resize file by allocating more space
if ! fallocate -l "$DISK_SPACE" "$DISK_FILE"; then
if ! truncate -s "$DISK_SPACE" "$DISK_FILE"; then
error "$FAIL" && exit 75
fi
fi
fi
;;
qcow2)
if ! qemu-img resize -f "$DISK_FMT" "$DISK_FILE" "$DISK_SPACE" ; then
error "$FAIL" && exit 72
fi
;;
esac
}
convertDisk() {
local CONV_FLAGS="-p"
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() { createDisk() {
@@ -150,34 +92,52 @@ createDisk() {
local DISK_SPACE=$2 local DISK_SPACE=$2
local DISK_DESC=$3 local DISK_DESC=$3
local DISK_FMT=$4 local DISK_FMT=$4
local GB FAIL SPACE SPACE_GB local FS=$5
local DATA_SIZE DIR SPACE FA
FAIL="Could not create a $DISK_SPACE $DISK_FMT file for $DISK_DESC ($DISK_FILE)" DATA_SIZE=$(numfmt --from=iec "$DISK_SPACE")
rm -f "$DISK_FILE"
if [[ "$ALLOCATE" != [Nn]* ]]; then
# Check free diskspace
DIR=$(dirname "$DISK_FILE")
SPACE=$(df --output=avail -B 1 "$DIR" | tail -n 1)
if (( DATA_SIZE > SPACE )); then
local SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))
error "Not enough free space to create a $DISK_DESC of $DISK_SPACE in $DIR, it has only $SPACE_GB GB available..."
error "Please specify a smaller ${DISK_DESC^^}_SIZE or disable preallocation by setting ALLOCATE=N." && exit 76
fi
fi
info "Creating a $DISK_TYPE $DISK_DESC image in $DISK_FMT format with a size of $DISK_SPACE..."
local FAIL="Could not create a $DISK_TYPE $DISK_FMT $DISK_DESC image of $DISK_SPACE ($DISK_FILE)"
case "${DISK_FMT,,}" in case "${DISK_FMT,,}" in
raw) raw)
if [[ "$ALLOCATE" == [Nn]* ]]; then
if isCow "$FS"; then
if ! touch "$DISK_FILE"; then
error "$FAIL" && exit 77
fi
{ chattr +C "$DISK_FILE"; } || :
fi
if [[ "$ALLOCATE" == [Nn]* ]]; then
# Create an empty file # Create an empty file
if ! truncate -s "$DISK_SPACE" "$DISK_FILE"; then if ! truncate -s "$DATA_SIZE" "$DISK_FILE"; then
rm -f "$DISK_FILE" rm -f "$DISK_FILE"
error "$FAIL" && exit 77 error "$FAIL" && exit 77
fi fi
else else
# Check free diskspace
SPACE=$(df --output=avail -B 1 "$DIR" | tail -n 1)
SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))
if (( DATA_SIZE > SPACE )); then
error "Not enough free space to create a $DISK_DESC of $DISK_SPACE in $DIR, it has only $SPACE_GB GB available.."
error "Please specify a smaller ${DISK_DESC^^}_SIZE or disable preallocation by setting DISK_FMT to \"qcow2\"." && exit 76
fi
# Create an empty file # Create an empty file
if ! fallocate -l "$DISK_SPACE" "$DISK_FILE"; then if ! fallocate -l "$DATA_SIZE" "$DISK_FILE"; then
if ! truncate -s "$DISK_SPACE" "$DISK_FILE"; then if ! truncate -s "$DATA_SIZE" "$DISK_FILE"; then
rm -f "$DISK_FILE" rm -f "$DISK_FILE"
error "$FAIL" && exit 77 error "$FAIL" && exit 77
fi fi
@@ -186,12 +146,189 @@ createDisk() {
fi fi
;; ;;
qcow2) qcow2)
if ! qemu-img create -f "$DISK_FMT" -- "$DISK_FILE" "$DISK_SPACE" ; then
local DISK_PARAM="$DISK_ALLOC"
isCow "$FS" && DISK_PARAM="$DISK_PARAM,nocow=on"
[ -n "$DISK_FLAGS" ] && DISK_PARAM="$DISK_PARAM,$DISK_FLAGS"
if ! qemu-img create -f "$DISK_FMT" -o "$DISK_PARAM" -- "$DISK_FILE" "$DATA_SIZE" ; then
rm -f "$DISK_FILE" rm -f "$DISK_FILE"
error "$FAIL" && exit 70 error "$FAIL" && exit 70
fi fi
;; ;;
esac esac
if isCow "$FS"; then
FA=$(lsattr "$DISK_FILE")
if [[ "$FA" != *"C"* ]]; then
error "Failed to disable COW for $DISK_DESC image $DISK_FILE on ${FS^^} filesystem (returned $FA)"
fi
fi
return 0
}
resizeDisk() {
local DISK_FILE=$1
local DISK_SPACE=$2
local DISK_DESC=$3
local DISK_FMT=$4
local FS=$5
local CUR_SIZE DATA_SIZE DIR SPACE
CUR_SIZE=$(getSize "$DISK_FILE")
DATA_SIZE=$(numfmt --from=iec "$DISK_SPACE")
local REQ=$((DATA_SIZE-CUR_SIZE))
(( REQ < 1 )) && error "Shrinking disks is not supported yet, please increase ${DISK_DESC^^}_SIZE." && exit 71
if [[ "$ALLOCATE" != [Nn]* ]]; then
# Check free diskspace
DIR=$(dirname "$DISK_FILE")
SPACE=$(df --output=avail -B 1 "$DIR" | tail -n 1)
if (( REQ > SPACE )); then
local SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))
error "Not enough free space to resize $DISK_DESC to $DISK_SPACE in $DIR, it has only $SPACE_GB GB available.."
error "Please specify a smaller ${DISK_DESC^^}_SIZE or disable preallocation by setting ALLOCATE=N." && exit 74
fi
fi
local GB=$(( (CUR_SIZE + 1073741823)/1073741824 ))
info "Resizing $DISK_DESC from ${GB}G to $DISK_SPACE..."
local FAIL="Could not resize the $DISK_TYPE $DISK_FMT $DISK_DESC image from ${GB}G to $DISK_SPACE ($DISK_FILE)"
case "${DISK_FMT,,}" in
raw)
if [[ "$ALLOCATE" == [Nn]* ]]; then
# Resize file by changing its length
if ! truncate -s "$DATA_SIZE" "$DISK_FILE"; then
error "$FAIL" && exit 75
fi
else
# Resize file by allocating more space
if ! fallocate -l "$DATA_SIZE" "$DISK_FILE"; then
if ! truncate -s "$DATA_SIZE" "$DISK_FILE"; then
error "$FAIL" && exit 75
fi
fi
fi
;;
qcow2)
if ! qemu-img resize -f "$DISK_FMT" "--$DISK_ALLOC" "$DISK_FILE" "$DATA_SIZE" ; then
error "$FAIL" && exit 72
fi
;;
esac
return 0
}
convertDisk() {
local SOURCE_FILE=$1
local SOURCE_FMT=$2
local DST_FILE=$3
local DST_FMT=$4
local DISK_BASE=$5
local DISK_DESC=$6
local FS=$7
[ -f "$DST_FILE" ] && error "Conversion failed, destination file $DST_FILE already exists?" && exit 79
[ ! -f "$SOURCE_FILE" ] && error "Conversion failed, source file $SOURCE_FILE does not exists?" && exit 79
local TMP_FILE="$DISK_BASE.tmp"
rm -f "$TMP_FILE"
if [[ "$ALLOCATE" != [Nn]* ]]; then
local DIR CUR_SIZE SPACE
# Check free diskspace
DIR=$(dirname "$TMP_FILE")
CUR_SIZE=$(getSize "$SOURCE_FILE")
SPACE=$(df --output=avail -B 1 "$DIR" | tail -n 1)
if (( CUR_SIZE > SPACE )); then
local SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))
error "Not enough free space to convert $DISK_DESC to $DST_FMT in $DIR, it has only $SPACE_GB GB available..."
error "Please free up some disk space or disable preallocation by setting ALLOCATE=N." && exit 76
fi
fi
info "Converting $DISK_DESC to $DST_FMT, please wait until completed..."
local CONV_FLAGS="-p"
local DISK_PARAM="$DISK_ALLOC"
isCow "$FS" && DISK_PARAM="$DISK_PARAM,nocow=on"
if [[ "$DST_FMT" != "raw" ]]; then
if [[ "$ALLOCATE" == [Nn]* ]]; then
CONV_FLAGS="$CONV_FLAGS -c"
fi
[ -n "$DISK_FLAGS" ] && DISK_PARAM="$DISK_PARAM,$DISK_FLAGS"
fi
# shellcheck disable=SC2086
if ! qemu-img convert -f "$SOURCE_FMT" $CONV_FLAGS -o "$DISK_PARAM" -O "$DST_FMT" -- "$SOURCE_FILE" "$TMP_FILE"; then
rm -f "$TMP_FILE"
error "Failed to convert $DISK_TYPE $DISK_DESC image to $DST_FMT format in $DIR, is there enough space available?" && exit 79
fi
if [[ "$DST_FMT" == "raw" ]]; then
if [[ "$ALLOCATE" != [Nn]* ]]; then
# Work around qemu-img bug
CUR_SIZE=$(stat -c%s "$TMP_FILE")
if ! fallocate -l "$CUR_SIZE" "$TMP_FILE"; then
error "Failed to allocate $CUR_SIZE bytes for $DISK_DESC image $TMP_FILE"
fi
fi
fi
rm -f "$SOURCE_FILE"
mv "$TMP_FILE" "$DST_FILE"
if isCow "$FS"; then
FA=$(lsattr "$DST_FILE")
if [[ "$FA" != *"C"* ]]; then
error "Failed to disable COW for $DISK_DESC image $DST_FILE on ${FS^^} filesystem (returned $FA)"
fi
fi
info "Conversion of $DISK_DESC to $DST_FMT completed succesfully!"
return 0
}
checkFS () {
local FS=$1
local DISK_FILE=$2
local DISK_DESC=$3
local DIR FA
DIR=$(dirname "$DISK_FILE")
[ ! -d "$DIR" ] && return 0
if [[ "${FS,,}" == "overlay"* ]]; then
info "Warning: the filesystem of $DIR is OverlayFS, this usually means it was binded to an invalid path!"
fi
if isCow "$FS"; then
if [ -f "$DISK_FILE" ]; then
FA=$(lsattr "$DISK_FILE")
if [[ "$FA" != *"C"* ]]; then
info "Warning: COW (copy on write) is not disabled for $DISK_DESC image file $DISK_FILE, this is recommended on ${FS^^} filesystems!"
fi
fi
fi
return 0
} }
addDisk () { addDisk () {
@@ -203,27 +340,28 @@ addDisk () {
local DISK_INDEX=$6 local DISK_INDEX=$6
local DISK_ADDRESS=$7 local DISK_ADDRESS=$7
local DISK_FMT=$8 local DISK_FMT=$8
local FS DIR CUR_SIZE DATA_SIZE DISK_FILE local DISK_FILE="$DISK_BASE.$DISK_EXT"
local DIR DATA_SIZE FS PREV_FMT PREV_EXT CUR_SIZE
DISK_FILE="$DISK_BASE.$DISK_EXT"
DIR=$(dirname "$DISK_FILE") DIR=$(dirname "$DISK_FILE")
[ ! -d "$DIR" ] && return 0 [ ! -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" [ -z "$DISK_SPACE" ] && DISK_SPACE="16G"
DISK_SPACE=$(echo "$DISK_SPACE" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g') 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") DATA_SIZE=$(numfmt --from=iec "$DISK_SPACE")
if (( DATA_SIZE < 6442450944 )); then if (( DATA_SIZE < 6442450944 )); then
error "Please increase ${DISK_DESC^^}_SIZE to at least 6 GB." && exit 73 if (( DATA_SIZE < 1 )); then
error "Invalid value for ${DISK_DESC^^}_SIZE: $DISK_SPACE" && exit 73
else
error "Please increase ${DISK_DESC^^}_SIZE to at least 6 GB." && exit 73
fi
fi fi
FS=$(stat -f -c %T "$DIR")
checkFS "$FS" "$DISK_FILE" "$DISK_DESC" || exit $?
if ! [ -f "$DISK_FILE" ] ; then if ! [ -f "$DISK_FILE" ] ; then
local PREV_EXT PREV_FMT PREV_FILE TMP_FILE
if [[ "${DISK_FMT,,}" != "raw" ]]; then if [[ "${DISK_FMT,,}" != "raw" ]]; then
PREV_FMT="raw" PREV_FMT="raw"
@@ -231,24 +369,9 @@ addDisk () {
PREV_FMT="qcow2" PREV_FMT="qcow2"
fi fi
PREV_EXT="$(fmt2ext "$PREV_FMT")" PREV_EXT="$(fmt2ext "$PREV_FMT")"
PREV_FILE="$DISK_BASE.$PREV_EXT"
if [ -f "$PREV_FILE" ] ; then if [ -f "$DISK_BASE.$PREV_EXT" ] ; then
convertDisk "$DISK_BASE.$PREV_EXT" "$PREV_FMT" "$DISK_FILE" "$DISK_FMT" "$DISK_BASE" "$DISK_DESC" "$FS" || exit $?
info "Detected that ${DISK_DESC^^}_FMT changed from \"$PREV_FMT\" to \"$DISK_FMT\"."
info "Starting conversion of $DISK_DESC to this new format, please wait until completed..."
TMP_FILE="$DISK_BASE.tmp"
rm -f "$TMP_FILE"
if ! convertDisk "$PREV_FILE" "$PREV_FMT" "$TMP_FILE" "$DISK_FMT" ; then
rm -f "$TMP_FILE"
error "Failed to convert $DISK_DESC to $DISK_FMT format." && exit 79
fi
mv "$TMP_FILE" "$DISK_FILE"
rm -f "$PREV_FILE"
info "Conversion of $DISK_DESC completed succesfully!"
fi fi
fi fi
@@ -256,18 +379,18 @@ addDisk () {
CUR_SIZE=$(getSize "$DISK_FILE") CUR_SIZE=$(getSize "$DISK_FILE")
if [ "$DATA_SIZE" -gt "$CUR_SIZE" ]; then if (( DATA_SIZE > CUR_SIZE )); then
resizeDisk "$DISK_FILE" "$CUR_SIZE" "$DATA_SIZE" "$DISK_SPACE" "$DISK_DESC" "$DISK_FMT" || exit $? resizeDisk "$DISK_FILE" "$DISK_SPACE" "$DISK_DESC" "$DISK_FMT" "$FS" || exit $?
fi fi
else else
createDisk "$DISK_FILE" "$DISK_SPACE" "$DISK_DESC" "$DISK_FMT" || exit $? createDisk "$DISK_FILE" "$DISK_SPACE" "$DISK_DESC" "$DISK_FMT" "$FS" || 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,iothread=io2,bus=pcie.0,addr=$DISK_ADDRESS \
-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 \ -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"
@@ -276,6 +399,14 @@ addDisk () {
DISK_EXT="$(fmt2ext "$DISK_FMT")" || exit $? DISK_EXT="$(fmt2ext "$DISK_FMT")" || exit $?
if [[ "$ALLOCATE" == [Nn]* ]]; then
DISK_TYPE="growable"
DISK_ALLOC="preallocation=off"
else
DISK_TYPE="preallocated"
DISK_ALLOC="preallocation=falloc"
fi
DISK1_FILE="$STORAGE/data" DISK1_FILE="$STORAGE/data"
if [[ ! -f "$DISK1_FILE.img" ]] && [[ -f "$STORAGE/data${DISK_SIZE}.img" ]]; then if [[ ! -f "$DISK1_FILE.img" ]] && [[ -f "$STORAGE/data${DISK_SIZE}.img" ]]; then
# Fallback for legacy installs # Fallback for legacy installs
@@ -336,7 +467,7 @@ addDevice () {
[ ! -b "$DISK_DEV" ] && error "Device $DISK_DEV cannot be found! Please add it to the 'devices' section of your compose file." && exit 55 [ ! -b "$DISK_DEV" ] && error "Device $DISK_DEV cannot be found! Please add it to the 'devices' section of your compose file." && exit 55
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,iothread=io2,bus=pcie.0,addr=$DISK_ADDRESS \
-drive file=$DISK_DEV,if=none,id=drive-$DISK_ID,format=raw,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on \ -drive file=$DISK_DEV,if=none,id=drive-$DISK_ID,format=raw,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"

View File

@@ -23,12 +23,31 @@ if [[ "$CONSOLE" == [Yy]* ]]; then
exit $? exit $?
fi fi
set -m [[ "$DEBUG" == [Yy1]* ]] && info "$VERS" && set -x
( msg=$(qemu-system-x86_64 -daemonize -pidfile "$QEMU_PID" ${ARGS:+ $ARGS})
[[ "$DEBUG" == [Yy1]* ]] && info "$VERS" && set -x { set +x; } 2>/dev/null
qemu-system-x86_64 ${ARGS:+ $ARGS} & echo $! > "$QEMU_PID"
{ set +x; } 2>/dev/null
)
set +m
tail --pid "$(cat "$QEMU_PID")" --follow /dev/null & wait $! if [[ "$msg" != "char"* || "$msg" != *"serial0)" ]]; then
echo "$msg"
fi
dev="${msg#*/dev/p}"
dev="/dev/p${dev%% *}"
if [ ! -c "$dev" ]; then
dev=$(echo 'info chardev' | nc -q 1 -w 1 localhost "$QEMU_PORT" | tr -d '\000')
dev="${dev#*charserial0}"
dev="${dev#*pty:}"
dev="${dev%%$'\n'*}"
dev="${dev%%$'\r'*}"
fi
if [ ! -c "$dev" ]; then
error "Device '$dev' not found!"
finish 34
fi
cat "$dev" 2>/dev/null & wait $! || true
sleep 1
finish 0

View File

@@ -8,16 +8,17 @@ fi
[ ! -d /dev/dri ] && mkdir -m 755 /dev/dri [ ! -d /dev/dri ] && mkdir -m 755 /dev/dri
if [ ! -c /dev/dri/card0 ]; then if [ ! -c /dev/dri/card0 ]; then
mknod /dev/dri/card0 c 226 0 if mknod /dev/dri/card0 c 226 0; then
chmod 666 /dev/dri/card0
fi
fi fi
if [ ! -c /dev/dri/renderD128 ]; then if [ ! -c /dev/dri/renderD128 ]; then
mknod /dev/dri/renderD128 c 226 128 if mknod /dev/dri/renderD128 c 226 128; then
chmod 666 /dev/dri/renderD128
fi
fi fi
chmod 666 /dev/dri/card0
chmod 666 /dev/dri/renderD128
addPackage "xserver-xorg-video-intel" "Intel GPU drivers" addPackage "xserver-xorg-video-intel" "Intel GPU drivers"
addPackage "qemu-system-modules-opengl" "OpenGL module" addPackage "qemu-system-modules-opengl" "OpenGL module"

View File

@@ -2,7 +2,6 @@
set -Eeuo pipefail set -Eeuo pipefail
: ${URL:=''} # URL of the PAT file to be downloaded. : ${URL:=''} # URL of the PAT file to be downloaded.
: ${DEV:='Y'} # Controls whether device nodes are created.
if [ -f "$STORAGE"/dsm.ver ]; then if [ -f "$STORAGE"/dsm.ver ]; then
BASE=$(cat "$STORAGE/dsm.ver") BASE=$(cat "$STORAGE/dsm.ver")
@@ -52,19 +51,18 @@ MIN_ROOT=471859200
MIN_SPACE=6442450944 MIN_SPACE=6442450944
FS=$(stat -f -c %T "$STORAGE") FS=$(stat -f -c %T "$STORAGE")
if [[ "$FS" == "overlay"* ]]; then if [[ "${FS,,}" == "overlay"* ]]; then
info "Warning: the filesystem of $STORAGE is OverlayFS, this usually means it was binded to an invalid path!" info "Warning: the filesystem of $STORAGE is OverlayFS, this usually means it was binded to an invalid path!"
fi fi
if [[ "$FS" != "fat"* && "$FS" != "vfat"* && "$FS" != "exfat"* && \ if [[ "${FS,,}" != "fat"* && "${FS,,}" != "vfat"* && "${FS,,}" != "exfat"* && \
"$FS" != "ntfs"* && "$FS" != "fuse"* && "$FS" != "msdos"* ]]; then "${FS,,}" != "ntfs"* && "${FS,,}" != "fuse"* && "${FS,,}" != "msdos"* ]]; then
TMP="$STORAGE/tmp" TMP="$STORAGE/tmp"
else else
TMP="/tmp/dsm" TMP="/tmp/dsm"
SPACE=$(df --output=avail -B 1 /tmp | tail -n 1) SPACE=$(df --output=avail -B 1 /tmp | tail -n 1)
if (( MIN_SPACE > SPACE )); then if (( MIN_SPACE > SPACE )); then
TMP="$STORAGE/tmp" error "The ${FS^^} filesystem of $STORAGE does not support UNIX permissions, and no space left in container!" && exit 93
info "Warning: the $FS filesystem of $STORAGE does not support UNIX permissions.."
fi fi
fi fi
@@ -74,15 +72,9 @@ rm -rf "$TMP" && mkdir -p "$TMP"
SPACE=$(df --output=avail -B 1 / | tail -n 1) SPACE=$(df --output=avail -B 1 / | tail -n 1)
(( MIN_ROOT > SPACE )) && error "Not enough free space in container root, need at least 450 MB available." && exit 96 (( MIN_ROOT > SPACE )) && error "Not enough free space in container root, need at least 450 MB available." && exit 96
SPACE=$(df --output=avail -B 1 "$TMP" | tail -n 1) SPACE=$(df --output=avail -B 1 "$STORAGE" | tail -n 1)
SPACE_GB=$(( (SPACE + 1073741823)/1073741824 )) SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))
(( MIN_SPACE > SPACE )) && error "Not enough free space for installation in $STORAGE, have $SPACE_GB GB available but need at least 6 GB." && exit 95 (( MIN_SPACE > SPACE )) && error "Not enough free space for installation in $STORAGE, have $SPACE_GB GB available but need at least 6 GB." && exit 94
if [[ "$TMP" != "$STORAGE/tmp" ]]; then
SPACE=$(df --output=avail -B 1 "$STORAGE" | tail -n 1)
SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))
(( MIN_SPACE > SPACE )) && error "Not enough free space for installation in $STORAGE, have $SPACE_GB GB available but need at least 6 GB." && exit 94
fi
# Check if output is to interactive TTY # Check if output is to interactive TTY
if [ -t 1 ]; then if [ -t 1 ]; then
@@ -93,6 +85,7 @@ fi
# Download the required files from the Synology website # Download the required files from the Synology website
ROOT="Y"
RDC="$STORAGE/dsm.rd" RDC="$STORAGE/dsm.rd"
if [ ! -f "$RDC" ]; then if [ ! -f "$RDC" ]; then
@@ -132,14 +125,12 @@ if [ -f "$RDC" ]; then
{ xz -dc <"$RDC" >"$TMP/rd" 2>/dev/null; rc=$?; } || : { xz -dc <"$RDC" >"$TMP/rd" 2>/dev/null; rc=$?; } || :
(( rc != 1 )) && error "Failed to unxz $RDC, reason $rc" && exit 91 (( rc != 1 )) && error "Failed to unxz $RDC, reason $rc" && exit 91
if [[ "$DEV" == [Nn]* ]]; then { (cd "$TMP" && cpio -idm <"$TMP/rd" 2>/dev/null); rc=$?; } || :
# Exclude dev/ from cpio extract
{ (cd "$TMP" && cpio -it < "$TMP/rd" | grep -Ev 'dev/' | while read -r entry; do cpio -idm "$entry" < "$TMP/rd" 2>/dev/null; done); rc=$?; } || : if (( rc != 0 )); then
ROOT="N"
{ (cd "$TMP" && fakeroot cpio -idmu <"$TMP/rd" 2>/dev/null); rc=$?; } || :
(( rc != 0 )) && error "Failed to extract $RDC, reason $rc" && exit 92 (( rc != 0 )) && error "Failed to extract $RDC, reason $rc" && exit 92
else
{ (cd "$TMP" && cpio -idm <"$TMP/rd" 2>/dev/null); rc=$?; } || :
(( rc != 0 )) && error "Failed to extract $RDC, reason $rc"
(( rc != 0 )) && error "If the container runs unprivileged, please set DEV=N to exclude device nodes." && exit 92
fi fi
mkdir -p /run/extract mkdir -p /run/extract
@@ -192,15 +183,14 @@ if ((SIZE<250000000)); then
error "The specified PAT file is probably an update pack as it's too small." && exit 62 error "The specified PAT file is probably an update pack as it's too small." && exit 62
fi fi
info "Install: Extracting downloaded image..."
if { tar tf "$PAT"; } >/dev/null 2>&1; then if { tar tf "$PAT"; } >/dev/null 2>&1; then
info "Install: Extracting downloaded image..."
tar xpf "$PAT" -C "$TMP/." tar xpf "$PAT" -C "$TMP/."
else else
info "Install: Extracting downloaded image..."
export LD_LIBRARY_PATH="/run/extract" export LD_LIBRARY_PATH="/run/extract"
if [ "$ARCH" == "amd64" ]; then if [ "$ARCH" == "amd64" ]; then
@@ -215,12 +205,7 @@ else
fi fi
HDA="$TMP/hda1" info "Install: Preparing system partition..."
IDB="$TMP/indexdb"
PKG="$TMP/packages"
HDP="$TMP/synohdpack_img"
[ ! -f "$HDA.tgz" ] && error "The PAT file contains no OS image." && exit 64
BOOT=$(find "$TMP" -name "*.bin.zip") BOOT=$(find "$TMP" -name "*.bin.zip")
[ ! -f "$BOOT" ] && error "The PAT file contains no boot image." && exit 67 [ ! -f "$BOOT" ] && error "The PAT file contains no boot image." && exit 67
@@ -230,15 +215,29 @@ unzip -q -o "$BOOT".zip -d "$TMP"
SYSTEM="$TMP/sys.img" SYSTEM="$TMP/sys.img"
SYSTEM_SIZE=4954537983 SYSTEM_SIZE=4954537983
rm -f "$SYSTEM"
# Check free diskspace # Check free diskspace
SPACE=$(df --output=avail -B 1 "$TMP" | tail -n 1) SPACE=$(df --output=avail -B 1 "$TMP" | tail -n 1)
SPACE_GB=$(( (SPACE + 1073741823)/1073741824 )) SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))
(( SYSTEM_SIZE > SPACE )) && error "Not enough free space to create a 4 GB system disk, have only $SPACE_GB GB available." && exit 97 (( SYSTEM_SIZE > SPACE )) && error "Not enough free space to create a 4 GB system disk, have only $SPACE_GB GB available." && exit 97
if ! touch "$SYSTEM"; then
error "Could not create file $SYSTEM for the system disk." && exit 98
fi
if [[ "${FS,,}" == "xfs" || "${FS,,}" == "zfs" || "${FS,,}" == "btrfs" || "${FS,,}" == "bcachefs" ]]; then
{ chattr +C "$SYSTEM"; } || :
FA=$(lsattr "$SYSTEM")
if [[ "$FA" != *"C"* ]]; then
error "Failed to disable COW for system image $SYSTEM on ${FS^^} filesystem (returned $FA)"
fi
fi
if ! fallocate -l "$SYSTEM_SIZE" "$SYSTEM"; then if ! fallocate -l "$SYSTEM_SIZE" "$SYSTEM"; then
if ! truncate -s "$SYSTEM_SIZE" "$SYSTEM"; then if ! truncate -s "$SYSTEM_SIZE" "$SYSTEM"; then
rm -f "$SYSTEM" && error "Could not allocate a file for the system disk." && exit 98 rm -f "$SYSTEM"
error "Could not allocate file $SYSTEM for the system disk." && exit 98
fi fi
fi fi
@@ -247,7 +246,11 @@ fi
# Check the filesize # Check the filesize
SIZE=$(stat -c%s "$SYSTEM") SIZE=$(stat -c%s "$SYSTEM")
[[ SIZE -ne SYSTEM_SIZE ]] && rm -f "$SYSTEM" && error "System disk has the wrong size: $SIZE" && exit 90
if [[ SIZE -ne SYSTEM_SIZE ]]; then
rm -f "$SYSTEM"
error "System disk has the wrong size: $SIZE vs $SYSTEM_SIZE" && exit 90
fi
PART="$TMP/partition.fdisk" PART="$TMP/partition.fdisk"
@@ -263,33 +266,55 @@ PART="$TMP/partition.fdisk"
sfdisk -q "$SYSTEM" < "$PART" sfdisk -q "$SYSTEM" < "$PART"
info "Install: Extracting system partition..."
MOUNT="$TMP/system" MOUNT="$TMP/system"
rm -rf "$MOUNT" && mkdir -p "$MOUNT" rm -rf "$MOUNT" && mkdir -p "$MOUNT"
info "Install: Extracting system partition..."
HDA="$TMP/hda1"
IDB="$TMP/indexdb"
PKG="$TMP/packages"
HDP="$TMP/synohdpack_img"
[ ! -f "$HDA.tgz" ] && error "The PAT file contains no OS image." && exit 64
mv "$HDA.tgz" "$HDA.txz" mv "$HDA.tgz" "$HDA.txz"
if [[ "$DEV" == [Nn]* ]]; then if [[ "$ROOT" != [Nn]* ]]; then
# Exclude dev/ from tar extract
tar xpfJ "$HDA.txz" --absolute-names --exclude="dev" -C "$MOUNT/"
else
tar xpfJ "$HDA.txz" --absolute-names -C "$MOUNT/" tar xpfJ "$HDA.txz" --absolute-names -C "$MOUNT/"
fi fi
[ -d "$PKG" ] && mv "$PKG/" "$MOUNT/.SynoUpgradePackages/" [ -d "$PKG" ] && mv "$PKG/" "$MOUNT/.SynoUpgradePackages/"
rm -f "$MOUNT/.SynoUpgradePackages/ActiveInsight-"* rm -f "$MOUNT/.SynoUpgradePackages/ActiveInsight-"*
[ -f "$HDP.txz" ] && tar xpfJ "$HDP.txz" --absolute-names -C "$MOUNT/" [ -f "$HDP.txz" ] && tar xpfJ "$HDP.txz" --absolute-names -C "$MOUNT/"
[ -f "$IDB.txz" ] && tar xpfJ "$IDB.txz" --absolute-names -C "$MOUNT/usr/syno/synoman/indexdb/"
info "Install: Installing system partition..." if [ -f "$IDB.txz" ]; then
INDEX_DB="$MOUNT/usr/syno/synoman/indexdb/"
mkdir -p "$INDEX_DB"
tar xpfJ "$IDB.txz" --absolute-names -C "$INDEX_DB"
fi
LABEL="1.44.1-42218" LABEL="1.44.1-42218"
OFFSET="1048576" # 2048 * 512 OFFSET="1048576" # 2048 * 512
NUMBLOCKS="622560" # (4980480 * 512) / 4096 NUMBLOCKS="622560" # (4980480 * 512) / 4096
mke2fs -q -t ext4 -b 4096 -d "$MOUNT/" -L "$LABEL" -F -E "offset=$OFFSET" "$SYSTEM" "$NUMBLOCKS" if [[ "$ROOT" != [Nn]* ]]; then
info "Install: Installing system partition..."
mke2fs -q -t ext4 -b 4096 -d "$MOUNT/" -L "$LABEL" -F -E "offset=$OFFSET" "$SYSTEM" "$NUMBLOCKS"
else
fakeroot -- bash -c "set -Eeu;\
tar xpfJ $HDA.txz --absolute-names --skip-old-files -C $MOUNT/;\
printf '%b%s%b' '\E[1;34m \E[1;36m' 'Install: Installing system partition...' '\E[0m\n';\
mke2fs -q -t ext4 -b 4096 -d $MOUNT/ -L $LABEL -F -E offset=$OFFSET $SYSTEM $NUMBLOCKS"
fi
rm -rf "$MOUNT" rm -rf "$MOUNT"

View File

@@ -15,6 +15,8 @@ set -Eeuo pipefail
: ${DNSMASQ:='/usr/sbin/dnsmasq'} : ${DNSMASQ:='/usr/sbin/dnsmasq'}
: ${DNSMASQ_CONF_DIR:='/etc/dnsmasq.d'} : ${DNSMASQ_CONF_DIR:='/etc/dnsmasq.d'}
ADD_ERR="Please add the following setting to your container:"
# ###################################### # ######################################
# Functions # Functions
# ###################################### # ######################################
@@ -27,7 +29,7 @@ configureDHCP() {
if (( rc != 0 )); then if (( rc != 0 )); then
error "Cannot create macvtap interface. Please make sure the network type is 'macvlan' and not 'ipvlan'," error "Cannot create macvtap interface. Please make sure the network type is 'macvlan' and not 'ipvlan',"
error "and that the NET_ADMIN capability has been added to the container config: --cap-add NET_ADMIN" && exit 16 error "and that the NET_ADMIN capability has been added to the container: --cap-add NET_ADMIN" && exit 16
fi fi
while ! ip link set "$VM_NET_TAP" up; do while ! ip link set "$VM_NET_TAP" up; do
@@ -53,15 +55,13 @@ configureDHCP() {
{ exec 30>>"$TAP_PATH"; rc=$?; } 2>/dev/null || : { exec 30>>"$TAP_PATH"; rc=$?; } 2>/dev/null || :
if (( rc != 0 )); then if (( rc != 0 )); then
error "Cannot create TAP interface ($rc). Please add the following docker settings to your " error "Cannot create TAP interface ($rc). $ADD_ERR --device-cgroup-rule='c *:* rwm'" && exit 21
error "container: --device-cgroup-rule='c $MAJOR:* rwm' --device=/dev/vhost-net" && exit 21
fi fi
{ exec 40>>/dev/vhost-net; rc=$?; } 2>/dev/null || : { exec 40>>/dev/vhost-net; rc=$?; } 2>/dev/null || :
if (( rc != 0 )); then if (( rc != 0 )); then
error "VHOST can not be found ($rc). Please add the following " error "VHOST can not be found ($rc). $ADD_ERR --device=/dev/vhost-net" && exit 22
error "docker setting to your container: --device=/dev/vhost-net" && exit 22
fi fi
NET_OPTS="-netdev tap,id=hostnet0,vhost=on,vhostfd=40,fd=30" NET_OPTS="-netdev tap,id=hostnet0,vhost=on,vhostfd=40,fd=30"
@@ -100,8 +100,7 @@ configureNAT () {
{ ip link add dev dockerbridge type bridge ; rc=$?; } || : { ip link add dev dockerbridge type bridge ; rc=$?; } || :
if (( rc != 0 )); then if (( rc != 0 )); then
error "Capability NET_ADMIN has not been set most likely. Please add the " error "Failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && exit 23
error "following docker setting to your container: --cap-add NET_ADMIN" && exit 23
fi fi
ip address add ${VM_NET_IP%.*}.1/24 broadcast ${VM_NET_IP%.*}.255 dev dockerbridge ip address add ${VM_NET_IP%.*}.1/24 broadcast ${VM_NET_IP%.*}.255 dev dockerbridge
@@ -138,7 +137,7 @@ configureNAT () {
if [[ $(< /proc/sys/net/ipv4/ip_forward) -eq 0 ]]; then if [[ $(< /proc/sys/net/ipv4/ip_forward) -eq 0 ]]; then
{ sysctl -w net.ipv4.ip_forward=1 ; rc=$?; } || : { sysctl -w net.ipv4.ip_forward=1 ; rc=$?; } || :
if (( rc != 0 )); then if (( rc != 0 )); then
error "Please add the following docker setting to your container: --sysctl net.ipv4.ip_forward=1" && exit 24 error "IP forwarding is disabled. $ADD_ERR --sysctl net.ipv4.ip_forward=1" && exit 24
fi fi
fi fi
@@ -154,16 +153,19 @@ configureNAT () {
closeNetwork () { closeNetwork () {
exec 30<&- || true
exec 40<&- || true
if [[ "$DHCP" == [Yy1]* ]]; then if [[ "$DHCP" == [Yy1]* ]]; then
{ pkill -f server.sh || true; } 2>/dev/null fKill "server.sh"
ip link set "$VM_NET_TAP" down || true ip link set "$VM_NET_TAP" down || true
ip link delete "$VM_NET_TAP" || true ip link delete "$VM_NET_TAP" || true
else else
{ pkill -f dnsmasq || true; } 2>/dev/null fKill "dnsmasq"
ip link set "$VM_NET_TAP" down promisc off || true ip link set "$VM_NET_TAP" down promisc off || true
ip link delete "$VM_NET_TAP" || true ip link delete "$VM_NET_TAP" || true
@@ -178,21 +180,25 @@ closeNetwork () {
# Configure Network # Configure Network
# ###################################### # ######################################
{ pkill -f server.sh || true; } 2>/dev/null fKill "server.sh"
# Create the necessary file structure for /dev/net/tun # Create the necessary file structure for /dev/net/tun
if [ ! -c /dev/net/tun ]; then if [ ! -c /dev/net/tun ]; then
[ ! -d /dev/net ] && mkdir -m 755 /dev/net [ ! -d /dev/net ] && mkdir -m 755 /dev/net
mknod /dev/net/tun c 10 200 if mknod /dev/net/tun c 10 200; then
chmod 666 /dev/net/tun chmod 666 /dev/net/tun
fi
fi fi
[ ! -c /dev/net/tun ] && error "TUN network interface not available..." && exit 25 if [ ! -c /dev/net/tun ]; then
error "TUN device missing. $ADD_ERR --cap-add NET_ADMIN" && exit 25
fi
# Create the necessary file structure for /dev/vhost-net # Create the necessary file structure for /dev/vhost-net
if [ ! -c /dev/vhost-net ]; then if [ ! -c /dev/vhost-net ]; then
mknod /dev/vhost-net c 10 238 if mknod /dev/vhost-net c 10 238; then
chmod 660 /dev/vhost-net chmod 660 /dev/vhost-net
fi
fi fi
update-alternatives --set iptables /usr/sbin/iptables-legacy > /dev/null update-alternatives --set iptables /usr/sbin/iptables-legacy > /dev/null
@@ -209,9 +215,7 @@ fi
if [[ "$DHCP" == [Yy1]* ]]; then if [[ "$DHCP" == [Yy1]* ]]; then
if [[ "$GATEWAY" == "172."* ]]; then if [[ "$GATEWAY" == "172."* ]]; then
if [[ "$DEBUG" == [Yy1]* ]]; then if [[ "$DEBUG" != [Yy1]* ]]; then
info "Warning: Are you sure the container is on a macvlan network?"
else
error "You can only enable DHCP while the container is on a macvlan network!" && exit 26 error "You can only enable DHCP while the container is on a macvlan network!" && exit 26
fi fi
fi fi

View File

@@ -3,38 +3,92 @@ set -Eeuo pipefail
# Configure QEMU for graceful shutdown # Configure QEMU for graceful shutdown
API_CMD=6
API_TIMEOUT=50
API_HOST="127.0.0.1:2210"
QEMU_PORT=7100 QEMU_PORT=7100
QEMU_TIMEOUT=50 QEMU_TIMEOUT=50
QEMU_PID=/run/qemu.pid QEMU_PID="/run/qemu.pid"
QEMU_COUNT=/run/qemu.count QEMU_COUNT="/run/qemu.count"
if [[ "$KVM" == [Nn]* ]]; then
API_TIMEOUT=$(( API_TIMEOUT*2 ))
QEMU_TIMEOUT=$(( QEMU_TIMEOUT*2 ))
fi
rm -f "$QEMU_PID" rm -f "$QEMU_PID"
rm -f "$QEMU_COUNT" rm -f "$QEMU_COUNT"
_trap(){ _trap() {
func="$1" ; shift func="$1" ; shift
for sig ; do for sig ; do
trap "$func $sig" "$sig" trap "$func $sig" "$sig"
done
}
finish() {
local pid
local reason=$1
if [ -f "$QEMU_PID" ]; then
pid="$(cat "$QEMU_PID")"
echo && error "Forcefully terminating QEMU process, reason: $reason..."
{ kill -15 "$pid" || true; } 2>/dev/null
while isAlive "$pid"; do
sleep 1
# Workaround for zombie pid
[ ! -f "$QEMU_PID" ] && break
done done
fi
fKill "print.sh"
fKill "host.bin"
closeNetwork
sleep 1
echo && echo " Shutdown completed!"
exit "$reason"
} }
_graceful_shutdown() { _graceful_shutdown() {
set +e local code=$?
local cnt response local pid cnt response
[ ! -f "$QEMU_PID" ] && exit 130 set +e
[ -f "$QEMU_COUNT" ] && return
if [ -f "$QEMU_COUNT" ]; then
echo && info "Ignored $1 signal, already shutting down..."
return
fi
echo 0 > "$QEMU_COUNT" echo 0 > "$QEMU_COUNT"
echo && info "Received $1 signal, sending shutdown command..." echo && info "Received $1 signal, sending shutdown command..."
if [ ! -f "$QEMU_PID" ]; then
echo && error "QEMU PID file does not exist?"
finish "$code" && return "$code"
fi
pid="$(cat "$QEMU_PID")"
if ! isAlive "$pid"; then
echo && error "QEMU process does not exist?"
finish "$code" && return "$code"
fi
# Don't send the powerdown signal because vDSM ignores ACPI signals # Don't send the powerdown signal because vDSM ignores ACPI signals
# 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
url="http://127.0.0.1:2210/read?command=6&timeout=50" url="http://$API_HOST/read?command=$API_CMD&timeout=$API_TIMEOUT"
response=$(curl -sk -m 52 -S "$url" 2>&1) response=$(curl -sk -m "$(( API_TIMEOUT+2 ))" -S "$url" 2>&1)
if [[ "$response" =~ "\"success\"" ]]; then if [[ "$response" =~ "\"success\"" ]]; then
@@ -43,40 +97,34 @@ _graceful_shutdown() {
else else
response="${response#*message\"\: \"}" response="${response#*message\"\: \"}"
echo && error "Failed to send shutdown command: ${response%%\"*}" [ -z "$response" ] && response="second signal"
echo && error "Forcefully terminating because of: ${response%%\"*}"
kill -15 "$(cat "$QEMU_PID")" { kill -15 "$pid" || true; } 2>/dev/null
pkill -f qemu-system-x86_64 || true
fi fi
while [ "$(cat $QEMU_COUNT)" -lt "$QEMU_TIMEOUT" ]; do while [ "$(cat $QEMU_COUNT)" -lt "$QEMU_TIMEOUT" ]; do
! isAlive "$pid" && break
sleep 1
# Increase the counter # Increase the counter
echo $(($(cat $QEMU_COUNT)+1)) > "$QEMU_COUNT" cnt=$(($(cat $QEMU_COUNT)+1))
echo $cnt > "$QEMU_COUNT"
# Try to connect to qemu [[ "$DEBUG" == [Yy1]* ]] && info "Shutting down, waiting... ($cnt/$QEMU_TIMEOUT)"
if echo 'info version'| nc -q 1 -w 1 localhost "$QEMU_PORT" >/dev/null 2>&1 ; then
sleep 1 # Workaround for zombie pid
[ ! -f "$QEMU_PID" ] && break
cnt="$(cat $QEMU_COUNT)/$QEMU_TIMEOUT"
[[ "$DEBUG" == [Yy1]* ]] && info "Shutting down, waiting... ($cnt)"
fi
done done
echo && echo " Quitting..." if [ "$(cat $QEMU_COUNT)" -ge "$QEMU_TIMEOUT" ]; then
echo 'quit' | nc -q 1 -w 1 localhost "$QEMU_PORT" >/dev/null 2>&1 || true echo && error "Shutdown timeout reached!"
fi
{ pkill -f print.sh || true; } 2>/dev/null finish "$code" && return "$code"
{ pkill -f host.bin || true; } 2>/dev/null
closeNetwork
sleep 1
return
} }
_trap _graceful_shutdown SIGTERM SIGHUP SIGINT SIGABRT SIGQUIT _trap _graceful_shutdown SIGTERM SIGHUP SIGINT SIGABRT SIGQUIT

View File

@@ -1,12 +1,16 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -Eeuo pipefail set -Eeuo pipefail
: ${DHCP:='N'}
: ${VM_NET_DEV:='eth0'}
info () { printf "%b%s%b" "\E[1;34m \E[1;36m" "$1" "\E[0m\n" >&2; } info () { printf "%b%s%b" "\E[1;34m \E[1;36m" "$1" "\E[0m\n" >&2; }
error () { printf "%b%s%b" "\E[1;31m " "ERROR: $1" "\E[0m\n" >&2; } error () { printf "%b%s%b" "\E[1;31m " "ERROR: $1" "\E[0m\n" >&2; }
file="/run/dsm.url" file="/run/dsm.url"
shutdown="/run/qemu.count" shutdown="/run/qemu.count"
url="http://127.0.0.1:2210/read?command=10" url="http://127.0.0.1:2210/read?command=10"
resp_err="Guest returned an invalid response:" resp_err="Guest returned an invalid response:"
jq_err="Failed to parse response from guest: jq error" jq_err="Failed to parse response from guest: jq error"
@@ -19,11 +23,9 @@ do
sleep 3 sleep 3
[ -f "$shutdown" ] && exit 1 [ -f "$shutdown" ] && exit 1
# Healthcheck may have intervened
[ -f "$file" ] && break [ -f "$file" ] && break
# Retrieve IP from guest VM # Retrieve network info from guest VM
{ json=$(curl -m 20 -sk "$url"); rc=$?; } || : { json=$(curl -m 20 -sk "$url"); rc=$?; } || :
[ -f "$shutdown" ] && exit 1 [ -f "$shutdown" ] && exit 1
@@ -46,7 +48,11 @@ do
{ ip=$(echo "$json" | jq -r '.data.data.ip.data[] | select((.name=="eth0") and has("ip")).ip'); rc=$?; } || : { ip=$(echo "$json" | jq -r '.data.data.ip.data[] | select((.name=="eth0") and has("ip")).ip'); rc=$?; } || :
(( rc != 0 )) && error "$jq_err $rc ( $json )" && continue (( rc != 0 )) && error "$jq_err $rc ( $json )" && continue
[[ "$ip" == "null" ]] && error "$resp_err $json" && continue [[ "$ip" == "null" ]] && error "$resp_err $json" && continue
[ -z "$ip" ] && continue
if [ -z "$ip" ]; then
[[ "$DHCP" == [Yy1]* ]] && continue
ip="20.20.20.21"
fi
echo "$ip:$port" > $file echo "$ip:$port" > $file
@@ -62,7 +68,7 @@ if [[ "$location" != "20.20"* ]]; then
else else
ip=$(ip address show dev eth0 | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/) ip=$(ip address show dev "$VM_NET_DEV" | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/)
port="${location##*:}" port="${location##*:}"
if [[ "$ip" == "172."* ]]; then if [[ "$ip" == "172."* ]]; then

View File

@@ -11,6 +11,7 @@ trap 'error "Status $? while: $BASH_COMMAND (line $LINENO/$BASH_LINENO)"' ERR
# Docker environment variables # Docker environment variables
: ${TZ:=''} # System local timezone
: ${GPU:='N'} # Disable GPU passthrough : ${GPU:='N'} # Disable GPU passthrough
: ${KVM:='Y'} # Enable KVM acceleration : ${KVM:='Y'} # Enable KVM acceleration
: ${DEBUG:='N'} # Disable debugging mode : ${DEBUG:='N'} # Disable debugging mode
@@ -43,12 +44,46 @@ rm -f /run/qemu.count
# Cleanup dirs # Cleanup dirs
rm -rf /tmp/dsm rm -rf /tmp/dsm
rm -f /tmp/server.*
rm -rf "$STORAGE/tmp" rm -rf "$STORAGE/tmp"
# Helper functions # Helper functions
getCountry () { isAlive() {
local pid=$1
if kill -0 "$pid" 2>/dev/null; then
return 0
fi
return 1
}
pKill() {
local pid=$1
{ kill -15 "$pid" || true; } 2>/dev/null
while isAlive "$pid"; do
sleep 0.1
done
return 0
}
fKill () {
local name=$1
{ pkill -f "$name" || true; } 2>/dev/null
while pgrep -f -l "$name" >/dev/null; do
sleep 0.1
done
return 0
}
getCountry () {
local url=$1 local url=$1
local query=$2 local query=$2
local rc json result local rc json result
@@ -69,6 +104,13 @@ getCountry () {
setCountry () { setCountry () {
[[ "${TZ,,}" == "asia/harbin" ]] && COUNTRY="CN"
[[ "${TZ,,}" == "asia/beijing" ]] && COUNTRY="CN"
[[ "${TZ,,}" == "asia/urumqi" ]] && COUNTRY="CN"
[[ "${TZ,,}" == "asia/kashgar" ]] && COUNTRY="CN"
[[ "${TZ,,}" == "asia/shanghai" ]] && COUNTRY="CN"
[[ "${TZ,,}" == "asia/chongqing" ]] && COUNTRY="CN"
[ -z "$COUNTRY" ] && getCountry "https://api.ipapi.is" ".location.country_code" [ -z "$COUNTRY" ] && getCountry "https://api.ipapi.is" ".location.country_code"
[ -z "$COUNTRY" ] && getCountry "https://ifconfig.co/json" ".country_iso" [ -z "$COUNTRY" ] && getCountry "https://ifconfig.co/json" ".country_iso"
[ -z "$COUNTRY" ] && getCountry "https://ipinfo.io/json" ".country" [ -z "$COUNTRY" ] && getCountry "https://ipinfo.io/json" ".country"
@@ -78,7 +120,6 @@ setCountry () {
} }
addPackage () { addPackage () {
local pkg=$1 local pkg=$1
local desc=$2 local desc=$2

View File

@@ -47,10 +47,9 @@ done
# Configure serial ports # Configure serial ports
SERIAL_OPTS="\ SERIAL_OPTS="\
-serial mon:stdio \
-device virtio-serial-pci,id=virtio-serial0,bus=pcie.0,addr=0x3 \
-chardev pty,id=charserial0 \ -chardev pty,id=charserial0 \
-device isa-serial,chardev=charserial0,id=serial0 \ -device isa-serial,chardev=charserial0,id=serial0 \
-device virtio-serial-pci,id=virtio-serial0,bus=pcie.0,addr=0x3 \
-chardev socket,id=charchannel0,host=127.0.0.1,port=12345,reconnect=10 \ -chardev socket,id=charchannel0,host=127.0.0.1,port=12345,reconnect=10 \
-device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=vchannel" -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=vchannel"