diff --git a/Dockerfile b/Dockerfile index a2e68ed..c5bc7cd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,11 @@ -FROM golang:1.20 AS builder - -COPY serial/ /src/serial/ -WORKDIR /src/serial - -RUN go get -d -v golang.org/x/net/html -RUN go get -d -v github.com/gorilla/mux -RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o /src/serial/main . - FROM debian:bookworm-20230320-slim RUN apt-get update && apt-get -y upgrade && \ apt-get --no-install-recommends -y install \ - jq \ - curl \ - cpio \ wget \ - unzip \ - procps \ dnsmasq \ iptables \ iproute2 \ - xz-utils \ - btrfs-progs \ bridge-utils \ netcat-openbsd \ ca-certificates \ @@ -31,43 +15,20 @@ RUN apt-get update && apt-get -y upgrade && \ COPY run.sh /run/ COPY disk.sh /run/ COPY power.sh /run/ -COPY serial.sh /run/ -COPY server.sh /run/ COPY install.sh /run/ COPY network.sh /run/ -COPY agent/agent.sh /agent/ -COPY agent/service.sh /agent/ - -COPY --from=builder /src/serial/main /run/serial.bin - RUN ["chmod", "+x", "/run/run.sh"] -RUN ["chmod", "+x", "/run/disk.sh"] -RUN ["chmod", "+x", "/run/power.sh"] -RUN ["chmod", "+x", "/run/serial.sh"] -RUN ["chmod", "+x", "/run/server.sh"] RUN ["chmod", "+x", "/run/install.sh"] -RUN ["chmod", "+x", "/run/network.sh"] -RUN ["chmod", "+x", "/run/serial.bin"] - -COPY disks/template.img.xz /data/ VOLUME /storage EXPOSE 22 -EXPOSE 80 -EXPOSE 139 -EXPOSE 443 -EXPOSE 445 -EXPOSE 5000 -EXPOSE 5001 ENV CPU_CORES 1 ENV DISK_SIZE 16G ENV RAM_SIZE 512M -#ENV URL https://global.synologydownload.com/download/DSM/beta/7.2/64216/DSM_VirtualDSM_64216.pat -#ENV URL https://global.synologydownload.com/download/DSM/release/7.0.1/42218/DSM_VirtualDSM_42218.pat -ENV URL https://global.synologydownload.com/download/DSM/release/7.1.1/42962-1/DSM_VirtualDSM_42962.pat +ENV BOOT https://ftp.halifax.rwth-aachen.de/osdn/clonezilla/78259/clonezilla-live-3.0.3-22-amd64.iso ENTRYPOINT ["/run/run.sh"] diff --git a/agent/agent.sh b/agent/agent.sh deleted file mode 100644 index 72656a5..0000000 --- a/agent/agent.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash -set -u - -declare nmi - -function checkNMI { - - nmi=$(cat /proc/interrupts | grep NMI) - nmi=$(echo "$nmi" | sed 's/[^0-9]*//g') - nmi=$(echo "$nmi" | sed 's/^0*//') - - if [ "$nmi" != "" ]; then - - echo "Received shutdown request through NMI.." > /dev/ttyS0 - - /usr/syno/sbin/synoshutdown -s > /dev/null - exit 0 - - fi - -} - -chmod 666 /dev/ttyS0 -checkNMI - -first_run=false - -for filename in /usr/local/packages/*.spk; do - if [ -f "$filename" ]; then - first_run=true - fi -done - -if [ "$first_run" = true ]; then - for filename in /usr/local/packages/*.spk; do - if [ -f "$filename" ]; then - - /usr/syno/bin/synopkg install "$filename" > /dev/null - - BASE=$(basename "$filename" .spk) - BASE="${BASE%%-*}" - - /usr/syno/bin/synopkg start "$BASE" > /dev/null - - rm "$filename" - - fi - done -else - - sleep 5 - -fi - -echo "-------------------------------------------" > /dev/ttyS0 -echo " You can now login to DSM at port 5000 " > /dev/ttyS0 -echo "-------------------------------------------" > /dev/ttyS0 - -while true; do - - checkNMI - sleep 1 - -done - diff --git a/agent/service.sh b/agent/service.sh deleted file mode 100644 index 4bf057d..0000000 --- a/agent/service.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -PIDFILE="/var/run/agent.pid" -LOGFILE="/var/log/agent.log" -SCRIPT="/usr/local/bin/agent.sh" - -status() { - if [ -f "$PIDFILE" ]; then - echo 'Service running' >&2 - return 1 - fi -} - -start() { - if [ -f "$PIDFILE" ] && kill -0 "$(cat "$PIDFILE")"; then - echo 'Service already running' >&2 - return 1 - fi - printf 'Starting agent service...' >&2 - "$SCRIPT" &> "$LOGFILE" & echo $! > "$PIDFILE" -} - -stop() { - if [ ! -f "$PIDFILE" ] || ! kill -0 "$(cat "$PIDFILE")"; then - echo 'Service not running' >&2 - return 1 - fi - echo 'Stopping agent service' >&2 - kill -15 "$(cat "$PIDFILE")" && rm -f "$PIDFILE" - echo 'Service stopped' >&2 -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status - ;; - restart) - stop - start - ;; - *) - echo "Usage: $0 {start|stop|restart}" -esac diff --git a/build.sh b/build.sh index a1911bf..a7242c2 100644 --- a/build.sh +++ b/build.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -e -docker build --tag dsm . -docker images dsm:latest --format "{{.Repository}}:{{.Tag}} -> {{.Size}}" -docker run --rm -it --name dsm --device="/dev/kvm" --cap-add NET_ADMIN -p 80:5000 -p 443:5001 -p 5000:5000 -p 5001:5001 docker.io/library/dsm +docker build --tag qemu . +docker images qemu:latest --format "{{.Repository}}:{{.Tag}} -> {{.Size}}" +docker run --rm -it --name qemu --device="/dev/kvm" --cap-add NET_ADMIN -p 80:80 docker.io/library/qemu diff --git a/disk.sh b/disk.sh index ae20646..aa59964 100644 --- a/disk.sh +++ b/disk.sh @@ -2,50 +2,21 @@ set -eu IMG="/storage" -BASE=$(basename "$URL" .pat) - -FILE="$IMG/$BASE.boot.img" -[ ! -f "$FILE" ] && echo "ERROR: Virtual DSM boot-image does not exist ($FILE)" && exit 81 - -FILE="$IMG/$BASE.system.img" -[ ! -f "$FILE" ] && echo "ERROR: Virtual DSM system-image does not exist ($FILE)" && exit 82 +FILE="$IMG/boot.img" +[ ! -f "$FILE" ] && echo "ERROR: Boot image does not exist ($FILE)" && exit 81 DISK_SIZE=$(echo "${DISK_SIZE}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g') NEW_SIZE=$(numfmt --from=iec "${DISK_SIZE}") -FILE="$IMG/data$DISK_SIZE.img" - -if [ ! -f "$FILE" ]; then - truncate -s "${NEW_SIZE}" "${FILE}" - mkfs.btrfs -q -L data -d single -m single "${FILE}" > /dev/null - #qemu-img convert -f raw -O qcow2 -o extended_l2=on,cluster_size=128k,compression_type=zstd,preallocation=metadata "$TMP" "$FILE" -fi - -[ ! -f "$FILE" ] && echo "ERROR: Virtual DSM data-image does not exist ($FILE)" && exit 83 - -#OLD_SIZE=$(stat -c%s "${FILE}") -# -#if [ "$NEW_SIZE" -ne "$OLD_SIZE" ]; then -# echo "Resizing data disk from $OLD_SIZE to $NEW_SIZE bytes" -# -# if [ "$NEW_SIZE" -gt "$OLD_SIZE" ]; then -# truncate -s "${NEW_SIZE}" "${FILE}" -# btrfs filesystem resize "${NEW_SIZE}" "${FILE}" -# fi -# -# if [ "$NEW_SIZE" -lt "$OLD_SIZE" ]; then -# btrfs filesystem resize "${NEW_SIZE}" "${FILE}" -# truncate -s "${NEW_SIZE}" "${FILE}" -# fi -#fi +FILE="$IMG/data${DISK_SIZE}.img" +[ ! -f "$FILE" ] && truncate -s "${NEW_SIZE}" "${FILE}" +[ ! -f "$FILE" ] && echo "ERROR: Data image does not exist ($FILE)" && exit 83 KVM_DISK_OPTS="\ - -device virtio-scsi-pci,id=hw-synoboot,bus=pcie.0,addr=0xa \ - -drive file=${IMG}/${BASE}.boot.img,if=none,id=drive-synoboot,format=raw,cache=none,aio=native,discard=on,detect-zeroes=on \ - -device scsi-hd,bus=hw-synoboot.0,channel=0,scsi-id=0,lun=0,drive=drive-synoboot,id=synoboot0,rotation_rate=1,bootindex=1 \ - -device virtio-scsi-pci,id=hw-synosys,bus=pcie.0,addr=0xb \ - -drive file=${IMG}/${BASE}.system.img,if=none,id=drive-synosys,format=raw,cache=none,aio=native,discard=on,detect-zeroes=on \ - -device scsi-hd,bus=hw-synosys.0,channel=0,scsi-id=0,lun=0,drive=drive-synosys,id=synosys0,rotation_rate=1,bootindex=2 \ - -device virtio-scsi-pci,id=hw-userdata,bus=pcie.0,addr=0xc \ + -device virtio-scsi-pci,id=hw-boot,bus=pcie.0,addr=0xa \ + -drive file=${IMG}/boot.img,if=none,id=drive-boot,format=raw,cache=none,aio=native,discard=on,detect-zeroes=on \ + -device scsi-hd,bus=hw-boot.0,channel=0,scsi-id=0,lun=0,drive=drive-boot,id=boot0,rotation_rate=1,bootindex=1 \ + -device virtio-scsi-pci,id=hw-userdata,bus=pcie.0,addr=0xb \ -drive file=${IMG}/data${DISK_SIZE}.img,if=none,id=drive-userdata,format=raw,cache=none,aio=native,discard=on,detect-zeroes=on \ - -device scsi-hd,bus=hw-userdata.0,channel=0,scsi-id=0,lun=0,drive=drive-userdata,id=userdata0,rotation_rate=1,bootindex=3" + -device scsi-hd,bus=hw-userdata.0,channel=0,scsi-id=0,lun=0,drive=drive-userdata,id=userdata0,rotation_rate=1,bootindex=2" + diff --git a/docker-compose.yml b/docker-compose.yml index 030bbcd..ace8937 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,18 +1,18 @@ version: "3" services: vm: - container_name: dsm - image: kroese/virtual-dsm:latest + container_name: qemu + image: kroese/docker-qemu:latest environment: CPU_CORES: "1" RAM_SIZE: "512M" - DISK_SIZE: "16G" + DISK_SIZE: "16G" + BOOT: "https://ftp.halifax.rwth-aachen.de/osdn/clonezilla/78259/clonezilla-live-3.0.3-22-amd64.iso" devices: - /dev/kvm cap_add: - NET_ADMIN ports: - - 5000:5000 - - 5001:5001 + - 22:22 restart: on-failure stop_grace_period: 60s diff --git a/install.sh b/install.sh index 98235a2..f3ac650 100644 --- a/install.sh +++ b/install.sh @@ -2,43 +2,14 @@ set -eu IMG="/storage" -BASE=$(basename "$URL" .pat) - [ ! -d "$IMG" ] && echo "Storage folder (${IMG}) not found!" && exit 69 -[ ! -f "/run/server.sh" ] && echo "Script must run inside Docker container!" && exit 60 - -[ ! -f "$IMG/$BASE.boot.img" ] && rm -f "$IMG"/"$BASE".system.img -[ -f "$IMG/$BASE.system.img" ] && exit 0 - -# Display wait message on port 5000 -/run/server.sh 5000 > /dev/null & +[ -f "$IMG/boot.img" ] && exit 0 TMP="$IMG/tmp" -echo "Install: Downloading extractor..." - -rm -rf $TMP && mkdir -p $TMP - -FILE="$TMP/rd.gz" -curl -r 64493568-69886247 -s -k -o "$FILE" https://global.synologydownload.com/download/DSM/release/7.0.1/42218/DSM_VirtualDSM_42218.pat - -set +e -xz -dc <$TMP/rd.gz >$TMP/rd 2>/dev/null -(cd $TMP && cpio -idm <$TMP/rd 2>/dev/null) -set -e - -mkdir -p /run/extract -for file in $TMP/usr/lib/libcurl.so.4 $TMP/usr/lib/libmbedcrypto.so.5 $TMP/usr/lib/libmbedtls.so.13 $TMP/usr/lib/libmbedx509.so.1 $TMP/usr/lib/libmsgpackc.so.2 $TMP/usr/lib/libsodium.so $TMP/usr/lib/libsynocodesign-ng-virtual-junior-wins.so.7 $TMP/usr/syno/bin/scemd; do - cp "$file" /run/extract/ -done - -mv /run/extract/scemd /run/extract/syno_extract_system_patch -chmod +x /run/extract/syno_extract_system_patch - -echo "Install: Downloading $URL..." - -FILE="$TMP/dsm.pat" +echo "Install: Downloading $BOOT..." +FILE="$TMP/boot.img" rm -rf $TMP && mkdir -p $TMP # Check if running with interactive TTY or redirected to docker log @@ -50,105 +21,7 @@ fi [ ! -f "$FILE" ] && echo "Download failed" && exit 61 -SIZE=$(stat -c%s "$FILE") - -if ((SIZE<250000000)); then - echo "Invalid PAT file: File is an update pack which contains no OS image." && exit 62 -fi - -echo "Install: Extracting downloaded system image..." - -if { tar tf "$FILE"; } >/dev/null 2>&1; then - tar xpf $FILE -C $TMP/. -else - export LD_LIBRARY_PATH="/run/extract" - if ! /run/extract/syno_extract_system_patch $FILE $TMP/. ; then - echo "Invalid PAT file: File is an update pack which contains no OS image." && exit 63 - fi - export LD_LIBRARY_PATH="" -fi - -HDA="$TMP/hda1" -IDB="$TMP/indexdb" -PKG="$TMP/packages" -HDP="$TMP/synohdpack_img" - -[ ! -f "$HDA.tgz" ] && echo "Invalid PAT file: File contains no OS image." && exit 64 -[ ! -f "$HDP.txz" ] && echo "Invalid PAT file: HD pack not found." && exit 65 -[ ! -f "$IDB.txz" ] && echo "Invalid PAT file: IndexDB file not found." && exit 66 -[ ! -d "$PKG" ] && echo "Invalid PAT file: File contains no packages." && exit 68 - -BOOT=$(find $TMP -name "*.bin.zip") - -[ ! -f "$BOOT" ] && echo "Invalid PAT file: boot file not found." && exit 67 - -BOOT=$(echo "$BOOT" | head -c -5) -unzip -q -o "$BOOT".zip -d $TMP - -echo "Install: Extracting prepared disk image..." - -SYSTEM="$TMP/temp.img" -PLATE="/data/template.img" - -rm -f $PLATE -unxz $PLATE.xz -mv -f $PLATE $SYSTEM - -echo "Install: Extracting system partition..." - -PRIVILEGED=false -LABEL="1.44.1-42218" -OFFSET="1048576" # 2048 * 512 -NUMBLOCKS="622560" # 2550005760 / 4096 - -MOUNT="/mnt/tmp" -rm -rf $MOUNT && mkdir -p $MOUNT - -mount -t ext4 -o loop,offset=$OFFSET $SYSTEM $MOUNT 2>/dev/null && PRIVILEGED=true - -rm -rf ${MOUNT:?}/{,.[!.],..?}* - -mv -f $HDA.tgz $HDA.txz - -tar xpfJ $HDP.txz --absolute-names -C $MOUNT/ -tar xpfJ $HDA.txz --absolute-names -C $MOUNT/ -tar xpfJ $IDB.txz --absolute-names -C $MOUNT/usr/syno/synoman/indexdb/ - -LOC="$MOUNT/usr/local" -mkdir -p $LOC -mv $PKG/ $LOC/ - -LOC="$MOUNT/usr/local/bin" -mkdir -p $LOC -cp /agent/agent.sh $LOC/agent.sh -chmod +x $LOC/agent.sh - -LOC="$MOUNT/usr/local/etc/rc.d" -mkdir -p $LOC -cp /agent/service.sh $LOC/agent.sh -chmod +x $LOC/agent.sh - -# Store agent version -echo "2" > "$IMG"/agent.ver - -if [ "$PRIVILEGED" = false ]; then - - echo "Install: Installing system partition..." - - # Workaround for containers that are not privileged to mount loop devices - mke2fs -q -t ext4 -b 4096 -d $MOUNT/ -L $LABEL -F -E offset=$OFFSET $SYSTEM $NUMBLOCKS - -else - - umount $MOUNT - -fi - -rm -rf $MOUNT - -mv -f "$BOOT" "$IMG"/"$BASE".boot.img -mv -f "$SYSTEM" "$IMG"/"$BASE".system.img +mv -f "$BOOT" "$IMG"/boot.img rm -rf $TMP -exit 0 diff --git a/network.sh b/network.sh index db4ca54..fde9f91 100644 --- a/network.sh +++ b/network.sh @@ -18,7 +18,7 @@ setupLocalDhcp () { IP="$2" MAC="$1" CIDR="24" - HOSTNAME="VirtualDSM" + HOSTNAME="QEMU" # dnsmasq configuration: DNSMASQ_OPTS="$DNSMASQ_OPTS --dhcp-range=$IP,$IP --dhcp-host=$MAC,,$IP,$HOSTNAME,infinite --dhcp-option=option:netmask,255.255.255.0" # Create lease file for faster resolve @@ -61,14 +61,6 @@ if [ ! -c /dev/net/tun ]; then fi [ ! -c /dev/net/tun ] && echo "Error: TUN network interface not available..." && exit 85 -[ ! -d "$IMG" ] && echo "Storage folder (${IMG}) not found!" && exit 86 - -#If environment variabele not set fall back to file -if [ -z "$VM_NET_MAC" ]; then - FILE="${IMG}/guest.mac" - [ ! -f "$FILE" ] && echo "00:11:32:2C:A7:85" > "$FILE" - VM_NET_MAC=$(cat "${FILE}") -fi update-alternatives --set iptables /usr/sbin/iptables-legacy > /dev/null update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy > /dev/null diff --git a/power.sh b/power.sh index 40696b5..e78c0ac 100644 --- a/power.sh +++ b/power.sh @@ -25,29 +25,8 @@ _graceful_shutdown(){ echo "Received $1 signal, shutting down..." echo 0 > "${_QEMU_SHUTDOWN_COUNTER}" - # Don't send the powerdown signal because vDSM ignores ACPI signals - # echo 'system_powerdown' | nc -q 1 -w 1 localhost "${QEMU_MONPORT}">/dev/null - - # Send shutdown command to guest agent tools instead via serial port - RESPONSE=$(curl -s -m 2 -S http://127.0.0.1:2210/write?command=6 2>&1) - - if [[ ! "${RESPONSE}" =~ "\"success\"" ]] ; then - - echo "Could not send shutdown command to guest, error: $RESPONSE" - - FILE="${IMG}/agent.ver" - [ ! -f "$FILE" ] && echo "1" > "$FILE" - AGENT_VERSION=$(cat "${FILE}") - - if ((AGENT_VERSION < 2)); then - echo "Please update the agent to allow gracefull shutdowns..." - pkill -f qemu-system-x86_64 - else - # Send a NMI interrupt which will be detected by the kernel - echo 'nmi' | nc -q 1 -w 1 localhost "${QEMU_MONPORT}">/dev/null - fi - - fi + # Send the shutdown (system_powerdown) command to the QMP monitor + echo 'system_powerdown' | nc -q 1 -w 1 localhost "${QEMU_MONPORT}">/dev/null while [ "$(cat ${_QEMU_SHUTDOWN_COUNTER})" -lt "${QEMU_POWERDOWN_TIMEOUT}" ]; do diff --git a/readme.md b/readme.md index 4104901..3f98806 100644 --- a/readme.md +++ b/readme.md @@ -1,24 +1,23 @@ -virtual-dsm +docker-qemu ============= [![build_img]][build_url] -[![gh_last_release_svg]][dsm-docker-hub] -[![Docker Image Size]][dsm-docker-hub] -[![Docker Pulls Count]][dsm-docker-hub] +[![gh_last_release_svg]][qemu-docker-hub] +[![Docker Image Size]][qemu-docker-hub] +[![Docker Pulls Count]][qemu-docker-hub] -[build_url]: https://github.com/kroese/virtual-dsm/actions -[dsm-docker-hub]: https://hub.docker.com/r/kroese/virtual-dsm +[build_url]: https://github.com/kroese/docker-qemu/actions +[qemu-docker-hub]: https://hub.docker.com/r/kroese/docker-qemu -[build_img]: https://github.com/kroese/virtual-dsm/actions/workflows/build.yml/badge.svg -[Docker Image Size]: https://img.shields.io/docker/image-size/kroese/virtual-dsm/latest -[Docker Pulls Count]: https://img.shields.io/docker/pulls/kroese/virtual-dsm.svg?style=flat -[gh_last_release_svg]: https://img.shields.io/docker/v/kroese/virtual-dsm?arch=amd64&sort=date +[build_img]: https://github.com/kroese/docker-qemu/actions/workflows/build.yml/badge.svg +[Docker Image Size]: https://img.shields.io/docker/image-size/kroese/docker-qemu/latest +[Docker Pulls Count]: https://img.shields.io/docker/pulls/kroese/docker-qemu.svg?style=flat +[gh_last_release_svg]: https://img.shields.io/docker/v/kroese/docker-qemu?arch=amd64&sort=date -A docker container of Virtual DSM v7.2 +A docker container of QEMU ## Features - - Upgrades supported - KVM acceleration - Graceful shutdown @@ -31,16 +30,16 @@ version: "3" services: vm: container_name: dsm - image: kroese/virtual-dsm:latest + image: kroese/docker-qemu:latest environment: DISK_SIZE: "16G" + BOOT: "https://ftp.halifax.rwth-aachen.de/osdn/clonezilla/78259/clonezilla-live-3.0.3-22-amd64.iso" devices: - /dev/kvm cap_add: - NET_ADMIN ports: - - 5000:5000 - - 5001:5001 + - 22:22 restart: on-failure stop_grace_period: 60s ``` @@ -48,7 +47,7 @@ services: Via `docker run` ```bash -docker run -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-timeout 60 kroese/virtual-dsm:latest +docker run -p 22:22 --device=/dev/kvm --cap-add NET_ADMIN --stop-timeout 60 kroese/docker-qemu:latest ``` ## FAQ @@ -118,15 +117,3 @@ docker run -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-timeout 60 ``` You can also switch back and forth between versions this way without loosing your file data. - - * ### What are the differences compared to standard DSM? ### - - There are only three minor differences: the Virtual Machine Manager package is not available, Surveillance Station does not include any free licenses, and logging in to your Synology account is not supported. - -## Acknowledgments - -Based on an [article](https://jxcn.org/2022/04/vdsm-first-try/) by JXCN. - -## Disclaimer - -Only run this container on original Synology hardware, any other use is not permitted and might not be legal. diff --git a/run.sh b/run.sh index d6969ba..1890b4b 100755 --- a/run.sh +++ b/run.sh @@ -2,7 +2,7 @@ set -eu if /run/install.sh; then - echo "Starting Virtual DSM..." + echo "Starting QEMU..." else echo "Installation failed (code $?)" && exit 81 fi @@ -15,9 +15,10 @@ source /run/network.sh [ -z "${KVM_NET_OPTS}" ] && echo "Error: Failed to setup network..." && exit 84 -source /run/serial.sh - -[ -z "${KVM_SERIAL_OPTS}" ] && echo "Error: Failed to setup serial..." && exit 85 +KVM_SERIAL_OPTS="\ + -serial mon:stdio \ + -device virtio-serial-pci,id=virtio-serial0,bus=pcie.0,addr=0x3 \ + -chardev pty,id=charserial0" source /run/power.sh diff --git a/serial.sh b/serial.sh deleted file mode 100644 index b0f35f1..0000000 --- a/serial.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -# Docker environment variabeles -: ${HOST_SERIAL:=''} -: ${GUEST_SERIAL:=''} - -permanent="DSM" -serialstart="2000" - -[ ! -d "$IMG" ] && echo "Storage folder (${IMG}) not found!" && exit 69 - -#If environment variabele not set fall back to file -if [ -z "$HOST_SERIAL" ]; then - FILE="${IMG}/host.serial" - if [ ! -f "$FILE" ]; then - SERIAL="$(echo "$serialstart" | tr ' ' '\n' | sort -R | tail -1)$permanent"$(printf "%06d" $((RANDOM % 30000 + 1))) - echo $SERIAL > "$FILE" - fi - HOST_SERIAL=$(cat "${FILE}") -fi - -#If environment variabele not set fall back to file -if [ -z "$GUEST_SERIAL" ]; then - FILE="${IMG}/guest.serial" - if [ ! -f "$FILE" ]; then - SERIAL="$(echo "$serialstart" | tr ' ' '\n' | sort -R | tail -1)$permanent"$(printf "%06d" $((RANDOM % 30000 + 1))) - echo $SERIAL > "$FILE" - fi - GUEST_SERIAL=$(cat "${FILE}") -fi - -CPU=$(lscpu | sed -nr '/Model name/ s/.*:\s*(.*) @ .*/\1/p' | sed ':a;s/ / /;ta' | sed s/"(R)"//g | sed s/"-"//g | sed 's/[^[:alnum:] ]\+//g') - -if [ -n "$CPU" ]; then - CPU="$CPU,," -else - CPU="QEMU, Virtual CPU, X86_64" -fi - -./run/serial.bin -cpu="${CPU_CORES}" \ - -cpu_arch="${CPU}" \ - -buildnumber=42962 \ - -vmmts=1679863686 \ - -hostsn="${HOST_SERIAL}" \ - -guestsn="${GUEST_SERIAL}" \ - -vmmversion="2.6.1-12139" \ - -guestuuid="ba13a19a-c0c1-4fef-9346-915ed3b98341" > /dev/null 2>&1 & - -KVM_SERIAL_OPTS="\ - -serial mon:stdio \ - -device virtio-serial-pci,id=virtio-serial0,bus=pcie.0,addr=0x3 \ - -chardev pty,id=charserial0 \ - -device isa-serial,chardev=charserial0,id=serial0 \ - -chardev socket,id=charchannel0,host=127.0.0.1,port=12345,reconnect=10 \ - -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=vchannel" diff --git a/serial/doc.go b/serial/doc.go deleted file mode 100644 index 1eccfdf..0000000 --- a/serial/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// vdsm-serial project doc.go - -/* -vdsm-serial document -*/ -package main diff --git a/serial/go.mod b/serial/go.mod deleted file mode 100644 index 2dc9a8d..0000000 --- a/serial/go.mod +++ /dev/null @@ -1,4 +0,0 @@ -module vdsm-serial - -go 1.20 - diff --git a/serial/go.sum b/serial/go.sum deleted file mode 100644 index 8b13789..0000000 --- a/serial/go.sum +++ /dev/null @@ -1 +0,0 @@ - diff --git a/serial/main.go b/serial/main.go deleted file mode 100644 index 94838e4..0000000 --- a/serial/main.go +++ /dev/null @@ -1,263 +0,0 @@ -package main - -import ( - "bytes" - "encoding/binary" - "flag" - "fmt" - "log" - "net" - "strconv" - "net/http" - "math/rand" - "github.com/gorilla/mux" -) - -type REQ struct { - RandID int64 - GuestUUID [16]byte - GuestID int64 - IsReq int32 - IsResp int32 - NeedResponse int32 - ReqLength int32 - RespLength int32 - CommandID int32 - SubCommand int32 - Reserve int32 -} - -var HostSN = flag.String("hostsn", "0000000000000", "Host SN, 13 bytes") -var GuestSN = flag.String("guestsn", "0000000000000", "Guest SN, 13 bytes") -var GuestUUID = flag.String("guestuuid", "ba13a19a-c0c1-4fef-9346-915ed3b98341", "Guest UUID") -var GuestCPUs = flag.Int("cpu", 1, "Num of Guest cpu") -var GuestCPU_ARCH = flag.String("cpu_arch", "QEMU, Virtual CPU, X86_64", "CPU arch") -var HostDSMBuildNumber = flag.Int("buildnumber", 42962, "Build Number of Host") -var HostDSMfixNumber = flag.Int("fixNumber", 0, "Fix Number of Host") -var VMMVersion = flag.String("vmmversion", "2.6.1-12139", "VMM version") -var VMMTimestamp = flag.Int("vmmts", 1679863686, "VMM Timestamp") -var Cluster_UUID = "3bdea92b-68f4-4fe9-aa4b-d645c3c63864" - -var ApiPort = flag.String("api", ":2210", "API port") -var ListenAddr = flag.String("addr", "0.0.0.0:12345", "Listen address") - -var LastConnection net.Conn - -func main() { - - flag.Parse() - - r := mux.NewRouter() - r.HandleFunc("/", home) - r.HandleFunc("/write", write) - go http.ListenAndServe(*ApiPort, r) - - listener, err := net.Listen("tcp", *ListenAddr) - - if err != nil { - log.Println("Error listening", err.Error()) - return - } - - log.Println("Start listen on " + *ListenAddr) - - for { - conn, err := listener.Accept() - if err != nil { - log.Println("Error on accept", err.Error()) - return - } - log.Printf("New connection from %s\n", conn.RemoteAddr().String()) - - go incoming_conn(conn) - } -} - -func incoming_conn(conn net.Conn) { - - LastConnection = conn - - for { - buf := make([]byte, 4096) - len, err := conn.Read(buf) - if err != nil { - log.Println("Error on read", err.Error()) - return - } - if len != 4096 { - log.Printf("Read %d Bytes, not 4096\n", len) - // something wrong, close and wait for reconnect - conn.Close() - return - } - go process_req(buf, conn) - //log.Printf("Read %d Bytes\n%#v\n", len, string(buf[:len])) - } -} - -var commandsName = map[int]string{ - 3: "Guest Power info", - 4: "Host DSM version", - 5: "Guest SN", - 7: "Guest CPU info", - 9: "Host DSM version", - 8: "VMM version", - 10: "Get Guest Info", - 11: "Guest UUID", - 12: "Cluster UUID", - 13: "Host SN", - 16: "Update Deadline", - 17: "Guest Timestamp", -} - -func process_req(buf []byte, conn net.Conn) { - var req REQ - var data string - err := binary.Read(bytes.NewReader(buf), binary.LittleEndian, &req) - if err != nil { - log.Printf("Error on decode %s\n", err) - return - } - - if req.IsReq == 1 { - data = string(buf[64 : 64+req.ReqLength]) - } else if req.IsResp == 1 { - data = string(buf[64 : 64+req.RespLength]) - } - - // log.Printf("%#v\n", req) - log.Printf("Command: %s from Guest:%d \n", commandsName[int(req.CommandID)], req.GuestID) - if data != "" { - log.Printf("Info: %s\n", data) - } - // Hard code of command - switch req.CommandID { - case 3: - // Guest start/reboot - case 4: - // Host DSM version - data = fmt.Sprintf(`{"buildnumber":%d,"smallfixnumber":%d}`, *HostDSMBuildNumber, *HostDSMfixNumber) - case 5: - // Guest SN - data = *GuestSN - case 7: - // CPU info - // {"cpuinfo":"QEMU, Virtual CPU, X86_64, 1" "vcpu_num":1} - data = fmt.Sprintf(`{"cpuinfo":"%s","vcpu_num":%d}`, - *GuestCPU_ARCH+", "+strconv.Itoa(*GuestCPUs), *GuestCPUs) - case 8: - data = fmt.Sprintf(`{"id":"Virtualization","name":"Virtual Machine Manager","timestamp":%d,"version":"%s"}`, - *VMMTimestamp, *VMMVersion) - case 9: - // Version Info - case 10: - // Guest Info - case 11: - // Guest UUID - data = *GuestUUID - case 12: - // cluster UUID - data = Cluster_UUID - case 13: - // Host SN - data = *HostSN - case 16: - // Update Dead line time, always 0x7fffffffffffffff - data = "9223372036854775807" - case 17: - // TimeStamp - default: - log.Printf("No handler for this command %d\n", req.CommandID) - return - } - - // if it's a req and need response - if req.IsReq == 1 && req.NeedResponse == 1 { - buf = make([]byte, 0, 4096) - writer := bytes.NewBuffer(buf) - req.IsResp = 1 - req.IsReq = 0 - req.ReqLength = 0 - req.RespLength = int32(len([]byte(data)) + 1) - log.Printf("Response data: %s\n", data) - - // write to buf - binary.Write(writer, binary.LittleEndian, &req) - writer.Write([]byte(data)) - res := writer.Bytes() - // full fill 4096 - buf = make([]byte, 4096, 4096) - copy(buf, res) - conn.Write(buf) - } -} - -func home(w http.ResponseWriter, r *http.Request) { - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`{"status": "error", "data": null, "message": "No command specified"}`)) -} - - -func write(w http.ResponseWriter, r *http.Request) { - - w.Header().Set("Content-Type", "application/json") - - var err error - var commandID int - - query := r.URL.Query() - commandID, err = strconv.Atoi(query.Get("command")) - - if (err != nil || commandID < 1) { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`{"status": "error", "data": null, "message": "Invalid command ID"}`)) - return - } - - if (send_command((int32)(commandID), 1) == false) { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`{"status": "error", "data": null, "message": "Failed to send command"}`)) - return - } - - w.WriteHeader(http.StatusOK) - w.Write([]byte(`{"status": "success", "data": null, "message": null}`)) - return -} - -func send_command(CommandID int32, SubCommand int32) bool { - - var req REQ - - req.CommandID = CommandID - req.SubCommand = SubCommand - - req.IsReq = 1 - req.IsResp = 0 - req.ReqLength = 0 - req.RespLength = 0 - req.NeedResponse = 0 - req.GuestID = 10000000 - req.RandID = rand.Int63() - - var buf = make([]byte, 0, 4096) - var writer = bytes.NewBuffer(buf) - - // write to buf - binary.Write(writer, binary.LittleEndian, &req) - res := writer.Bytes() - - // full fill 4096 - buf = make([]byte, 4096, 4096) - copy(buf, res) - - //log.Printf("Writing command %d\n", CommandID) - - if (LastConnection == nil) { return false } - - LastConnection.Write(buf) - return true - -} diff --git a/server.sh b/server.sh deleted file mode 100644 index 16f22ce..0000000 --- a/server.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -set -eu - -HTML="