mirror of
https://github.com/vdsm/virtual-dsm.git
synced 2025-11-07 02:23:42 +08:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fa68908a9 | ||
|
|
740dbec1b1 | ||
|
|
440d203730 | ||
|
|
1a83c67e2c | ||
|
|
34a707a2a5 | ||
|
|
cabb2cdfc9 | ||
|
|
dc52ccf172 | ||
|
|
bdd7fec3c3 | ||
|
|
bd8b03d089 | ||
|
|
a10588b0ce | ||
|
|
3503b86e12 | ||
|
|
9e124980cd | ||
|
|
675aa5e122 | ||
|
|
2a62d4e938 | ||
|
|
9cbb51cc86 | ||
|
|
7790f81d15 | ||
|
|
fdbff4879b | ||
|
|
739e679a66 | ||
|
|
0dea507d85 | ||
|
|
4f524c47d8 | ||
|
|
0c74201eb4 | ||
|
|
1e13258bc9 |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -8,6 +8,10 @@ on:
|
|||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**/*.md'
|
- '**/*.md'
|
||||||
- '**/*.yml'
|
- '**/*.yml'
|
||||||
|
- '**/*.js'
|
||||||
|
- '**/*.css'
|
||||||
|
- '**/*.html'
|
||||||
|
- 'web/**'
|
||||||
- '.gitignore'
|
- '.gitignore'
|
||||||
- '.dockerignore'
|
- '.dockerignore'
|
||||||
- '.github/**'
|
- '.github/**'
|
||||||
|
|||||||
2
.github/workflows/hub.yml
vendored
2
.github/workflows/hub.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
-
|
-
|
||||||
name: Docker Hub Description
|
name: Docker Hub Description
|
||||||
uses: peter-evans/dockerhub-description@v3
|
uses: peter-evans/dockerhub-description@v4
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ Virtual DSM in a docker container.
|
|||||||
|
|
||||||
- Multiple disks
|
- Multiple disks
|
||||||
- KVM acceleration
|
- KVM acceleration
|
||||||
- GPU pass-through
|
|
||||||
- Upgrades supported
|
- Upgrades supported
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -47,7 +46,7 @@ services:
|
|||||||
Via `docker run`
|
Via `docker run`
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -it --rm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-timeout 60 vdsm/virtual-dsm
|
docker run -it --rm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-timeout 120 vdsm/virtual-dsm
|
||||||
```
|
```
|
||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
@@ -56,13 +55,11 @@ docker run -it --rm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-ti
|
|||||||
|
|
||||||
Very simple! These are the steps:
|
Very simple! These are the steps:
|
||||||
|
|
||||||
- Start the container and get some coffee.
|
- Start the container and connect to [port 5000](http://localhost:5000) using your web browser.
|
||||||
|
|
||||||
- Connect to port 5000 of the container in your web browser.
|
|
||||||
|
|
||||||
- Wait until DSM is ready, choose an username and password, and you will be taken to the desktop.
|
- Wait until DSM is ready, choose an username and password, and you will be taken to the desktop.
|
||||||
|
|
||||||
- Enjoy your brand new machine, and don't forget to star this repo!
|
Enjoy your brand new machine, and don't forget to star this repo!
|
||||||
|
|
||||||
* ### How do I change the size of the disk?
|
* ### How do I change the size of the disk?
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ set -Eeuo pipefail
|
|||||||
|
|
||||||
DEF_OPTS="-nodefaults -boot strict=on"
|
DEF_OPTS="-nodefaults -boot strict=on"
|
||||||
RAM_OPTS=$(echo "-m $RAM_SIZE" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
|
RAM_OPTS=$(echo "-m $RAM_SIZE" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
|
||||||
CPU_OPTS="-cpu $CPU_MODEL -smp $CPU_CORES,sockets=1,dies=1,cores=$CPU_CORES,threads=1"
|
CPU_OPTS="-cpu $CPU_FLAGS -smp $CPU_CORES,sockets=1,dies=1,cores=$CPU_CORES,threads=1"
|
||||||
MAC_OPTS="-machine type=q35,usb=off,dump-guest-core=off,hpet=off${KVM_OPTS}"
|
MAC_OPTS="-machine type=q35,usb=off,vmport=off,dump-guest-core=off,hpet=off${KVM_OPTS}"
|
||||||
DEV_OPTS="-device virtio-balloon-pci,id=balloon0,bus=pcie.0,addr=0x4"
|
DEV_OPTS="-device virtio-balloon-pci,id=balloon0,bus=pcie.0,addr=0x4"
|
||||||
DEV_OPTS="$DEV_OPTS -object rng-random,id=objrng0,filename=/dev/urandom"
|
DEV_OPTS="$DEV_OPTS -object rng-random,id=objrng0,filename=/dev/urandom"
|
||||||
DEV_OPTS="$DEV_OPTS -device virtio-rng-pci,rng=objrng0,id=rng0,bus=pcie.0,addr=0x1c"
|
DEV_OPTS="$DEV_OPTS -device virtio-rng-pci,rng=objrng0,id=rng0,bus=pcie.0,addr=0x1c"
|
||||||
|
|||||||
12
src/disk.sh
12
src/disk.sh
@@ -112,8 +112,8 @@ createDisk() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MSG="Creating a $DISK_TYPE $DISK_DESC image in $DISK_FMT format with a size of $DISK_SPACE..."
|
html "Creating a $DISK_DESC image..."
|
||||||
info "$MSG" && html "$MSG"
|
info "Creating a $DISK_SPACE $DISK_TYPE $DISK_DESC image in $DISK_FMT format..."
|
||||||
|
|
||||||
local FAIL="Could not create a $DISK_TYPE $DISK_FMT $DISK_DESC image of $DISK_SPACE ($DISK_FILE)"
|
local FAIL="Could not create a $DISK_TYPE $DISK_FMT $DISK_DESC image of $DISK_SPACE ($DISK_FILE)"
|
||||||
|
|
||||||
@@ -266,8 +266,8 @@ convertDisk() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MSG="Converting $DISK_DESC to $DST_FMT, please wait until completed..."
|
html "Converting $DISK_DESC to $DST_FMT..."
|
||||||
info "$MSG" && html "$MSG"
|
info "Converting $DISK_DESC to $DST_FMT, please wait until completed..."
|
||||||
|
|
||||||
local CONV_FLAGS="-p"
|
local CONV_FLAGS="-p"
|
||||||
local DISK_PARAM="$DISK_ALLOC"
|
local DISK_PARAM="$DISK_ALLOC"
|
||||||
@@ -306,8 +306,8 @@ convertDisk() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MSG="Conversion of $DISK_DESC to $DST_FMT completed succesfully!"
|
html "Conversion of $DISK_DESC completed..."
|
||||||
info "$MSG" && html "$MSG"
|
info "Conversion of $DISK_DESC to $DST_FMT completed succesfully!"
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,13 @@ cd /run
|
|||||||
|
|
||||||
trap - ERR
|
trap - ERR
|
||||||
|
|
||||||
|
info "Booting $APP using $VERS..."
|
||||||
|
[[ "$DEBUG" == [Yy1]* ]] && echo "Arguments: $ARGS" && echo
|
||||||
|
|
||||||
if [[ "$CONSOLE" == [Yy]* ]]; then
|
if [[ "$CONSOLE" == [Yy]* ]]; then
|
||||||
exec qemu-system-x86_64 ${ARGS:+ $ARGS}
|
exec qemu-system-x86_64 ${ARGS:+ $ARGS}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && info "$VERS" && echo "Arguments: $ARGS" && echo
|
|
||||||
{ qemu-system-x86_64 ${ARGS:+ $ARGS} >"$QEMU_OUT" 2>"$QEMU_LOG"; rc=$?; } || :
|
{ qemu-system-x86_64 ${ARGS:+ $ARGS} >"$QEMU_OUT" 2>"$QEMU_LOG"; rc=$?; } || :
|
||||||
(( rc != 0 )) && error "$(<"$QEMU_LOG")" && exit 15
|
(( rc != 0 )) && error "$(<"$QEMU_LOG")" && exit 15
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ RDC="$STORAGE/dsm.rd"
|
|||||||
if [ ! -f "$RDC" ]; then
|
if [ ! -f "$RDC" ]; then
|
||||||
|
|
||||||
MSG="Downloading installer..."
|
MSG="Downloading installer..."
|
||||||
|
PRG="Downloading installer ([P])..."
|
||||||
info "Install: $MSG" && html "$MSG"
|
info "Install: $MSG" && html "$MSG"
|
||||||
|
|
||||||
RD="$TMP/rd.gz"
|
RD="$TMP/rd.gz"
|
||||||
@@ -112,7 +113,11 @@ if [ ! -f "$RDC" ]; then
|
|||||||
VERIFY="b4215a4b213ff5154db0488f92c87864"
|
VERIFY="b4215a4b213ff5154db0488f92c87864"
|
||||||
LOC="$DL/release/7.0.1/42218/DSM_VirtualDSM_42218.pat"
|
LOC="$DL/release/7.0.1/42218/DSM_VirtualDSM_42218.pat"
|
||||||
|
|
||||||
|
rm -f "$RD"
|
||||||
|
/run/progress.sh "$RD" "$PRG" &
|
||||||
{ curl -r "$POS" -sfk -S -o "$RD" "$LOC"; rc=$?; } || :
|
{ curl -r "$POS" -sfk -S -o "$RD" "$LOC"; rc=$?; } || :
|
||||||
|
|
||||||
|
fKill "progress.sh"
|
||||||
(( rc != 0 )) && error "Failed to download $LOC, reason: $rc" && exit 60
|
(( rc != 0 )) && error "Failed to download $LOC, reason: $rc" && exit 60
|
||||||
|
|
||||||
SUM=$(md5sum "$RD" | cut -f 1 -d " ")
|
SUM=$(md5sum "$RD" | cut -f 1 -d " ")
|
||||||
@@ -123,7 +128,11 @@ if [ ! -f "$RDC" ]; then
|
|||||||
rm "$RD"
|
rm "$RD"
|
||||||
rm -f "$PAT"
|
rm -f "$PAT"
|
||||||
|
|
||||||
|
html "$MSG"
|
||||||
|
/run/progress.sh "$PAT" "$PRG" &
|
||||||
{ wget "$LOC" -O "$PAT" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || :
|
{ wget "$LOC" -O "$PAT" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || :
|
||||||
|
|
||||||
|
fKill "progress.sh"
|
||||||
(( rc != 0 )) && error "Failed to download $LOC , reason: $rc" && exit 60
|
(( rc != 0 )) && error "Failed to download $LOC , reason: $rc" && exit 60
|
||||||
|
|
||||||
tar --extract --file="$PAT" --directory="$(dirname "$RD")"/. "$(basename "$RD")"
|
tar --extract --file="$PAT" --directory="$(dirname "$RD")"/. "$(basename "$RD")"
|
||||||
@@ -174,8 +183,11 @@ fi
|
|||||||
|
|
||||||
rm -rf "$TMP" && mkdir -p "$TMP"
|
rm -rf "$TMP" && mkdir -p "$TMP"
|
||||||
|
|
||||||
MSG="Downloading $BASE.pat..."
|
info "Install: Downloading $BASE.pat..."
|
||||||
info "Install: $MSG" && html "$MSG"
|
|
||||||
|
MSG="Downloading DSM..."
|
||||||
|
PRG="Downloading DSM ([P])..."
|
||||||
|
html "$MSG"
|
||||||
|
|
||||||
PAT="/$BASE.pat"
|
PAT="/$BASE.pat"
|
||||||
rm -f "$PAT"
|
rm -f "$PAT"
|
||||||
@@ -186,7 +198,11 @@ if [[ "$URL" == "file://"* ]]; then
|
|||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
/run/progress.sh "$PAT" "$PRG" &
|
||||||
|
|
||||||
{ wget "$URL" -O "$PAT" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || :
|
{ wget "$URL" -O "$PAT" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || :
|
||||||
|
|
||||||
|
fKill "progress.sh"
|
||||||
(( rc != 0 )) && error "Failed to download $URL , reason: $rc" && exit 69
|
(( rc != 0 )) && error "Failed to download $URL , reason: $rc" && exit 69
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -83,7 +83,9 @@ configureDNS() {
|
|||||||
DNSMASQ_OPTS=$(echo "$DNSMASQ_OPTS" | sed 's/\t/ /g' | tr -s ' ' | sed 's/^ *//')
|
DNSMASQ_OPTS=$(echo "$DNSMASQ_OPTS" | sed 's/\t/ /g' | tr -s ' ' | sed 's/^ *//')
|
||||||
|
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && set -x
|
[[ "$DEBUG" == [Yy1]* ]] && set -x
|
||||||
$DNSMASQ ${DNSMASQ_OPTS:+ $DNSMASQ_OPTS}
|
if ! $DNSMASQ ${DNSMASQ_OPTS:+ $DNSMASQ_OPTS}; then
|
||||||
|
error "Failed to start dnsmasq, reason: $?" && exit 29
|
||||||
|
fi
|
||||||
{ set +x; } 2>/dev/null
|
{ set +x; } 2>/dev/null
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo
|
[[ "$DEBUG" == [Yy1]* ]] && echo
|
||||||
|
|
||||||
@@ -254,8 +256,8 @@ if [[ "$DHCP" == [Yy1]* ]]; then
|
|||||||
# Configuration for DHCP IP
|
# Configuration for DHCP IP
|
||||||
configureDHCP
|
configureDHCP
|
||||||
|
|
||||||
MSG="Please wait while discovering IP..."
|
MSG="Booting DSM instance..."
|
||||||
html "$MSG" "2000"
|
html "$MSG"
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ terminal() {
|
|||||||
|
|
||||||
_graceful_shutdown() {
|
_graceful_shutdown() {
|
||||||
|
|
||||||
local cnt=0
|
|
||||||
local code=$?
|
local code=$?
|
||||||
local pid url response
|
local pid url response
|
||||||
|
|
||||||
@@ -144,6 +143,8 @@ _graceful_shutdown() {
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local cnt=0
|
||||||
|
|
||||||
while [ "$cnt" -lt "$QEMU_TIMEOUT" ]; do
|
while [ "$cnt" -lt "$QEMU_TIMEOUT" ]; do
|
||||||
|
|
||||||
! isAlive "$pid" && break
|
! isAlive "$pid" && break
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "$1" "\E[0m\n" >&2; }
|
|||||||
error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: $1" "\E[0m\n" >&2; }
|
error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: $1" "\E[0m\n" >&2; }
|
||||||
|
|
||||||
file="/run/shm/dsm.url"
|
file="/run/shm/dsm.url"
|
||||||
|
info="/run/shm/msg.html"
|
||||||
page="/run/shm/index.html"
|
page="/run/shm/index.html"
|
||||||
address="/run/shm/qemu.ip"
|
address="/run/shm/qemu.ip"
|
||||||
shutdown="/run/shm/qemu.end"
|
shutdown="/run/shm/qemu.end"
|
||||||
@@ -80,6 +81,7 @@ if [[ "$location" != "20.20"* ]]; then
|
|||||||
HTML="${HTML/\[5\]/}"
|
HTML="${HTML/\[5\]/}"
|
||||||
|
|
||||||
echo "$HTML" > "$page"
|
echo "$HTML" > "$page"
|
||||||
|
echo "$body" > "$info"
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
|||||||
17
src/proc.sh
17
src/proc.sh
@@ -5,8 +5,8 @@ set -Eeuo pipefail
|
|||||||
|
|
||||||
: "${KVM:="Y"}"
|
: "${KVM:="Y"}"
|
||||||
: "${HOST_CPU:=""}"
|
: "${HOST_CPU:=""}"
|
||||||
|
: "${CPU_FLAGS:=""}"
|
||||||
: "${CPU_MODEL:="host"}"
|
: "${CPU_MODEL:="host"}"
|
||||||
: "${CPU_FEATURES:="+ssse3,+sse4.1,+sse4.2"}"
|
|
||||||
|
|
||||||
[ "$ARCH" != "amd64" ] && KVM="N"
|
[ "$ARCH" != "amd64" ] && KVM="N"
|
||||||
|
|
||||||
@@ -37,6 +37,7 @@ fi
|
|||||||
|
|
||||||
if [[ "$KVM" != [Nn]* ]]; then
|
if [[ "$KVM" != [Nn]* ]]; then
|
||||||
|
|
||||||
|
CPU_FEATURES="kvm=on"
|
||||||
KVM_OPTS=",accel=kvm -enable-kvm"
|
KVM_OPTS=",accel=kvm -enable-kvm"
|
||||||
|
|
||||||
if ! grep -qE '^flags.* (sse4_2)' /proc/cpuinfo; then
|
if ! grep -qE '^flags.* (sse4_2)' /proc/cpuinfo; then
|
||||||
@@ -48,15 +49,23 @@ if [[ "$KVM" != [Nn]* ]]; then
|
|||||||
else
|
else
|
||||||
|
|
||||||
KVM_OPTS=""
|
KVM_OPTS=""
|
||||||
|
CPU_FEATURES="+ssse3,+sse4.1,+sse4.2"
|
||||||
|
|
||||||
|
if [[ "${CPU_MODEL,,}" == "host"* ]]; then
|
||||||
|
|
||||||
if [[ "$CPU_MODEL" == "host"* ]]; then
|
|
||||||
if [[ "$ARCH" == "amd64" ]]; then
|
if [[ "$ARCH" == "amd64" ]]; then
|
||||||
CPU_MODEL="max,$CPU_FEATURES"
|
CPU_MODEL="max"
|
||||||
else
|
else
|
||||||
CPU_MODEL="qemu64,$CPU_FEATURES"
|
CPU_MODEL="qemu64"
|
||||||
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -z "$CPU_FLAGS" ]; then
|
||||||
|
CPU_FLAGS="$CPU_MODEL,$CPU_FEATURES"
|
||||||
|
else
|
||||||
|
CPU_FLAGS="$CPU_MODEL,$CPU_FEATURES,$CPU_FLAGS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$HOST_CPU" ]; then
|
if [ -z "$HOST_CPU" ]; then
|
||||||
|
|||||||
32
src/progress.sh
Normal file
32
src/progress.sh
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
escape () {
|
||||||
|
local s
|
||||||
|
s=${1//&/\&}
|
||||||
|
s=${s//</\<}
|
||||||
|
s=${s//>/\>}
|
||||||
|
s=${s//'"'/\"}
|
||||||
|
printf -- %s "$s"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
file="$1"
|
||||||
|
body=$(escape "$2")
|
||||||
|
info="/run/shm/msg.html"
|
||||||
|
|
||||||
|
if [[ "$body" == *"..." ]]; then
|
||||||
|
body="<p class=\"loading\">${body/.../}</p>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
bytes=$(du -sb "$file" | cut -f1)
|
||||||
|
if (( bytes > 1000 )); then
|
||||||
|
size=$(echo "$bytes" | numfmt --to=iec --suffix=B | sed -r 's/([A-Z])/ \1/')
|
||||||
|
echo "${body//(\[P\])/($size)}"> "$info"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
24
src/reset.sh
24
src/reset.sh
@@ -29,6 +29,7 @@ echo
|
|||||||
# Helper variables
|
# Helper variables
|
||||||
|
|
||||||
STORAGE="/storage"
|
STORAGE="/storage"
|
||||||
|
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"
|
||||||
FOOTER1="$APP for Docker v$(</run/version)"
|
FOOTER1="$APP for Docker v$(</run/version)"
|
||||||
@@ -39,20 +40,20 @@ MINOR=$(uname -r | cut -d '.' -f2)
|
|||||||
ARCH=$(dpkg --print-architecture)
|
ARCH=$(dpkg --print-architecture)
|
||||||
VERS=$(qemu-system-x86_64 --version | head -n 1 | cut -d '(' -f 1)
|
VERS=$(qemu-system-x86_64 --version | head -n 1 | cut -d '(' -f 1)
|
||||||
|
|
||||||
|
# Check system
|
||||||
|
|
||||||
|
if [ ! -d "/dev/shm" ]; then
|
||||||
|
error "Directory /dev/shm not found!" && exit 14
|
||||||
|
else
|
||||||
|
[ ! -d "/run/shm" ] && ln -s /dev/shm /run/shm
|
||||||
|
fi
|
||||||
|
|
||||||
# Check folder
|
# Check folder
|
||||||
|
|
||||||
if [ ! -d "$STORAGE" ]; then
|
if [ ! -d "$STORAGE" ]; then
|
||||||
error "Storage folder ($STORAGE) not found!" && exit 13
|
error "Storage folder ($STORAGE) not found!" && exit 13
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -d "/run/shm" ]; then
|
|
||||||
if [ -d "/dev/shm" ]; then
|
|
||||||
ln -s /dev/shm /run/shm
|
|
||||||
else
|
|
||||||
error "Folder /dev/shm not found!" && exit 14
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Cleanup files
|
# Cleanup files
|
||||||
rm -f /run/shm/qemu.*
|
rm -f /run/shm/qemu.*
|
||||||
rm -f /run/shm/dsm.url
|
rm -f /run/shm/dsm.url
|
||||||
@@ -118,6 +119,7 @@ html()
|
|||||||
{
|
{
|
||||||
local title
|
local title
|
||||||
local body
|
local body
|
||||||
|
local script
|
||||||
local footer
|
local footer
|
||||||
|
|
||||||
title=$(escape "$APP")
|
title=$(escape "$APP")
|
||||||
@@ -129,10 +131,7 @@ html()
|
|||||||
body="<p class=\"loading\">${body/.../}</p>"
|
body="<p class=\"loading\">${body/.../}</p>"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local timeout="4999"
|
[ -n "${2:-}" ] && script="$2" || script=""
|
||||||
[ -n "${2:-}" ] && timeout="$2"
|
|
||||||
local script="<script>setTimeout(() => { document.location.reload(); }, $timeout);</script>"
|
|
||||||
[[ "$timeout" == "0" ]] && script=""
|
|
||||||
|
|
||||||
local HTML
|
local HTML
|
||||||
HTML=$(<"$TEMPLATE")
|
HTML=$(<"$TEMPLATE")
|
||||||
@@ -143,6 +142,7 @@ html()
|
|||||||
HTML="${HTML/\[5\]/$FOOTER2}"
|
HTML="${HTML/\[5\]/$FOOTER2}"
|
||||||
|
|
||||||
echo "$HTML" > "$PAGE"
|
echo "$HTML" > "$PAGE"
|
||||||
|
echo "$body" > "$INFO"
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
167
web/css/style.css
Normal file
167
web/css/style.css
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
body {
|
||||||
|
color: white;
|
||||||
|
background-color: #125bdb;
|
||||||
|
font-smoothing: antialiased;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
font-family: Verdana, Geneva, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#info {
|
||||||
|
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
width: 98%;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0px;
|
||||||
|
height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
color: #0c8aeb;
|
||||||
|
text-shadow: 0 0 1px #0c8aeb;
|
||||||
|
}
|
||||||
|
|
||||||
|
#empty {
|
||||||
|
height: 40px;
|
||||||
|
/* Same height as footer */
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
a:hover,
|
||||||
|
a:active,
|
||||||
|
a:visited {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a:link,
|
||||||
|
footer a:visited,
|
||||||
|
footer a:active {
|
||||||
|
color: #0c8aeb;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a:hover {
|
||||||
|
color: #73e6ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading:after {
|
||||||
|
content: " .";
|
||||||
|
animation: dots 1s steps(5, end) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes dots {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
20% {
|
||||||
|
color: rgba(0, 0, 0, 0);
|
||||||
|
text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
color: white;
|
||||||
|
text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
60% {
|
||||||
|
text-shadow: 0.25em 0 0 white, 0.5em 0 0 rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
80%,
|
||||||
|
100% {
|
||||||
|
text-shadow: 0.25em 0 0 white, 0.5em 0 0 white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner_LWk7 {
|
||||||
|
animation: spinner_GWy6 1.2s linear infinite, spinner_BNNO 1.2s linear infinite
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner_yOMU {
|
||||||
|
animation: spinner_GWy6 1.2s linear infinite, spinner_pVqn 1.2s linear infinite;
|
||||||
|
animation-delay: .15s
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner_KS4S {
|
||||||
|
animation: spinner_GWy6 1.2s linear infinite, spinner_6uKB 1.2s linear infinite;
|
||||||
|
animation-delay: .3s
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner_zVee {
|
||||||
|
animation: spinner_GWy6 1.2s linear infinite, spinner_Qw4x 1.2s linear infinite;
|
||||||
|
animation-delay: .45s
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spinner_GWy6 {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
50% {
|
||||||
|
width: 9px;
|
||||||
|
height: 9px
|
||||||
|
}
|
||||||
|
|
||||||
|
10% {
|
||||||
|
width: 11px;
|
||||||
|
height: 11px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spinner_BNNO {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
50% {
|
||||||
|
x: 1.5px;
|
||||||
|
y: 1.5px
|
||||||
|
}
|
||||||
|
|
||||||
|
10% {
|
||||||
|
x: .5px;
|
||||||
|
y: .5px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spinner_pVqn {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
50% {
|
||||||
|
x: 13.5px;
|
||||||
|
y: 1.5px
|
||||||
|
}
|
||||||
|
|
||||||
|
10% {
|
||||||
|
x: 12.5px;
|
||||||
|
y: .5px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spinner_6uKB {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
50% {
|
||||||
|
x: 13.5px;
|
||||||
|
y: 13.5px
|
||||||
|
}
|
||||||
|
|
||||||
|
10% {
|
||||||
|
x: 12.5px;
|
||||||
|
y: 12.5px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spinner_Qw4x {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
50% {
|
||||||
|
x: 1.5px;
|
||||||
|
y: 13.5px
|
||||||
|
}
|
||||||
|
|
||||||
|
10% {
|
||||||
|
x: .5px;
|
||||||
|
y: 12.5px
|
||||||
|
}
|
||||||
|
}
|
||||||
1
web/img/favicon.svg
Normal file
1
web/img/favicon.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg id="Capa_1" enable-background="new 0 0 511.962 511.962" height="512" viewBox="0 0 511.962 511.962" width="512" xmlns="http://www.w3.org/2000/svg"><g><path d="m489.965 120.063c0-5.77-3.31-11.028-8.512-13.524l-218.984-105.063c-4.102-1.967-8.875-1.967-12.977 0l-218.985 105.063c-5.202 2.496-8.511 7.755-8.511 13.524l-.003 271.834c0 5.77 3.31 11.028 8.512 13.524l218.989 105.064c2.051.983 4.27 1.476 6.488 1.476 2.219 0 4.438-.492 6.488-1.476l218.989-105.064c5.202-2.496 8.512-7.755 8.512-13.524z" fill="#4e6ba6"/><path d="m489.965 120.063c0-5.77-3.31-11.028-8.512-13.524l-218.984-105.063c-2.051-.984-4.269-1.476-6.488-1.476v511.962c2.219 0 4.438-.492 6.488-1.476l218.989-105.064c5.202-2.496 8.512-7.755 8.512-13.524z" fill="#28487a"/><path d="m425.812 160.441c0-2.27-.519-4.457-1.457-6.432l-336.701-.095c-.967 1.999-1.504 4.22-1.504 6.526l-.002 191.081c0 5.769 3.31 11.028 8.512 13.524l154.833 74.285c2.051.983 4.27 1.476 6.488 1.476 2.219 0 4.438-.492 6.488-1.476l154.834-74.285c5.202-2.496 8.512-7.755 8.512-13.524z" fill="#8dc2eb"/><path d="m424.354 154.009h-168.373v286.798c2.219 0 4.438-.492 6.488-1.476l154.834-74.285c5.202-2.496 8.512-7.755 8.512-13.524l-.003-191.081c0-2.27-.52-4.458-1.458-6.432z" fill="#5e9ff6"/><path d="m417.3 146.916-154.831-74.284c-4.102-1.967-8.875-1.967-12.977 0l-154.831 74.284c-3.122 1.498-5.555 3.996-7.007 6.998l168.328 80.812 168.374-80.717c-1.448-3.044-3.9-5.579-7.056-7.093z" fill="#ecf9fd"/><path d="m417.3 146.916-154.831-74.284c-2.051-.983-4.27-1.476-6.488-1.476v163.569l168.374-80.717c-1.447-3.043-3.899-5.578-7.055-7.092z" fill="#d9f3fc"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -5,22 +5,30 @@
|
|||||||
[1]
|
[1]
|
||||||
<meta http-equiv="Cache-Control" content="no-cache" />
|
<meta http-equiv="Cache-Control" content="no-cache" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
<link rel="stylesheet" type="text/css" href="/css/style.css" />
|
||||||
|
<link rel="icon" href="/img/favicon.svg" type="image/x-icon">
|
||||||
[2]
|
[2]
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="page-container">
|
<div id="page">
|
||||||
<div id="content-wrap">
|
<div id="content">
|
||||||
<h1>[3]</h1>
|
<svg id="spinner" width="64" height="64" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect class="spinner_LWk7" fill="#0c8aeb" x="1.5" y="1.5" rx="1" width="9" height="9"/>
|
||||||
|
<rect class="spinner_yOMU" fill="#0c8aeb" x="13.5" y="1.5" rx="1" width="9" height="9"/>
|
||||||
|
<rect class="spinner_KS4S" fill="#0c8aeb" x="13.5" y="13.5" rx="1" width="9" height="9"/>
|
||||||
|
<rect class="spinner_zVee" fill="#0c8aeb" x="1.5" y="13.5" rx="1" width="9" height="9"/>
|
||||||
|
</svg>
|
||||||
|
<h1 id="info">[3]</h1>
|
||||||
</div>
|
</div>
|
||||||
<div id="empty-space">
|
<div id="empty">
|
||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<footer id="footer">
|
||||||
[4]<br />
|
[4]<br />
|
||||||
[5]
|
[5]
|
||||||
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<script type="text/javascript" src="/js/script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
130
web/js/script.js
Normal file
130
web/js/script.js
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
var request;
|
||||||
|
var interval = 1000;
|
||||||
|
|
||||||
|
function getInfo() {
|
||||||
|
|
||||||
|
var url = "/msg.html";
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (window.XMLHttpRequest) {
|
||||||
|
request = new XMLHttpRequest();
|
||||||
|
} else {
|
||||||
|
throw "XMLHttpRequest not available!";
|
||||||
|
}
|
||||||
|
|
||||||
|
request.onreadystatechange = processInfo;
|
||||||
|
request.open("GET", url, true);
|
||||||
|
request.send();
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
var err = "Error: " + e.message;
|
||||||
|
console.log(err);
|
||||||
|
setError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function processInfo() {
|
||||||
|
try {
|
||||||
|
if (request.readyState != 4) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg = request.responseText;
|
||||||
|
if (msg == null || msg.length == 0) {
|
||||||
|
setInfo("Booting DSM instance", true);
|
||||||
|
schedule();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var notFound = (request.status == 404);
|
||||||
|
|
||||||
|
if (request.status == 200) {
|
||||||
|
if (msg.toLowerCase().indexOf("<html>") !== -1) {
|
||||||
|
notFound = true;
|
||||||
|
} else {
|
||||||
|
if (msg.toLowerCase().indexOf("href=") !== -1) {
|
||||||
|
var div = document.createElement("div");
|
||||||
|
div.innerHTML = msg;
|
||||||
|
var url = div.querySelector("a").href;
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.assign(url);
|
||||||
|
}, 3000);
|
||||||
|
setInfo(msg);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
setInfo(msg);
|
||||||
|
schedule();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notFound) {
|
||||||
|
setInfo("Connecting to web portal", true);
|
||||||
|
reload();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
setError("Error: Received statuscode " + request.status);
|
||||||
|
schedule();
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
var err = "Error: " + e.message;
|
||||||
|
console.log(err);
|
||||||
|
setError(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setInfo(msg, loading, error) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (msg == null || msg.length == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var el = document.getElementById("spinner");
|
||||||
|
|
||||||
|
error = !!error;
|
||||||
|
if (!error) {
|
||||||
|
el.style.visibility = 'visible';
|
||||||
|
} else {
|
||||||
|
el.style.visibility = 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
|
loading = !!loading;
|
||||||
|
if (loading) {
|
||||||
|
msg = "<p class=\"loading\">" + msg + "</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
el = document.getElementById("info");
|
||||||
|
|
||||||
|
if (el.innerHTML != msg) {
|
||||||
|
el.innerHTML = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Error: " + e.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setError(text) {
|
||||||
|
return setInfo(text, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function schedule() {
|
||||||
|
setTimeout(getInfo, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reload() {
|
||||||
|
setTimeout(() => {
|
||||||
|
document.location.reload();
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
schedule();
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
body {
|
|
||||||
color: white;
|
|
||||||
background-color: #125bdb;
|
|
||||||
font-family: Verdana, Arial, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
#content-wrap {
|
|
||||||
text-align: center;
|
|
||||||
padding: 20px;
|
|
||||||
margin-top: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#footer {
|
|
||||||
width: 98%;
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0px;
|
|
||||||
height: 40px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#empty-space {
|
|
||||||
height: 40px;
|
|
||||||
/* Same height as footer */
|
|
||||||
}
|
|
||||||
|
|
||||||
a,
|
|
||||||
a:hover,
|
|
||||||
a:active,
|
|
||||||
a:visited {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading:after {
|
|
||||||
content: " .";
|
|
||||||
animation: dots 1s steps(5, end) infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes dots {
|
|
||||||
|
|
||||||
0%,
|
|
||||||
20% {
|
|
||||||
color: rgba(0, 0, 0, 0);
|
|
||||||
text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
40% {
|
|
||||||
color: white;
|
|
||||||
text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
60% {
|
|
||||||
text-shadow: 0.25em 0 0 white, 0.5em 0 0 rgba(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
80%,
|
|
||||||
100% {
|
|
||||||
text-shadow: 0.25em 0 0 white, 0.5em 0 0 white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user