Compare commits

..

16 Commits

Author SHA1 Message Date
Kroese
5e8bbc2868 fix: Remove unnecessary operation (#1097) 2025-10-24 04:30:21 +02:00
Kroese
4e48920309 fix: Do not assume Podman never has privileges (#1096) 2025-10-24 01:19:38 +02:00
Kroese
8b145924b9 fix: Reduce spare disk space threshold (#1093)
Some checks failed
Update / dockerHubDescription (push) Has been cancelled
2025-10-22 02:47:50 +02:00
Kroese
a0328e1e9c fix: Inherit owner from parent folder (#1092) 2025-10-22 02:38:57 +02:00
Kroese
b7f5214a7b build: Add code quality checks (#1091) 2025-10-22 00:59:35 +02:00
Kroese
b0e4c4ac5f docs: Update docker run command (#1090) 2025-10-21 23:15:31 +02:00
Kroese
bbb67aac93 build: Add review workflow for shell formatting (#1089) 2025-10-21 22:39:50 +02:00
Kroese
433c83b393 fix: Kill QEMU after 5 seconds if it hangs (#1088) 2025-10-19 17:56:44 +02:00
Kroese
5577178eeb fix: Only display non-zero percentage (#1087) 2025-10-19 17:32:25 +02:00
Kroese
221b0242fa fix: Kill QEMU after 5 seconds when it hangs (#1086) 2025-10-19 16:57:51 +02:00
Kroese
c05623f8af fix: Round filesize up to nearest cluster (#1085) 2025-10-19 14:38:36 +02:00
Kroese
eb9884cc96 feat: Improve Github Codespaces configuration (#1084) 2025-10-19 12:48:40 +02:00
Kroese
8e2490e6bc feat: Improve Github Codespaces configuration (#1082) 2025-10-19 10:40:03 +02:00
Kroese
399243886e feat: Show directory size (#1083) 2025-10-19 09:40:45 +02:00
Kroese
b0dbfcb805 feat: Improve Github Codespaces configuration (#1081) 2025-10-19 01:14:11 +02:00
Kroese
dec2dc9230 feat: Check free diskspace during startup (#1080) 2025-10-17 16:47:43 +02:00
11 changed files with 314 additions and 120 deletions

View File

@@ -1,9 +1,8 @@
services: services:
dsm: dsm:
container_name: dsm container_name: dsm
image: vdsm/virtual-dsm image: ghcr.io/vdsm/virtual-dsm
environment: environment:
ALLOCATE: "Y"
RAM_SIZE: "half" RAM_SIZE: "half"
DISK_SIZE: "max" DISK_SIZE: "max"
CPU_CORES: "max" CPU_CORES: "max"

View File

@@ -1,18 +1,17 @@
{ {
"name": "Virtual DSM", "name": "Virtual DSM",
"service": "dsm", "service": "vdsm",
"containerEnv": {
"ALLOCATE": "Y"
},
"forwardPorts": [5000], "forwardPorts": [5000],
"portsAttributes": { "portsAttributes": {
"5000": { "5000": {
"label": "Web", "label": "Web",
"onAutoForward": "openBrowser" "onAutoForward": "notify"
} }
}, },
"otherPortsAttributes": { "otherPortsAttributes": {
"onAutoForward": "silent" "onAutoForward": "ignore"
}, },
"dockerComposeFile": "codespaces.yml" "dockerComposeFile": "codespaces.yml",
"workspaceFolder": "/workspaces/vdsm",
"initializeCommand": "docker system prune --all --force"
} }

66
.github/workflows/review.yml vendored Normal file
View File

@@ -0,0 +1,66 @@
on:
pull_request:
name: "Review"
permissions:
contents: read
pull-requests: write
checks: write
jobs:
review:
name: review
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v5
-
name: Spelling
uses: reviewdog/action-misspell@v1
with:
locale: "US"
level: warning
pattern: |
*.md
*.sh
reporter: github-pr-review
github_token: ${{ secrets.REPO_ACCESS_TOKEN }}
-
name: Hadolint
uses: reviewdog/action-hadolint@v1
with:
level: warning
reporter: github-pr-review
hadolint_ignore: DL3008 DL3003 DL3006 DL3013
github_token: ${{ secrets.REPO_ACCESS_TOKEN }}
-
name: YamlLint
uses: reviewdog/action-yamllint@v1
with:
level: warning
reporter: github-pr-review
github_token: ${{ secrets.REPO_ACCESS_TOKEN }}
-
name: ActionLint
uses: reviewdog/action-actionlint@v1
with:
level: warning
reporter: github-pr-review
github_token: ${{ secrets.REPO_ACCESS_TOKEN }}
-
name: Shellformat
uses: reviewdog/action-shfmt@v1
with:
level: warning
shfmt_flags: "-i 2 -ci -bn"
github_token: ${{ secrets.REPO_ACCESS_TOKEN }}
-
name: Shellcheck
uses: reviewdog/action-shellcheck@v1
with:
level: warning
reporter: github-pr-review
shellcheck_flags: -x -e SC2001 -e SC2034 -e SC2064 -e SC2317 -e SC2153 -e SC2028
github_token: ${{ secrets.REPO_ACCESS_TOKEN }}

View File

@@ -47,7 +47,7 @@ services:
##### Via Docker CLI: ##### Via Docker CLI:
```bash ```bash
docker run -it --rm --name dsm -e "DISK_SIZE=256G" -p 5000:5000 --device=/dev/kvm --device=/dev/net/tun --cap-add NET_ADMIN -v "${PWD:-.}/dsm:/storage" --stop-timeout 120 vdsm/virtual-dsm docker run -it --rm --name dsm -e "DISK_SIZE=256G" -p 5000:5000 --device=/dev/kvm --device=/dev/net/tun --cap-add NET_ADMIN -v "${PWD:-.}/dsm:/storage" --stop-timeout 120 docker.io/vdsm/virtual-dsm
``` ```
##### Via Kubernetes: ##### Via Kubernetes:

View File

@@ -17,8 +17,16 @@ SYSTEM="$STORAGE/$BASE.system.img"
[ ! -s "$BOOT" ] && error "Virtual DSM boot-image does not exist ($BOOT)" && exit 81 [ ! -s "$BOOT" ] && error "Virtual DSM boot-image does not exist ($BOOT)" && exit 81
[ ! -s "$SYSTEM" ] && error "Virtual DSM system-image does not exist ($SYSTEM)" && exit 82 [ ! -s "$SYSTEM" ] && error "Virtual DSM system-image does not exist ($SYSTEM)" && exit 82
if ! setOwner "$BOOT"; then
error "Failed to set the owner for \"$BOOT\" !"
fi
if ! setOwner "$SYSTEM"; then
error "Failed to set the owner for \"$SYSTEM\" !"
fi
fmt2ext() { fmt2ext() {
local DISK_FMT=$1 local DISK_FMT="$1"
case "${DISK_FMT,,}" in case "${DISK_FMT,,}" in
qcow2) qcow2)
@@ -34,7 +42,7 @@ fmt2ext() {
} }
ext2fmt() { ext2fmt() {
local DISK_EXT=$1 local DISK_EXT="$1"
case "${DISK_EXT,,}" in case "${DISK_EXT,,}" in
qcow2) qcow2)
@@ -50,7 +58,7 @@ ext2fmt() {
} }
getSize() { getSize() {
local DISK_FILE=$1 local DISK_FILE="$1"
local DISK_EXT DISK_FMT local DISK_EXT DISK_FMT
DISK_EXT=$(echo "${DISK_FILE//*./}" | sed 's/^.*\.//') DISK_EXT=$(echo "${DISK_FILE//*./}" | sed 's/^.*\.//')
@@ -70,7 +78,7 @@ getSize() {
} }
isCow() { isCow() {
local FS=$1 local FS="$1"
if [[ "${FS,,}" == "btrfs" ]]; then if [[ "${FS,,}" == "btrfs" ]]; then
return 0 return 0
@@ -80,7 +88,7 @@ isCow() {
} }
supportsDirect() { supportsDirect() {
local FS=$1 local FS="$1"
if [[ "${FS,,}" == "ecryptfs" || "${FS,,}" == "tmpfs" ]]; then if [[ "${FS,,}" == "ecryptfs" || "${FS,,}" == "tmpfs" ]]; then
return 1 return 1
@@ -91,11 +99,11 @@ supportsDirect() {
createDisk() { createDisk() {
local DISK_FILE=$1 local DISK_FILE="$1"
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 FS=$5 local FS="$5"
local DATA_SIZE DIR SPACE GB FA local DATA_SIZE DIR SPACE GB FA
rm -f "$DISK_FILE" rm -f "$DISK_FILE"
@@ -113,6 +121,7 @@ createDisk() {
error "Not enough free space to create a $DISK_DESC of ${DISK_SPACE/G/ GB} in $DIR, it has only $GB available..." error "Not enough free space to create a $DISK_DESC of ${DISK_SPACE/G/ GB} in $DIR, it has only $GB available..."
error "Please specify a smaller ${DISK_DESC^^}_SIZE or disable preallocation by setting ALLOCATE=N." && exit 76 error "Please specify a smaller ${DISK_DESC^^}_SIZE or disable preallocation by setting ALLOCATE=N." && exit 76
fi fi
fi fi
html "Creating a $DISK_DESC image..." html "Creating a $DISK_DESC image..."
@@ -177,11 +186,11 @@ createDisk() {
resizeDisk() { resizeDisk() {
local DISK_FILE=$1 local DISK_FILE="$1"
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 FS=$5 local FS="$5"
local CUR_SIZE DATA_SIZE DIR SPACE GB local CUR_SIZE DATA_SIZE DIR SPACE GB
CUR_SIZE=$(getSize "$DISK_FILE") CUR_SIZE=$(getSize "$DISK_FILE")
@@ -200,6 +209,7 @@ resizeDisk() {
error "Not enough free space to resize $DISK_DESC to ${DISK_SPACE/G/ GB} in $DIR, it has only $GB available.." error "Not enough free space to resize $DISK_DESC to ${DISK_SPACE/G/ GB} in $DIR, it has only $GB available.."
error "Please specify a smaller ${DISK_DESC^^}_SIZE or disable preallocation by setting ALLOCATE=N." && exit 74 error "Please specify a smaller ${DISK_DESC^^}_SIZE or disable preallocation by setting ALLOCATE=N." && exit 74
fi fi
fi fi
GB=$(formatBytes "$CUR_SIZE") GB=$(formatBytes "$CUR_SIZE")
@@ -245,13 +255,13 @@ resizeDisk() {
convertDisk() { convertDisk() {
local SOURCE_FILE=$1 local SOURCE_FILE="$1"
local SOURCE_FMT=$2 local SOURCE_FMT="$2"
local DST_FILE=$3 local DST_FILE="$3"
local DST_FMT=$4 local DST_FMT="$4"
local DISK_BASE=$5 local DISK_BASE="$5"
local DISK_DESC=$6 local DISK_DESC="$6"
local FS=$7 local FS="$7"
[ -f "$DST_FILE" ] && error "Conversion failed, destination file $DST_FILE already exists?" && exit 79 [ -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 [ ! -f "$SOURCE_FILE" ] && error "Conversion failed, source file $SOURCE_FILE does not exists?" && exit 79
@@ -273,6 +283,7 @@ convertDisk() {
error "Not enough free space to convert $DISK_DESC to $DST_FMT in $DIR, it has only $GB available..." error "Not enough free space to convert $DISK_DESC to $DST_FMT in $DIR, it has only $GB available..."
error "Please free up some disk space or disable preallocation by setting ALLOCATE=N." && exit 76 error "Please free up some disk space or disable preallocation by setting ALLOCATE=N." && exit 76
fi fi
fi fi
local msg="Converting $DISK_DESC to $DST_FMT" local msg="Converting $DISK_DESC to $DST_FMT"
@@ -327,31 +338,31 @@ convertDisk() {
checkFS () { checkFS () {
local FS=$1 local FS="$1"
local DISK_FILE=$2 local DISK_FILE="$2"
local DISK_DESC=$3 local DISK_DESC="$3"
local DIR FA local DIR FA
DIR=$(dirname "$DISK_FILE") DIR=$(dirname "$DISK_FILE")
[ ! -d "$DIR" ] && return 0 [ ! -d "$DIR" ] && return 0
if [[ "${FS,,}" == "overlay"* ]]; then if [[ "${FS,,}" == "overlay"* && "$PODMAN" != [Yy1]* ]]; then
info "Warning: the filesystem of $DIR is OverlayFS, this usually means it was binded to an invalid path!" warn "the filesystem of $DIR is OverlayFS, this usually means it was binded to an invalid path!"
fi fi
if [[ "${FS,,}" == "fuse"* ]]; then if [[ "${FS,,}" == "fuse"* ]]; then
info "Warning: the filesystem of $DIR is FUSE, this extra layer will negatively affect performance!" warn "the filesystem of $DIR is FUSE, this extra layer will negatively affect performance!"
fi fi
if ! supportsDirect "$FS"; then if ! supportsDirect "$FS"; then
info "Warning: the filesystem of $DIR is $FS, which does not support O_DIRECT mode, adjusting settings..." warn "the filesystem of $DIR is $FS, which does not support O_DIRECT mode, adjusting settings..."
fi fi
if isCow "$FS"; then if isCow "$FS"; then
if [ -f "$DISK_FILE" ]; then if [ -f "$DISK_FILE" ]; then
FA=$(lsattr "$DISK_FILE") FA=$(lsattr "$DISK_FILE")
if [[ "$FA" != *"C"* ]]; then 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!" warn "COW (copy on write) is not disabled for $DISK_DESC image file $DISK_FILE, this is recommended on ${FS^^} filesystems!"
fi fi
fi fi
fi fi
@@ -361,15 +372,15 @@ checkFS () {
createDevice () { createDevice () {
local DISK_FILE=$1 local DISK_FILE="$1"
local DISK_TYPE=$2 local DISK_TYPE="$2"
local DISK_INDEX=$3 local DISK_INDEX="$3"
local DISK_ADDRESS=$4 local DISK_ADDRESS="$4"
local DISK_FMT=$5 local DISK_FMT="$5"
local DISK_IO=$6 local DISK_IO="$6"
local DISK_CACHE=$7 local DISK_CACHE="$7"
local DISK_SERIAL=$8 local DISK_SERIAL="$8"
local DISK_SECTORS=$9 local DISK_SECTORS="$9"
local DISK_ID="data$DISK_INDEX" local DISK_ID="data$DISK_INDEX"
local index="" local index=""
@@ -415,16 +426,16 @@ createDevice () {
addDisk () { addDisk () {
local DISK_BASE=$1 local DISK_BASE="$1"
local DISK_TYPE=$2 local DISK_TYPE="$2"
local DISK_DESC=$3 local DISK_DESC="$3"
local DISK_SPACE=$4 local DISK_SPACE="$4"
local DISK_INDEX=$5 local DISK_INDEX="$5"
local DISK_ADDRESS=$6 local DISK_ADDRESS="$6"
local DISK_FMT=$7 local DISK_FMT="$7"
local DISK_IO=$8 local DISK_IO="$8"
local DISK_CACHE=$9 local DISK_CACHE="$9"
local DISK_EXT DIR SPACE GB DATA_SIZE FS PREV_FMT PREV_EXT CUR_SIZE local DISK_EXT DIR SPACE GB DATA_SIZE FS PREV_FMT PREV_EXT CUR_SIZE LEFT FREE USED
DISK_EXT=$(fmt2ext "$DISK_FMT") DISK_EXT=$(fmt2ext "$DISK_FMT")
local DISK_FILE="$DISK_BASE.$DISK_EXT" local DISK_FILE="$DISK_BASE.$DISK_EXT"
@@ -434,23 +445,23 @@ addDisk () {
if [[ "${DISK_SPACE,,}" == "max" || "${DISK_SPACE,,}" == "half" ]]; then if [[ "${DISK_SPACE,,}" == "max" || "${DISK_SPACE,,}" == "half" ]]; then
local SPARE=2147483648 local SPARE=1073741824
SPACE=$(df --output=avail -B 1 "$DIR" | tail -n 1) FREE=$(df --output=avail -B 1 "$DIR" | tail -n 1)
if [[ "${DISK_SPACE,,}" == "max" ]]; then if [[ "${DISK_SPACE,,}" == "max" ]]; then
SPACE=$((SPACE-SPARE)) FREE=$(( FREE - SPARE ))
else else
SPACE=$(( SPACE / 2 )) FREE=$(( FREE / 2 ))
fi fi
(( SPACE < SPARE )) && SPACE="$SPARE" (( FREE < SPARE )) && FREE="$SPARE"
GB=$(( SPACE/1073741825 )) GB=$(( FREE / 1073741825 ))
DISK_SPACE="${GB}G" DISK_SPACE="${GB}G"
fi fi
SPACE="${DISK_SPACE// /}" SPACE="${DISK_SPACE// /}"
[ -z "$SPACE" ] && SPACE="16G" [ -z "$SPACE" ] && SPACE="256G"
[ -z "${SPACE//[0-9. ]}" ] && SPACE="${SPACE}G" [ -z "${SPACE//[0-9. ]}" ] && SPACE="${SPACE}G"
SPACE=$(echo "${SPACE^^}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g') SPACE=$(echo "${SPACE^^}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
@@ -461,7 +472,7 @@ addDisk () {
DATA_SIZE=$(numfmt --from=iec "$SPACE") DATA_SIZE=$(numfmt --from=iec "$SPACE")
if (( DATA_SIZE < 6442450944 )); then if (( DATA_SIZE < 6442450944 )); then
error "Please increase ${DISK_DESC^^}_SIZE to at least 6 GB." && exit 73 error "Please increase the ${DISK_DESC^^}_SIZE variable to at least 6 GB." && exit 73
fi fi
FS=$(stat -f -c %T "$DIR") FS=$(stat -f -c %T "$DIR")
@@ -472,7 +483,7 @@ addDisk () {
DISK_CACHE="writeback" DISK_CACHE="writeback"
fi fi
if ! [ -s "$DISK_FILE" ] ; then if [ ! -s "$DISK_FILE" ] ; then
if [[ "${DISK_FMT,,}" != "raw" ]]; then if [[ "${DISK_FMT,,}" != "raw" ]]; then
PREV_FMT="raw" PREV_FMT="raw"
@@ -485,6 +496,7 @@ addDisk () {
if [ -s "$DISK_BASE.$PREV_EXT" ] ; then if [ -s "$DISK_BASE.$PREV_EXT" ] ; then
convertDisk "$DISK_BASE.$PREV_EXT" "$PREV_FMT" "$DISK_FILE" "$DISK_FMT" "$DISK_BASE" "$DISK_DESC" "$FS" || exit $? convertDisk "$DISK_BASE.$PREV_EXT" "$PREV_FMT" "$DISK_FILE" "$DISK_FMT" "$DISK_BASE" "$DISK_DESC" "$FS" || exit $?
fi fi
fi fi
if [ -s "$DISK_FILE" ]; then if [ -s "$DISK_FILE" ]; then
@@ -492,7 +504,18 @@ addDisk () {
CUR_SIZE=$(getSize "$DISK_FILE") CUR_SIZE=$(getSize "$DISK_FILE")
if (( DATA_SIZE > CUR_SIZE )); then if (( DATA_SIZE > CUR_SIZE )); then
resizeDisk "$DISK_FILE" "$SPACE" "$DISK_DESC" "$DISK_FMT" "$FS" || exit $? resizeDisk "$DISK_FILE" "$SPACE" "$DISK_DESC" "$DISK_FMT" "$FS" || exit $?
else
if (( DATA_SIZE < CUR_SIZE )); then
if [[ "${DISK_SPACE,,}" != "max" && "${DISK_SPACE,,}" != "half" ]]; then
info "You decreased the ${DISK_DESC^^}_SIZE variable to ${DISK_SPACE/G/ GB} but shrinking disks is not supported, will be ignored..."
fi
fi
fi fi
else else
@@ -501,6 +524,39 @@ addDisk () {
fi fi
if [ -f "$DISK_FILE" ] && [[ "$ALLOCATE" == [Nn]* ]]; then
CUR_SIZE=$(getSize "$DISK_FILE")
USED=$(du -sB 1 "$DISK_FILE" | cut -f1)
FREE=$(df --output=avail -B 1 "$DIR" | tail -n 1)
LEFT=$(( CUR_SIZE - USED - FREE ))
if (( LEFT > 0 )); then
GB=$(formatBytes "$FREE")
LEFT=$(formatBytes "$LEFT")
CUR_SIZE=$(formatBytes "$CUR_SIZE")
msg="the virtual size of the ${DISK_DESC,,} is $CUR_SIZE"
if [[ "$USED" == "0" ]]; then
msg+=","
else
USED=$(formatBytes "$USED")
msg+=" (of which $USED is used),"
fi
warn "$msg but there is only $GB of free space left in $DIR, make at least $LEFT more room available!"
fi
fi
if [ -f "$DISK_FILE" ]; then
if ! setOwner "$DISK_FILE"; then
error "Failed to set the owner for \"$DISK_FILE\" !"
fi
fi
DISK_OPTS+=$(createDevice "$DISK_FILE" "$DISK_TYPE" "$DISK_INDEX" "$DISK_ADDRESS" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE" "" "") DISK_OPTS+=$(createDevice "$DISK_FILE" "$DISK_TYPE" "$DISK_INDEX" "$DISK_ADDRESS" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE" "" "")
return 0 return 0
@@ -508,10 +564,10 @@ addDisk () {
addDevice () { addDevice () {
local DISK_DEV=$1 local DISK_DEV="$1"
local DISK_TYPE=$2 local DISK_TYPE="$2"
local DISK_INDEX=$3 local DISK_INDEX="$3"
local DISK_ADDRESS=$4 local DISK_ADDRESS="$4"
[ -z "$DISK_DEV" ] && return 0 [ -z "$DISK_DEV" ] && return 0
[ ! -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

View File

@@ -31,7 +31,6 @@ if [ -n "$URL" ] && [ ! -s "$FILE" ] && [ ! -d "$DIR" ]; then
BASE=$(basename "$URL" .pat) BASE=$(basename "$URL" .pat)
if [ ! -s "$STORAGE/$BASE.system.img" ]; then if [ ! -s "$STORAGE/$BASE.system.img" ]; then
BASE=$(basename "${URL%%\?*}" .pat) BASE=$(basename "${URL%%\?*}" .pat)
BASE="${BASE//+/ }"
printf -v BASE '%b' "${BASE//%/\\x}" printf -v BASE '%b' "${BASE//%/\\x}"
BASE="${BASE//[!A-Za-z0-9._-]/_}" BASE="${BASE//[!A-Za-z0-9._-]/_}"
fi fi
@@ -66,7 +65,6 @@ fi
if [ ! -s "$FILE" ]; then if [ ! -s "$FILE" ]; then
BASE=$(basename "${URL%%\?*}" .pat) BASE=$(basename "${URL%%\?*}" .pat)
BASE="${BASE//+/ }"
printf -v BASE '%b' "${BASE//%/\\x}" printf -v BASE '%b' "${BASE//%/\\x}"
BASE="${BASE//[!A-Za-z0-9._-]/_}" BASE="${BASE//[!A-Za-z0-9._-]/_}"
fi fi
@@ -82,16 +80,16 @@ rm -f "$STORAGE/$BASE.system.img"
# Check filesystem # Check filesystem
FS=$(stat -f -c %T "$STORAGE") FS=$(stat -f -c %T "$STORAGE")
if [[ "${FS,,}" == "overlay"* ]]; then if [[ "${FS,,}" == "overlay"* && "$PODMAN" != [Yy1]* ]]; then
info "Warning: the filesystem of $STORAGE is OverlayFS, this usually means it was binded to an invalid path!" warn "the filesystem of $STORAGE is OverlayFS, this usually means it was binded to an invalid path!"
fi fi
if [[ "${FS,,}" == "fuse"* ]]; then if [[ "${FS,,}" == "fuse"* ]]; then
info "Warning: the filesystem of $STORAGE is FUSE, this extra layer will negatively affect performance!" warn "the filesystem of $STORAGE is FUSE, this extra layer will negatively affect performance!"
fi fi
if [[ "${FS,,}" == "ecryptfs" || "${FS,,}" == "tmpfs" ]]; then if [[ "${FS,,}" == "ecryptfs" || "${FS,,}" == "tmpfs" ]]; then
info "Warning: the filesystem of $STORAGE is $FS, which does not support O_DIRECT mode, adjusting settings..." warn "the filesystem of $STORAGE is $FS, which does not support O_DIRECT mode, adjusting settings..."
fi fi
if [[ "${FS,,}" == "fat"* || "${FS,,}" == "vfat"* || "${FS,,}" == "msdos"* ]]; then if [[ "${FS,,}" == "fat"* || "${FS,,}" == "vfat"* || "${FS,,}" == "msdos"* ]]; then
@@ -100,6 +98,10 @@ fi
if [[ "${FS,,}" != "exfat"* && "${FS,,}" != "ntfs"* && "${FS,,}" != "unknown"* ]]; then if [[ "${FS,,}" != "exfat"* && "${FS,,}" != "ntfs"* && "${FS,,}" != "unknown"* ]]; then
TMP="$STORAGE/tmp" TMP="$STORAGE/tmp"
rm -rf "$TMP"
if ! makeDir "$TMP"; then
error "Failed to create directory \"$TMP\" !" && exit 93
fi
else else
TMP="/tmp/dsm" TMP="/tmp/dsm"
TMP_SPACE=2147483648 TMP_SPACE=2147483648
@@ -108,9 +110,8 @@ else
if (( TMP_SPACE > SPACE )); then if (( TMP_SPACE > SPACE )); then
error "Not enough free space inside the container, have $SPACE_MB available but need at least 2 GB." && exit 93 error "Not enough free space inside the container, have $SPACE_MB available but need at least 2 GB." && exit 93
fi fi
fi
rm -rf "$TMP" && mkdir -p "$TMP" rm -rf "$TMP" && mkdir -p "$TMP"
fi
# Check free diskspace # Check free diskspace
ROOT_SPACE=536870912 ROOT_SPACE=536870912
@@ -224,6 +225,8 @@ if ! touch "$SYSTEM"; then
error "Could not create file $SYSTEM for the system disk." && exit 98 error "Could not create file $SYSTEM for the system disk." && exit 98
fi fi
! setOwner "$SYSTEM" && error "Failed to set the owner for \"$SYSTEM\" !"
if [[ "${FS,,}" == "btrfs" ]]; then if [[ "${FS,,}" == "btrfs" ]]; then
{ chattr +C "$SYSTEM"; } || : { chattr +C "$SYSTEM"; } || :
FA=$(lsattr "$SYSTEM") FA=$(lsattr "$SYSTEM")
@@ -256,7 +259,11 @@ PART="$TMP/partition.fdisk"
sfdisk -q "$SYSTEM" < "$PART" sfdisk -q "$SYSTEM" < "$PART"
MOUNT="$TMP/system" MOUNT="$TMP/system"
rm -rf "$MOUNT" && mkdir -p "$MOUNT" rm -rf "$MOUNT"
if ! makeDir "$MOUNT"; then
error "Failed to create directory \"$MOUNT\" !" && exit 93
fi
MSG="Extracting system partition..." MSG="Extracting system partition..."
info "Install: $MSG" && html "$MSG" info "Install: $MSG" && html "$MSG"
@@ -291,6 +298,7 @@ fakeroot -- bash -c "set -Eeu;\
rm -rf "$MOUNT" rm -rf "$MOUNT"
echo "$BASE" > "$STORAGE/dsm.ver" echo "$BASE" > "$STORAGE/dsm.ver"
! setOwner "$STORAGE/dsm.ver" && error "Failed to set the owner for \"$STORAGE/dsm.ver\" !"
if [[ "$URL" == "file://$STORAGE/$BASE.pat" ]]; then if [[ "$URL" == "file://$STORAGE/$BASE.pat" ]]; then
rm -f "$PAT" rm -f "$PAT"
@@ -298,7 +306,13 @@ else
mv -f "$PAT" "$STORAGE/$BASE.pat" mv -f "$PAT" "$STORAGE/$BASE.pat"
fi fi
if [ -f "$STORAGE/$BASE.pat" ]; then
! setOwner "$STORAGE/$BASE.pat" && error "Failed to set the owner for \"$STORAGE/$BASE.pat\" !"
fi
mv -f "$BOOT" "$STORAGE/$BASE.boot.img" mv -f "$BOOT" "$STORAGE/$BASE.boot.img"
! setOwner "$STORAGE/$BASE.boot.img" && error "Failed to set the owner for \"$STORAGE/$BASE.boot.img\" !"
rm -rf "$TMP" rm -rf "$TMP"
return 0 return 0

View File

@@ -218,11 +218,14 @@ getUserPorts() {
for hostport in ${exclude//,/ }; do for hostport in ${exclude//,/ }; do
local val="${hostport///tcp}" local port="${hostport///tcp}"
port="${port///udp}"
if [[ "$num" == "${val///udp}" ]]; then if [[ "$num" == "$port" ]]; then
num="" num=""
warn "Could not assign port ${val///udp} to \"USER_PORTS\" because it is already in \"HOST_PORTS\"!" if [[ "$port" != "$WEB_PORT" ]]; then
warn "Could not assign port $port to \"USER_PORTS\" because it is already in \"HOST_PORTS\"!"
fi
fi fi
done done
@@ -343,6 +346,12 @@ configurePasst() {
PASST_OPTS+=" -H $VM_NET_HOST" PASST_OPTS+=" -H $VM_NET_HOST"
PASST_OPTS+=" -M $GATEWAY_MAC" PASST_OPTS+=" -M $GATEWAY_MAC"
local uid gid
uid=$(id -u)
gid=$(id -g)
PASST_OPTS+=" --runas $uid:$gid"
PASST_OPTS+=" -P /var/run/passt.pid" PASST_OPTS+=" -P /var/run/passt.pid"
PASST_OPTS+=" -l $log" PASST_OPTS+=" -l $log"
PASST_OPTS+=" -q" PASST_OPTS+=" -q"
@@ -394,7 +403,6 @@ configureNAT() {
# 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
[[ "$PODMAN" == [Yy1]* ]] && return 1
[ ! -d /dev/net ] && mkdir -m 755 /dev/net [ ! -d /dev/net ] && mkdir -m 755 /dev/net
if mknod /dev/net/tun c 10 200; then if mknod /dev/net/tun c 10 200; then
chmod 666 /dev/net/tun chmod 666 /dev/net/tun
@@ -402,6 +410,7 @@ configureNAT() {
fi fi
if [ ! -c /dev/net/tun ]; then if [ ! -c /dev/net/tun ]; then
[[ "$PODMAN" == [Yy1]* ]] && return 1
warn "$tuntap" && return 1 warn "$tuntap" && return 1
fi fi
@@ -409,6 +418,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 > /dev/null 2>&1; rc=$?; } || : { sysctl -w net.ipv4.ip_forward=1 > /dev/null 2>&1; rc=$?; } || :
if (( rc != 0 )) || [[ $(< /proc/sys/net/ipv4/ip_forward) -eq 0 ]]; then if (( rc != 0 )) || [[ $(< /proc/sys/net/ipv4/ip_forward) -eq 0 ]]; then
[[ "$PODMAN" == [Yy1]* ]] && return 1
warn "IP forwarding is disabled. $ADD_ERR --sysctl net.ipv4.ip_forward=1" warn "IP forwarding is disabled. $ADD_ERR --sysctl net.ipv4.ip_forward=1"
return 1 return 1
fi fi
@@ -435,6 +445,7 @@ configureNAT() {
{ ip link add dev "$VM_NET_BRIDGE" type bridge ; rc=$?; } || : { ip link add dev "$VM_NET_BRIDGE" type bridge ; rc=$?; } || :
if (( rc != 0 )); then if (( rc != 0 )); then
[[ "$PODMAN" == [Yy1]* ]] && return 1
warn "failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && return 1 warn "failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && return 1
fi fi
@@ -449,6 +460,7 @@ configureNAT() {
# QEMU Works with taps, set tap to the bridge created # QEMU Works with taps, set tap to the bridge created
if ! ip tuntap add dev "$VM_NET_TAP" mode tap; then if ! ip tuntap add dev "$VM_NET_TAP" mode tap; then
[[ "$PODMAN" == [Yy1]* ]] && return 1
warn "$tuntap" && return 1 warn "$tuntap" && return 1
fi fi
@@ -697,7 +709,7 @@ getInfo() {
[ -z "$MTU" ] && MTU="0" [ -z "$MTU" ] && MTU="0"
if [[ "${ADAPTER,,}" != "virtio-net-pci" ]]; then if [[ "${ADAPTER,,}" != "virtio-net-pci" ]]; then
if [[ "$MTU" != "0" && "$MTU" != "1500" ]]; then if [[ "$MTU" != "0" ]] && [ "$MTU" -lt "1500" ]; then
warn "MTU size is $MTU, but cannot be set for $ADAPTER adapters!" && MTU="0" warn "MTU size is $MTU, but cannot be set for $ADAPTER adapters!" && MTU="0"
fi fi
fi fi
@@ -710,6 +722,7 @@ getInfo() {
# Generate MAC address based on Docker container ID in hostname # Generate MAC address based on Docker container ID in hostname
VM_NET_MAC=$(echo "$HOST" | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:11:32:\3:\4:\5/') VM_NET_MAC=$(echo "$HOST" | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:11:32:\3:\4:\5/')
echo "${VM_NET_MAC^^}" > "$file" echo "${VM_NET_MAC^^}" > "$file"
! setOwner "$file" && error "Failed to set the owner for \"$file\" !"
fi fi
fi fi
@@ -727,13 +740,6 @@ getInfo() {
GATEWAY_MAC=$(echo "$VM_NET_MAC" | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/') GATEWAY_MAC=$(echo "$VM_NET_MAC" | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/')
if [[ "$PODMAN" == [Yy1]* && "$DHCP" != [Yy1]* ]]; then
if [ -z "$NETWORK" ] || [[ "${NETWORK^^}" == "Y" ]]; then
# By default Podman has no permissions for NAT networking
NETWORK="user"
fi
fi
if [[ "$DEBUG" == [Yy1]* ]]; then if [[ "$DEBUG" == [Yy1]* ]]; then
line="Host: $HOST IP: $IP Gateway: $GATEWAY Interface: $VM_NET_DEV MAC: $VM_NET_MAC MTU: $mtu" line="Host: $HOST IP: $IP Gateway: $GATEWAY Interface: $VM_NET_DEV MAC: $VM_NET_MAC MTU: $mtu"
[[ "$MTU" != "0" && "$MTU" != "$mtu" ]] && line+=" ($MTU)" [[ "$MTU" != "0" && "$MTU" != "$mtu" ]] && line+=" ($MTU)"
@@ -795,8 +801,12 @@ else
closeBridge closeBridge
NETWORK="user" NETWORK="user"
if [[ "$PODMAN" != [Yy1]* ]]; then
msg="falling back to user-mode networking!" msg="falling back to user-mode networking!"
msg="failed to setup NAT networking, $msg" msg="failed to setup NAT networking, $msg"
warn "$msg"
fi
fi ;; fi ;;
@@ -828,7 +838,7 @@ else
"passt" | "slirp" ) "passt" | "slirp" )
if [ -z "$USER_PORTS" ]; then if [ -z "$USER_PORTS" ]; then
info "Notice: because user-mode networking is active, if you need to expose ports, add them to the \"USER_PORTS\" variable." info "Notice: because user-mode networking is active, when you need to forward custom ports to DSM, add them to the \"USER_PORTS\" variable."
fi ;; fi ;;
esac esac

View File

@@ -33,6 +33,7 @@ _trap() {
finish() { finish() {
local pid local pid
local cnt=0
local reason=$1 local reason=$1
touch "$QEMU_END" touch "$QEMU_END"
@@ -40,14 +41,24 @@ finish() {
if [ -s "$QEMU_PID" ]; then if [ -s "$QEMU_PID" ]; then
pid=$(<"$QEMU_PID") pid=$(<"$QEMU_PID")
echo && error "Forcefully terminating QEMU process, reason: $reason..." echo && error "Forcefully terminating Virtual DSM, reason: $reason..."
{ kill -15 "$pid" || true; } 2>/dev/null { kill -15 "$pid" || true; } 2>/dev/null
while isAlive "$pid"; do while isAlive "$pid"; do
sleep 1 sleep 1
cnt=$((cnt+1))
# Workaround for zombie pid # Workaround for zombie pid
[ ! -s "$QEMU_PID" ] && break [ ! -s "$QEMU_PID" ] && break
if [ "$cnt" == "5" ]; then
echo && error "QEMU did not terminate itself, forcefully killing process..."
{ kill -9 "$pid" || true; } 2>/dev/null
fi
done done
fi fi
fKill "print.sh" fKill "print.sh"

View File

@@ -1,6 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -Eeuo pipefail set -Eeuo pipefail
info="/run/shm/msg.html"
escape () { escape () {
local s local s
s=${1//&/\&amp;} s=${1//&/\&amp;}
@@ -11,28 +13,33 @@ escape () {
return 0 return 0
} }
file="$1" path="$1"
total="$2" total="$2"
body=$(escape "$3") body=$(escape "$3")
info="/run/shm/msg.html"
if [[ "$body" == *"..." ]]; then if [[ "$body" == *"..." ]]; then
body="<p class=\"loading\">${body/.../}</p>" body="<p class=\"loading\">${body::-3}</p>"
fi fi
while true while true
do do
if [ -s "$file" ]; then
bytes=$(du -sb "$file" | cut -f1) if [ ! -s "$path" ] && [ ! -d "$path" ]; then
if (( bytes > 1000 )); then bytes="0"
else
bytes=$(du -sb "$path" | cut -f1)
fi
if (( bytes > 4096 )); then
if [ -z "$total" ] || [[ "$total" == "0" ]] || [ "$bytes" -gt "$total" ]; then if [ -z "$total" ] || [[ "$total" == "0" ]] || [ "$bytes" -gt "$total" ]; then
size=$(numfmt --to=iec --suffix=B "$bytes" | sed -r 's/([A-Z])/ \1/') size=$(numfmt --to=iec --suffix=B "$bytes" | sed -r 's/([A-Z])/ \1/')
else else
size="$(echo "$bytes" "$total" | awk '{printf "%.1f", $1 * 100 / $2}')" size="$(echo "$bytes" "$total" | awk '{printf "%.1f", $1 * 100 / $2}')"
size="$size%" size="$size%"
fi fi
echo "${body//(\[P\])/($size)}"> "$info" [[ "$size" != "0.0%" ]] && echo "${body//(\[P\])/($size)}"> "$info"
fi
fi fi
sleep 1 & wait $! sleep 1 & wait $!
done done

View File

@@ -78,8 +78,7 @@ fi
# Check folder # Check folder
if [[ "${COMMIT:-}" == [Yy1]* ]]; then if [[ "${STORAGE,,}" != "/storage" ]]; then
STORAGE="/local"
mkdir -p "$STORAGE" mkdir -p "$STORAGE"
fi fi
@@ -88,7 +87,9 @@ if [ ! -d "$STORAGE" ]; then
fi fi
if [ ! -w "$STORAGE" ]; then if [ ! -w "$STORAGE" ]; then
error "Storage folder ($STORAGE) is not writeable!" && exit 13 msg="Storage folder ($STORAGE) is not writeable!"
msg+=" If SELinux is active, you need to add the \":Z\" flag to the bind mount."
error "$msg" && exit 13
fi fi
# Check filesystem # Check filesystem

View File

@@ -67,6 +67,37 @@ fKill() {
return 0 return 0
} }
setOwner() {
local file="$1"
local dir uid gid
[ ! -f "$file" ] && return 1
dir=$(dirname -- "$file")
uid=$(stat -c '%u' "$dir")
gid=$(stat -c '%g' "$dir")
! chown "$uid:$gid" "$file" && return 1
return 0
}
makeDir() {
local path="$1"
local dir uid gid
[ -d "$path" ] && return 0
! mkdir -p "$path" && return 1
dir=$(dirname -- "$path")
uid=$(stat -c '%u' "$dir")
gid=$(stat -c '%g' "$dir")
! chown "$uid:$gid" "$path" && return 1
return 0
}
escape () { escape () {
local s local s
s=${1//&/\&amp;} s=${1//&/\&amp;}
@@ -123,11 +154,11 @@ cpu() {
fi fi
cpu="${cpu// CPU/}" cpu="${cpu// CPU/}"
cpu="${cpu// [0-9] Core}"
cpu="${cpu// [0-9][0-9] Core}"
cpu="${cpu// [0-9][0-9][0-9] Core}" cpu="${cpu// [0-9][0-9][0-9] Core}"
cpu="${cpu//[0-9]th Gen }" cpu="${cpu// [0-9][0-9] Core}"
cpu="${cpu// [0-9] Core}"
cpu="${cpu//[0-9][0-9]th Gen }" cpu="${cpu//[0-9][0-9]th Gen }"
cpu="${cpu//[0-9]th Gen }"
cpu="${cpu// Processor/}" cpu="${cpu// Processor/}"
cpu="${cpu// Quad core/}" cpu="${cpu// Quad core/}"
cpu="${cpu// Dual core/}" cpu="${cpu// Dual core/}"