Carry every VM address on one NIC via a cloud-init network snippet - #345
Merged
Conversation
v0l
force-pushed
the
feat/guest-multi-ip-343
branch
from
July 30, 2026 16:21
2286981 to
330bb80
Compare
v0l
force-pushed
the
feat/guest-multi-ip-343
branch
from
July 30, 2026 16:43
330bb80 to
e29a1be
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #343. Stacked on #339 (
feat/template-ip-resources-105) — merge that first, this rebases onto master after.Every assignment now goes on the VM's single NIC through a per-VM cloud-init network config, so the address counts #105 sells are actually configured in the guest.
make_network_config(lnvps_api/src/host/proxmox.rs:979) emits network-config v2 and returnsNonewhen the VM holds at most one address per family. Those VMs keep the existingipconfigoutput byte-for-byte, so nothing already deployed is reconfigured.write_snippet/ensure_network_snippet/remove_network_snippet(:441) reuse the vendor-snippet mechanics but per VM (lnvps-net-{vm_id}.yaml), uploaded over SFTP rather than echoed through a shell — the content is multi-line YAML.cicustomcomposesvendor=…,network=….create_vm,configure_vmand thepatch_firewallreconcile, so a VM whose assignments changed gets the file rewritten even when the volume ref compares equal.delete_vmremoves the file after destroy, best-effort: a leaked snippet costs a few hundred bytes, while failing there would report a destroyed VM as still present.ipconfigdid). A SLAAC range contributesaccept-ra: truerather than a pinned address.The
MAX_CONFIGURABLE_IPScap and its admin/order guards are gone — the technical reason for them no longer exists, and the plan's ownmin/maxremain the bound an operator sets. Defaults stay 1 everywhere, so no plan offers a choice until someone widens it.Why one NIC rather than several: on the OVH-backed ranges the addresses share one router-issued vMAC ("use existing" in the Control Panel, confirmed by Kieran), and a second NIC would need a second vMAC.
assign_macalready generates the vMAC once per VM.Verification:
cargo test --workspace --exclude lnvps_e2egreen,./scripts/run-e2e.sh169 passed in 16.6s, clean clippy on every file touched. The lifecycle e2e orders a 2x IPv4 custom VM again and asserts both the template count and that the extra address is billed.Not verified against a real hypervisor — there is no Proxmox in the e2e stack, so the generated config is covered by unit tests only. Before any plan is widened for customers, one VM on a live host (ideally on an OVH range) needs to confirm both addresses come up and traffic arrives on the second.
Originating channel: general.