Compare commits

..

29 Commits

Author SHA1 Message Date
Kroese
e77bca202b fix: Spelling mistake (#1105) 2025-11-06 03:46:35 +01:00
Kroese
2e6c01e934 feat: Detect if container is running in privileged mode (#1104) 2025-11-06 03:39:46 +01:00
Kroese
302c991c0c fix: Change condition for OverlayFS warning (#1103) 2025-11-06 03:22:47 +01:00
Kroese
a89007ee03 build: Use Github token (#1100) 2025-10-29 14:05:53 +01:00
Kroese
8a89149d58 feat: Check for SSE4 instruction set (#1099) 2025-10-29 08:32:42 +01:00
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
Kroese
2c44669d91 feat: Improve Codespaces configuration (#1079) 2025-10-17 13:25:02 +02:00
Kroese
175d90aad7 fix: Move order in entry file (#1078) 2025-10-17 13:04:03 +02:00
Kroese
e1e5f8f91d fix: Validate status messages (#1077) 2025-10-17 12:07:13 +02:00
Kroese
dff8abbe1e build: Validate JSON and YML files (#1076) 2025-10-17 10:05:52 +02:00
Kroese
0f97091e61 fix: Set network flag (#1075) 2025-10-17 01:39:49 +02:00
Kroese
ea0d7ee6cd feat: Implement extra disksize preset (#1074) 2025-10-17 00:17:30 +02:00
Kroese
75daa31d36 feat: Implement extra CPU_CORES preset (#1073) 2025-10-17 00:15:56 +02:00
Kroese
8c44319c45 feat: Move memory check to own module (#1072) 2025-10-16 23:49:16 +02:00
19 changed files with 478 additions and 229 deletions

View File

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

View File

@@ -1,20 +1,17 @@
{ {
"name": "Virtual DSM", "name": "Virtual DSM",
"service": "dsm", "service": "vdsm",
"containerEnv": {
"RAM_SIZE": "max",
"DISK_SIZE": "max",
"CPU_CORES": "max"
},
"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"
} }

View File

@@ -1,4 +1,5 @@
.dockerignore .dockerignore
.devcontainer
.git .git
.github .github
.gitignore .gitignore

View File

@@ -22,3 +22,8 @@ jobs:
dockerfile: Dockerfile dockerfile: Dockerfile
ignore: DL3008,DL3003,DL3006,DL3013 ignore: DL3008,DL3003,DL3006,DL3013
failure-threshold: warning failure-threshold: warning
-
name: Validate JSON and YML files
uses: GrantBirki/json-yaml-validate@v4
with:
yaml_exclude_regex: ".*\\kubernetes\\.yml$"

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.GITHUB_TOKEN }}
-
name: Hadolint
uses: reviewdog/action-hadolint@v1
with:
level: warning
reporter: github-pr-review
hadolint_ignore: DL3008 DL3003 DL3006 DL3013
github_token: ${{ secrets.GITHUB_TOKEN }}
-
name: YamlLint
uses: reviewdog/action-yamllint@v1
with:
level: warning
reporter: github-pr-review
github_token: ${{ secrets.GITHUB_TOKEN }}
-
name: ActionLint
uses: reviewdog/action-actionlint@v1
with:
level: warning
reporter: github-pr-review
github_token: ${{ secrets.GITHUB_TOKEN }}
-
name: Shellformat
uses: reviewdog/action-shfmt@v1
with:
level: warning
shfmt_flags: "-i 2 -ci -bn"
github_token: ${{ secrets.GITHUB_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.GITHUB_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

@@ -12,92 +12,4 @@ DEV_OPTS+=" -device virtio-rng-pci,rng=objrng0,id=rng0,bus=pcie.0,addr=0x1c"
ARGS="$DEF_OPTS $CPU_OPTS $RAM_OPTS $MAC_OPTS $DISPLAY_OPTS $MON_OPTS $SERIAL_OPTS $NET_OPTS $DISK_OPTS $DEV_OPTS $ARGUMENTS" ARGS="$DEF_OPTS $CPU_OPTS $RAM_OPTS $MAC_OPTS $DISPLAY_OPTS $MON_OPTS $SERIAL_OPTS $NET_OPTS $DISK_OPTS $DEV_OPTS $ARGUMENTS"
ARGS=$(echo "$ARGS" | sed 's/\t/ /g' | tr -s ' ') ARGS=$(echo "$ARGS" | sed 's/\t/ /g' | tr -s ' ')
# Check available memory as the very last step
RAM_AVAIL=$(free -b | grep -m 1 Mem: | awk '{print $7}')
if [[ "$RAM_CHECK" != [Nn]* && "${RAM_SIZE,,}" != "max" && "${RAM_SIZE,,}" != "half" ]]; then
AVAIL_MEM=$(formatBytes "$RAM_AVAIL")
if (( (RAM_WANTED + RAM_SPARE) > RAM_AVAIL )); then
msg="Your configured RAM_SIZE of ${RAM_SIZE/G/ GB} is too high for the $AVAIL_MEM of memory available,"
if [[ "${FS,,}" == "zfs" ]]; then
info "$msg but since ZFS is active this will be ignored."
else
RAM_SIZE="max"
warn "$msg it will automatically be adjusted to a lower amount."
fi
else
if (( (RAM_WANTED + (RAM_SPARE * 3)) > RAM_AVAIL )); then
msg="your configured RAM_SIZE of ${RAM_SIZE/G/ GB} is very close to the $AVAIL_MEM of memory available,"
if [[ "${FS,,}" == "zfs" ]]; then
info "$msg but since ZFS is active this will be ignored."
else
warn "$msg please consider a lower amount."
fi
fi
fi
fi
if [[ "${RAM_SIZE,,}" == "half" ]]; then
RAM_WANTED=$(( RAM_AVAIL / 2 ))
RAM_WANTED=$(( RAM_WANTED / 1073741825 ))
if (( "$RAM_WANTED" < 1 )); then
RAM_WANTED=$(( RAM_AVAIL / 2 ))
RAM_WANTED=$(( RAM_WANTED / 1048577 ))
RAM_SIZE="${RAM_WANTED}M"
else
RAM_SIZE="${RAM_WANTED}G"
fi
fi
if [[ "${RAM_SIZE,,}" == "max" ]]; then
RAM_WANTED=$(( RAM_AVAIL - (RAM_SPARE * 3) ))
RAM_WANTED=$(( RAM_WANTED / 1073741825 ))
if (( "$RAM_WANTED" < 1 )); then
RAM_WANTED=$(( RAM_AVAIL - (RAM_SPARE * 2) ))
RAM_WANTED=$(( RAM_WANTED / 1073741825 ))
if (( "$RAM_WANTED" < 1 )); then
RAM_WANTED=$(( RAM_AVAIL - RAM_SPARE ))
RAM_WANTED=$(( RAM_WANTED / 1073741825 ))
if (( "$RAM_WANTED" < 1 )); then
RAM_WANTED=$(( RAM_AVAIL - RAM_SPARE ))
RAM_WANTED=$(( RAM_WANTED / 1048577 ))
if (( "$RAM_WANTED" < 1 )); then
RAM_WANTED=$(( RAM_AVAIL ))
RAM_WANTED=$(( RAM_WANTED / 1048577 ))
fi
RAM_SIZE="${RAM_WANTED}M"
else
RAM_SIZE="${RAM_WANTED}G"
fi
else
RAM_SIZE="${RAM_WANTED}G"
fi
else
RAM_SIZE="${RAM_WANTED}G"
fi
fi
if [[ "$DEBUG" == [Yy1]* ]]; then
printf "QEMU arguments:\n\n%s\n\n" "${ARGS// -/$'\n-'}"
fi
return 0 return 0

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,16 +186,16 @@ 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")
DATA_SIZE=$(numfmt --from=iec "$DISK_SPACE") DATA_SIZE=$(numfmt --from=iec "$DISK_SPACE")
local REQ=$((DATA_SIZE-CUR_SIZE)) local REQ=$(( DATA_SIZE - CUR_SIZE ))
(( REQ < 1 )) && error "Shrinking disks is not supported yet, please increase ${DISK_DESC^^}_SIZE." && exit 71 (( REQ < 1 )) && error "Shrinking disks is not supported yet, please increase ${DISK_DESC^^}_SIZE." && exit 71
if [[ "$ALLOCATE" != [Nn]* ]]; then if [[ "$ALLOCATE" != [Nn]* ]]; then
@@ -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"* && "${ENGINE,,}" == "docker" ]]; 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"
@@ -432,18 +443,25 @@ addDisk () {
DIR=$(dirname "$DISK_FILE") DIR=$(dirname "$DISK_FILE")
[ ! -d "$DIR" ] && return 0 [ ! -d "$DIR" ] && return 0
if [[ "${DISK_SPACE,,}" == "max" ]]; then if [[ "${DISK_SPACE,,}" == "max" || "${DISK_SPACE,,}" == "half" ]]; then
local SPARE=536870912 local SPARE=1073741824
SPACE=$(df --output=avail -B 1 "$DIR" | tail -n 1) FREE=$(df --output=avail -B 1 "$DIR" | tail -n 1)
(( SPACE < SPARE )) && SPACE="$SPARE" || SPACE=$((SPACE-SPARE))
GB=$(( SPACE/1073741825 )) if [[ "${DISK_SPACE,,}" == "max" ]]; then
FREE=$(( FREE - SPARE ))
else
FREE=$(( FREE / 2 ))
fi
(( FREE < SPARE )) && FREE="$SPARE"
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')
@@ -454,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")
@@ -465,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"
@@ -478,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
@@ -485,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
@@ -494,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
@@ -501,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

@@ -18,7 +18,9 @@ cd /run
. proc.sh # Initialize processor . proc.sh # Initialize processor
. serial.sh # Initialize serialport . serial.sh # Initialize serialport
. power.sh # Configure shutdown . power.sh # Configure shutdown
. memory.sh # Check available memory
. config.sh # Configure arguments . config.sh # Configure arguments
. finish.sh # Finish initialization
trap - ERR trap - ERR

8
src/finish.sh Normal file
View File

@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -Eeuo pipefail
if [[ "$DEBUG" == [Yy1]* ]]; then
printf "QEMU arguments:\n\n%s\n\n" "${ARGS// -/$'\n-'}"
fi
return 0

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"* && "${ENGINE,,}" == "docker" ]]; 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,10 +110,9 @@ 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
rm -rf "$TMP" && mkdir -p "$TMP"
fi fi
rm -rf "$TMP" && mkdir -p "$TMP"
# Check free diskspace # Check free diskspace
ROOT_SPACE=536870912 ROOT_SPACE=536870912
SPACE=$(df --output=avail -B 1 / | tail -n 1) SPACE=$(df --output=avail -B 1 / | tail -n 1)
@@ -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

86
src/memory.sh Normal file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/env bash
set -Eeuo pipefail
RAM_AVAIL=$(free -b | grep -m 1 Mem: | awk '{print $7}')
if [[ "$RAM_CHECK" != [Nn]* && "${RAM_SIZE,,}" != "max" && "${RAM_SIZE,,}" != "half" ]]; then
AVAIL_MEM=$(formatBytes "$RAM_AVAIL")
if (( (RAM_WANTED + RAM_SPARE) > RAM_AVAIL )); then
msg="Your configured RAM_SIZE of ${RAM_SIZE/G/ GB} is too high for the $AVAIL_MEM of memory available,"
if [[ "${FS,,}" == "zfs" ]]; then
info "$msg but since ZFS is active this will be ignored."
else
RAM_SIZE="max"
warn "$msg it will automatically be adjusted to a lower amount."
fi
else
if (( (RAM_WANTED + (RAM_SPARE * 3)) > RAM_AVAIL )); then
msg="your configured RAM_SIZE of ${RAM_SIZE/G/ GB} is very close to the $AVAIL_MEM of memory available,"
if [[ "${FS,,}" == "zfs" ]]; then
info "$msg but since ZFS is active this will be ignored."
else
warn "$msg please consider a lower amount."
fi
fi
fi
fi
if [[ "${RAM_SIZE,,}" == "half" ]]; then
RAM_WANTED=$(( RAM_AVAIL / 2 ))
RAM_WANTED=$(( RAM_WANTED / 1073741825 ))
if (( "$RAM_WANTED" < 1 )); then
RAM_WANTED=$(( RAM_AVAIL / 2 ))
RAM_WANTED=$(( RAM_WANTED / 1048577 ))
RAM_SIZE="${RAM_WANTED}M"
else
RAM_SIZE="${RAM_WANTED}G"
fi
fi
if [[ "${RAM_SIZE,,}" == "max" ]]; then
RAM_WANTED=$(( RAM_AVAIL - (RAM_SPARE * 3) ))
RAM_WANTED=$(( RAM_WANTED / 1073741825 ))
if (( "$RAM_WANTED" < 1 )); then
RAM_WANTED=$(( RAM_AVAIL - (RAM_SPARE * 2) ))
RAM_WANTED=$(( RAM_WANTED / 1073741825 ))
if (( "$RAM_WANTED" < 1 )); then
RAM_WANTED=$(( RAM_AVAIL - RAM_SPARE ))
RAM_WANTED=$(( RAM_WANTED / 1073741825 ))
if (( "$RAM_WANTED" < 1 )); then
RAM_WANTED=$(( RAM_AVAIL - RAM_SPARE ))
RAM_WANTED=$(( RAM_WANTED / 1048577 ))
if (( "$RAM_WANTED" < 1 )); then
RAM_WANTED=$(( RAM_AVAIL ))
RAM_WANTED=$(( RAM_WANTED / 1048577 ))
fi
RAM_SIZE="${RAM_WANTED}M"
else
RAM_SIZE="${RAM_WANTED}G"
fi
else
RAM_SIZE="${RAM_WANTED}G"
fi
else
RAM_SIZE="${RAM_WANTED}G"
fi
fi
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
@@ -271,6 +274,7 @@ getSlirp() {
configureSlirp() { configureSlirp() {
NETWORK="slirp"
[[ "$DEBUG" == [Yy1]* ]] && echo "Configuring slirp networking..." [[ "$DEBUG" == [Yy1]* ]] && echo "Configuring slirp networking..."
local ip="$IP" local ip="$IP"
@@ -302,9 +306,10 @@ configureSlirp() {
configurePasst() { configurePasst() {
NETWORK="passt"
[[ "$DEBUG" == [Yy1]* ]] && echo "Configuring user-mode networking..." [[ "$DEBUG" == [Yy1]* ]] && echo "Configuring user-mode networking..."
local log="/var/log/passt.log" local log="/tmp/passt.log"
rm -f "$log" rm -f "$log"
local pid="/var/run/dnsmasq.pid" local pid="/var/run/dnsmasq.pid"
@@ -341,7 +346,7 @@ configurePasst() {
PASST_OPTS+=" -H $VM_NET_HOST" PASST_OPTS+=" -H $VM_NET_HOST"
PASST_OPTS+=" -M $GATEWAY_MAC" PASST_OPTS+=" -M $GATEWAY_MAC"
PASST_OPTS+=" -P /var/run/passt.pid" PASST_OPTS+=" -P /tmp/passt.pid"
PASST_OPTS+=" -l $log" PASST_OPTS+=" -l $log"
PASST_OPTS+=" -q" PASST_OPTS+=" -q"
@@ -392,7 +397,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
@@ -400,6 +404,7 @@ configureNAT() {
fi fi
if [ ! -c /dev/net/tun ]; then if [ ! -c /dev/net/tun ]; then
[[ "$ROOTLESS" == [Yy1]* && "$DEBUG" != [Yy1]* ]] && return 1
warn "$tuntap" && return 1 warn "$tuntap" && return 1
fi fi
@@ -407,6 +412,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
[[ "$ROOTLESS" == [Yy1]* && "$DEBUG" != [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
@@ -433,6 +439,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
[[ "$ROOTLESS" == [Yy1]* && "$DEBUG" != [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
@@ -447,6 +454,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
[[ "$ROOTLESS" == [Yy1]* && "$DEBUG" != [Yy1]* ]] && return 1
warn "$tuntap" && return 1 warn "$tuntap" && return 1
fi fi
@@ -522,11 +530,11 @@ configureNAT() {
closeBridge() { closeBridge() {
local pid="/var/run/dnsmasq.pid" local pid="/tmp/passt.pid"
[ -s "$pid" ] && pKill "$(<"$pid")" [ -s "$pid" ] && pKill "$(<"$pid")"
rm -f "$pid" rm -f "$pid"
pid="/var/run/passt.pid" pid="/var/run/dnsmasq.pid"
[ -s "$pid" ] && pKill "$(<"$pid")" [ -s "$pid" ] && pKill "$(<"$pid")"
rm -f "$pid" rm -f "$pid"
@@ -584,8 +592,8 @@ closeNetwork() {
cleanUp() { cleanUp() {
# Clean up old files # Clean up old files
rm -f /tmp/passt.pid
rm -f /etc/resolv.dnsmasq rm -f /etc/resolv.dnsmasq
rm -f /var/run/passt.pid
rm -f /var/run/dnsmasq.pid rm -f /var/run/dnsmasq.pid
if [[ -d "/sys/class/net/$VM_NET_TAP" ]]; then if [[ -d "/sys/class/net/$VM_NET_TAP" ]]; then
@@ -626,7 +634,7 @@ getInfo() {
[ -d "/sys/class/net/net1" ] && VM_NET_DEV="net1" [ -d "/sys/class/net/net1" ] && VM_NET_DEV="net1"
[ -d "/sys/class/net/net2" ] && VM_NET_DEV="net2" [ -d "/sys/class/net/net2" ] && VM_NET_DEV="net2"
[ -d "/sys/class/net/net3" ] && VM_NET_DEV="net3" [ -d "/sys/class/net/net3" ] && VM_NET_DEV="net3"
# Automaticly detect the default network interface # Automatically detect the default network interface
[ -z "$VM_NET_DEV" ] && VM_NET_DEV=$(awk '$2 == 00000000 { print $1 }' /proc/net/route) [ -z "$VM_NET_DEV" ] && VM_NET_DEV=$(awk '$2 == 00000000 { print $1 }' /proc/net/route)
[ -z "$VM_NET_DEV" ] && VM_NET_DEV="eth0" [ -z "$VM_NET_DEV" ] && VM_NET_DEV="eth0"
fi fi
@@ -695,7 +703,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
@@ -708,6 +716,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
@@ -725,13 +734,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)"
@@ -785,7 +787,7 @@ else
fi fi
case "${NETWORK,,}" in case "${NETWORK,,}" in
"user"* | "passt" | "slirp" ) ;; "passt" | "slirp" | "user"* ) ;;
"tap" | "tun" | "tuntap" | "y" ) "tap" | "tun" | "tuntap" | "y" )
# Configure tap interface # Configure tap interface
@@ -793,18 +795,20 @@ else
closeBridge closeBridge
NETWORK="user" NETWORK="user"
if [[ "$ROOTLESS" != [Yy1]* || "$DEBUG" == [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 ;;
esac esac
[[ "${NETWORK,,}" == "user"* ]] && NETWORK="passt"
case "${NETWORK,,}" in case "${NETWORK,,}" in
"tap" | "tun" | "tuntap" | "y" ) ;; "tap" | "tun" | "tuntap" | "y" ) ;;
"passt" ) "passt" | "user"* )
# Configure for user-mode networking (passt) # Configure for user-mode networking (passt)
if ! configurePasst; then if ! configurePasst; then
@@ -828,7 +832,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

@@ -33,9 +33,8 @@ if [[ "$KVM" != [Nn]* ]]; then
KVM_OPTS=",accel=kvm -enable-kvm -global kvm-pit.lost_tick_policy=discard" KVM_OPTS=",accel=kvm -enable-kvm -global kvm-pit.lost_tick_policy=discard"
if ! grep -qw "sse4_2" <<< "$flags"; then if ! grep -qw "sse4_2" <<< "$flags"; then
info "Your CPU does not have the SSE4 instruction set that Virtual DSM requires, it will be emulated..." error "Your CPU does not have the SSE4 instruction set that Virtual DSM requires!"
[ -z "$CPU_MODEL" ] && CPU_MODEL="qemu64" [[ "$DEBUG" != [Yy1]* ]] && exit 88
CPU_FEATURES+=",+ssse3,+sse4.1,+sse4.2"
fi fi
if [ -z "$CPU_MODEL" ]; then if [ -z "$CPU_MODEL" ]; then

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

@@ -24,19 +24,40 @@ trap 'error "Status $? while: $BASH_COMMAND (line $LINENO/$BASH_LINENO)"' ERR
# Helper variables # Helper variables
PODMAN="N" ROOTLESS="N"
PRIVILEGED="N"
ENGINE="Docker" ENGINE="Docker"
PROCESS="${APP,,}" PROCESS="${APP,,}"
PROCESS="${PROCESS// /-}" PROCESS="${PROCESS// /-}"
if [ -f "/run/.containerenv" ]; then if [ -f "/run/.containerenv" ]; then
PODMAN="Y" ENGINE="${container:-}"
if [[ "${ENGINE,,}" == *"podman"* ]]; then
ROOTLESS="Y"
ENGINE="Podman" ENGINE="Podman"
else
[ -z "$ENGINE" ] && ENGINE="Kubernetes"
fi
fi fi
echo " Starting $APP for $ENGINE v$(</run/version)..." echo " Starting $APP for $ENGINE v$(</run/version)..."
echo " For support visit $SUPPORT" echo " For support visit $SUPPORT"
# Get the capability bounding set
CAP_BND=$(grep '^CapBnd:' /proc/$$/status | awk '{print $2}')
CAP_BND=$(printf "%d" "0x${CAP_BND}")
# Get the last capability number
LAST_CAP=$(cat /proc/sys/kernel/cap_last_cap)
# Calculate the maximum capability value
MAX_CAP=$(((1 << (LAST_CAP + 1)) - 1))
if [ "${CAP_BND}" -eq "${MAX_CAP}" ]; then
ROOTLESS="N"
PRIVILEGED="Y"
fi
INFO="/run/shm/msg.html" INFO="/run/shm/msg.html"
PAGE="/run/shm/index.html" PAGE="/run/shm/index.html"
TEMPLATE="/var/www/index.html" TEMPLATE="/var/www/index.html"
@@ -59,6 +80,8 @@ fi
CPU_CORES="${CPU_CORES// /}" CPU_CORES="${CPU_CORES// /}"
[[ "${CPU_CORES,,}" == "max" ]] && CPU_CORES="$CORES" [[ "${CPU_CORES,,}" == "max" ]] && CPU_CORES="$CORES"
[[ "${CPU_CORES,,}" == "half" ]] && CPU_CORES=$(( CORES / 2 ))
[[ "${CPU_CORES,,}" == "0" ]] && CPU_CORES="1"
[ -n "${CPU_CORES//[0-9 ]}" ] && error "Invalid amount of CPU_CORES: $CPU_CORES" && exit 15 [ -n "${CPU_CORES//[0-9 ]}" ] && error "Invalid amount of CPU_CORES: $CPU_CORES" && exit 15
if [ "$CPU_CORES" -gt "$CORES" ]; then if [ "$CPU_CORES" -gt "$CORES" ]; then
@@ -76,8 +99,7 @@ fi
# Check folder # Check folder
if [[ "${COMMIT:-}" == [Yy1]* ]]; then if [[ "${STORAGE,,}" != "/storage" ]]; then
STORAGE="/local"
mkdir -p "$STORAGE" mkdir -p "$STORAGE"
fi fi
@@ -86,7 +108,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
@@ -163,6 +187,10 @@ if [[ "$KVM" != [Nn]* ]]; then
if ! grep -qw "vmx\|svm" <<< "$flags"; then if ! grep -qw "vmx\|svm" <<< "$flags"; then
KVM_ERR="(not enabled in BIOS)" KVM_ERR="(not enabled in BIOS)"
fi fi
if ! grep -qw "sse4_2" <<< "$flags"; then
error "Your CPU does not have the SSE4 instruction set that Virtual DSM requires!"
[[ "$DEBUG" != [Yy1]* ]] && exit 88
fi
fi fi
fi fi
fi fi

View File

@@ -1,16 +1,31 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -Eeuo pipefail set -Eeuo pipefail
lastmsg=""
path="/run/shm/msg.html" path="/run/shm/msg.html"
if [ -f "$path" ] && [ -s "$path" ]; then refresh() {
echo -n "s: " && cat "$path"
fi [ ! -f "$path" ] && return 0
[ ! -s "$path" ] && return 0
msg=$(< "$path")
msg="${msg%$'\n'}"
[ -z "$msg" ] && return 0
[[ "$msg" == "$lastmsg" ]] && return 0
lastmsg="$msg"
echo "s: $msg"
return 0
}
refresh
inotifywait -m "$path" | inotifywait -m "$path" |
while read -r fp event fn; do while read -r fp event fn; do
case "${event,,}" in case "${event,,}" in
"modify"* ) echo -n "s: " && cat "$path" ;; "modify"* ) refresh ;;
"delete_self" ) echo "c: vnc" ;; "delete_self" ) echo "c: vnc" ;;
esac esac
done done

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/}"