Read port forwards from per-VM forwards.conf files
A QEMU config file section cannot hold more than one hostfwd entry, so the forwards move out of the ini files into qemu/<vm>/forwards.conf, one "LABEL HOST_PORT GUEST_PORT" rule per line. The new vmforwards.py parses them, skips rules whose host port is taken and builds the -netdev argument, which every launcher now passes instead of relying on a netdev section in the ini or on -nic. The ini files move to qemu/<vm>/config.ini and qemu/<vm>/<os>-<arch>.ini. The *_SSH_PORT / *_RDP_PORT variables and --rdp-port / --ssh-port still replace the host port of the SSH and RDP rules. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
07a2c6db3e
commit
78f6fd424b
29 files changed
+272
-131
No files matched your search
+21
-15
@@ -3,13 +3,14 @@
|
||||
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import vmforwards
|
||||
|
||||
script_dir = Path(__file__).resolve().parent
|
||||
env = os.environ.get
|
||||
|
||||
@@ -69,11 +70,13 @@ native_arch = normalize_arch(platform.machine())
|
||||
host_arch = normalize_arch(env("VM_IMAGE_ARCH") or native_arch)
|
||||
qemu_binary = "qemu-system-aarch64" if host_arch == "arm64" else "qemu-system-x86_64"
|
||||
qemu_config_template = Path(
|
||||
env("UBUNTU_VM_QEMU_CONFIG") or script_dir / "qemu" / "ubuntu2604.ini")
|
||||
env("UBUNTU_VM_QEMU_CONFIG") or script_dir / "qemu" / "ubuntu2604" / "config.ini")
|
||||
host_os = platform.system().lower()
|
||||
if host_os == "darwin" and host_arch == "amd64":
|
||||
die("amd64 guests are not supported on macOS hosts; use an arm64 image")
|
||||
qemu_platform_config = script_dir / "qemu" / f"ubuntu2604-{host_os}-{host_arch}.ini"
|
||||
qemu_platform_config = script_dir / "qemu" / "ubuntu2604" / f"{host_os}-{host_arch}.ini"
|
||||
forwards_file = Path(
|
||||
env("UBUNTU_VM_FORWARDS") or script_dir / "qemu" / "ubuntu2604" / "forwards.conf")
|
||||
|
||||
|
||||
def pick_firmware(override, *candidates):
|
||||
@@ -126,11 +129,13 @@ Usage: {Path(sys.argv[0]).name} [--daemon] [--download-only] [--state-dir DIR] [
|
||||
|
||||
Start an Ubuntu 26.04 LTS cloud image virtual machine. A writable overlay is
|
||||
created in the state directory (default: vm/ubuntu2604/), so the downloaded
|
||||
base image is never modified. The VM hardware (memory, CPUs, SSH port forward,
|
||||
...) is defined in qemu/ubuntu2604.ini, which is rendered to qemu.ini in the
|
||||
state directory and loaded with QEMU's -readconfig, followed by
|
||||
qemu/ubuntu2604-<os>-<arch>.ini (os is linux or darwin, arch is amd64 or arm64). Later QEMU arguments override them, e.g.
|
||||
base image is never modified. The VM hardware (memory, CPUs, ...) is defined
|
||||
in qemu/ubuntu2604/config.ini, which is rendered to qemu.ini in the state directory
|
||||
and loaded with QEMU's -readconfig, followed by
|
||||
qemu/ubuntu2604/<os>-<arch>.ini (os is linux or darwin, arch is amd64 or arm64). Later QEMU arguments override them, e.g.
|
||||
`-- -m 4G -smp 4`.
|
||||
Host port forwards, one "LABEL HOST_PORT GUEST_PORT" rule per line, are
|
||||
read from qemu/ubuntu2604/forwards.conf.
|
||||
|
||||
Options:
|
||||
--daemon Run in the background while keeping the graphical window
|
||||
@@ -150,7 +155,8 @@ Environment variables:
|
||||
UBUNTU_VM_UEFI_VARS UEFI variable-store template path (auto-detected for the selected architecture)
|
||||
UBUNTU_VM_DISPLAY QEMU display backend (default: cocoa on macOS, gtk elsewhere)
|
||||
UBUNTU_VM_QEMU_CONFIG QEMU config template rendered into the state directory and
|
||||
passed to -readconfig (default: qemu/ubuntu2604.ini)
|
||||
passed to -readconfig (default: qemu/ubuntu2604/config.ini)
|
||||
UBUNTU_VM_FORWARDS Port forward file (default: qemu/ubuntu2604/forwards.conf)
|
||||
""")
|
||||
|
||||
|
||||
@@ -266,24 +272,24 @@ except (KeyError, ValueError) as error:
|
||||
die(f"invalid placeholder in {qemu_config_template}: {error}")
|
||||
qemu_config.write_text(qemu_config_text)
|
||||
|
||||
forwards = vmforwards.usable_forwards(vmforwards.load_forwards(forwards_file))
|
||||
|
||||
qemu_args = [
|
||||
"-readconfig", str(qemu_config),
|
||||
"-readconfig", str(qemu_platform_config),
|
||||
# "max" is the host CPU under KVM/HVF and the fullest model under TCG.
|
||||
"-cpu", "max",
|
||||
# The config file's [netdev] does not stop QEMU from adding its default
|
||||
# NIC, a second user network without the SSH port forward.
|
||||
# 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
|
||||
# QEMU from adding its default NIC as well.
|
||||
"-netdev", vmforwards.netdev_argument(forwards),
|
||||
"-nic", "none",
|
||||
"-display", display_backend,
|
||||
]
|
||||
|
||||
print(f"Starting Ubuntu 26.04 ({host_arch}) from {qemu_config_template} "
|
||||
f"and {qemu_platform_config}.", flush=True)
|
||||
# The SSH port forward lives in the config file, e.g. hostfwd = "tcp::2225-:22".
|
||||
ssh_forward = re.search(r'hostfwd\s*=\s*"tcp:[^:"]*:(\d+)-[^:"]*:22"', qemu_config_text)
|
||||
if ssh_forward:
|
||||
print(f"SSH is forwarded to localhost:{ssh_forward.group(1)}: "
|
||||
f"ssh -p {ssh_forward.group(1)} guofang@localhost", flush=True)
|
||||
vmforwards.print_forwards(forwards)
|
||||
|
||||
if daemonize:
|
||||
log_file.write_text("")
|
||||
|
||||
Reference in new issue
Block a user