diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..7d8a4e9
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,36 @@
+services:
+ - name: docker:dind
+
+default:
+ image: docker:latest
+ artifacts:
+ expire_in: 1 week
+ interruptible: true
+ retry:
+ max: 2
+ when: runner_system_failure
+ tags:
+ - infra-docker-dind
+
+variables:
+ DOCKER_DRIVER: overlay2
+
+stages:
+ - build
+
+build:
+ stage: build
+ variables:
+ IMAGE_NAME: "registry.digitalarsenal.net/low-level-hacks/third-party-build/dockur_windows"
+ rules:
+ - if: $CI_COMMIT_TAG
+ variables:
+ IMAGE_VERSION: "$CI_COMMIT_TAG"
+ - if: $CI_COMMIT_TAG == null
+ variables:
+ IMAGE_VERSION: "$CI_COMMIT_REF_SLUG"
+ before_script:
+ - apk add --no-cache docker-compose bash kmod
+ script:
+ - docker login -u "$CI_REGISTRY_USER" -p "$REGISTRY_PUSH_ACCESS_TOKEN" "$CI_REGISTRY"
+ - ./prepare_image.sh
diff --git a/Dockerfile b/Dockerfile
index b3eedfb..ba6997b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -29,6 +29,8 @@ RUN set -eu && \
COPY --chmod=755 ./src /run/
COPY --chmod=755 ./assets /run/assets
+RUN mkdir /storage
+
ADD --chmod=664 https://github.com/qemus/virtiso-whql/releases/download/v1.9.44-0/virtio-win-1.9.44.tar.xz /drivers.txz
FROM dockurr/windows-arm:${VERSION_ARG} AS build-arm64
@@ -37,7 +39,6 @@ FROM build-${TARGETARCH}
ARG VERSION_ARG="0.00"
RUN echo "$VERSION_ARG" > /run/version
-VOLUME /storage
EXPOSE 8006 3389
ENV VERSION="11"
diff --git a/compose.yml b/compose.yml
index 3735189..57ad009 100644
--- a/compose.yml
+++ b/compose.yml
@@ -1,20 +1,19 @@
services:
- windows:
+ windows-build:
build: .
- container_name: windows
+ container_name: windows-build
privileged: true
healthcheck:
- test: "[ -f /data/ready ] || exit 1"
- interval: 60s
- retries: 5
- start_period: 480s
+ test: "[ -f /data/prepared ] || exit 1"
+ interval: 30s
+ retries: 50
+ start_period: 600s
timeout: 2s
environment:
VERSION: "11"
USERNAME: "bill"
PASSWORD: "gates"
- DEBUG: "y"
- MANUAL: "n"
+ DISK_FMT: "qcow2"
devices:
- /dev/kvm
- /dev/net/tun
@@ -22,29 +21,31 @@ services:
- NET_ADMIN
ports:
- 8006:8006
- - 3389:3389/tcp
- - 3389:3389/udp
stop_grace_period: 2m
volumes:
- ./scripts:/oem
- - ./shared:/data
- ./custom.xml:/custom.xml
- networks:
- vlan:
- ipv4_address: 192.168.0.100
- vlan-1:
- ipv4_address: 192.168.1.100
+ - ./custom.iso:/custom.iso
-networks:
- vlan:
- driver: bridge
- ipam:
- driver: default
- config:
- - subnet: 192.168.0.0/24
- vlan-1:
- driver: bridge
- ipam:
- driver: default
- config:
- - subnet: 192.168.1.0/24
\ No newline at end of file
+ windows-installed:
+ image: $IMAGE_NAME:$IMAGE_VERSION
+ container_name: windows-installed
+ privileged: true
+ healthcheck:
+ test: "[ -f /storage/ready ] || exit 1"
+ interval: 30s
+ retries: 20
+ start_period: 60s
+ timeout: 2s
+ environment:
+ VERSION: "11"
+ USERNAME: "bill"
+ PASSWORD: "gates"
+ devices:
+ - /dev/kvm
+ - /dev/net/tun
+ cap_add:
+ - NET_ADMIN
+ ports:
+ - 8006:8006
+ stop_grace_period: 2m
diff --git a/custom.xml b/custom.xml
index 29729f9..d630612 100644
--- a/custom.xml
+++ b/custom.xml
@@ -105,6 +105,10 @@
4
reg.exe add "HKLM\SYSTEM\Setup\MoSetup" /v AllowUpgradesWithUnsupportedTPMOrCPU /t REG_DWORD /d 1 /f
+
+ 5
+ reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\msiserver" /v Start /t REG_DWORD /d 2 /f
+
@@ -456,12 +460,12 @@
24
- cmd /C if exist "C:\OEM\install.bat" start "Install" "cmd /C C:\OEM\install.bat"
+ cmd /C if exist "C:\OEM\install.bat" cmd /C C:\OEM\install.bat
Execute custom script from the OEM folder if exists
25
- cmd /C "type nul > \\host.lan\Data\ready"
+ cmd /C "type nul > \\host.lan\Data\prepared"
Let host known that all configuration is done
diff --git a/env.sh b/env.sh
new file mode 100755
index 0000000..64c21db
--- /dev/null
+++ b/env.sh
@@ -0,0 +1,2 @@
+export IMAGE_NAME=${IMAGE_NAME:-"dockur_windows_installed"}
+export IMAGE_VERSION=${IMAGE_VERSION:-"latest"}
\ No newline at end of file
diff --git a/prepare_image.sh b/prepare_image.sh
new file mode 100755
index 0000000..19cde37
--- /dev/null
+++ b/prepare_image.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+set -Eeuo pipefail
+
+source env.sh
+
+echo "start to build and install windows"
+docker compose up windows-build -d --wait --build
+
+echo "windows installed, now stop container"
+docker stop windows-build
+
+echo "commit all the changes"
+docker commit windows-build "$IMAGE_NAME:$IMAGE_VERSION"
+docker images
+
+docker push "$IMAGE_NAME:$IMAGE_VERSION"
+
+echo "start container with windows installed"
+docker compose up windows-installed -d --wait
diff --git a/scripts/dependencies_windows.ps1 b/scripts/dependencies_windows.ps1
index 06a9101..568330d 100644
--- a/scripts/dependencies_windows.ps1
+++ b/scripts/dependencies_windows.ps1
@@ -109,6 +109,39 @@ function Install-WinDump() {
Validate-FileHash $BinaryPath $Hash SHA1
}
+function Install-QGA() {
+ # Define QEMU Guest Agent installer URL (change version if needed)
+ $QGA_URL = "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso"
+ $QGA_ISO = "$env:TEMP\virtio-win.iso"
+
+ # Download QEMU Guest Agent ISO
+ Write-Host "Downloading QEMU Guest Agent ISO..."
+ curl.exe -L $QGA_URL -o $QGA_ISO
+
+ # Mount the ISO
+ Write-Host "Mounting ISO..."
+ $mount = Mount-DiskImage -ImagePath $QGA_ISO -PassThru | Get-Volume
+ $QGA_DRIVE = $mount.DriveLetter + ":"
+
+ # Define installer path
+ $QGA_MSI = "$QGA_DRIVE\guest-agent\qemu-ga-x86_64.msi"
+
+ # Install QEMU Guest Agent
+ Write-Host "Installing QEMU Guest Agent..."
+ Start-Process msiexec.exe -ArgumentList "/i `"$QGA_MSI`" /quiet /norestart" -Wait -NoNewWindow
+
+ Get-Service QEMU-GA
+
+ # Unmount the ISO
+ Write-Host "Unmounting ISO..."
+ Dismount-DiskImage -ImagePath $QGA_ISO
+
+ # Cleanup
+ Remove-Item -Path $QGA_ISO -Force
+
+ Write-Host "QEMU Guest Agent installation complete."
+}
+
[System.IO.Directory]::CreateDirectory("C:\workspace")
CheckStatus
@@ -127,4 +160,7 @@ CheckStatus
Install-WinDump
CheckStatus
+Install-QGA
+CheckStatus
+
pip install Pyro5==5.15
diff --git a/scripts/install.bat b/scripts/install.bat
index 2f430c2..cd0a3e2 100644
--- a/scripts/install.bat
+++ b/scripts/install.bat
@@ -5,5 +5,3 @@ powershell -ExecutionPolicy Bypass -File "optimize.ps1"
powershell -ExecutionPolicy Bypass -File "disable_updates.ps1"
popd
-
-shutdown /f /r /t 0
diff --git a/src/install.sh b/src/install.sh
index e22b99e..54eebd5 100644
--- a/src/install.sh
+++ b/src/install.sh
@@ -1036,13 +1036,17 @@ if ! startInstall; then
exit 68
fi
+if [ -e /storage/*.qcow2 ]; then
+ html "Windows already installed, skipping image preparation..."
+ return 0
+fi
+
if [ ! -s "$ISO" ] || [ ! -f "$ISO" ]; then
if ! downloadImage "$ISO" "$VERSION" "$LANGUAGE"; then
rm -f "$ISO" 2> /dev/null || true
exit 61
fi
fi
-
if ! extractImage "$ISO" "$DIR" "$VERSION"; then
rm -f "$ISO" 2> /dev/null || true
exit 62
diff --git a/src/network.sh b/src/network.sh
index 2f90705..da15ef0 100644
--- a/src/network.sh
+++ b/src/network.sh
@@ -4,24 +4,17 @@ set -Eeuo pipefail
# Docker environment variables
: "${MAC:=""}"
-: "${MAC_2:=""}"
: "${DHCP:="N"}"
-: "${NETWORK:="bridge"}"
+: "${NETWORK:="Y"}"
: "${USER_PORTS:=""}"
: "${HOST_PORTS:=""}"
: "${ADAPTER:="virtio-net-pci"}"
-: "${ADAPTER_2:="virtio-net-pci"}"
-: "${VM_NET_DEV:="eth0"}"
-: "${VM_NET_DEV_2:="eth1"}"
+: "${VM_NET_DEV:=""}"
: "${VM_NET_TAP:="qemu"}"
-: "${VM_NET_TAP_2:="qemu_2"}"
: "${VM_NET_MAC:="$MAC"}"
-: "${VM_NET_MAC_2:="$MAC_2"}"
: "${VM_NET_HOST:="QEMU"}"
-: "${VM_NET_HOST_2:="QEMU_2"}"
-: "${VM_NET_IP:="192.168.0.101"}"
-: "${VM_NET_IP_2:="192.168.1.101"}"
+: "${VM_NET_IP:="20.20.20.21"}"
: "${DNSMASQ_OPTS:=""}"
: "${DNSMASQ:="/usr/sbin/dnsmasq"}"
@@ -33,28 +26,106 @@ ADD_ERR="Please add the following setting to your container:"
# Functions
# ######################################
+configureDHCP() {
+
+ # Create the necessary file structure for /dev/vhost-net
+ if [ ! -c /dev/vhost-net ]; then
+ if mknod /dev/vhost-net c 10 238; then
+ chmod 660 /dev/vhost-net
+ fi
+ fi
+
+ # Create a macvtap network for the VM guest
+ {
+ msg=$(ip link add link "$VM_NET_DEV" name "$VM_NET_TAP" address "$VM_NET_MAC" type macvtap mode bridge 2>&1)
+ rc=$?
+ } || :
+
+ case "$msg" in
+ "RTNETLINK answers: File exists"*)
+ while ! ip link add link "$VM_NET_DEV" name "$VM_NET_TAP" address "$VM_NET_MAC" type macvtap mode bridge; do
+ info "Waiting for macvtap interface to become available.."
+ sleep 5
+ done
+ ;;
+ "RTNETLINK answers: Invalid argument"*)
+ error "Cannot create macvtap interface. Please make sure that the network type of the container is 'macvlan' and not 'ipvlan'."
+ return 1
+ ;;
+ "RTNETLINK answers: Operation not permitted"*)
+ error "No permission to create macvtap interface. Please make sure that your host kernel supports it and that the NET_ADMIN capability is set."
+ return 1
+ ;;
+ *)
+ [ -n "$msg" ] && echo "$msg" >&2
+ if ((rc != 0)); then
+ error "Cannot create macvtap interface."
+ return 1
+ fi
+ ;;
+ esac
+
+ while ! ip link set "$VM_NET_TAP" up; do
+ info "Waiting for MAC address $VM_NET_MAC to become available..."
+ sleep 2
+ done
+
+ local TAP_NR TAP_PATH MAJOR MINOR
+ TAP_NR=$(>"$TAP_PATH"
+ rc=$?
+ } 2>/dev/null || :
+
+ if ((rc != 0)); then
+ error "Cannot create TAP interface ($rc). $ADD_ERR --device-cgroup-rule='c *:* rwm'" && return 1
+ fi
+
+ {
+ exec 40>>/dev/vhost-net
+ rc=$?
+ } 2>/dev/null || :
+
+ if ((rc != 0)); then
+ error "VHOST can not be found ($rc). $ADD_ERR --device=/dev/vhost-net" && return 1
+ fi
+
+ NET_OPTS="-netdev tap,id=hostnet0,vhost=on,vhostfd=40,fd=30"
+
+ return 0
+}
+
configureDNS() {
- # Create lease file for faster resolve
- echo "0 $VM_NET_MAC $VM_NET_IP $VM_NET_HOST 01:$VM_NET_MAC" >/var/lib/misc/dnsmasq.leases
- echo "0 $VM_NET_MAC_2 $VM_NET_IP_2 $VM_NET_HOST_2 01:$VM_NET_MAC_2" >>/var/lib/misc/dnsmasq.leases
- chmod 644 /var/lib/misc/dnsmasq.leases
# dnsmasq configuration:
- # eth0 - Provides both DNS and Default Gateway
- DNSMASQ_OPTS+=" --dhcp-range=$VM_NET_IP,$VM_NET_IP"
- DNSMASQ_OPTS+=" --dhcp-host=$VM_NET_MAC,,$VM_NET_IP,$VM_NET_HOST,infinite"
- DNSMASQ_OPTS+=" --dhcp-option=option:netmask,255.255.255.0"
- DNSMASQ_OPTS+=" --dhcp-option=option:dns-server,${VM_NET_IP%.*}.1"
+ DNSMASQ_OPTS+=" --dhcp-range=$VM_NET_IP,$VM_NET_IP --dhcp-host=$VM_NET_MAC,,$VM_NET_IP,$VM_NET_HOST,infinite --dhcp-option=option:netmask,255.255.255.0"
+
+ # Create lease file for faster resolve
+ echo "0 $VM_NET_MAC $VM_NET_IP $VM_NET_HOST 01:$VM_NET_MAC" >/var/lib/misc/dnsmasq.leases
+ chmod 644 /var/lib/misc/dnsmasq.leases
+
+ # Set DNS server and gateway
+ DNSMASQ_OPTS+=" --dhcp-option=option:dns-server,${VM_NET_IP%.*}.1 --dhcp-option=option:router,${VM_NET_IP%.*}.1"
+
+ # Add DNS entry for container
DNSMASQ_OPTS+=" --address=/host.lan/${VM_NET_IP%.*}.1"
- # eth1 - Provides only DNS, no default gateway
- DNSMASQ_OPTS+=" --dhcp-range=$VM_NET_IP_2,$VM_NET_IP_2"
- DNSMASQ_OPTS+=" --dhcp-host=$VM_NET_MAC_2,,$VM_NET_IP_2,$VM_NET_HOST_2,infinite"
- DNSMASQ_OPTS+=" --dhcp-option=option:netmask,255.255.255.0"
- DNSMASQ_OPTS+=" --dhcp-option=option:dns-server,${VM_NET_IP_2%.*}.1"
- DNSMASQ_OPTS+=" --address=/host.lan/${VM_NET_IP_2%.*}.1"
-
- # Cleanup and start dnsmasq
DNSMASQ_OPTS=$(echo "$DNSMASQ_OPTS" | sed 's/\t/ /g' | tr -s ' ' | sed 's/^ *//')
if ! $DNSMASQ ${DNSMASQ_OPTS:+ $DNSMASQ_OPTS}; then
@@ -116,9 +187,6 @@ configureUser() {
forward=$(getUserPorts "$USER_PORTS")
[ -n "$forward" ] && NET_OPTS+=",$forward"
- NET_OPTS+=" -netdev user,id=hostnet1,host=${VM_NET_IP_2%.*}.1,net=${VM_NET_IP_2%.*}.0/24,dhcpstart=$VM_NET_IP_2,hostname=$VM_NET_HOST_2"
- [ -n "$forward" ] && NET_OPTS+=",$forward"
-
return 0
}
@@ -161,14 +229,6 @@ configureNAT() {
error "Failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && return 1
fi
- {
- ip link add dev dockerbridge_2 type bridge
- rc=$?
- } || :
- if ((rc != 0)); then
- error "Failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && return 1
- fi
-
if ! ip address add "${VM_NET_IP%.*}.1/24" broadcast "${VM_NET_IP%.*}.255" dev dockerbridge; then
error "Failed to add IP address!" && return 1
fi
@@ -178,15 +238,6 @@ configureNAT() {
sleep 2
done
- if ! ip address add "${VM_NET_IP_2%.*}.1/24" broadcast "${VM_NET_IP_2%.*}.255" dev dockerbridge_2; then
- error "Failed to add IP address!" && return 1
- fi
-
- while ! ip link set dockerbridge_2 up; do
- info "Waiting for IP address to become available..."
- sleep 2
- done
-
# QEMU Works with taps, set tap to the bridge created
if ! ip tuntap add dev "$VM_NET_TAP" mode tap; then
error "$tuntap" && return 1
@@ -201,19 +252,6 @@ configureNAT() {
error "Failed to set IP link!" && return 1
fi
- if ! ip tuntap add dev "$VM_NET_TAP_2" mode tap; then
- error "$tuntap" && return 1
- fi
-
- while ! ip link set "$VM_NET_TAP_2" up promisc on; do
- info "Waiting for TAP to become available..."
- sleep 2
- done
-
- if ! ip link set dev "$VM_NET_TAP_2" master dockerbridge_2; then
- error "Failed to set IP link!" && return 1
- fi
-
# Add internet connection to the VM
update-alternatives --set iptables /usr/sbin/iptables-legacy >/dev/null
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy >/dev/null
@@ -233,19 +271,6 @@ configureNAT() {
error "Failed to configure IP tables!" && return 1
fi
- if ! iptables -t nat -A POSTROUTING -o "$VM_NET_DEV_2" -j MASQUERADE; then
- error "$tables" && return 1
- fi
-
- # shellcheck disable=SC2086
- if ! iptables -t nat -A PREROUTING -i "$VM_NET_DEV_2" -d "$IP_2" -p tcp${exclude} -j DNAT --to "$VM_NET_IP_2"; then
- error "Failed to configure IP tables!" && return 1
- fi
-
- if ! iptables -t nat -A PREROUTING -i "$VM_NET_DEV_2" -d "$IP_2" -p udp -j DNAT --to "$VM_NET_IP_2"; then
- error "Failed to configure IP tables!" && return 1
- fi
-
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 >/dev/null 2>&1 || true
@@ -263,24 +288,11 @@ configureNAT() {
NET_OPTS+=",script=no,downscript=no"
- NET_OPTS+=" -netdev tap,id=hostnet1,ifname=$VM_NET_TAP_2"
-
- if [ -c /dev/vhost-net ]; then
- {
- exec 41>>/dev/vhost-net
- rc=$?
- } 2>/dev/null || :
- ((rc == 0)) && NET_OPTS+=",vhost=on,vhostfd=41"
- fi
-
- NET_OPTS+=",script=no,downscript=no"
-
configureDNS || return 1
- return 0/
+ return 0
}
-
configureBridge() {
local tuntap="TUN device is missing. $ADD_ERR --device /dev/net/tun"
@@ -320,21 +332,21 @@ configureBridge() {
error "Failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && return 1
fi
- {
- ip link add dev dockerbridge_2 type bridge
- rc=$?
- } || :
- if ((rc != 0)); then
- error "Failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && return 1
- fi
+ # {
+ # ip link add dev dockerbridge_2 type bridge
+ # rc=$?
+ # } || :
+ # if ((rc != 0)); then
+ # error "Failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && return 1
+ # fi
# We need freshly created bridge to have IP address of the container
# For this reason we need to migrate IP from eth0 to dockerbridge.
for addr in $(ip --json addr show dev $VM_NET_DEV | jq -c '.[0].addr_info[] | select(.family == "inet")'); do
- cidr_addr=$(echo $addr | jq -r '[ .local, .prefixlen|tostring] | join("/")');
+ cidr_addr=$(echo $addr | jq -r '[ .local, .prefixlen|tostring] | join("/")')
if ! ip addr add dev dockerbridge $cidr_addr; then
- error "Failed to add address for dockerbridge interface"
- exit 30
+ error "Failed to add address for dockerbridge interface"
+ exit 30
fi
done
if ! ip addr flush dev $VM_NET_DEV; then
@@ -347,24 +359,24 @@ configureBridge() {
sleep 2
done
- # We need freshly created bridge to have IP address of the container
- # For this reason we need to migrate IP from eth0 to dockerbridge.
- for addr in $(ip --json addr show dev $VM_NET_DEV_2 | jq -c '.[0].addr_info[] | select(.family == "inet")'); do
- cidr_addr=$(echo $addr | jq -r '[ .local, .prefixlen|tostring] | join("/")');
- if ! ip addr add dev dockerbridge_2 $cidr_addr; then
- error "Failed to add address for dockerbridge_2 interface"
- exit 30
- fi
- done
- if ! ip addr flush dev $VM_NET_DEV_2; then
- error "Failed to clear $VM_NET_DEV_2 interface addresses"
- exit 30
- fi
+ # # We need freshly created bridge to have IP address of the container
+ # # For this reason we need to migrate IP from eth0 to dockerbridge.
+ # for addr in $(ip --json addr show dev $VM_NET_DEV_2 | jq -c '.[0].addr_info[] | select(.family == "inet")'); do
+ # cidr_addr=$(echo $addr | jq -r '[ .local, .prefixlen|tostring] | join("/")')
+ # if ! ip addr add dev dockerbridge_2 $cidr_addr; then
+ # error "Failed to add address for dockerbridge_2 interface"
+ # exit 30
+ # fi
+ # done
+ # if ! ip addr flush dev $VM_NET_DEV_2; then
+ # error "Failed to clear $VM_NET_DEV_2 interface addresses"
+ # exit 30
+ # fi
- while ! ip link set dockerbridge_2 up; do
- info "Waiting for IP address to become available..."
- sleep 2
- done
+ # while ! ip link set dockerbridge_2 up; do
+ # info "Waiting for IP address to become available..."
+ # sleep 2
+ # done
# QEMU Works with taps, set tap to the bridge created
if ! ip tuntap add dev "$VM_NET_TAP" mode tap; then
@@ -384,18 +396,18 @@ configureBridge() {
error "Failed to attach docker interface to bridge"
fi
- if ! ip tuntap add dev "$VM_NET_TAP_2" mode tap; then
- error "$tuntap" && return 1
- fi
+ # if ! ip tuntap add dev "$VM_NET_TAP_2" mode tap; then
+ # error "$tuntap" && return 1
+ # fi
- while ! ip link set "$VM_NET_TAP_2" up promisc on; do
- info "Waiting for TAP to become available..."
- sleep 2
- done
+ # while ! ip link set "$VM_NET_TAP_2" up promisc on; do
+ # info "Waiting for TAP to become available..."
+ # sleep 2
+ # done
- if ! ip link set dev "$VM_NET_TAP_2" master dockerbridge_2; then
- error "Failed to set IP link!" && return 1
- fi
+ # if ! ip link set dev "$VM_NET_TAP_2" master dockerbridge_2; then
+ # error "Failed to set IP link!" && return 1
+ # fi
# add initial default route as well
if ! ip route add default dev dockerbridge via ${VM_NET_IP%.*}.1; then
@@ -414,17 +426,17 @@ configureBridge() {
NET_OPTS+=",script=no,downscript=no"
- NET_OPTS+=" -netdev tap,id=hostnet1,ifname=$VM_NET_TAP_2"
+ # NET_OPTS+=" -netdev tap,id=hostnet1,ifname=$VM_NET_TAP_2"
- if [ -c /dev/vhost-net ]; then
- {
- exec 41>>/dev/vhost-net
- rc=$?
- } 2>/dev/null || :
- ((rc == 0)) && NET_OPTS+=",vhost=on,vhostfd=41"
- fi
+ # if [ -c /dev/vhost-net ]; then
+ # {
+ # exec 41>>/dev/vhost-net
+ # rc=$?
+ # } 2>/dev/null || :
+ # ((rc == 0)) && NET_OPTS+=",vhost=on,vhostfd=41"
+ # fi
- NET_OPTS+=",script=no,downscript=no"
+ # NET_OPTS+=",script=no,downscript=no"
return 0
@@ -438,15 +450,13 @@ closeNetwork() {
[[ "$NETWORK" == [Nn]* ]] && return 0
+ exec 30<&- || true
exec 40<&- || true
- exec 41<&- || true
if [[ "$DHCP" == [Yy1]* ]]; then
ip link set "$VM_NET_TAP" down || true
ip link delete "$VM_NET_TAP" || true
- ip link set "$VM_NET_TAP_2" down || true
- ip link delete "$VM_NET_TAP_2" || true
else
@@ -457,13 +467,9 @@ closeNetwork() {
ip link set "$VM_NET_TAP" down promisc off || true
ip link delete "$VM_NET_TAP" || true
- ip link set "$VM_NET_TAP_2" down promisc off || true
- ip link delete "$VM_NET_TAP_2" || true
ip link set dockerbridge down || true
ip link delete dockerbridge || true
- ip link set dockerbridge_2 down || true
- ip link delete dockerbridge_2 || true
fi
@@ -494,22 +500,28 @@ checkOS() {
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
+ [ -z "$VM_NET_DEV" ] && VM_NET_DEV=$(awk '$2 == 00000000 { print $1 }' /proc/net/route)
+ [ -z "$VM_NET_DEV" ] && VM_NET_DEV="eth0"
+ fi
+
if [ ! -d "/sys/class/net/$VM_NET_DEV" ]; then
error "Network interface '$VM_NET_DEV' does not exist inside the container!"
error "$ADD_ERR -e \"VM_NET_DEV=NAME\" to specify another interface name." && exit 27
fi
- if [ ! -d "/sys/class/net/$VM_NET_DEV_2" ]; then
- error "Network interface '$VM_NET_DEV_2' does not exist inside the container!"
- error "$ADD_ERR -e \"VM_NET_DEV_2=NAME\" to specify another interface name." && exit 27
- fi
-
if [ -z "$MAC" ]; then
local file="$STORAGE/$PROCESS.mac"
+ [ -s "$file" ] && MAC=$(<"$file")
if [ -z "$MAC" ]; then
# Generate MAC address based on Docker container ID in hostname
- MAC=$(printf '02:%02x:%02x:%02x:%02x:%02x\n' \
- $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)))
+ MAC=$(echo "$HOST" | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/')
echo "${MAC^^}" >"$file"
fi
fi
@@ -526,34 +538,9 @@ getInfo() {
error "Invalid MAC address: '$VM_NET_MAC', should be 12 or 17 digits long!" && exit 28
fi
- if [ -z "$MAC_2" ]; then
- local file="$STORAGE/$PROCESS.mac"
- if [ -z "$MAC_2" ]; then
- # Generate MAC address based on Docker container ID in hostname
- MAC_2=$(printf '02:%02x:%02x:%02x:%02x:%02x\n' \
- $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)))
- echo "${MAC_2^^}" >>"$file"
- fi
- fi
-
- VM_NET_MAC_2="${MAC_2^^}"
- VM_NET_MAC_2="${VM_NET_MAC_2//-/:}"
-
- if [[ ${#VM_NET_MAC_2} == 12 ]]; then
- m="$VM_NET_MAC_2"
- VM_NET_MAC_2="${m:0:2}:${m:2:2}:${m:4:2}:${m:6:2}:${m:8:2}:${m:10:2}"
- fi
-
- if [[ ${#VM_NET_MAC_2} != 17 ]]; then
- error "Invalid MAC address: '$VM_NET_MAC_2', should be 12 or 17 digits long!" && exit 28
- fi
-
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/)
- GATEWAY_2=$(ip route list dev "$VM_NET_DEV_2" | awk ' /^default/ {print $3}')
- IP_2=$(ip address show dev "$VM_NET_DEV_2" | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/)
-
return 0
}
@@ -574,67 +561,83 @@ if [[ "$DEBUG" == [Yy1]* ]]; then
[ -f /etc/resolv.conf ] && grep '^nameserver*' /etc/resolv.conf
echo
fi
-if [[ "$DEBUG" == [Yy1]* ]]; then
- info "Host: $HOST IP: $IP_2 Gateway: $GATEWAY_2 Interface: $VM_NET_DEV_2 MAC: $VM_NET_MAC_2"
- [ -f /etc/resolv.conf ] && grep '^nameserver*' /etc/resolv.conf
- echo
-fi
-if [[ "$IP" != "172."* ]] && [[ "$IP" != "10.8"* ]] && [[ "$IP" != "10.9"* ]]; then
+if [[ "$DHCP" == [Yy1]* ]]; then
+
checkOS
-fi
-if [[ "${NETWORK,,}" == "user"* ]]; then
-
- # Configure for usermode networking (slirp)
- configureUser || exit 24
-
-elif [[ "${NETWORK,,}" == "bridge"* ]]; then
- # CONFIGURE Bridge
- html "Configuring bridged network"
-
- if ! configureBridge; then
-
- error "Failed to setup bridge networking"
-
- ip link set "$VM_NET_TAP" down promisc off &>null || true
- ip link delete "$VM_NET_TAP" &>null || true
- ip link set "$VM_NET_TAP_2" down promisc off &>null || true
- ip link delete "$VM_NET_TAP_2" &>null || true
-
- ip link set dockerbridge down &>null || true
- ip link delete dockerbridge &>null || true
- ip link set dockerbridge_2 down &>null || true
- ip link delete dockerbridge_2 &>null || true
-
- exit 25
+ if [[ "$IP" == "172."* ]]; then
+ warn "container IP starts with 172.* which is often a sign that you are not on a macvlan network (required for DHCP)!"
fi
+ # Configure for macvtap interface
+ configureDHCP || exit 20
+
else
- # Configure for tap interface
- if ! configureNAT; then
+ if [[ "$IP" != "172."* ]] && [[ "$IP" != "10.8"* ]] && [[ "$IP" != "10.9"* ]]; then
+ checkOS
+ fi
- error "Failed to setup NAT networking"
+ if [[ "${NETWORK,,}" == [Yy1]* ]]; then
- ip link set "$VM_NET_TAP" down promisc off &>null || true
- ip link delete "$VM_NET_TAP" &>null || true
- ip link set "$VM_NET_TAP_2" down promisc off &>null || true
- ip link delete "$VM_NET_TAP_2" &>null || true
+ # Configure for tap interface
+ if ! configureNAT; then
- ip link set dockerbridge down &>null || true
- ip link delete dockerbridge &>null || true
- ip link set dockerbridge_2 down &>null || true
- ip link delete dockerbridge_2 &>null || true
+ NETWORK="user"
+ warn "falling back to usermode networking! Performance will be bad and port mapping will not work."
- exit 25
+ ip link set "$VM_NET_TAP" down promisc off &>null || true
+ ip link delete "$VM_NET_TAP" &>null || true
+
+ ip link set dockerbridge down &>null || true
+ ip link delete dockerbridge &>null || true
+
+ fi
+
+ fi
+
+ if [[ "${NETWORK,,}" == "user"* ]]; then
+
+ # Configure for usermode networking (slirp)
+ configureUser || exit 24
+
+ fi
+
+ if [[ "${NETWORK,,}" == "bridge"* ]]; then
+
+ # Configure for usermode networking (slirp)
+ # CONFIGURE Bridge
+ html "Configuring bridged network"
+
+ if ! configureBridge; then
+
+ error "Failed to setup bridge networking"
+
+ ip link set "$VM_NET_TAP" down promisc off &>null || true
+ ip link delete "$VM_NET_TAP" &>null || true
+ # ip link set "$VM_NET_TAP_2" down promisc off &>null || true
+ # ip link delete "$VM_NET_TAP_2" &>null || true
+
+ ip link set dockerbridge down &>null || true
+ ip link delete dockerbridge &>null || true
+ # ip link set dockerbridge_2 down &>null || true
+ # ip link delete dockerbridge_2 &>null || true
+
+ exit 25
+ fi
fi
fi
NET_OPTS+=" -device $ADAPTER,romfile=,netdev=hostnet0,mac=$VM_NET_MAC,id=net0"
-NET_OPTS+=" -device $ADAPTER_2,romfile=,netdev=hostnet1,mac=$VM_NET_MAC_2,id=net1"
+# NET_OPTS+=" -device $ADAPTER_2,romfile=,netdev=hostnet1,mac=$VM_NET_MAC_2,id=net1"
+
+NET_OPTS+=" -device virtio-serial-pci,id=virtserial0,bus=pcie.0,addr=0x6"
+NET_OPTS+=" -chardev socket,id=qga0,path=/tmp/qga.sock,server=on,wait=off"
+NET_OPTS+=" -device virtio-serial"
+NET_OPTS+=" -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0"
html "Initialized network successfully..."
return 0
diff --git a/src/power.sh b/src/power.sh
index e7ceaff..3e36701 100644
--- a/src/power.sh
+++ b/src/power.sh
@@ -36,6 +36,7 @@ boot() {
fi
if [ -z "$fail" ]; then
info "Windows started succesfully, visit http://localhost:8006/ to view the screen..."
+ touch "$STORAGE/ready"
return 0
fi
fi
@@ -161,6 +162,10 @@ _graceful_shutdown() {
set +e
+ if [ -f "$STORAGE/ready" ]; then
+ rm $STORAGE/ready
+ fi
+
if [ -f "$QEMU_END" ]; then
info "Received $1 while already shutting down..."
return