Warn instead of failing when a forwarded host port is in use in the Windows 11 launcher
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e1e5a2149c
commit
c63c25c7b1
1 file changed
+29
-3
+29
-3
@@ -4,6 +4,7 @@
|
|||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
|
import socket
|
||||||
import string
|
import string
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
@@ -33,6 +34,17 @@ def capture(command):
|
|||||||
return result.stdout.rstrip("\n")
|
return result.stdout.rstrip("\n")
|
||||||
|
|
||||||
|
|
||||||
|
def port_in_use(port):
|
||||||
|
"""True if a host TCP port cannot be bound, as QEMU does for a hostfwd rule."""
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as probe:
|
||||||
|
probe.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
try:
|
||||||
|
probe.bind(("", int(port)))
|
||||||
|
except OSError:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def is_executable(path):
|
def is_executable(path):
|
||||||
return path.is_file() and os.access(path, os.X_OK)
|
return path.is_file() and os.access(path, os.X_OK)
|
||||||
|
|
||||||
@@ -296,6 +308,19 @@ except (KeyError, ValueError) as error:
|
|||||||
die(f"invalid placeholder in {qemu_config_template}: {error}")
|
die(f"invalid placeholder in {qemu_config_template}: {error}")
|
||||||
qemu_config.write_text(qemu_config_text)
|
qemu_config.write_text(qemu_config_text)
|
||||||
|
|
||||||
|
# QEMU refuses to start when a forwarded host port is taken, so warn and leave
|
||||||
|
# that forward out instead.
|
||||||
|
forwards = []
|
||||||
|
forwarded_ports = []
|
||||||
|
for label, host_port, guest_port in (("RDP", rdp_port, 3389), ("SSH", ssh_port, 22)):
|
||||||
|
in_use = port_in_use(host_port)
|
||||||
|
forwarded_ports.append((label, host_port, not in_use))
|
||||||
|
if in_use:
|
||||||
|
print(f"Warning: host port {host_port} is already in use; "
|
||||||
|
f"{label} will not be forwarded to the guest.", file=sys.stderr)
|
||||||
|
else:
|
||||||
|
forwards.append(f"hostfwd=tcp::{host_port}-:{guest_port}")
|
||||||
|
|
||||||
qemu_args = [
|
qemu_args = [
|
||||||
"-readconfig", str(qemu_config),
|
"-readconfig", str(qemu_config),
|
||||||
"-readconfig", str(qemu_arch_config),
|
"-readconfig", str(qemu_arch_config),
|
||||||
@@ -304,7 +329,7 @@ qemu_args = [
|
|||||||
# A config file section cannot hold two hostfwd entries, so the network
|
# A config file section cannot hold two hostfwd entries, so the network
|
||||||
# that the NIC in the config file uses is defined here. -nic none stops
|
# that the NIC in the config file uses is defined here. -nic none stops
|
||||||
# QEMU from adding its default NIC as well.
|
# QEMU from adding its default NIC as well.
|
||||||
"-netdev", f"user,id=net0,hostfwd=tcp::{rdp_port}-:3389,hostfwd=tcp::{ssh_port}-:22",
|
"-netdev", ",".join(["user,id=net0", *forwards]),
|
||||||
"-nic", "none",
|
"-nic", "none",
|
||||||
"-display", display_backend,
|
"-display", display_backend,
|
||||||
# "-display", "none", "-spice", "port=5900,addr=127.0.0.1,disable-ticketing=on,agent-mouse=off", "-device", "virtio-vga",
|
# "-display", "none", "-spice", "port=5900,addr=127.0.0.1,disable-ticketing=on,agent-mouse=off", "-device", "virtio-vga",
|
||||||
@@ -324,8 +349,9 @@ elif installing:
|
|||||||
print("Starting Windows 11 from the QCOW2 base image.")
|
print("Starting Windows 11 from the QCOW2 base image.")
|
||||||
else:
|
else:
|
||||||
print("Starting Windows 11 normally.")
|
print("Starting Windows 11 normally.")
|
||||||
print(f"Account: guofang / password; RDP: localhost:{rdp_port}; SSH: localhost:{ssh_port}",
|
print("Account: guofang / password; " + "; ".join(
|
||||||
flush=True)
|
f"{label}: localhost:{port}" for label, port, forwarded in forwarded_ports if forwarded),
|
||||||
|
flush=True)
|
||||||
|
|
||||||
if daemonize:
|
if daemonize:
|
||||||
log_file.write_text("")
|
log_file.write_text("")
|
||||||
|
|||||||
Reference in new issue
Block a user