From f0cbd0ad9888d12cb4854dc3e989208dc3cca994 Mon Sep 17 00:00:00 2001 From: Steven Miller Date: Sat, 7 Mar 2026 13:03:47 -0500 Subject: [PATCH 1/8] network: avoid deleting taps when running set is unknown --- lib/network/bridge_linux.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/network/bridge_linux.go b/lib/network/bridge_linux.go index c3cf3304..cef2908c 100644 --- a/lib/network/bridge_linux.go +++ b/lib/network/bridge_linux.go @@ -775,14 +775,16 @@ func (m *manager) queryNetworkState(bridgeName string) (*Network, error) { // CleanupOrphanedTAPs removes TAP devices that aren't used by any running instance. // runningInstanceIDs is a list of instance IDs that currently have a running VMM. -// Pass nil to skip cleanup entirely (used when we couldn't determine running instances). +// Pass nil or an empty list to skip cleanup entirely (used when we couldn't +// determine an authoritative list of running instances for this host). // Returns the number of TAPs deleted. func (m *manager) CleanupOrphanedTAPs(ctx context.Context, runningInstanceIDs []string) int { log := logger.FromContext(ctx) - // If nil, skip cleanup entirely to avoid accidentally deleting TAPs for running VMs - if runningInstanceIDs == nil { - log.DebugContext(ctx, "skipping TAP cleanup (nil instance list)") + // Skip cleanup when we don't have an authoritative running set. + // This avoids deleting TAPs created by other concurrent hypeman processes/tests. + if len(runningInstanceIDs) == 0 { + log.DebugContext(ctx, "skipping TAP cleanup (empty instance list)") return 0 } From 135d8174840436c2807c15eaf69264c8435da37f Mon Sep 17 00:00:00 2001 From: Steven Miller Date: Sat, 7 Mar 2026 13:07:45 -0500 Subject: [PATCH 2/8] deps: bump oapi runtime for generated client compatibility --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index bf2cbdd1..aea5119c 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/miekg/dns v1.1.68 github.com/nrednav/cuid2 v1.1.0 github.com/oapi-codegen/nethttp-middleware v1.1.2 - github.com/oapi-codegen/runtime v1.1.2 + github.com/oapi-codegen/runtime v1.2.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.1 github.com/opencontainers/runtime-spec v1.2.1 diff --git a/go.sum b/go.sum index 7e44f095..9ac47a29 100644 --- a/go.sum +++ b/go.sum @@ -189,8 +189,8 @@ github.com/nrednav/cuid2 v1.1.0 h1:Y2P9Fo1Iz7lKuwcn+fS0mbxkNvEqoNLUtm0+moHCnYc= github.com/nrednav/cuid2 v1.1.0/go.mod h1:jBjkJAI+QLM4EUGvtwGDHC1cP1QQrRNfLo/A7qJFDhA= github.com/oapi-codegen/nethttp-middleware v1.1.2 h1:TQwEU3WM6ifc7ObBEtiJgbRPaCe513tvJpiMJjypVPA= github.com/oapi-codegen/nethttp-middleware v1.1.2/go.mod h1:5qzjxMSiI8HjLljiOEjvs4RdrWyMPKnExeFS2kr8om4= -github.com/oapi-codegen/runtime v1.1.2 h1:P2+CubHq8fO4Q6fV1tqDBZHCwpVpvPg7oKiYzQgXIyI= -github.com/oapi-codegen/runtime v1.1.2/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= +github.com/oapi-codegen/runtime v1.2.0 h1:RvKc1CVS1QeKSNzO97FBQbSMZyQ8s6rZd+LpmzwHMP4= +github.com/oapi-codegen/runtime v1.2.0/go.mod h1:Y7ZhmmlE8ikZOmuHRRndiIm7nf3xcVv+YMweKgG1DT0= github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= @@ -248,8 +248,8 @@ github.com/u-root/u-root v0.15.0 h1:8JXfjAA/Vs8EXfZUA2ftvoHbiYYLdaU8umJ461aq+Jw= github.com/u-root/u-root v0.15.0/go.mod h1:/0Qr7qJeDwWxoKku2xKQ4Szc+SwBE3g9VE8jNiamsmc= github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM= github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= -github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= -github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/vbatts/go-mtree v0.6.1-0.20250911112631-8307d76bc1b9 h1:R6l9BtUe83abUGu1YKGkfa17wMMFLt6mhHVQ8MxpfRE= github.com/vbatts/go-mtree v0.6.1-0.20250911112631-8307d76bc1b9/go.mod h1:W7bcG9PCn6lFY+ljGlZxx9DONkxL3v8a7HyN+PrSrjA= github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo= From 7c4d9ce417dc4db345a069ca0460055302b94352 Mon Sep 17 00:00:00 2001 From: Steven Miller Date: Sat, 7 Mar 2026 13:14:40 -0500 Subject: [PATCH 3/8] api: decouple instance network mapping from generated tag shape --- cmd/api/api/instances.go | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/cmd/api/api/instances.go b/cmd/api/api/instances.go index 10da1074..faff8a88 100644 --- a/cmd/api/api/instances.go +++ b/cmd/api/api/instances.go @@ -723,23 +723,21 @@ func instanceToOAPI(inst instances.Instance) oapi.Instance { uploadBwStr = &s } - // Build network object with ip/mac and bandwidth nested inside - netObj := &struct { - BandwidthDownload *string `json:"bandwidth_download,omitempty"` - BandwidthUpload *string `json:"bandwidth_upload,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - Ip *string `json:"ip"` - Mac *string `json:"mac"` - Name *string `json:"name,omitempty"` - }{ - Enabled: lo.ToPtr(inst.NetworkEnabled), - BandwidthDownload: downloadBwStr, - BandwidthUpload: uploadBwStr, + // Build network payload as JSON to avoid compile-time coupling to + // generated anonymous struct tags in oapi.Instance.Network. + networkPayload := map[string]any{ + "enabled": inst.NetworkEnabled, + } + if downloadBwStr != nil { + networkPayload["bandwidth_download"] = *downloadBwStr + } + if uploadBwStr != nil { + networkPayload["bandwidth_upload"] = *uploadBwStr } if inst.NetworkEnabled { - netObj.Name = lo.ToPtr("default") - netObj.Ip = lo.ToPtr(inst.IP) - netObj.Mac = lo.ToPtr(inst.MAC) + networkPayload["name"] = "default" + networkPayload["ip"] = inst.IP + networkPayload["mac"] = inst.MAC } // Convert hypervisor type @@ -763,7 +761,7 @@ func instanceToOAPI(inst instances.Instance) oapi.Instance { OverlaySize: lo.ToPtr(overlaySizeStr), Vcpus: lo.ToPtr(inst.Vcpus), DiskIoBps: diskIoBpsStr, - Network: netObj, + Network: nil, CreatedAt: inst.CreatedAt, StartedAt: inst.StartedAt, StoppedAt: inst.StoppedAt, @@ -772,6 +770,10 @@ func instanceToOAPI(inst instances.Instance) oapi.Instance { Hypervisor: &hvType, } + if b, err := json.Marshal(networkPayload); err == nil { + _ = json.Unmarshal(b, &oapiInst.Network) + } + if inst.ExitMessage != "" { oapiInst.ExitMessage = lo.ToPtr(inst.ExitMessage) } From 7e51d5c9cdb36c1e8891888a5a5e5ac537255a55 Mon Sep 17 00:00:00 2001 From: Steven Miller Date: Sat, 7 Mar 2026 13:18:36 -0500 Subject: [PATCH 4/8] ci: trigger stability run 2/5 From 63aa3ee5e2ec4032055453c410c5adc7f56ca01f Mon Sep 17 00:00:00 2001 From: Steven Miller Date: Sat, 7 Mar 2026 13:23:11 -0500 Subject: [PATCH 5/8] ci: verify required linux test binaries under sudo path --- .github/workflows/test.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cab7a17d..a7c5fe3b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,7 +38,19 @@ jobs: sudo apt-get install -y erofs-utils e2fsprogs iptables fi go mod download - + + - name: Verify Linux test toolchain + run: | + set -euo pipefail + TEST_PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH" + for bin in mkfs.erofs mkfs.ext4 iptables; do + if ! sudo env "PATH=$TEST_PATH" command -v "$bin" >/dev/null; then + echo "missing required binary under sudo PATH: $bin" + exit 1 + fi + sudo env "PATH=$TEST_PATH" command -v "$bin" + done + # Avoids rate limits when running the tests # Tests includes pulling, then converting to disk images - name: Login to Docker Hub From 9242e0ac9ebbc31445a80fcf1e6397a2254f778c Mon Sep 17 00:00:00 2001 From: Steven Miller Date: Sat, 7 Mar 2026 13:25:01 -0500 Subject: [PATCH 6/8] ci: run sudo tool probes via bash builtin command -v --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a7c5fe3b..2a500dfc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,11 +44,11 @@ jobs: set -euo pipefail TEST_PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH" for bin in mkfs.erofs mkfs.ext4 iptables; do - if ! sudo env "PATH=$TEST_PATH" command -v "$bin" >/dev/null; then + if ! sudo env "PATH=$TEST_PATH" bash -lc "command -v '$bin' >/dev/null"; then echo "missing required binary under sudo PATH: $bin" exit 1 fi - sudo env "PATH=$TEST_PATH" command -v "$bin" + sudo env "PATH=$TEST_PATH" bash -lc "command -v '$bin'" done # Avoids rate limits when running the tests From 540d1e47ab4ab26c14b3f52c22889e25f8b0105d Mon Sep 17 00:00:00 2001 From: Steven Miller Date: Sat, 7 Mar 2026 13:27:59 -0500 Subject: [PATCH 7/8] ci: trigger stability run 2/5 after merge From f3b95a1b3aef630e83ceddabed5be4b4d2aa0416 Mon Sep 17 00:00:00 2001 From: Steven Miller Date: Sat, 7 Mar 2026 13:30:44 -0500 Subject: [PATCH 8/8] ci: trigger stability run 3/5 after merge