Compare commits

...

22 Commits
v5.16 ... v5.19

Author SHA1 Message Date
Kroese
9fa68908a9 feat: Show download progress (#608) 2024-01-29 05:40:06 +01:00
Kroese
740dbec1b1 build: Exclude web folder (#607) 2024-01-29 02:29:05 +01:00
Kroese
440d203730 fix: Stylesheet (#606) 2024-01-29 02:27:04 +01:00
Kroese
1a83c67e2c feat: Font smoothing (#605) 2024-01-29 02:01:51 +01:00
Kroese
34a707a2a5 docs: Readme (#603) 2024-01-27 19:51:26 +01:00
Kroese
cabb2cdfc9 docs: Readme (#602) 2024-01-27 19:10:43 +01:00
Kroese
dc52ccf172 docs: Readme (#601) 2024-01-27 19:06:10 +01:00
Kroese
bdd7fec3c3 fix: Space after URL (#600) 2024-01-27 02:01:27 +01:00
Kroese
bd8b03d089 docs: Readme (#599) 2024-01-26 06:29:15 +01:00
Kroese
a10588b0ce fix: Check dnsmasq (#598) 2024-01-26 02:19:31 +01:00
renovate[bot]
3503b86e12 chore(deps): update peter-evans/dockerhub-description action to v4 (#597)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-25 17:05:28 +01:00
Kroese
9e124980cd fix: Disk message (#596) 2024-01-25 17:02:50 +01:00
Kroese
675aa5e122 docs: Readme (#595) 2024-01-23 21:49:18 +01:00
Kroese
2a62d4e938 feat: Display console arguments (#594) 2024-01-23 19:32:15 +01:00
Kroese
9cbb51cc86 feat: Display QEMU version (#593) 2024-01-23 19:29:07 +01:00
Kroese
7790f81d15 fix: Trap exit code (#592) 2024-01-23 18:46:47 +01:00
Kroese
fdbff4879b fix: Incorrect path (#591) 2024-01-23 03:06:29 +01:00
Kroese
739e679a66 feat: Check for SHM (#590) 2024-01-23 03:04:47 +01:00
Kroese
0dea507d85 feat: Shorter messages (#588) 2024-01-23 00:15:11 +01:00
Kroese
4f524c47d8 docs: Readme (#587) 2024-01-22 03:24:00 +01:00
Kroese
0c74201eb4 feat: CPU flags (#586) 2024-01-21 20:52:53 +01:00
Kroese
1e13258bc9 feat: Dynamic page content (#585) 2024-01-21 18:35:55 +01:00
18 changed files with 545 additions and 233 deletions

View File

@@ -8,6 +8,10 @@ on:
paths-ignore: paths-ignore:
- '**/*.md' - '**/*.md'
- '**/*.yml' - '**/*.yml'
- '**/*.js'
- '**/*.css'
- '**/*.html'
- 'web/**'
- '.gitignore' - '.gitignore'
- '.dockerignore' - '.dockerignore'
- '.github/**' - '.github/**'

View File

@@ -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 }}

View File

@@ -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?

View File

@@ -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"

View File

@@ -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
} }

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
View File

@@ -0,0 +1,32 @@
#!/usr/bin/env bash
set -Eeuo pipefail
escape () {
local s
s=${1//&/\&amp;}
s=${s//</\&lt;}
s=${s//>/\&gt;}
s=${s//'"'/\&quot;}
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

View File

@@ -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
View 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
View 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

View File

@@ -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
View 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();

View File

@@ -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;
}
}