From db9adcaf7a5a2a5a44d65e4ffe236dad34603c06 Mon Sep 17 00:00:00 2001 From: MickLesk <47820557+MickLesk@users.noreply.github.com> Date: Wed, 7 Oct 2026 19:20:49 +0200 Subject: [PATCH 1/3] Add shared VM helpers for imports, releases, checksums and first boot vm/common.func (loaded by the Proxmox and Incus engines) adds vm_require_tools, vm_release_asset, vm_latest_from_index, vm_firstboot_unit, vm_wait_http and a standard summary/finish block. pve/vm-core.func adds vm_import_disk, vm_start_vm, vm_guest_exec, vm_wait_guest_agent and vm_wait_for_ip; Incus refuses those explicitly. get_vm_ip matches the NIC by MAC and skips container bridges, wait_for_cloud_init uses the guest agent, and checksum discovery covers OpenWrt, FreeBSD and TurnKey plus --checksum-url. vm-app.func now uses these helpers instead of its own copies. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/verify-split-files.yml | 5 + core/build.func | 2 +- docs/README.md | 1 + docs/backends.md | 3 +- docs/vm.md | 49 +- incus/vm-core.func | 54 ++- pve/vm-app.func | 56 +-- pve/vm-core.func | 172 ++++++- tests/vm-helpers.sh | 565 +++++++++++++++++++++++ vm/cloud-init.func | 58 ++- vm/common.func | 412 +++++++++++++++++ 11 files changed, 1294 insertions(+), 83 deletions(-) create mode 100644 tests/vm-helpers.sh create mode 100644 vm/common.func diff --git a/.github/workflows/verify-split-files.yml b/.github/workflows/verify-split-files.yml index e94b868..6494fd1 100644 --- a/.github/workflows/verify-split-files.yml +++ b/.github/workflows/verify-split-files.yml @@ -24,6 +24,7 @@ on: - "incus/**" - "tests/vm-iso-storage.sh" - "tests/vm-consoles.sh" + - "tests/vm-helpers.sh" - ".github/workflows/verify-split-files.yml" push: branches: [main] @@ -39,6 +40,7 @@ on: - "incus/**" - "tests/vm-iso-storage.sh" - "tests/vm-consoles.sh" + - "tests/vm-helpers.sh" - ".github/workflows/verify-split-files.yml" workflow_dispatch: @@ -66,6 +68,9 @@ jobs: - name: VM console regression tests run: bash tests/vm-consoles.sh + - name: VM helper regression tests + run: bash tests/vm-helpers.sh + - name: Prefetch lists cover every engine file run: | set -euo pipefail diff --git a/core/build.func b/core/build.func index d31fd18..bf748a4 100644 --- a/core/build.func +++ b/core/build.func @@ -236,7 +236,7 @@ _CS_ENGINE_FILES=( api/errorlog.func api/exitcodes.func api/sysinfo.func api/telemetry.func ui/build-ui.func ui/advanced.func ui/defaults.func - ui/menu.func ui/validate.func vm/cloud-init.func + ui/menu.func ui/validate.func vm/cloud-init.func vm/common.func core/core.func core/dev-mode.func core/error_handler.func lxc/install.func lxc/platform.func host/preflight.func host/source-origin.func lib/tools.func lib/db.func diff --git a/docs/README.md b/docs/README.md index 53f58b5..2d650ca 100644 --- a/docs/README.md +++ b/docs/README.md @@ -104,6 +104,7 @@ an update before it starts. | [`api/sysinfo.func`](../api/sysinfo.func) | Host and container facts, origin detection | | [`api/telemetry.func`](../api/telemetry.func) | Payload assembly and delivery | | [`vm/cloud-init.func`](../vm/cloud-init.func) | Cloud-init configuration for VMs | +| [`vm/common.func`](../vm/common.func) | Backend-independent VM script helpers (tools, releases, checksums, first boot, summary) | | [`pve/backend.func`](../pve/backend.func) | Container creation via `pct` | | [`pve/vm-core.func`](../pve/vm-core.func) | VM creation via `qm` | | [`pve/vm-app.func`](../pve/vm-app.func) | Running LXC applications inside a VM | diff --git a/docs/backends.md b/docs/backends.md index a71bcf6..ca47423 100644 --- a/docs/backends.md +++ b/docs/backends.md @@ -140,7 +140,8 @@ is changed. Missing or invalid ISO storage is reported before VM creation. On Incus this helper explicitly fails: these installer scripts require Proxmox's `pvesm` and `qm`. -Run the host-independent regression tests with `bash tests/vm-iso-storage.sh`. +Run the host-independent regression tests with `bash tests/vm-iso-storage.sh` +and, for the shared VM helpers, `bash tests/vm-helpers.sh`. ### Backend-specific VM creation diff --git a/docs/vm.md b/docs/vm.md index 055cd3e..dfd71b6 100644 --- a/docs/vm.md +++ b/docs/vm.md @@ -1,4 +1,4 @@ -# `vm/` — cloud-init +# `vm/` — cloud-init and shared VM helpers Back to the [index](README.md). @@ -27,8 +27,55 @@ helpers as unavailable is what keeps it on its fallback branch instead of letting it call into a function that would need `qm`. `vm_provision` applies the same `CLOUDINIT_*` variables through the `cloud-init.*` instance keys. +`get_vm_ip [timeout] [mac]` reads addresses through the guest agent. +Pass the VM's MAC: only that NIC then counts, which is the only reliable answer +once the guest runs Docker, Podman or Kubernetes. Without a MAC, bridge and +tunnel interfaces those create are skipped; loopback and link-local addresses +never count. `wait_for_cloud_init` asks the guest agent +(`cloud-init status --wait`) first, which needs neither an address nor SSH +keys, and falls back to SSH only for guests without an agent. + One thing to know before editing it: this file declares its functions as `function name() {` rather than `name() {` — the only one that does, apart from `get_lxc_ip` in [`core/core.func`](../core/core.func). Anything that greps for function definitions across the engine will miss them unless it accounts for that. + +## [`common.func`](../vm/common.func) + +Helpers a VM script needs whatever the hypervisor. Both +[`pve/vm-core.func`](../pve/vm-core.func) and +[`incus/vm-core.func`](../incus/vm-core.func) load it, so a script finds the +same functions on either host. Nothing in it calls `qm` or `incus`. + +| Function | Contract | +| --- | --- | +| `vm_require_tools ...` | Installs the packages for missing commands (`jq`, `xz`, `virt-customize`, `unzip`, `zstd`, `7z`, …) before anything is created; returns non-zero, with the reason, when it cannot. | +| `vm_release_asset [tag]` | Resolves a release through [`lib/forge.func`](../lib/forge.func) — tokens, rate limits and the API-less GitHub fallback included. Sets `VM_RELEASE_TAG`, `VM_RELEASE_VERSION`, `VM_RELEASE_ASSET`, `VM_RELEASE_URL` and, from GitHub's asset digest, `VM_RELEASE_SHA256`. | +| `vm_latest_from_index [--sort-by ] [--probe ]...` | Newest match on an HTML download index (`grep -oP`, so `\K` works). `--sort-by` orders by part of the match; each `--probe` template is tried newest first and the first answering URL wins. Sets `VM_INDEX_LATEST` and `VM_INDEX_URL`. Never falls back to a hardcoded release. | +| `vm_firstboot_unit