mirror of
https://github.com/vdsm/virtual-dsm.git
synced 2025-11-06 18:13:43 +08:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5dd5c2e46 | ||
|
|
d1d920372a | ||
|
|
12d8fd3ed0 | ||
|
|
729aed536e | ||
|
|
b588f8c90d | ||
|
|
1f1007a0f1 | ||
|
|
2ec37e2802 | ||
|
|
3126b3847b | ||
|
|
41e0157e9d | ||
|
|
1d64410849 | ||
|
|
55034b0f40 | ||
|
|
acffcf3774 | ||
|
|
fba0eb527b | ||
|
|
d9fc2714a6 | ||
|
|
d1f1772d74 | ||
|
|
bf1d47e4f3 | ||
|
|
3da564dfd1 | ||
|
|
abd30b9d91 | ||
|
|
c86408cbd6 | ||
|
|
1f51974c48 | ||
|
|
29f4cde296 | ||
|
|
c4a0035062 | ||
|
|
6724ddbd7d | ||
|
|
8d8ed63122 | ||
|
|
6f4ea81907 | ||
|
|
6d162744ec | ||
|
|
145b4aab5b | ||
|
|
2e4eb56d0b | ||
|
|
39c019193e | ||
|
|
faec563b4a | ||
|
|
9840f8e07a | ||
|
|
3a5895fa0f | ||
|
|
1bac5c8a7f | ||
|
|
dd76c60e2a | ||
|
|
ac78cc7dc5 | ||
|
|
66ac2d2002 | ||
|
|
0bd099d704 | ||
|
|
d2dac3cfb4 |
62
.github/ISSUE_TEMPLATE/1-issue.yml
vendored
Normal file
62
.github/ISSUE_TEMPLATE/1-issue.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: "\U0001F6A8 Technical issue"
|
||||
description: When you're experiencing problems using the container
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there no existing issue for this?
|
||||
description: Please search to see if no solution was already provided before.
|
||||
options:
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
- type: input
|
||||
id: cpu
|
||||
attributes:
|
||||
label: Machine specifications
|
||||
description: The processor and RAM amount in your machine.
|
||||
placeholder: e.g. Intel N5105 / 16 GB
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating system
|
||||
description: The distribution and kernel version (as shown by `uname -a`).
|
||||
placeholder: e.g. Ubuntu 24.04 / Kernel 6.8.0-22-generic
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: docker
|
||||
attributes:
|
||||
label: Docker version
|
||||
description: The version of the Docker engine (as shown by `docker -v`).
|
||||
placeholder: e.g. 26.0.1
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: summary
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of your issue.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: compose
|
||||
attributes:
|
||||
label: Docker compose
|
||||
description: The compose file (or otherwise the `docker run` command used).
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: log
|
||||
attributes:
|
||||
label: Docker log
|
||||
description: The logfile of the container (as shown by `docker logs dsm`).
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshot
|
||||
attributes:
|
||||
label: Screenshots (optional)
|
||||
description: Screenshots that might help to make the problem more clear.
|
||||
validations:
|
||||
required: false
|
||||
44
.github/ISSUE_TEMPLATE/2-feature.yml
vendored
Normal file
44
.github/ISSUE_TEMPLATE/2-feature.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: "\U0001F680 Feature request"
|
||||
description: Suggest an idea for improving the container
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there no existing feature request for this?
|
||||
description: Please search to see if the feature was not already requested before.
|
||||
options:
|
||||
- label: I have searched the existing feature requests
|
||||
required: true
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Is your proposal related to a problem?
|
||||
description: |
|
||||
Provide a clear and concise description of what the problem is.
|
||||
For example, "I'm always frustrated when..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Describe the solution you'd like.
|
||||
description: |
|
||||
Provide a clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Describe alternatives you've considered.
|
||||
description: |
|
||||
Let us know about other solutions you've tried or researched.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: |
|
||||
Is there anything else you can add about the proposal?
|
||||
You might want to link to related issues here, if you haven't already.
|
||||
64
.github/ISSUE_TEMPLATE/3-bug.yml
vendored
Normal file
64
.github/ISSUE_TEMPLATE/3-bug.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
name: "\U0001F41E Bug report"
|
||||
description: Create a report to help us improve the container
|
||||
title: "[Bug]: "
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there no existing bug report for this?
|
||||
description: Please search to see if the bug was not already reported before.
|
||||
options:
|
||||
- label: I have searched the existing bug reports
|
||||
required: true
|
||||
- type: input
|
||||
id: cpu
|
||||
attributes:
|
||||
label: Machine specifications
|
||||
description: The processor and RAM amount in your machine.
|
||||
placeholder: e.g. Intel N5105 / 16 GB
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating system
|
||||
description: The distribution and kernel version (as shown by `uname -a`).
|
||||
placeholder: e.g. Ubuntu 24.04 / Kernel 6.8.0-22-generic
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: docker
|
||||
attributes:
|
||||
label: Docker version
|
||||
description: The version of the Docker engine (as shown by `docker -v`).
|
||||
placeholder: e.g. 26.0.1
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: summary
|
||||
attributes:
|
||||
label: Description
|
||||
description: Describe the expected behaviour, the actual behaviour, and the steps to reproduce.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: compose
|
||||
attributes:
|
||||
label: Docker compose
|
||||
description: The compose file (or otherwise the `docker run` command used).
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: log
|
||||
attributes:
|
||||
label: Docker log
|
||||
description: The logfile of the container (as shown by `docker logs dsm`).
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshot
|
||||
attributes:
|
||||
label: Screenshots (optional)
|
||||
description: Screenshots that might help to make the problem more clear.
|
||||
validations:
|
||||
required: false
|
||||
26
.github/ISSUE_TEMPLATE/4-question.yml
vendored
Normal file
26
.github/ISSUE_TEMPLATE/4-question.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: "\U00002753 General question"
|
||||
description: Questions about the container not related to an issue
|
||||
title: "[Question]: "
|
||||
labels: ["question"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is your question not already answered in the FAQ?
|
||||
description: Please read the [FAQ](https://github.com/vdsm/virtual-dsm/blob/master/readme.md) carefully to avoid asking duplicate questions.
|
||||
options:
|
||||
- label: I made sure the question is not listed in the [FAQ](https://github.com/vdsm/virtual-dsm/blob/master/readme.md).
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is this a general question and not a technical issue?
|
||||
description: For questions related to issues you must use the [technical issue](https://github.com/vdsm/virtual-dsm/issues/new?assignees=&labels=&projects=&template=1-issue.yml) form instead. It contains all the right fields (system info, logfiles, etc.) we need in order to be able to help you.
|
||||
options:
|
||||
- label: I am sure my question is not about a technical issue.
|
||||
required: true
|
||||
- type: textarea
|
||||
id: question
|
||||
attributes:
|
||||
label: Question
|
||||
description: What's the question you have about the container?
|
||||
validations:
|
||||
required: true
|
||||
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -78,7 +78,7 @@ jobs:
|
||||
context: .
|
||||
push: true
|
||||
provenance: false
|
||||
platforms: linux/amd64,linux/arm64,linux/arm
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
annotations: ${{ steps.meta.outputs.annotations }}
|
||||
|
||||
24
Dockerfile
24
Dockerfile
@@ -10,11 +10,13 @@ FROM qemux/qemu-host:2.04 as builder
|
||||
FROM debian:trixie-slim
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
ARG DEBCONF_NOWARNINGS "yes"
|
||||
ARG DEBIAN_FRONTEND "noninteractive"
|
||||
ARG DEBCONF_NONINTERACTIVE_SEEN "true"
|
||||
ARG VERSION_ARG="0.0"
|
||||
ARG DEBCONF_NOWARNINGS="yes"
|
||||
ARG DEBIAN_FRONTEND="noninteractive"
|
||||
ARG DEBCONF_NONINTERACTIVE_SEEN="true"
|
||||
|
||||
RUN if [ "$TARGETPLATFORM" != "linux/amd64" ]; then extra="qemu-user"; fi && \
|
||||
RUN set -eu && extra="" && \
|
||||
if [ "$TARGETPLATFORM" != "linux/amd64" ]; then extra="qemu-user"; fi && \
|
||||
apt-get update && \
|
||||
apt-get --no-install-recommends -y install \
|
||||
jq \
|
||||
@@ -41,14 +43,13 @@ RUN if [ "$TARGETPLATFORM" != "linux/amd64" ]; then extra="qemu-user"; fi && \
|
||||
apt-get clean && \
|
||||
unlink /etc/nginx/sites-enabled/default && \
|
||||
sed -i 's/^worker_processes.*/worker_processes 1;/' /etc/nginx/nginx.conf && \
|
||||
echo "$VERSION_ARG" > /run/version && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
COPY ./src /run/
|
||||
COPY ./web /var/www/
|
||||
COPY --from=builder /qemu-host.bin /run/host.bin
|
||||
|
||||
RUN chmod +x /run/*.sh && chmod +x /run/*.bin
|
||||
RUN mv /var/www/nginx.conf /etc/nginx/sites-enabled/web.conf
|
||||
COPY --chmod=755 ./src /run/
|
||||
COPY --chmod=755 ./web /var/www/
|
||||
COPY --chmod=755 --from=builder /qemu-host.bin /run/host.bin
|
||||
COPY --chmod=744 ./web/nginx.conf /etc/nginx/sites-enabled/web.conf
|
||||
|
||||
VOLUME /storage
|
||||
EXPOSE 22 139 445 5000
|
||||
@@ -57,9 +58,6 @@ ENV RAM_SIZE "1G"
|
||||
ENV DISK_SIZE "16G"
|
||||
ENV CPU_CORES "1"
|
||||
|
||||
ARG VERSION_ARG "0.0"
|
||||
RUN echo "$VERSION_ARG" > /run/version
|
||||
|
||||
HEALTHCHECK --interval=60s --start-period=45s --retries=2 CMD /run/check.sh
|
||||
|
||||
ENTRYPOINT ["/usr/bin/tini", "-s", "/run/entry.sh"]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
version: "3"
|
||||
services:
|
||||
dsm:
|
||||
container_name: dsm
|
||||
@@ -13,5 +12,4 @@ services:
|
||||
- 5000:5000
|
||||
volumes:
|
||||
- /var/dsm:/storage
|
||||
restart: on-failure
|
||||
stop_grace_period: 2m
|
||||
|
||||
58
kubernetes.yml
Normal file
58
kubernetes.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: dsm-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 16Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: dsm
|
||||
labels:
|
||||
name: dsm
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 120 # the Kubernetes default is 30 seconds and it may be not enough
|
||||
containers:
|
||||
- name: dsm
|
||||
image: vdsm/virtual-dsm
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
protocol: TCP
|
||||
resources:
|
||||
limits:
|
||||
devices.kubevirt.io/kvm: 1
|
||||
securityContext:
|
||||
privileged: true
|
||||
env:
|
||||
- name: RAM_SIZE
|
||||
value: 1G
|
||||
- name: CPU_CORES
|
||||
value: "1"
|
||||
- name: DISK_SIZE
|
||||
value: "16G" # Kubernetes uses Gi, but DSM uses GB
|
||||
volumeMounts:
|
||||
- mountPath: /storage
|
||||
name: storage
|
||||
volumes:
|
||||
- name: storage
|
||||
persistentVolumeClaim:
|
||||
claimName: dsm-pvc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: dsm
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
name: dsm
|
||||
ports:
|
||||
- name: tcp-5000
|
||||
port: 5000
|
||||
targetPort: 5000
|
||||
nodePort: 31150
|
||||
54
readme.md
54
readme.md
@@ -24,7 +24,6 @@ Virtual DSM in a Docker container.
|
||||
Via Docker Compose:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
dsm:
|
||||
container_name: dsm
|
||||
@@ -39,14 +38,19 @@ services:
|
||||
- 5000:5000
|
||||
volumes:
|
||||
- /var/dsm:/storage
|
||||
restart: on-failure
|
||||
stop_grace_period: 2m
|
||||
```
|
||||
|
||||
Via Docker CLI:
|
||||
|
||||
```bash
|
||||
docker run -it --rm --name dsm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-timeout 120 vdsm/virtual-dsm
|
||||
docker run -it --name dsm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-timeout 120 vdsm/virtual-dsm
|
||||
```
|
||||
|
||||
Via Kubernetes:
|
||||
|
||||
```shell
|
||||
kubectl apply -f kubernetes.yml
|
||||
```
|
||||
|
||||
## FAQ
|
||||
@@ -61,17 +65,6 @@ docker run -it --rm --name dsm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMI
|
||||
|
||||
Enjoy your brand new machine, and don't forget to star this repo!
|
||||
|
||||
* ### How do I change the size of the disk?
|
||||
|
||||
To expand the default size of 16 GB, locate the `DISK_SIZE` setting in your compose file and modify it to your preferred capacity:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
DISK_SIZE: "128G"
|
||||
```
|
||||
|
||||
This can also be used to resize the existing disk to a larger capacity without any data loss.
|
||||
|
||||
* ### How do I change the storage location?
|
||||
|
||||
To change the storage location, include the following bind mount in your compose file:
|
||||
@@ -82,6 +75,17 @@ docker run -it --rm --name dsm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMI
|
||||
```
|
||||
|
||||
Replace the example path `/var/dsm` with the desired storage folder.
|
||||
|
||||
* ### How do I change the size of the disk?
|
||||
|
||||
To expand the default size of 16 GB, locate the `DISK_SIZE` setting in your compose file and modify it to your preferred capacity:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
DISK_SIZE: "128G"
|
||||
```
|
||||
|
||||
This can also be used to resize the existing disk to a larger capacity without any data loss.
|
||||
|
||||
* ### How do I create a growable disk?
|
||||
|
||||
@@ -114,14 +118,13 @@ docker run -it --rm --name dsm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMI
|
||||
It is possible to pass-through disk devices directly by adding them to your compose file in this way:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
DEVICE2: "/dev/sda"
|
||||
DEVICE3: "/dev/sdb"
|
||||
devices:
|
||||
- /dev/sda
|
||||
- /dev/sdb
|
||||
- /dev/disk/by-uuid/12345-12345-12345-12345-12345:/disk2
|
||||
- /dev/disk/by-uuid/45678-45678-45678-45678-45678:/disk3
|
||||
```
|
||||
|
||||
Make sure to bind the disk via its UUID (obtainable via `lsblk -o name,uuid`) instead of its name (`/dev/sdc`), to prevent ever binding the wrong disk when the drive letters happen to change.
|
||||
|
||||
Please note that the device needs to be totally empty (without any partition table) otherwise DSM does not always format it into a volume.
|
||||
|
||||
Do NOT use this feature with the goal of sharing files from the host, they will all be lost without warning when DSM creates the volume.
|
||||
@@ -130,7 +133,7 @@ docker run -it --rm --name dsm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMI
|
||||
|
||||
By default, a single CPU core and 1 GB of RAM are allocated to the container.
|
||||
|
||||
To increase this, add the following environment variables:
|
||||
If there arises a need to increase this, add the following environment variables:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
@@ -226,6 +229,15 @@ docker run -it --rm --name dsm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMI
|
||||
|
||||
With this method, it is even possible to switch between different versions while keeping all your file data intact.
|
||||
|
||||
If you don't have internet access, it's also possible to skip the download by setting URL to:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
URL: "DSM_VirtualDSM_42218.pat"
|
||||
```
|
||||
|
||||
after placing a file called `DSM_VirtualDSM_42218.pat` in your `/storage` folder.
|
||||
|
||||
* ### What are the differences compared to the standard DSM?
|
||||
|
||||
There are only two minor differences: the Virtual Machine Manager package is not available, and Surveillance Station will not include any free licenses.
|
||||
@@ -249,5 +261,5 @@ Only run this container on Synology hardware, any other use is not permitted by
|
||||
|
||||
[Build]: https://github.com/vdsm/virtual-dsm/actions/workflows/build.yml/badge.svg
|
||||
[Size]: https://img.shields.io/docker/image-size/vdsm/virtual-dsm/latest?color=066da5&label=size
|
||||
[Pulls]: https://img.shields.io/docker/pulls/kroese/virtual-dsm.svg?style=flat&label=pulls&logo=docker
|
||||
[Pulls]: https://img.shields.io/docker/pulls/vdsm/virtual-dsm.svg?style=flat&label=pulls&logo=docker
|
||||
[Version]: https://img.shields.io/docker/v/vdsm/virtual-dsm/latest?arch=amd64&sort=semver&color=066da5
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
set -Eeuo pipefail
|
||||
|
||||
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_FLAGS -smp $CPU_CORES,sockets=1,dies=1,cores=$CPU_CORES,threads=1"
|
||||
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"
|
||||
@@ -12,4 +12,26 @@ DEV_OPTS="$DEV_OPTS -device virtio-rng-pci,rng=objrng0,id=rng0,bus=pcie.0,addr=0
|
||||
ARGS="$DEF_OPTS $CPU_OPTS $RAM_OPTS $MAC_OPTS $DISPLAY_OPTS $MON_OPTS $SERIAL_OPTS $NET_OPTS $DISK_OPTS $DEV_OPTS $ARGUMENTS"
|
||||
ARGS=$(echo "$ARGS" | sed 's/\t/ /g' | tr -s ' ')
|
||||
|
||||
# Check available memory as the very last step
|
||||
|
||||
if [[ "$RAM_CHECK" != [Nn]* ]]; then
|
||||
|
||||
RAM_AVAIL=$(free -b | grep -m 1 Mem: | awk '{print $7}')
|
||||
AVAIL_GB=$(( RAM_AVAIL/1073741824 ))
|
||||
|
||||
if (( (RAM_WANTED + RAM_SPARE) > RAM_AVAIL )); then
|
||||
error "Your configured RAM_SIZE of $WANTED_GB GB is too high for the $AVAIL_GB GB of memory available, please set a lower value."
|
||||
exit 17
|
||||
fi
|
||||
|
||||
if (( (RAM_WANTED + (RAM_SPARE * 3)) > RAM_AVAIL )); then
|
||||
warn "your configured RAM_SIZE of $WANTED_GB GB is very close to the $AVAIL_GB GB of memory available, please consider a lower value."
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if [[ "$DEBUG" == [Yy1]* ]]; then
|
||||
printf "Arguments:\n\n%s" "${ARGS// -/$'\n-'}" && echo
|
||||
fi
|
||||
|
||||
return 0
|
||||
|
||||
152
src/disk.sh
152
src/disk.sh
@@ -5,6 +5,7 @@ set -Eeuo pipefail
|
||||
|
||||
: "${DISK_IO:="native"}" # I/O Mode, can be set to 'native', 'threads' or 'io_turing'
|
||||
: "${DISK_FMT:="raw"}" # Disk file format, 'raw' by default for best performance
|
||||
: "${DISK_TYPE:=""}" # Device type to be used, choose "ide", "usb", "blk" or "scsi"
|
||||
: "${DISK_FLAGS:=""}" # Specifies the options for use with the qcow2 disk format
|
||||
: "${DISK_CACHE:="none"}" # Caching mode, can be set to 'writeback' for better performance
|
||||
: "${DISK_DISCARD:="on"}" # Controls whether unmap (TRIM) commands are passed to the host.
|
||||
@@ -16,15 +17,6 @@ SYSTEM="$STORAGE/$BASE.system.img"
|
||||
[ ! -s "$BOOT" ] && error "Virtual DSM boot-image does not exist ($BOOT)" && exit 81
|
||||
[ ! -s "$SYSTEM" ] && error "Virtual DSM system-image does not exist ($SYSTEM)" && exit 82
|
||||
|
||||
DISK_OPTS="\
|
||||
-object iothread,id=io2 \
|
||||
-device virtio-scsi-pci,id=hw-synoboot,iothread=io2,bus=pcie.0,addr=0xa \
|
||||
-drive file=$BOOT,if=none,id=drive-synoboot,format=raw,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on \
|
||||
-device scsi-hd,bus=hw-synoboot.0,channel=0,scsi-id=0,lun=0,drive=drive-synoboot,id=synoboot0,rotation_rate=$DISK_ROTATION,bootindex=1 \
|
||||
-device virtio-scsi-pci,id=hw-synosys,iothread=io2,bus=pcie.0,addr=0xb \
|
||||
-drive file=$SYSTEM,if=none,id=drive-synosys,format=raw,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on \
|
||||
-device scsi-hd,bus=hw-synosys.0,channel=0,scsi-id=0,lun=0,drive=drive-synosys,id=synosys0,rotation_rate=$DISK_ROTATION,bootindex=2"
|
||||
|
||||
fmt2ext() {
|
||||
local DISK_FMT=$1
|
||||
|
||||
@@ -87,6 +79,16 @@ isCow() {
|
||||
return 1
|
||||
}
|
||||
|
||||
supportsDirect() {
|
||||
local FS=$1
|
||||
|
||||
if [[ "${FS,,}" == "ecryptfs" ]] || [[ "${FS,,}" == "tmpfs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
createDisk() {
|
||||
local DISK_FILE=$1
|
||||
local DISK_SPACE=$2
|
||||
@@ -113,9 +115,9 @@ createDisk() {
|
||||
fi
|
||||
|
||||
html "Creating a $DISK_DESC image..."
|
||||
info "Creating a $DISK_SPACE $DISK_TYPE $DISK_DESC image in $DISK_FMT format..."
|
||||
info "Creating a $DISK_SPACE $DISK_STYLE $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_STYLE $DISK_FMT $DISK_DESC image of $DISK_SPACE ($DISK_FILE)"
|
||||
|
||||
case "${DISK_FMT,,}" in
|
||||
raw)
|
||||
@@ -200,7 +202,7 @@ resizeDisk() {
|
||||
MSG="Resizing $DISK_DESC from ${GB}G to $DISK_SPACE..."
|
||||
info "$MSG" && html "$MSG"
|
||||
|
||||
local FAIL="Could not resize the $DISK_TYPE $DISK_FMT $DISK_DESC image from ${GB}G to $DISK_SPACE ($DISK_FILE)"
|
||||
local FAIL="Could not resize the $DISK_STYLE $DISK_FMT $DISK_DESC image from ${GB}G to $DISK_SPACE ($DISK_FILE)"
|
||||
|
||||
case "${DISK_FMT,,}" in
|
||||
raw)
|
||||
@@ -283,7 +285,7 @@ convertDisk() {
|
||||
# shellcheck disable=SC2086
|
||||
if ! qemu-img convert -f "$SOURCE_FMT" $CONV_FLAGS -o "$DISK_PARAM" -O "$DST_FMT" -- "$SOURCE_FILE" "$TMP_FILE"; then
|
||||
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_STYLE $DISK_DESC image to $DST_FMT format in $DIR, is there enough space available?" && exit 79
|
||||
fi
|
||||
|
||||
if [[ "$DST_FMT" == "raw" ]]; then
|
||||
@@ -329,6 +331,10 @@ checkFS () {
|
||||
info "Warning: the filesystem of $DIR is FUSE, this extra layer will negatively affect performance!"
|
||||
fi
|
||||
|
||||
if ! supportsDirect "$FS"; then
|
||||
info "Warning: the filesystem of $DIR is $FS, which does not support O_DIRECT mode, adjusting settings..."
|
||||
fi
|
||||
|
||||
if isCow "$FS"; then
|
||||
if [ -f "$DISK_FILE" ]; then
|
||||
FA=$(lsattr "$DISK_FILE")
|
||||
@@ -342,31 +348,59 @@ checkFS () {
|
||||
}
|
||||
|
||||
createDevice () {
|
||||
|
||||
local DISK_ID=$1
|
||||
local DISK_FILE=$2
|
||||
local DISK_FILE=$1
|
||||
local DISK_TYPE=$2
|
||||
local DISK_INDEX=$3
|
||||
local DISK_ADDRESS=$4
|
||||
local DISK_FMT=$5
|
||||
local DISK_IO=$6
|
||||
local DISK_CACHE=$7
|
||||
local DISK_ID="data$DISK_INDEX"
|
||||
|
||||
echo "-drive file=$DISK_FILE,if=none,id=drive-$DISK_ID,format=$DISK_FMT,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on \
|
||||
-device virtio-scsi-pci,id=hw-$DISK_ID,iothread=io2,bus=pcie.0,addr=$DISK_ADDRESS \
|
||||
-device scsi-hd,bus=hw-$DISK_ID.0,channel=0,scsi-id=0,lun=0,drive=drive-$DISK_ID,id=$DISK_ID,rotation_rate=$DISK_ROTATION,bootindex=$DISK_INDEX"
|
||||
local index=""
|
||||
[ -n "$DISK_INDEX" ] && index=",bootindex=$DISK_INDEX"
|
||||
local result="-drive file=$DISK_FILE,id=$DISK_ID,if=none,format=$DISK_FMT,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on"
|
||||
|
||||
case "${DISK_TYPE,,}" in
|
||||
"usb" )
|
||||
result="$result \
|
||||
-device usb-storage,drive=${DISK_ID}${index}"
|
||||
;;
|
||||
"ide" )
|
||||
result="$result \
|
||||
-device ide-hd,drive=${DISK_ID},bus=ide.$DISK_INDEX,rotation_rate=$DISK_ROTATION${index}"
|
||||
echo "$result"
|
||||
;;
|
||||
"blk" | "virtio-blk" )
|
||||
result="$result \
|
||||
-device virtio-blk-pci,drive=${DISK_ID},scsi=off,bus=pcie.0,addr=$DISK_ADDRESS,iothread=io2${index}"
|
||||
echo "$result"
|
||||
;;
|
||||
"scsi" | "virtio-scsi" )
|
||||
result="$result \
|
||||
-device virtio-scsi-pci,id=${DISK_ID}b,bus=pcie.0,addr=$DISK_ADDRESS,iothread=io2 \
|
||||
-device scsi-hd,drive=${DISK_ID},bus=${DISK_ID}b.0,channel=0,scsi-id=0,lun=0,rotation_rate=$DISK_ROTATION${index}"
|
||||
echo "$result"
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
addDisk () {
|
||||
local DISK_ID=$1
|
||||
local DISK_BASE=$2
|
||||
local DISK_EXT=$3
|
||||
local DISK_DESC=$4
|
||||
local DISK_SPACE=$5
|
||||
local DISK_INDEX=$6
|
||||
local DISK_ADDRESS=$7
|
||||
local DISK_FMT=$8
|
||||
local DISK_BASE=$1
|
||||
local DISK_TYPE=$2
|
||||
local DISK_DESC=$3
|
||||
local DISK_SPACE=$4
|
||||
local DISK_INDEX=$5
|
||||
local DISK_ADDRESS=$6
|
||||
local DISK_FMT=$7
|
||||
local DISK_IO=$8
|
||||
local DISK_CACHE=$9
|
||||
local DISK_EXT DIR DATA_SIZE FS PREV_FMT PREV_EXT CUR_SIZE OPTS
|
||||
|
||||
DISK_EXT=$(fmt2ext "$DISK_FMT")
|
||||
local DISK_FILE="$DISK_BASE.$DISK_EXT"
|
||||
local DIR DATA_SIZE FS PREV_FMT PREV_EXT CUR_SIZE OPTS
|
||||
|
||||
DIR=$(dirname "$DISK_FILE")
|
||||
[ ! -d "$DIR" ] && return 0
|
||||
@@ -386,6 +420,11 @@ addDisk () {
|
||||
FS=$(stat -f -c %T "$DIR")
|
||||
checkFS "$FS" "$DISK_FILE" "$DISK_DESC" || exit $?
|
||||
|
||||
if ! supportsDirect "$FS"; then
|
||||
DISK_IO="threads"
|
||||
DISK_CACHE="writeback"
|
||||
fi
|
||||
|
||||
if ! [ -s "$DISK_FILE" ] ; then
|
||||
|
||||
if [[ "${DISK_FMT,,}" != "raw" ]]; then
|
||||
@@ -414,25 +453,23 @@ addDisk () {
|
||||
|
||||
fi
|
||||
|
||||
OPTS=$(createDevice "$DISK_ID" "$DISK_FILE" "$DISK_INDEX" "$DISK_ADDRESS" "$DISK_FMT")
|
||||
OPTS=$(createDevice "$DISK_FILE" "$DISK_TYPE" "$DISK_INDEX" "$DISK_ADDRESS" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE")
|
||||
DISK_OPTS="$DISK_OPTS $OPTS"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
addDevice () {
|
||||
|
||||
local DISK_ID=$1
|
||||
local DISK_DEV=$2
|
||||
local DISK_DESC=$3
|
||||
local DISK_INDEX=$4
|
||||
local DISK_ADDRESS=$5
|
||||
local DISK_DEV=$1
|
||||
local DISK_TYPE=$2
|
||||
local DISK_INDEX=$3
|
||||
local DISK_ADDRESS=$4
|
||||
|
||||
[ -z "$DISK_DEV" ] && return 0
|
||||
[ ! -b "$DISK_DEV" ] && error "Device $DISK_DEV cannot be found! Please add it to the 'devices' section of your compose file." && exit 55
|
||||
|
||||
local OPTS
|
||||
OPTS=$(createDevice "$DISK_ID" "$DISK_DEV" "$DISK_INDEX" "$DISK_ADDRESS" "raw")
|
||||
OPTS=$(createDevice "$DISK_DEV" "$DISK_TYPE" "$DISK_INDEX" "$DISK_ADDRESS" "raw" "$DISK_IO" "$DISK_CACHE")
|
||||
DISK_OPTS="$DISK_OPTS $OPTS"
|
||||
|
||||
return 0
|
||||
@@ -440,7 +477,11 @@ addDevice () {
|
||||
|
||||
html "Initializing disks..."
|
||||
|
||||
DISK_EXT=$(fmt2ext "$DISK_FMT")
|
||||
case "${DISK_TYPE,,}" in
|
||||
"" ) DISK_TYPE="scsi" ;;
|
||||
"ide" | "usb" | "blk" | "scsi" ) ;;
|
||||
* ) error "Invalid DISK_TYPE, value \"$DISK_TYPE\" is unrecognized!" && exit 80 ;;
|
||||
esac
|
||||
|
||||
if [ -z "$ALLOCATE" ]; then
|
||||
if [[ "${DISK_FMT,,}" == "raw" ]]; then
|
||||
@@ -451,13 +492,17 @@ if [ -z "$ALLOCATE" ]; then
|
||||
fi
|
||||
|
||||
if [[ "$ALLOCATE" == [Nn]* ]]; then
|
||||
DISK_TYPE="growable"
|
||||
DISK_STYLE="growable"
|
||||
DISK_ALLOC="preallocation=off"
|
||||
else
|
||||
DISK_TYPE="preallocated"
|
||||
DISK_STYLE="preallocated"
|
||||
DISK_ALLOC="preallocation=falloc"
|
||||
fi
|
||||
|
||||
DISK_OPTS=$(createDevice "$BOOT" "$DISK_TYPE" "1" "0xa" "raw" "$DISK_IO" "$DISK_CACHE")
|
||||
OPTS=$(createDevice "$SYSTEM" "$DISK_TYPE" "2" "0xb" "raw" "$DISK_IO" "$DISK_CACHE")
|
||||
DISK_OPTS="$DISK_OPTS $OPTS"
|
||||
|
||||
DISK1_FILE="$STORAGE/data"
|
||||
if [[ ! -f "$DISK1_FILE.img" ]] && [[ -f "$STORAGE/data${DISK_SIZE}.img" ]]; then
|
||||
# Fallback for legacy installs
|
||||
@@ -501,29 +546,42 @@ DISK4_FILE="/storage4/data4"
|
||||
: "${DEVICE3:=""}"
|
||||
: "${DEVICE4:=""}"
|
||||
|
||||
[ -z "$DEVICE" ] && [ -b "/disk" ] && DEVICE="/disk"
|
||||
[ -z "$DEVICE" ] && [ -b "/disk1" ] && DEVICE="/disk1"
|
||||
[ -z "$DEVICE2" ] && [ -b "/disk2" ] && DEVICE2="/disk2"
|
||||
[ -z "$DEVICE3" ] && [ -b "/disk3" ] && DEVICE3="/disk3"
|
||||
[ -z "$DEVICE4" ] && [ -b "/disk4" ] && DEVICE4="/disk4"
|
||||
|
||||
[ -z "$DEVICE" ] && [ -b "/dev/disk1" ] && DEVICE="/dev/disk1"
|
||||
[ -z "$DEVICE2" ] && [ -b "/dev/disk2" ] && DEVICE2="/dev/disk2"
|
||||
[ -z "$DEVICE3" ] && [ -b "/dev/disk3" ] && DEVICE3="/dev/disk3"
|
||||
[ -z "$DEVICE4" ] && [ -b "/dev/disk4" ] && DEVICE4="/dev/disk4"
|
||||
|
||||
if [ -n "$DEVICE" ]; then
|
||||
addDevice "userdata" "$DEVICE" "device" "3" "0xc" || exit $?
|
||||
addDevice "$DEVICE" "$DISK_TYPE" "3" "0xc" || exit $?
|
||||
else
|
||||
addDisk "userdata" "$DISK1_FILE" "$DISK_EXT" "disk" "$DISK_SIZE" "3" "0xc" "$DISK_FMT" || exit $?
|
||||
addDisk "$DISK1_FILE" "$DISK_TYPE" "disk" "$DISK_SIZE" "3" "0xc" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE" || exit $?
|
||||
fi
|
||||
|
||||
if [ -n "$DEVICE2" ]; then
|
||||
addDevice "userdata2" "$DEVICE2" "device2" "4" "0xd" || exit $?
|
||||
addDevice "$DEVICE2" "$DISK_TYPE" "4" "0xd" || exit $?
|
||||
else
|
||||
addDisk "userdata2" "$DISK2_FILE" "$DISK_EXT" "disk2" "$DISK2_SIZE" "4" "0xd" "$DISK_FMT" || exit $?
|
||||
addDisk "$DISK2_FILE" "$DISK_TYPE" "disk2" "$DISK2_SIZE" "4" "0xd" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE" || exit $?
|
||||
fi
|
||||
|
||||
if [ -n "$DEVICE3" ]; then
|
||||
addDevice "userdata3" "$DEVICE3" "device3" "5" "0xe" || exit $?
|
||||
addDevice "$DEVICE3" "$DISK_TYPE" "5" "0xe" || exit $?
|
||||
else
|
||||
addDisk "userdata3" "$DISK3_FILE" "$DISK_EXT" "disk3" "$DISK3_SIZE" "5" "0xe" "$DISK_FMT" || exit $?
|
||||
addDisk "$DISK3_FILE" "$DISK_TYPE" "disk3" "$DISK3_SIZE" "5" "0xe" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE" || exit $?
|
||||
fi
|
||||
|
||||
if [ -n "$DEVICE4" ]; then
|
||||
addDevice "userdata4" "$DEVICE4" "device4" "6" "0xf" || exit $?
|
||||
addDevice "$DEVICE4" "$DISK_TYPE" "6" "0xf" || exit $?
|
||||
else
|
||||
addDisk "userdata4" "$DISK4_FILE" "$DISK_EXT" "disk4" "$DISK4_SIZE" "6" "0xf" "$DISK_FMT" || exit $?
|
||||
addDisk "$DISK4_FILE" "$DISK_TYPE" "disk4" "$DISK4_SIZE" "6" "0xf" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE" || exit $?
|
||||
fi
|
||||
|
||||
DISK_OPTS="$DISK_OPTS -object iothread,id=io2"
|
||||
|
||||
html "Initialized disks successfully..."
|
||||
return 0
|
||||
|
||||
@@ -18,8 +18,7 @@ cd /run
|
||||
|
||||
trap - ERR
|
||||
|
||||
info "Booting $APP using $VERS..."
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Arguments: $ARGS" && echo
|
||||
info "Booting ${APP}..."
|
||||
|
||||
if [[ "$CONSOLE" == [Yy]* ]]; then
|
||||
exec qemu-system-x86_64 ${ARGS:+ $ARGS}
|
||||
|
||||
@@ -18,6 +18,13 @@ if [ -n "$URL" ]; then
|
||||
: "${BASE//+/ }"; printf -v BASE '%b' "${_//%/\\x}"
|
||||
BASE=$(echo "$BASE" | sed -e 's/[^A-Za-z0-9._-]/_/g')
|
||||
fi
|
||||
if [[ "${URL,,}" != "http"* ]]; then
|
||||
if [ -s "$STORAGE/$BASE.pat" ]; then
|
||||
URL="file://$STORAGE/$BASE.pat"
|
||||
else
|
||||
error "File $STORAGE/$BASE.pat does not exist!" && exit 65
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -s "$STORAGE/$BASE.boot.img" ]] && [[ -s "$STORAGE/$BASE.system.img" ]]; then
|
||||
@@ -53,8 +60,6 @@ rm -f "$STORAGE/$BASE.agent"
|
||||
rm -f "$STORAGE/$BASE.boot.img"
|
||||
rm -f "$STORAGE/$BASE.system.img"
|
||||
|
||||
[[ "$DEBUG" == [Yy1]* ]] && set -x
|
||||
|
||||
# Check filesystem
|
||||
FS=$(stat -f -c %T "$STORAGE")
|
||||
|
||||
@@ -66,6 +71,10 @@ if [[ "${FS,,}" == "fuse"* ]]; then
|
||||
info "Warning: the filesystem of $STORAGE is FUSE, this extra layer will negatively affect performance!"
|
||||
fi
|
||||
|
||||
if [[ "${FS,,}" == "ecryptfs" ]] || [[ "${FS,,}" == "tmpfs" ]]; then
|
||||
info "Warning: the filesystem of $STORAGE is $FS, which does not support O_DIRECT mode, adjusting settings..."
|
||||
fi
|
||||
|
||||
if [[ "${FS,,}" == "fat"* || "${FS,,}" == "vfat"* || "${FS,,}" == "msdos"* ]]; then
|
||||
error "Unable to install on $FS filesystems, please use a different filesystem for /storage." && exit 61
|
||||
fi
|
||||
@@ -105,28 +114,45 @@ fi
|
||||
# Download the required files from the Synology website
|
||||
|
||||
ROOT="Y"
|
||||
RD="$TMP/rd.gz"
|
||||
RDC="$STORAGE/dsm.rd"
|
||||
|
||||
if [ ! -s "$RDC" ] && [[ "$URL" == "file://"* ]] && [[ "${URL,,}" == *"_42218.pat" ]]; then
|
||||
|
||||
rm -f "$RD"
|
||||
rm -f "$RDC"
|
||||
|
||||
tar --extract --file="${URL:7}" --directory="$(dirname "$RD")"/. "$(basename "$RD")"
|
||||
cp "$RD" "$RDC"
|
||||
|
||||
fi
|
||||
|
||||
if [ ! -s "$RDC" ]; then
|
||||
|
||||
rm -f "$RD"
|
||||
rm -f "$RDC"
|
||||
|
||||
MSG="Downloading installer..."
|
||||
PRG="Downloading installer ([P])..."
|
||||
info "Install: $MSG" && html "$MSG"
|
||||
|
||||
RD="$TMP/rd.gz"
|
||||
SIZE=5394188
|
||||
POS="65627648-71021835"
|
||||
VERIFY="b4215a4b213ff5154db0488f92c87864"
|
||||
LOC="$DL/release/7.0.1/42218/DSM_VirtualDSM_42218.pat"
|
||||
[[ "${URL,,}" == *"_42218.pat" ]] && LOC="$URL"
|
||||
|
||||
rm -f "$RD"
|
||||
rm -f "$RDC"
|
||||
/run/progress.sh "$RD" "$PRG" &
|
||||
{ curl -r "$POS" -sfk -S -o "$RD" "$LOC"; rc=$?; } || :
|
||||
/run/progress.sh "$RD" "$SIZE" "$PRG" &
|
||||
{ curl -r "$POS" -sfk --connect-timeout 10 -S -o "$RD" "$LOC"; rc=$?; } || :
|
||||
|
||||
fKill "progress.sh"
|
||||
|
||||
(( rc == 4 )) && error "Failed to download $LOC , network failure!" && exit 60
|
||||
|
||||
if (( rc != 0 )); then
|
||||
(( rc != 22 )) && error "Failed to download $LOC, reason: $rc" && exit 60
|
||||
if (( rc != 22 )) && (( rc != 56 )); then
|
||||
error "Failed to download $LOC, reason: $rc" && exit 60
|
||||
fi
|
||||
SUM="skip"
|
||||
else
|
||||
SUM=$(md5sum "$RD" | cut -f 1 -d " ")
|
||||
@@ -135,14 +161,17 @@ if [ ! -s "$RDC" ]; then
|
||||
if [ "$SUM" != "$VERIFY" ]; then
|
||||
|
||||
PAT="/install.pat"
|
||||
SIZE=379637760
|
||||
|
||||
rm -f "$RD"
|
||||
rm -f "$PAT"
|
||||
|
||||
html "$MSG"
|
||||
/run/progress.sh "$PAT" "$PRG" &
|
||||
{ wget "$LOC" -O "$PAT" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || :
|
||||
/run/progress.sh "$PAT" "$SIZE" "$PRG" &
|
||||
{ wget "$LOC" -O "$PAT" -q --no-check-certificate --timeout=10 --show-progress "$PROGRESS"; rc=$?; } || :
|
||||
|
||||
fKill "progress.sh"
|
||||
(( rc == 4 )) && error "Failed to download $LOC , network failure!" && exit 60
|
||||
(( rc != 0 )) && error "Failed to download $LOC , reason: $rc" && exit 60
|
||||
|
||||
tar --extract --file="$PAT" --directory="$(dirname "$RD")"/. "$(basename "$RD")"
|
||||
@@ -208,11 +237,16 @@ if [[ "$URL" == "file://"* ]]; then
|
||||
|
||||
else
|
||||
|
||||
/run/progress.sh "$PAT" "$PRG" &
|
||||
SIZE=0
|
||||
[[ "${URL,,}" == *"_69057.pat" ]] && SIZE=363837333
|
||||
[[ "${URL,,}" == *"_42218.pat" ]] && SIZE=379637760
|
||||
|
||||
{ wget "$URL" -O "$PAT" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || :
|
||||
/run/progress.sh "$PAT" "$SIZE" "$PRG" &
|
||||
|
||||
{ wget "$URL" -O "$PAT" -q --no-check-certificate --timeout=10 --show-progress "$PROGRESS"; rc=$?; } || :
|
||||
|
||||
fKill "progress.sh"
|
||||
(( rc == 4 )) && error "Failed to download $URL , network failure!" && exit 69
|
||||
(( rc != 0 )) && error "Failed to download $URL , reason: $rc" && exit 69
|
||||
|
||||
fi
|
||||
@@ -363,8 +397,5 @@ fi
|
||||
mv -f "$BOOT" "$STORAGE/$BASE.boot.img"
|
||||
rm -rf "$TMP"
|
||||
|
||||
{ set +x; } 2>/dev/null
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo
|
||||
|
||||
html "Installation finished successfully..."
|
||||
return 0
|
||||
|
||||
@@ -6,10 +6,12 @@ set -Eeuo pipefail
|
||||
: "${MAC:=""}"
|
||||
: "${DHCP:="N"}"
|
||||
: "${NETWORK:="Y"}"
|
||||
: "${HOST_PORTS:=""}"
|
||||
|
||||
: "${VM_NET_DEV:=""}"
|
||||
: "${VM_NET_TAP:="dsm"}"
|
||||
: "${VM_NET_MAC:="$MAC"}"
|
||||
: "${VM_NET_IP:="20.20.20.21"}"
|
||||
: "${VM_NET_HOST:="VirtualDSM"}"
|
||||
|
||||
: "${DNSMASQ_OPTS:=""}"
|
||||
@@ -35,8 +37,8 @@ configureDHCP() {
|
||||
{ ip link add link "$VM_NET_DEV" name "$VM_NET_TAP" address "$VM_NET_MAC" type macvtap mode bridge ; rc=$?; } || :
|
||||
|
||||
if (( rc != 0 )); then
|
||||
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: --cap-add NET_ADMIN" && exit 16
|
||||
error "Cannot create macvtap interface. Please make sure that the network type is 'macvlan' and not 'ipvlan',"
|
||||
error "that your kernel is recent (>4) and supports it, and that the container has the NET_ADMIN capability set." && exit 16
|
||||
fi
|
||||
|
||||
while ! ip link set "$VM_NET_TAP" up; do
|
||||
@@ -103,6 +105,21 @@ configureDNS() {
|
||||
return 0
|
||||
}
|
||||
|
||||
getPorts() {
|
||||
|
||||
local list=$1
|
||||
|
||||
[ -z "$list" ] && echo "" && return 0
|
||||
|
||||
if [[ "$list" != *","* ]]; then
|
||||
echo " ! --dport $list"
|
||||
else
|
||||
echo " -m multiport ! --dports $list"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
configureNAT() {
|
||||
|
||||
# Create the necessary file structure for /dev/net/tun
|
||||
@@ -119,15 +136,16 @@ configureNAT() {
|
||||
|
||||
# Check port forwarding flag
|
||||
if [[ $(< /proc/sys/net/ipv4/ip_forward) -eq 0 ]]; then
|
||||
{ sysctl -w net.ipv4.ip_forward=1 ; rc=$?; } || :
|
||||
if (( rc != 0 )); then
|
||||
{ sysctl -w net.ipv4.ip_forward=1 > /dev/null; rc=$?; } || :
|
||||
if (( rc != 0 )) || [[ $(< /proc/sys/net/ipv4/ip_forward) -eq 0 ]]; then
|
||||
error "IP forwarding is disabled. $ADD_ERR --sysctl net.ipv4.ip_forward=1" && exit 24
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create a bridge with a static IP for the VM guest
|
||||
local tables="The 'ip_tables' kernel module is not loaded. Try this command: sudo modprobe ip_tables iptable_nat"
|
||||
local tuntap="The 'tun' kernel module is not available. Try this command: 'sudo modprobe tun' or run the container with 'privileged: true'."
|
||||
|
||||
VM_NET_IP='20.20.20.21'
|
||||
# Create a bridge with a static IP for the VM guest
|
||||
|
||||
{ ip link add dev dockerbridge type bridge ; rc=$?; } || :
|
||||
|
||||
@@ -135,7 +153,7 @@ configureNAT() {
|
||||
error "Failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && exit 23
|
||||
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
|
||||
|
||||
while ! ip link set dockerbridge up; do
|
||||
info "Waiting for IP address to become available..."
|
||||
@@ -143,7 +161,9 @@ configureNAT() {
|
||||
done
|
||||
|
||||
# QEMU Works with taps, set tap to the bridge created
|
||||
ip tuntap add dev "$VM_NET_TAP" mode tap
|
||||
if ! ip tuntap add dev "$VM_NET_TAP" mode tap; then
|
||||
error "$tuntap" && exit 31
|
||||
fi
|
||||
|
||||
while ! ip link set "$VM_NET_TAP" up promisc on; do
|
||||
info "Waiting for TAP to become available..."
|
||||
@@ -156,13 +176,19 @@ configureNAT() {
|
||||
update-alternatives --set iptables /usr/sbin/iptables-legacy > /dev/null
|
||||
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy > /dev/null
|
||||
|
||||
iptables -t nat -A POSTROUTING -o "$VM_NET_DEV" -j MASQUERADE
|
||||
iptables -t nat -A PREROUTING -i "$VM_NET_DEV" -d "$IP" -p tcp -j DNAT --to "$VM_NET_IP"
|
||||
exclude=$(getPorts "$HOST_PORTS")
|
||||
|
||||
if ! iptables -t nat -A POSTROUTING -o "$VM_NET_DEV" -j MASQUERADE; then
|
||||
error "$tables" && exit 30
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
iptables -t nat -A PREROUTING -i "$VM_NET_DEV" -d "$IP" -p tcp${exclude} -j DNAT --to "$VM_NET_IP"
|
||||
iptables -t nat -A PREROUTING -i "$VM_NET_DEV" -d "$IP" -p udp -j DNAT --to "$VM_NET_IP"
|
||||
|
||||
if (( KERNEL > 4 )); then
|
||||
# Hack for guest VMs complaining about "bad udp checksums in 5 packets"
|
||||
iptables -A POSTROUTING -t mangle -p udp --dport bootpc -j CHECKSUM --checksum-fill || true
|
||||
iptables -A POSTROUTING -t mangle -p udp --dport bootpc -j CHECKSUM --checksum-fill > /dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
NET_OPTS="-netdev tap,ifname=$VM_NET_TAP,script=no,downscript=no,id=hostnet0"
|
||||
@@ -213,11 +239,33 @@ closeNetwork() {
|
||||
return 0
|
||||
}
|
||||
|
||||
checkOS() {
|
||||
|
||||
local name
|
||||
local os=""
|
||||
name=$(uname -a)
|
||||
|
||||
[[ "${name,,}" == *"darwin"* ]] && os="MacOS"
|
||||
[[ "${name,,}" == *"microsoft"* ]] && os="Windows"
|
||||
|
||||
if [ -n "$os" ]; then
|
||||
error "You are using Docker Desktop for $os which does not support macvlan, please revert to bridge networking!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
getInfo() {
|
||||
|
||||
if [ -z "$VM_NET_DEV" ]; then
|
||||
# Give Kubernetes priority over the default interface
|
||||
[ -d "/sys/class/net/net0" ] && VM_NET_DEV="net0"
|
||||
[ -d "/sys/class/net/net1" ] && VM_NET_DEV="net1"
|
||||
[ -d "/sys/class/net/net2" ] && VM_NET_DEV="net2"
|
||||
[ -d "/sys/class/net/net3" ] && VM_NET_DEV="net3"
|
||||
# Automaticly detect the default network interface
|
||||
VM_NET_DEV=$(awk '$2 == 00000000 { print $1 }' /proc/net/route)
|
||||
[ -z "$VM_NET_DEV" ] && VM_NET_DEV=$(awk '$2 == 00000000 { print $1 }' /proc/net/route)
|
||||
[ -z "$VM_NET_DEV" ] && VM_NET_DEV="eth0"
|
||||
fi
|
||||
|
||||
@@ -248,7 +296,7 @@ getInfo() {
|
||||
error "Invalid MAC address: '$VM_NET_MAC', should be 12 or 17 digits long!" && exit 28
|
||||
fi
|
||||
|
||||
GATEWAY=$(ip r | grep default | awk '{print $3}')
|
||||
GATEWAY=$(ip route list dev "$VM_NET_DEV" | awk ' /^default/ {print $3}')
|
||||
IP=$(ip address show dev "$VM_NET_DEV" | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/)
|
||||
echo "$IP" > /run/shm/qemu.ip
|
||||
|
||||
@@ -273,10 +321,16 @@ if [[ "$DEBUG" == [Yy1]* ]]; then
|
||||
echo
|
||||
fi
|
||||
|
||||
if [[ "$IP" == "172.17."* ]]; then
|
||||
warn "your container IP starts with 172.17.* which will cause conflicts when you install the Container Manager package inside DSM!"
|
||||
fi
|
||||
|
||||
if [[ "$DHCP" == [Yy1]* ]]; then
|
||||
|
||||
if [[ "$GATEWAY" == "172."* ]] && [[ "$DEBUG" != [Yy1]* ]]; then
|
||||
error "You can only enable DHCP while the container is on a macvlan network!" && exit 26
|
||||
! checkOS && exit 19
|
||||
|
||||
if [[ "$GATEWAY" == "172."* ]]; then
|
||||
warn "your gateway IP starts with 172.* which is often a sign that you are not on a macvlan network (required for DHCP)!"
|
||||
fi
|
||||
|
||||
# Configuration for DHCP IP
|
||||
@@ -287,6 +341,10 @@ if [[ "$DHCP" == [Yy1]* ]]; then
|
||||
|
||||
else
|
||||
|
||||
if [[ "$GATEWAY" != "172."* ]] && [[ "$GATEWAY" != "10."* ]]; then
|
||||
! checkOS && exit 19
|
||||
fi
|
||||
|
||||
# Shutdown nginx
|
||||
nginx -s stop 2> /dev/null
|
||||
fWait "nginx"
|
||||
|
||||
@@ -10,10 +10,11 @@ API_HOST="127.0.0.1:2210"
|
||||
QEMU_TERM=""
|
||||
QEMU_PORT=7100
|
||||
QEMU_TIMEOUT=50
|
||||
QEMU_PID="/run/shm/qemu.pid"
|
||||
QEMU_LOG="/run/shm/qemu.log"
|
||||
QEMU_OUT="/run/shm/qemu.out"
|
||||
QEMU_END="/run/shm/qemu.end"
|
||||
QEMU_DIR="/run/shm"
|
||||
QEMU_PID="$QEMU_DIR/qemu.pid"
|
||||
QEMU_LOG="$QEMU_DIR/qemu.log"
|
||||
QEMU_OUT="$QEMU_DIR/qemu.out"
|
||||
QEMU_END="$QEMU_DIR/qemu.end"
|
||||
|
||||
if [[ "$KVM" == [Nn]* ]]; then
|
||||
API_TIMEOUT=$(( API_TIMEOUT*2 ))
|
||||
|
||||
26
src/proc.sh
26
src/proc.sh
@@ -9,7 +9,10 @@ set -Eeuo pipefail
|
||||
: "${CPU_MODEL:=""}"
|
||||
: "${DEF_MODEL:="qemu64"}"
|
||||
|
||||
[ "$ARCH" != "amd64" ] && KVM="N"
|
||||
if [[ "${ARCH,,}" != "amd64" ]]; then
|
||||
KVM="N"
|
||||
warn "your CPU architecture is ${ARCH^^} and cannot provide KVM acceleration for x64 instructions, this will cause a major loss of performance."
|
||||
fi
|
||||
|
||||
if [[ "$KVM" != [Nn]* ]]; then
|
||||
|
||||
@@ -21,7 +24,8 @@ if [[ "$KVM" != [Nn]* ]]; then
|
||||
if ! sh -c 'echo -n > /dev/kvm' &> /dev/null; then
|
||||
KVM_ERR="(no write access)"
|
||||
else
|
||||
if ! grep -q -e vmx -e svm /proc/cpuinfo; then
|
||||
flags=$(sed -ne '/^flags/s/^.*: //p' /proc/cpuinfo)
|
||||
if ! grep -qw "vmx\|svm" <<< "$flags"; then
|
||||
KVM_ERR="(vmx/svm disabled)"
|
||||
fi
|
||||
fi
|
||||
@@ -29,9 +33,17 @@ if [[ "$KVM" != [Nn]* ]]; then
|
||||
|
||||
if [ -n "$KVM_ERR" ]; then
|
||||
KVM="N"
|
||||
error "KVM acceleration not available $KVM_ERR, this will cause a major loss of performance."
|
||||
error "See the FAQ on how to enable it, or continue without KVM by setting KVM=N (not recommended)."
|
||||
[[ "$DEBUG" != [Yy1]* ]] && exit 88
|
||||
if [[ "$OSTYPE" =~ ^darwin ]]; then
|
||||
warn "you are using MacOS which has no KVM support, this will cause a major loss of performance."
|
||||
else
|
||||
if grep -qi Microsoft /proc/version; then
|
||||
warn "you are using Windows 10 which has no KVM support, this will cause a major loss of performance."
|
||||
else
|
||||
error "KVM acceleration not available $KVM_ERR, this will cause a major loss of performance."
|
||||
error "See the FAQ on how to enable it, or continue without KVM by setting KVM=N (not recommended)."
|
||||
[[ "$DEBUG" != [Yy1]* ]] && exit 88
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
@@ -41,7 +53,7 @@ if [[ "$KVM" != [Nn]* ]]; then
|
||||
CPU_FEATURES="kvm=on,l3-cache=on"
|
||||
KVM_OPTS=",accel=kvm -enable-kvm -global kvm-pit.lost_tick_policy=discard"
|
||||
|
||||
if ! grep -qE '^flags.* (sse4_2)' /proc/cpuinfo; then
|
||||
if ! grep -qw "sse4_2" <<< "$flags"; then
|
||||
info "Your CPU does not have the SSE4 instruction set that Virtual DSM requires, it will be emulated..."
|
||||
[ -z "$CPU_MODEL" ] && CPU_MODEL="$DEF_MODEL"
|
||||
CPU_FEATURES="$CPU_FEATURES,+ssse3,+sse4.1,+sse4.2"
|
||||
@@ -89,7 +101,7 @@ else
|
||||
fi
|
||||
|
||||
if [ -z "$HOST_CPU" ]; then
|
||||
HOST_CPU=$(lscpu | grep 'Model name' | cut -f 2 -d ":" | awk '{$1=$1}1' | sed 's# @.*##g' | sed s/"(R)"//g | sed 's/[^[:alnum:] ]\+/ /g' | sed 's/ */ /g')
|
||||
HOST_CPU=$(lscpu | grep -m 1 'Model name' | cut -f 2 -d ":" | awk '{$1=$1}1' | sed 's# @.*##g' | sed s/"(R)"//g | sed 's/[^[:alnum:] ]\+/ /g' | sed 's/ */ /g')
|
||||
fi
|
||||
|
||||
if [ -n "$HOST_CPU" ]; then
|
||||
|
||||
@@ -12,7 +12,8 @@ escape () {
|
||||
}
|
||||
|
||||
file="$1"
|
||||
body=$(escape "$2")
|
||||
total="$2"
|
||||
body=$(escape "$3")
|
||||
info="/run/shm/msg.html"
|
||||
|
||||
if [[ "$body" == *"..." ]]; then
|
||||
@@ -24,7 +25,12 @@ do
|
||||
if [ -s "$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/')
|
||||
if [ -z "$total" ] || [[ "$total" == "0" ]]; then
|
||||
size=$(numfmt --to=iec --suffix=B "$bytes" | sed -r 's/([A-Z])/ \1/')
|
||||
else
|
||||
size=$(printf '%.1f\n' "$((bytes*100*100/total))e-2")
|
||||
size="$size%"
|
||||
fi
|
||||
echo "${body//(\[P\])/($size)}"> "$info"
|
||||
fi
|
||||
fi
|
||||
|
||||
51
src/reset.sh
51
src/reset.sh
@@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "$1" "\E[0m\n"; }
|
||||
error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: $1" "\E[0m\n" >&2; }
|
||||
warn () { printf "%b%s%b" "\E[1;31m❯ " "Warning: $1" "\E[0m\n" >&2; }
|
||||
info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "${1:-}" "\E[0m\n"; }
|
||||
error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: ${1:-}" "\E[0m\n" >&2; }
|
||||
warn () { printf "%b%s%b" "\E[1;31m❯ " "Warning: ${1:-}" "\E[0m\n" >&2; }
|
||||
|
||||
trap 'error "Status $? while: $BASH_COMMAND (line $LINENO/$BASH_LINENO)"' ERR
|
||||
|
||||
@@ -12,7 +12,6 @@ trap 'error "Status $? while: $BASH_COMMAND (line $LINENO/$BASH_LINENO)"' ERR
|
||||
|
||||
echo "❯ Starting $APP for Docker v$(</run/version)..."
|
||||
echo "❯ For support visit $SUPPORT"
|
||||
echo
|
||||
|
||||
# Docker environment variables
|
||||
|
||||
@@ -24,6 +23,7 @@ echo
|
||||
: "${ARGUMENTS:=""}" # Extra QEMU parameters
|
||||
: "${CPU_CORES:="1"}" # Amount of CPU cores
|
||||
: "${RAM_SIZE:="1G"}" # Maximum RAM amount
|
||||
: "${RAM_CHECK:="Y"}" # Check available RAM
|
||||
: "${DISK_SIZE:="16G"}" # Initial data disk size
|
||||
|
||||
# Helper variables
|
||||
@@ -38,11 +38,12 @@ TEMPLATE="/var/www/index.html"
|
||||
FOOTER1="$APP for Docker v$(</run/version)"
|
||||
FOOTER2="<a href='$SUPPORT'>$SUPPORT</a>"
|
||||
|
||||
SYS=$(uname -r)
|
||||
HOST=$(hostname -s)
|
||||
KERNEL=$(uname -r | cut -b 1)
|
||||
MINOR=$(uname -r | cut -d '.' -f2)
|
||||
KERNEL=$(echo "$SYS" | cut -b 1)
|
||||
MINOR=$(echo "$SYS" | cut -d '.' -f2)
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
VERS=$(qemu-system-x86_64 --version | head -n 1 | cut -d '(' -f 1)
|
||||
CPU=$(lscpu | grep -m 1 'Model name' | cut -f 2 -d ":" | awk '{$1=$1}1' | sed 's# @.*##g' | sed s/"(R)"//g | sed 's/[^[:alnum:] ]\+/ /g' | sed 's/ */ /g')
|
||||
|
||||
# Check system
|
||||
|
||||
@@ -58,6 +59,42 @@ if [ ! -d "$STORAGE" ]; then
|
||||
error "Storage folder ($STORAGE) not found!" && exit 13
|
||||
fi
|
||||
|
||||
# Check filesystem
|
||||
FS=$(stat -f -c %T "$STORAGE")
|
||||
|
||||
if [[ "${FS,,}" == "ecryptfs" ]] || [[ "${FS,,}" == "tmpfs" ]]; then
|
||||
DISK_IO="threads"
|
||||
DISK_CACHE="writeback"
|
||||
fi
|
||||
|
||||
# Read memory
|
||||
RAM_SPARE=500000000
|
||||
RAM_AVAIL=$(free -b | grep -m 1 Mem: | awk '{print $7}')
|
||||
RAM_TOTAL=$(free -b | grep -m 1 Mem: | awk '{print $2}')
|
||||
RAM_SIZE=$(echo "${RAM_SIZE^^}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
|
||||
RAM_WANTED=$(numfmt --from=iec "$RAM_SIZE")
|
||||
AVAIL_GB=$(( RAM_AVAIL/1073741824 ))
|
||||
TOTAL_GB=$(( (RAM_TOTAL + 1073741823)/1073741824 ))
|
||||
WANTED_GB=$(( (RAM_WANTED + 1073741823)/1073741824 ))
|
||||
|
||||
# Print system info
|
||||
SYS="${SYS/-generic/}"
|
||||
FS="${FS/ext2\/ext3/ext4}"
|
||||
SPACE=$(df --output=avail -B 1 "$STORAGE" | tail -n 1)
|
||||
SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))
|
||||
|
||||
echo "❯ CPU: ${CPU} | RAM: $AVAIL_GB/$TOTAL_GB GB | DISK: $SPACE_GB GB (${FS}) | HOST: ${SYS}..."
|
||||
echo
|
||||
|
||||
# Check memory
|
||||
|
||||
if [[ "$RAM_CHECK" != [Nn]* ]]; then
|
||||
if (( (RAM_WANTED + RAM_SPARE) > RAM_AVAIL )); then
|
||||
error "Your configured RAM_SIZE of $WANTED_GB GB is too high for the $AVAIL_GB GB of memory available, please set a lower value."
|
||||
exit 17
|
||||
fi
|
||||
fi
|
||||
|
||||
# Cleanup files
|
||||
rm -f /run/shm/qemu.*
|
||||
rm -f /run/shm/dsm.url
|
||||
|
||||
Reference in New Issue
Block a user