mirror of
https://github.com/vdsm/virtual-dsm.git
synced 2025-11-07 10:33:42 +08:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08e4084458 | ||
|
|
06f210846c | ||
|
|
74629e4b55 | ||
|
|
6e8af6e52f | ||
|
|
38611a7af2 | ||
|
|
f089acc01a | ||
|
|
5a7ecb48d6 | ||
|
|
5b3880aa5e | ||
|
|
4653aafbee | ||
|
|
281f2992ff | ||
|
|
4bdcf8bfe1 | ||
|
|
62acaa95bf | ||
|
|
369bff339d | ||
|
|
5332d387f4 | ||
|
|
f0d08ef263 | ||
|
|
e4334f9499 | ||
|
|
627ec56262 | ||
|
|
251cf8121e | ||
|
|
87fad1b0e9 | ||
|
|
698516ac8c |
@@ -29,7 +29,7 @@ RUN apt-get update && apt-get -y upgrade \
|
|||||||
iptables \
|
iptables \
|
||||||
iproute2 \
|
iproute2 \
|
||||||
dnsmasq \
|
dnsmasq \
|
||||||
fakeroot \
|
fakeroot \
|
||||||
net-tools \
|
net-tools \
|
||||||
qemu-utils \
|
qemu-utils \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ 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:
|
||||||
|
|||||||
@@ -169,8 +169,6 @@ 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'
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ set -Eeuo pipefail
|
|||||||
|
|
||||||
: ${VM_NET_DEV:='eth0'}
|
: ${VM_NET_DEV:='eth0'}
|
||||||
|
|
||||||
[ ! -f "/run/qemu.pid" ] && echo "QEMU not running yet.." && exit 0
|
|
||||||
[ -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
|
||||||
|
|||||||
39
src/cpu.sh
39
src/cpu.sh
@@ -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 have 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
|
||||||
|
|
||||||
|
|||||||
120
src/disk.sh
120
src/disk.sh
@@ -77,15 +77,28 @@ getSize() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isCow() {
|
||||||
|
local FS=$1
|
||||||
|
|
||||||
|
if [[ "${FS,,}" == "xfs" || "${FS,,}" == "zfs" || "${FS,,}" == "btrfs" || "${FS,,}" == "bcachefs" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
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 DATA_SIZE DIR SPACE
|
local FS=$5
|
||||||
|
local DATA_SIZE DIR SPACE FA
|
||||||
|
|
||||||
DATA_SIZE=$(numfmt --from=iec "$DISK_SPACE")
|
DATA_SIZE=$(numfmt --from=iec "$DISK_SPACE")
|
||||||
|
|
||||||
|
rm -f "$DISK_FILE"
|
||||||
|
|
||||||
if [[ "$ALLOCATE" != [Nn]* ]]; then
|
if [[ "$ALLOCATE" != [Nn]* ]]; then
|
||||||
|
|
||||||
# Check free diskspace
|
# Check free diskspace
|
||||||
@@ -104,8 +117,16 @@ createDisk() {
|
|||||||
|
|
||||||
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 "$DATA_SIZE" "$DISK_FILE"; then
|
if ! truncate -s "$DATA_SIZE" "$DISK_FILE"; then
|
||||||
rm -f "$DISK_FILE"
|
rm -f "$DISK_FILE"
|
||||||
@@ -125,15 +146,25 @@ createDisk() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
qcow2)
|
qcow2)
|
||||||
local DISK_OPTS="$DISK_ALLOC"
|
|
||||||
[ -n "$DISK_FLAGS" ] && DISK_OPTS="$DISK_OPTS,$DISK_FLAGS"
|
local DISK_PARAM="$DISK_ALLOC"
|
||||||
if ! qemu-img create -f "$DISK_FMT" -o "$DISK_OPTS" -- "$DISK_FILE" "$DATA_SIZE" ; then
|
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
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,6 +173,7 @@ resizeDisk() {
|
|||||||
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 CUR_SIZE DATA_SIZE DIR SPACE
|
local CUR_SIZE DATA_SIZE DIR SPACE
|
||||||
|
|
||||||
CUR_SIZE=$(getSize "$DISK_FILE")
|
CUR_SIZE=$(getSize "$DISK_FILE")
|
||||||
@@ -168,6 +200,7 @@ resizeDisk() {
|
|||||||
|
|
||||||
case "${DISK_FMT,,}" in
|
case "${DISK_FMT,,}" in
|
||||||
raw)
|
raw)
|
||||||
|
|
||||||
if [[ "$ALLOCATE" == [Nn]* ]]; then
|
if [[ "$ALLOCATE" == [Nn]* ]]; then
|
||||||
|
|
||||||
# Resize file by changing its length
|
# Resize file by changing its length
|
||||||
@@ -187,9 +220,11 @@ resizeDisk() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
qcow2)
|
qcow2)
|
||||||
|
|
||||||
if ! qemu-img resize -f "$DISK_FMT" "--$DISK_ALLOC" "$DISK_FILE" "$DATA_SIZE" ; then
|
if ! qemu-img resize -f "$DISK_FMT" "--$DISK_ALLOC" "$DISK_FILE" "$DATA_SIZE" ; then
|
||||||
error "$FAIL" && exit 72
|
error "$FAIL" && exit 72
|
||||||
fi
|
fi
|
||||||
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@@ -203,16 +238,18 @@ convertDisk() {
|
|||||||
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 CONV_FLAGS="-p"
|
local FS=$7
|
||||||
local DISK_OPTS="$DISK_ALLOC"
|
|
||||||
local TMP_FILE="$DISK_BASE.tmp"
|
|
||||||
local DIR CUR_SIZE SPACE
|
|
||||||
|
|
||||||
[ -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
|
||||||
|
|
||||||
|
local TMP_FILE="$DISK_BASE.tmp"
|
||||||
|
rm -f "$TMP_FILE"
|
||||||
|
|
||||||
if [[ "$ALLOCATE" != [Nn]* ]]; then
|
if [[ "$ALLOCATE" != [Nn]* ]]; then
|
||||||
|
|
||||||
|
local DIR CUR_SIZE SPACE
|
||||||
|
|
||||||
# Check free diskspace
|
# Check free diskspace
|
||||||
DIR=$(dirname "$TMP_FILE")
|
DIR=$(dirname "$TMP_FILE")
|
||||||
CUR_SIZE=$(getSize "$SOURCE_FILE")
|
CUR_SIZE=$(getSize "$SOURCE_FILE")
|
||||||
@@ -227,26 +264,29 @@ convertDisk() {
|
|||||||
|
|
||||||
info "Converting $DISK_DESC to $DST_FMT, please wait until completed..."
|
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 [[ "$DST_FMT" != "raw" ]]; then
|
||||||
if [[ "$ALLOCATE" == [Nn]* ]]; then
|
if [[ "$ALLOCATE" == [Nn]* ]]; then
|
||||||
CONV_FLAGS="$CONV_FLAGS -c"
|
CONV_FLAGS="$CONV_FLAGS -c"
|
||||||
fi
|
fi
|
||||||
[ -n "$DISK_FLAGS" ] && DISK_OPTS="$DISK_OPTS,$DISK_FLAGS"
|
[ -n "$DISK_FLAGS" ] && DISK_PARAM="$DISK_PARAM,$DISK_FLAGS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -f "$TMP_FILE"
|
|
||||||
|
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
if ! qemu-img convert -f "$SOURCE_FMT" $CONV_FLAGS -o "$DISK_OPTS" -O "$DST_FMT" -- "$SOURCE_FILE" "$TMP_FILE"; then
|
if ! qemu-img convert -f "$SOURCE_FMT" $CONV_FLAGS -o "$DISK_PARAM" -O "$DST_FMT" -- "$SOURCE_FILE" "$TMP_FILE"; then
|
||||||
rm -f "$TMP_FILE"
|
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
|
error "Failed to convert $DISK_TYPE $DISK_DESC image to $DST_FMT format in $DIR, is there enough space available?" && exit 79
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$DST_FMT" == "raw" ]]; then
|
if [[ "$DST_FMT" == "raw" ]]; then
|
||||||
if [[ "$ALLOCATE" != [Nn]* ]]; then
|
if [[ "$ALLOCATE" != [Nn]* ]]; then
|
||||||
|
# Work around qemu-img bug
|
||||||
CUR_SIZE=$(stat -c%s "$TMP_FILE")
|
CUR_SIZE=$(stat -c%s "$TMP_FILE")
|
||||||
if ! fallocate -l "$CUR_SIZE" "$TMP_FILE"; then
|
if ! fallocate -l "$CUR_SIZE" "$TMP_FILE"; then
|
||||||
info "Failed to allocate $CUR_SIZE bytes for $TMP_FILE"
|
error "Failed to allocate $CUR_SIZE bytes for $DISK_DESC image $TMP_FILE"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -254,44 +294,37 @@ convertDisk() {
|
|||||||
rm -f "$SOURCE_FILE"
|
rm -f "$SOURCE_FILE"
|
||||||
mv "$TMP_FILE" "$DST_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!"
|
info "Conversion of $DISK_DESC to $DST_FMT completed succesfully!"
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFS () {
|
checkFS () {
|
||||||
local DISK_FILE=$1
|
local FS=$1
|
||||||
local DIR FS FA
|
local DISK_FILE=$2
|
||||||
|
local DISK_DESC=$3
|
||||||
|
local DIR FA
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
if [[ "$FS" == "overlay"* ]]; then
|
|
||||||
info "Warning: the filesystem of $DIR is OverlayFS, this usually means it was binded to an invalid path!"
|
info "Warning: the filesystem of $DIR is OverlayFS, this usually means it was binded to an invalid path!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$FS" == "xfs" || "$FS" == "zfs" || "$FS" == "btrfs" || "$FS" == "bcachefs" ]]; then
|
if isCow "$FS"; then
|
||||||
local FLAG="nocow"
|
if [ -f "$DISK_FILE" ]; then
|
||||||
if [[ "$DISK_FLAGS" != *"$FLAG="* ]]; then
|
|
||||||
if [ -z "$DISK_FLAGS" ]; then
|
|
||||||
DISK_FLAGS="$FLAG=on"
|
|
||||||
else
|
|
||||||
DISK_FLAGS="$DISK_FLAGS,$FLAG=on"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "$DISK_FILE" ] ; then
|
|
||||||
FA=$(lsattr "$DISK_FILE")
|
FA=$(lsattr "$DISK_FILE")
|
||||||
[[ "$FA" == *"C"* ]] && FA=$(lsattr -d "$DIR")
|
if [[ "$FA" != *"C"* ]]; then
|
||||||
else
|
info "Warning: COW (copy on write) is not disabled for $DISK_DESC image file $DISK_FILE, this is recommended on ${FS^^} filesystems!"
|
||||||
FA=$(lsattr -d "$DIR")
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$FA" != *"C"* ]]; then
|
|
||||||
info "Warning: the filesystem of $DIR is ${FS^^}, and COW (copy on write) is not disabled for that folder!"
|
|
||||||
info "This will negatively affect performance, please empty the folder and disable COW (chattr +C <path>)."
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -308,7 +341,7 @@ addDisk () {
|
|||||||
local DISK_ADDRESS=$7
|
local DISK_ADDRESS=$7
|
||||||
local DISK_FMT=$8
|
local DISK_FMT=$8
|
||||||
local DISK_FILE="$DISK_BASE.$DISK_EXT"
|
local DISK_FILE="$DISK_BASE.$DISK_EXT"
|
||||||
local DIR DATA_SIZE PREV_FMT PREV_EXT CUR_SIZE
|
local DIR DATA_SIZE FS PREV_FMT PREV_EXT CUR_SIZE
|
||||||
|
|
||||||
DIR=$(dirname "$DISK_FILE")
|
DIR=$(dirname "$DISK_FILE")
|
||||||
[ ! -d "$DIR" ] && return 0
|
[ ! -d "$DIR" ] && return 0
|
||||||
@@ -325,7 +358,8 @@ addDisk () {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
checkFS "$DISK_FILE" || exit $?
|
FS=$(stat -f -c %T "$DIR")
|
||||||
|
checkFS "$FS" "$DISK_FILE" "$DISK_DESC" || exit $?
|
||||||
|
|
||||||
if ! [ -f "$DISK_FILE" ] ; then
|
if ! [ -f "$DISK_FILE" ] ; then
|
||||||
|
|
||||||
@@ -337,7 +371,7 @@ addDisk () {
|
|||||||
PREV_EXT="$(fmt2ext "$PREV_FMT")"
|
PREV_EXT="$(fmt2ext "$PREV_FMT")"
|
||||||
|
|
||||||
if [ -f "$DISK_BASE.$PREV_EXT" ] ; then
|
if [ -f "$DISK_BASE.$PREV_EXT" ] ; then
|
||||||
convertDisk "$DISK_BASE.$PREV_EXT" "$PREV_FMT" "$DISK_FILE" "$DISK_FMT" "$DISK_BASE" "$DISK_DESC" || exit $?
|
convertDisk "$DISK_BASE.$PREV_EXT" "$PREV_FMT" "$DISK_FILE" "$DISK_FMT" "$DISK_BASE" "$DISK_DESC" "$FS" || exit $?
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -346,12 +380,12 @@ 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" "$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
|
||||||
|
|
||||||
|
|||||||
15
src/entry.sh
15
src/entry.sh
@@ -23,12 +23,11 @@ if [[ "$CONSOLE" == [Yy]* ]]; then
|
|||||||
exit $?
|
exit $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
set -m
|
[[ "$DEBUG" == [Yy1]* ]] && info "$VERS" && set -x
|
||||||
(
|
qemu-system-x86_64 -daemonize -pidfile "$QEMU_PID" ${ARGS:+ $ARGS}
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && info "$VERS" && set -x
|
|
||||||
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 $!
|
{ set +x; } 2>/dev/null
|
||||||
|
cat /dev/pts/1 2>/dev/null & wait $! || true
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
finish 0
|
||||||
|
|||||||
11
src/gpu.sh
11
src/gpu.sh
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -51,26 +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" == "xfs" || "$FS" == "zfs" || "$FS" == "btrfs" || "$FS" == "bcachefs" ]]; then
|
|
||||||
FA=$(lsattr -d "$STORAGE")
|
|
||||||
if [[ "$FA" != *"C"* ]]; then
|
|
||||||
info "Warning: the filesystem of $STORAGE is ${FS^^}, and COW (copy on write) is not disabled for that folder!"
|
|
||||||
info "This will negatively affect performance, please empty the folder and disable COW (chattr +C <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
|
||||||
|
|
||||||
@@ -80,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
|
||||||
@@ -219,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
|
||||||
@@ -234,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
|
||||||
|
|
||||||
@@ -251,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"
|
||||||
|
|
||||||
@@ -267,15 +266,18 @@ PART="$TMP/partition.fdisk"
|
|||||||
|
|
||||||
sfdisk -q "$SYSTEM" < "$PART"
|
sfdisk -q "$SYSTEM" < "$PART"
|
||||||
|
|
||||||
info "Install: Extracting system partition..."
|
|
||||||
|
|
||||||
LABEL="1.44.1-42218"
|
|
||||||
OFFSET="1048576" # 2048 * 512
|
|
||||||
NUMBLOCKS="622560" # (4980480 * 512) / 4096
|
|
||||||
|
|
||||||
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 [[ "$ROOT" != [Nn]* ]]; then
|
if [[ "$ROOT" != [Nn]* ]]; then
|
||||||
@@ -295,6 +297,10 @@ if [ -f "$IDB.txz" ]; then
|
|||||||
tar xpfJ "$IDB.txz" --absolute-names -C "$INDEX_DB"
|
tar xpfJ "$IDB.txz" --absolute-names -C "$INDEX_DB"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
LABEL="1.44.1-42218"
|
||||||
|
OFFSET="1048576" # 2048 * 512
|
||||||
|
NUMBLOCKS="622560" # (4980480 * 512) / 4096
|
||||||
|
|
||||||
if [[ "$ROOT" != [Nn]* ]]; then
|
if [[ "$ROOT" != [Nn]* ]]; then
|
||||||
|
|
||||||
info "Install: Installing system partition..."
|
info "Install: Installing system partition..."
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
103
src/power.sh
103
src/power.sh
@@ -3,38 +3,88 @@ 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=55
|
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 quitting 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 && info "Shutdown completed!"
|
||||||
|
|
||||||
|
exit "$reason"
|
||||||
}
|
}
|
||||||
|
|
||||||
_graceful_shutdown() {
|
_graceful_shutdown() {
|
||||||
|
|
||||||
set +e
|
local code=$?
|
||||||
local cnt response
|
local pid cnt response
|
||||||
|
|
||||||
[ ! -f "$QEMU_PID" ] && exit 130
|
|
||||||
[ -f "$QEMU_COUNT" ] && return
|
[ -f "$QEMU_COUNT" ] && return
|
||||||
|
|
||||||
echo 0 > "$QEMU_COUNT"
|
echo 0 > "$QEMU_COUNT"
|
||||||
|
|
||||||
|
set +e
|
||||||
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,19 +93,17 @@ _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 quitting 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
|
||||||
|
|
||||||
# Try to connect to qemu
|
! isAlive "$pid" && break
|
||||||
if ! echo 'info version'| nc -q 1 -w 1 localhost "$QEMU_PORT" >/dev/null 2>&1 ; then
|
|
||||||
break
|
sleep 1
|
||||||
fi
|
|
||||||
|
|
||||||
# Increase the counter
|
# Increase the counter
|
||||||
cnt=$(($(cat $QEMU_COUNT)+1))
|
cnt=$(($(cat $QEMU_COUNT)+1))
|
||||||
@@ -63,23 +111,16 @@ _graceful_shutdown() {
|
|||||||
|
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && info "Shutting down, waiting... ($cnt/$QEMU_TIMEOUT)"
|
[[ "$DEBUG" == [Yy1]* ]] && info "Shutting down, waiting... ($cnt/$QEMU_TIMEOUT)"
|
||||||
|
|
||||||
|
# Workaround for zombie pid
|
||||||
|
[ ! -f "$QEMU_PID" ] && break
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$(cat $QEMU_COUNT)" -ge "$QEMU_TIMEOUT" ]; then
|
if [ "$(cat $QEMU_COUNT)" -ge "$QEMU_TIMEOUT" ]; then
|
||||||
echo && error "Shutdown timeout reached, forcefully quitting.."
|
echo && error "Shutdown timeout reached!"
|
||||||
else
|
|
||||||
echo && echo "❯ Quitting..."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo 'quit' | nc -q 1 -w 1 localhost "$QEMU_PORT" >/dev/null 2>&1 || true
|
finish "$code" && return "$code"
|
||||||
|
|
||||||
{ pkill -f print.sh || true; } 2>/dev/null
|
|
||||||
{ 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
|
||||||
|
|||||||
44
src/reset.sh
44
src/reset.sh
@@ -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
|
||||||
@@ -48,8 +49,41 @@ 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
|
||||||
@@ -70,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"
|
||||||
@@ -79,7 +120,6 @@ setCountry () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addPackage () {
|
addPackage () {
|
||||||
|
|
||||||
local pkg=$1
|
local pkg=$1
|
||||||
local desc=$2
|
local desc=$2
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user