From 7323ae399b2dbd85ede41f1b61b95c78a69031e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gytis=20Sto=C5=A1kevi=C4=8Dius?= Date: Mon, 31 Mar 2025 15:51:22 +0300 Subject: [PATCH 1/7] add static network interface configuration when network is bridge --- src/entry.sh | 47 +++++++++++++++++++++++-------------- src/network.sh | 63 ++++++++++++++++++++++++++++++++++++++++++++++---- src/power.sh | 15 ++++++------ 3 files changed, 95 insertions(+), 30 deletions(-) mode change 100644 => 100755 src/entry.sh mode change 100644 => 100755 src/network.sh diff --git a/src/entry.sh b/src/entry.sh old mode 100644 new mode 100755 index b037cdc..18d8e49 --- a/src/entry.sh +++ b/src/entry.sh @@ -8,32 +8,45 @@ SUPPORT="https://github.com/dockur/windows" cd /run -. reset.sh # Initialize system -. define.sh # Define versions -. mido.sh # Download code -. install.sh # Run installation -. disk.sh # Initialize disks -. display.sh # Initialize graphics -. network.sh # Initialize network -. samba.sh # Configure samba -. boot.sh # Configure boot -. proc.sh # Initialize processor -. power.sh # Configure shutdown -. config.sh # Configure arguments +. reset.sh # Initialize system +. define.sh # Define versions +. mido.sh # Download code +. install.sh # Run installation +. disk.sh # Initialize disks +. display.sh # Initialize graphics +. network.sh # Initialize network +. samba.sh # Configure samba +. boot.sh # Configure boot +. proc.sh # Initialize processor +. power.sh # Configure shutdown +. config.sh # Configure arguments trap - ERR version=$(qemu-system-x86_64 --version | head -n 1 | cut -d '(' -f 1 | awk '{ print $NF }') info "Booting ${APP}${BOOT_DESC} using QEMU v$version..." -{ qemu-system-x86_64 ${ARGS:+ $ARGS} >"$QEMU_OUT" 2>"$QEMU_LOG"; rc=$?; } || : -(( rc != 0 )) && error "$(<"$QEMU_LOG")" && exit 15 +{ + qemu-system-x86_64 ${ARGS:+ $ARGS} >"$QEMU_OUT" 2>"$QEMU_LOG" + rc=$? +} || : +((rc != 0)) && error "$(<"$QEMU_LOG")" && exit 15 terminal -( sleep 30; boot ) & +( + sleep 30 + boot + configure_guest_network_interface + info "Windows started succesfully, you can now connect using RDP" + if [[ "${NETWORK,,}" != "bridge"* ]]; then + info "or visit http://localhost:8006/ to view the screen..." + fi + touch "$STORAGE/ready" +) & tail -fn +0 "$QEMU_LOG" 2>/dev/null & -cat "$QEMU_TERM" 2> /dev/null | tee "$QEMU_PTY" & +cat "$QEMU_TERM" 2>/dev/null | tee "$QEMU_PTY" & wait $! || : -sleep 1 & wait $! +sleep 1 & +wait $! [ ! -f "$QEMU_END" ] && finish 0 diff --git a/src/network.sh b/src/network.sh old mode 100644 new mode 100755 index da15ef0..13835fb --- a/src/network.sh +++ b/src/network.sh @@ -25,6 +25,64 @@ ADD_ERR="Please add the following setting to your container:" # ###################################### # Functions # ###################################### +find_free_ip() { + local current_ip="$1" + local mask="$2" + + # Get network prefix + IFS='.' read -r i1 i2 i3 i4 <<<"$current_ip" + IFS='.' read -r m1 m2 m3 m4 <<<"$(ip -o -f inet addr show | awk '/scope global/ {print $4}' | cut -d'/' -f2)" + + network_ip=$((i1 & m1)).$((i2 & m2)).$((i3 & m3)).0 + base_ip="$i1.$i2.$i3" + + # Iterate over available IPs + for i in {2..254}; do + new_ip="$base_ip.$i" + if [[ "$new_ip" != "$current_ip" ]] && ! ping -c 1 -W 1 "$new_ip" &>/dev/null; then + echo "$new_ip" + return + fi + done + + echo "No free IP found" +} + +configure_guest_network_interface() { + if [[ "${NETWORK,,}" == "bridge"* ]]; then + + HOST_INTERFACE="dockerbridge" + CURRENT_IP=$(ip addr show $HOST_INTERFACE | grep -oP 'inet \K[\d.]+') + MASK="$(ip -4 addr show $HOST_INTERFACE | awk '/inet / {print $2}' | cut -d'/' -f2)" + + if [ -z "$CURRENT_IP" ]; then + echo "Error: Unable to retrieve the current IP address of $HOST_INTERFACE." + exit 1 + fi + + echo "Current Host IP: $CURRENT_IP" + + IFS='.' read -r -a ip_parts <<<"$CURRENT_IP" + NEW_HOST_IP=$(find_free_ip "$CURRENT_IP" "$MASK") + GW="${ip_parts[0]}.${ip_parts[1]}.${ip_parts[2]}.1" + + echo "New Host IP: $NEW_HOST_IP" + + ip addr del $CURRENT_IP/$MASK dev $HOST_INTERFACE + ip addr add $NEW_HOST_IP/$MASK dev $HOST_INTERFACE + + ip link set $HOST_INTERFACE down + ip link set $HOST_INTERFACE up + + route add default gw $GW + + echo -e '{"execute": "guest-exec", "arguments": {"path": "C:\\\\Windows\\\\System32\\\\netsh.exe", "arg": ["interface", "ipv4", "set", "address", "name=\\"Ethernet\\"", "static", "'"$CURRENT_IP"'", "255.255.255.0", "'"$GW"'"]}}' | nc -U /tmp/qga.sock -w 5 + echo -e '{"execute": "guest-exec", "arguments": {"path": "C:\\\\Windows\\\\System32\\\\netsh.exe", "arg": ["interface", "ipv4", "add", "dnsservers", "name=\\"Ethernet\\"", "address=\\"'$GW'\\"", "index=\\"1\\""]}}' | nc -U /tmp/qga.sock -w 5 + + fi + + return 0 +} configureDHCP() { @@ -409,11 +467,6 @@ configureBridge() { # 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 - error "Failed to setup default route" && return 10 - fi - NET_OPTS="-netdev tap,id=hostnet0,ifname=$VM_NET_TAP" if [ -c /dev/vhost-net ]; then diff --git a/src/power.sh b/src/power.sh index 3e36701..b619f5f 100644 --- a/src/power.sh +++ b/src/power.sh @@ -17,8 +17,9 @@ rm -f "$QEMU_DIR/qemu.*" touch "$QEMU_LOG" _trap() { - func="$1" ; shift - for sig ; do + func="$1" + shift + for sig; do trap "$func $sig" "$sig" done } @@ -35,8 +36,6 @@ boot() { grep -Fq "BOOTMGR is missing" "$QEMU_PTY" && fail="y" fi if [ -z "$fail" ]; then - info "Windows started succesfully, visit http://localhost:8006/ to view the screen..." - touch "$STORAGE/ready" return 0 fi fi @@ -129,7 +128,7 @@ terminal() { if [ -n "$msg" ]; then - if [[ "${msg,,}" != "char"* || "$msg" != *"serial0)" ]]; then + if [[ "${msg,,}" != "char"* || "$msg" != *"serial0)" ]]; then echo "$msg" fi @@ -193,13 +192,13 @@ _graceful_shutdown() { fi # Send ACPI shutdown signal - echo 'system_powerdown' | nc -q 1 -w 1 localhost "${QEMU_PORT}" > /dev/null + echo 'system_powerdown' | nc -q 1 -w 1 localhost "${QEMU_PORT}" >/dev/null local cnt=0 while [ "$cnt" -lt "$QEMU_TIMEOUT" ]; do sleep 1 - cnt=$((cnt+1)) + cnt=$((cnt + 1)) ! isAlive "$pid" && break # Workaround for zombie pid @@ -208,7 +207,7 @@ _graceful_shutdown() { info "Waiting for Windows to shutdown... ($cnt/$QEMU_TIMEOUT)" # Send ACPI shutdown signal - echo 'system_powerdown' | nc -q 1 -w 1 localhost "${QEMU_PORT}" > /dev/null + echo 'system_powerdown' | nc -q 1 -w 1 localhost "${QEMU_PORT}" >/dev/null done From 725d9296829ae9bdf277526a262175cb6fd46725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gytis=20Sto=C5=A1kevi=C4=8Dius?= Date: Mon, 31 Mar 2025 17:51:31 +0300 Subject: [PATCH 2/7] Make default network bridge --- compose.yml | 5 +---- src/network.sh | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/compose.yml b/compose.yml index 57ad009..b57b65e 100644 --- a/compose.yml +++ b/compose.yml @@ -14,13 +14,12 @@ services: USERNAME: "bill" PASSWORD: "gates" DISK_FMT: "qcow2" + NETWORK: "Y" devices: - /dev/kvm - /dev/net/tun cap_add: - NET_ADMIN - ports: - - 8006:8006 stop_grace_period: 2m volumes: - ./scripts:/oem @@ -46,6 +45,4 @@ services: - /dev/net/tun cap_add: - NET_ADMIN - ports: - - 8006:8006 stop_grace_period: 2m diff --git a/src/network.sh b/src/network.sh index 13835fb..53b61b8 100755 --- a/src/network.sh +++ b/src/network.sh @@ -5,7 +5,7 @@ set -Eeuo pipefail : "${MAC:=""}" : "${DHCP:="N"}" -: "${NETWORK:="Y"}" +: "${NETWORK:="bridge"}" : "${USER_PORTS:=""}" : "${HOST_PORTS:=""}" : "${ADAPTER:="virtio-net-pci"}" From 34cac42db588236d82b8a3d9abdb9610706b8254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gytis=20Sto=C5=A1kevi=C4=8Dius?= Date: Mon, 31 Mar 2025 18:23:21 +0300 Subject: [PATCH 3/7] Make prepare image more verbose --- prepare_image.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prepare_image.sh b/prepare_image.sh index 19cde37..96689ce 100755 --- a/prepare_image.sh +++ b/prepare_image.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -Eeuo pipefail +set -Eeuox pipefail source env.sh From 6e08a5a2eab15fba75bed680c4dc34a67bb0fa8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gytis=20Sto=C5=A1kevi=C4=8Dius?= Date: Mon, 31 Mar 2025 18:30:06 +0300 Subject: [PATCH 4/7] Add debug --- compose.yml | 1 + prepare_image.sh | 2 +- src/define.sh | 2 +- src/entry.sh | 2 +- src/install.sh | 2 +- src/mido.sh | 2 +- src/network.sh | 2 +- src/power.sh | 2 +- src/samba.sh | 2 +- 9 files changed, 9 insertions(+), 8 deletions(-) diff --git a/compose.yml b/compose.yml index b57b65e..ac286af 100644 --- a/compose.yml +++ b/compose.yml @@ -15,6 +15,7 @@ services: PASSWORD: "gates" DISK_FMT: "qcow2" NETWORK: "Y" + DEBUG: "Y" devices: - /dev/kvm - /dev/net/tun diff --git a/prepare_image.sh b/prepare_image.sh index 96689ce..90bfa33 100755 --- a/prepare_image.sh +++ b/prepare_image.sh @@ -4,7 +4,7 @@ set -Eeuox pipefail source env.sh echo "start to build and install windows" -docker compose up windows-build -d --wait --build +docker compose up windows-build --build echo "windows installed, now stop container" docker stop windows-build diff --git a/src/define.sh b/src/define.sh index a245248..279468b 100644 --- a/src/define.sh +++ b/src/define.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -Eeuo pipefail +set -Eeuox pipefail : "${WIDTH:=""}" : "${HEIGHT:=""}" diff --git a/src/entry.sh b/src/entry.sh index 18d8e49..6574d91 100755 --- a/src/entry.sh +++ b/src/entry.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -Eeuo pipefail +set -Eeuox pipefail : "${BOOT_MODE:="windows"}" diff --git a/src/install.sh b/src/install.sh index 54eebd5..f392c0e 100644 --- a/src/install.sh +++ b/src/install.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -Eeuo pipefail +set -Eeuox pipefail TMP="$STORAGE/tmp" DIR="$TMP/unpack" diff --git a/src/mido.sh b/src/mido.sh index 7c6112b..cd4171f 100644 --- a/src/mido.sh +++ b/src/mido.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -Eeuo pipefail +set -Eeuox pipefail handle_curl_error() { diff --git a/src/network.sh b/src/network.sh index 53b61b8..1fa4071 100755 --- a/src/network.sh +++ b/src/network.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -Eeuo pipefail +set -Eeuox pipefail # Docker environment variables diff --git a/src/power.sh b/src/power.sh index b619f5f..adc8fc6 100644 --- a/src/power.sh +++ b/src/power.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -Eeuo pipefail +set -Eeuox pipefail # Configure QEMU for graceful shutdown diff --git a/src/samba.sh b/src/samba.sh index e2c12c9..321d05d 100644 --- a/src/samba.sh +++ b/src/samba.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -Eeuo pipefail +set -Eeuox pipefail : "${SAMBA:="Y"}" From 5ed1a0c413d158ded3d83b4342f8168a30dafde6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gytis=20Sto=C5=A1kevi=C4=8Dius?= Date: Tue, 1 Apr 2025 11:00:21 +0300 Subject: [PATCH 5/7] Restore dettached compose up --- prepare_image.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prepare_image.sh b/prepare_image.sh index 90bfa33..96689ce 100755 --- a/prepare_image.sh +++ b/prepare_image.sh @@ -4,7 +4,7 @@ set -Eeuox pipefail source env.sh echo "start to build and install windows" -docker compose up windows-build --build +docker compose up windows-build -d --wait --build echo "windows installed, now stop container" docker stop windows-build From a5c2af4742e629e73b6961bf29236864f62b6fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gytis=20Sto=C5=A1kevi=C4=8Dius?= Date: Tue, 1 Apr 2025 11:11:22 +0300 Subject: [PATCH 6/7] update prepare script --- prepare_image.sh | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/prepare_image.sh b/prepare_image.sh index 96689ce..93f97dc 100755 --- a/prepare_image.sh +++ b/prepare_image.sh @@ -1,10 +1,18 @@ #!/usr/bin/env bash -set -Eeuox pipefail +set -Eeuo pipefail source env.sh echo "start to build and install windows" -docker compose up windows-build -d --wait --build +docker compose up windows-build -d --build + +echo "streaming logs..." +docker logs -f windows-build | tee windows-build.log & + +echo "waiting for windows-build container to be healthy..." +while [[ "$(docker inspect --format='{{.State.Health.Status}}' windows-build 2>/dev/null)" != "healthy" ]]; do + sleep 2 +done echo "windows installed, now stop container" docker stop windows-build @@ -13,7 +21,15 @@ 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 +docker compose up windows-installed -d + +echo "streaming logs..." +docker logs -f windows-installed | tee windows-installed.log & + +echo "waiting for windows-installed container to be healthy..." +while [[ "$(docker inspect --format='{{.State.Health.Status}}' windows-installed 2>/dev/null)" != "healthy" ]]; do + sleep 2 +done + +docker push "$IMAGE_NAME:$IMAGE_VERSION" From 0528800424cc9b889bc08035c5fb374acd1d4cb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gytis=20Sto=C5=A1kevi=C4=8Dius?= Date: Tue, 1 Apr 2025 15:29:25 +0300 Subject: [PATCH 7/7] Add option to have multiple bridges --- src/network.sh | 236 ++++++++++++++++++++++--------------------------- 1 file changed, 105 insertions(+), 131 deletions(-) diff --git a/src/network.sh b/src/network.sh index 1fa4071..17d7f0e 100755 --- a/src/network.sh +++ b/src/network.sh @@ -20,6 +20,7 @@ set -Eeuox pipefail : "${DNSMASQ:="/usr/sbin/dnsmasq"}" : "${DNSMASQ_CONF_DIR:="/etc/dnsmasq.d"}" +ETH_COUNT=$(ls /sys/class/net | grep -E '^eth[0-9]+$' | wc -l) ADD_ERR="Please add the following setting to your container:" # ###################################### @@ -50,34 +51,42 @@ find_free_ip() { configure_guest_network_interface() { if [[ "${NETWORK,,}" == "bridge"* ]]; then + for ((i = 0; i < ETH_COUNT; i++)); do + HOST_INTERFACE="dockerbridge$i" + CURRENT_IP=$(ip addr show $HOST_INTERFACE | grep -oP 'inet \K[\d.]+') + MASK="$(ip -4 addr show $HOST_INTERFACE | awk '/inet / {print $2}' | cut -d'/' -f2)" - HOST_INTERFACE="dockerbridge" - CURRENT_IP=$(ip addr show $HOST_INTERFACE | grep -oP 'inet \K[\d.]+') - MASK="$(ip -4 addr show $HOST_INTERFACE | awk '/inet / {print $2}' | cut -d'/' -f2)" + if [ -z "$CURRENT_IP" ]; then + echo "Error: Unable to retrieve the current IP address of $HOST_INTERFACE." + exit 1 + fi - if [ -z "$CURRENT_IP" ]; then - echo "Error: Unable to retrieve the current IP address of $HOST_INTERFACE." - exit 1 - fi + echo "Current Host IP: $CURRENT_IP" - echo "Current Host IP: $CURRENT_IP" + IFS='.' read -r -a ip_parts <<<"$CURRENT_IP" + NEW_HOST_IP=$(find_free_ip "$CURRENT_IP" "$MASK") + GW="${ip_parts[0]}.${ip_parts[1]}.${ip_parts[2]}.1" - IFS='.' read -r -a ip_parts <<<"$CURRENT_IP" - NEW_HOST_IP=$(find_free_ip "$CURRENT_IP" "$MASK") - GW="${ip_parts[0]}.${ip_parts[1]}.${ip_parts[2]}.1" + echo "New Host IP: $NEW_HOST_IP" - echo "New Host IP: $NEW_HOST_IP" + ip addr del $CURRENT_IP/$MASK dev $HOST_INTERFACE + ip addr add $NEW_HOST_IP/$MASK dev $HOST_INTERFACE - ip addr del $CURRENT_IP/$MASK dev $HOST_INTERFACE - ip addr add $NEW_HOST_IP/$MASK dev $HOST_INTERFACE + ip link set $HOST_INTERFACE down + ip link set $HOST_INTERFACE up - ip link set $HOST_INTERFACE down - ip link set $HOST_INTERFACE up + route add default gw $GW - route add default gw $GW + if [ $i -eq 0 ]; then + INTERFACE_NAME="Ethernet" + else + IDX=$((1 + i)) + INTERFACE_NAME="Ethernet $IDX" + fi - echo -e '{"execute": "guest-exec", "arguments": {"path": "C:\\\\Windows\\\\System32\\\\netsh.exe", "arg": ["interface", "ipv4", "set", "address", "name=\\"Ethernet\\"", "static", "'"$CURRENT_IP"'", "255.255.255.0", "'"$GW"'"]}}' | nc -U /tmp/qga.sock -w 5 - echo -e '{"execute": "guest-exec", "arguments": {"path": "C:\\\\Windows\\\\System32\\\\netsh.exe", "arg": ["interface", "ipv4", "add", "dnsservers", "name=\\"Ethernet\\"", "address=\\"'$GW'\\"", "index=\\"1\\""]}}' | nc -U /tmp/qga.sock -w 5 + echo -e '{"execute": "guest-exec", "arguments": {"path": "C:\\\\Windows\\\\System32\\\\netsh.exe", "capture-output": true, "arg": ["interface", "ipv4", "set", "address", "'"$INTERFACE_NAME"'", "static", "'$CURRENT_IP'", "255.255.255.0", "'$GW'"]}}' | nc -U /tmp/qga.sock -w 5 + echo -e '{"execute": "guest-exec", "arguments": {"path": "C:\\\\Windows\\\\System32\\\\netsh.exe", "capture-output": true, "arg": ["interface", "ipv4", "add", "dnsservers", "'"$INTERFACE_NAME"'", "1.1.1.1", "index=1"]}}' | nc -U /tmp/qga.sock -w 5 + done fi @@ -379,120 +388,72 @@ configureBridge() { fi fi - # Create a bridge with a static IP for the VM guest + for ((i = 0; i < ETH_COUNT; i++)); do + DOCKER_BRIDGE="dockerbridge$i" + NET_DEV="eth$i" + NET_TAP="qemu$i" + { + ip link add dev $DOCKER_BRIDGE type bridge + rc=$? + } || : - { - ip link add dev dockerbridge type bridge - rc=$? - } || : + if ((rc != 0)); then + error "Failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && return 1 + fi - 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 $NET_DEV | jq -c '.[0].addr_info[] | select(.family == "inet")'); do + cidr_addr=$(echo $addr | jq -r '[ .local, .prefixlen|tostring] | join("/")') + if ! ip addr add dev $DOCKER_BRIDGE $cidr_addr; then + error "Failed to add address for $DOCKER_BRIDGE interface" + exit 30 + fi + done - # { - # 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("/")') - if ! ip addr add dev dockerbridge $cidr_addr; then - error "Failed to add address for dockerbridge interface" + if ! ip addr flush dev $NET_DEV; then + error "Failed to clear $NET_DEV interface addresses" exit 30 fi - done - if ! ip addr flush dev $VM_NET_DEV; then - error "Failed to clear $VM_NET_DEV interface addresses" - exit 30 - fi - while ! ip link set dockerbridge up; do - info "Waiting for IP address to become available..." - sleep 2 - done + while ! ip link set $DOCKER_BRIDGE up; do + info "Waiting for IP address to become available..." + 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 + # QEMU Works with taps, set tap to the bridge created + if ! ip tuntap add dev "$NET_TAP" mode tap; then + error "$tuntap" && return 1 + fi - # while ! ip link set dockerbridge_2 up; do - # info "Waiting for IP address to become available..." - # sleep 2 - # done + while ! ip link set "$NET_TAP" up promisc on; do + info "Waiting for TAP 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 - fi + if ! ip link set dev "$NET_TAP" master $DOCKER_BRIDGE; then + error "Failed to set IP link!" && return 1 + fi - while ! ip link set "$VM_NET_TAP" up promisc on; do - info "Waiting for TAP to become available..." - sleep 2 - done + if ! ip link set dev "$NET_DEV" master $DOCKER_BRIDGE; then + error "Failed to attach docker interface to bridge" + fi - if ! ip link set dev "$VM_NET_TAP" master dockerbridge; then - error "Failed to set IP link!" && return 1 - fi - - if ! ip link set dev "$VM_NET_DEV" master dockerbridge; then - 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 - - # 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 - - NET_OPTS="-netdev tap,id=hostnet0,ifname=$VM_NET_TAP" - - if [ -c /dev/vhost-net ]; then - { - exec 40>>/dev/vhost-net + NET_OPTS+=" -netdev tap,id=hostnet$i,ifname=$NET_TAP" + if [ -c /dev/vhost-net ]; then + fd=$((40 + i)) + eval "exec $fd>>/dev/vhost-net" rc=$? - } 2>/dev/null || : - ((rc == 0)) && NET_OPTS+=",vhost=on,vhostfd=40" - fi + if ((rc == 0)); then + NET_OPTS+=",vhost=on,vhostfd=$fd" + fi + fi - NET_OPTS+=",script=no,downscript=no" + 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" + done return 0 - } closeNetwork() { @@ -518,11 +479,21 @@ closeNetwork() { [[ "${NETWORK,,}" == "user"* ]] && return 0 - ip link set "$VM_NET_TAP" down promisc off || true - ip link delete "$VM_NET_TAP" || true + if [[ "${NETWORK,,}" == "bridge"* ]]; then + for ((i = 0; i < ETH_COUNT; i++)); do + ip link set "qemu$i" down promisc off || true + ip link delete "qemu$i" || true - ip link set dockerbridge down || true - ip link delete dockerbridge || true + ip link set dockerbridge$i down || true + ip link delete dockerbridge$i || true + done + else + ip link set "$VM_NET_TAP" down promisc off || true + ip link delete "$VM_NET_TAP" || true + + ip link set dockerbridge down || true + ip link delete dockerbridge || true + fi fi @@ -666,16 +637,13 @@ else if ! configureBridge; then error "Failed to setup bridge networking" + for ((i = 0; i < ETH_COUNT; i++)); do + ip link set "$VM_NET_TAP$i" down promisc off &>null || true + ip link delete "$VM_NET_TAP$i" &>null || true - 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 + ip link set dockerbridge$i down &>null || true + ip link delete dockerbridge$i &>null || true + done exit 25 fi @@ -685,7 +653,13 @@ else 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" + +if [[ "${NETWORK,,}" == "bridge"* ]]; then + for ((i = 1; i < ETH_COUNT; i++)); do + MAC=$(printf "52:54:00:%02X:%02X:%02X" $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256))) + NET_OPTS+=" -device $ADAPTER,romfile=,netdev=hostnet$i,mac=$MAC,id=net$i" + done +fi 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"