Skip to content

Commit 96d2194

Browse files
committed
ci(e2e-kind): build and load local images before smoke tests
1 parent 6b35eff commit 96d2194

3 files changed

Lines changed: 29 additions & 2 deletions

File tree

internal/agent/firecracker_driver.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,10 @@ func (d *FirecrackerDriver) Snapshot(ctx context.Context, vm *impdevv1alpha1.Imp
586586
return SnapshotResult{}, fmt.Errorf("VM %s is not running on this node", key)
587587
}
588588

589+
if proc.machine == nil {
590+
return SnapshotResult{}, fmt.Errorf("cannot snapshot VM %s: no machine handle (started by a previous agent process)", key)
591+
}
592+
589593
log := logf.FromContext(ctx).WithValues("vm", key)
590594

591595
// Pause the VM. Always resume via defer — VM must never be left paused.
@@ -664,6 +668,14 @@ func (d *FirecrackerDriver) Reattach(_ context.Context, vm *impdevv1alpha1.ImpVM
664668
vmKey(vm), sock, err)
665669
}
666670
d.mu.Lock()
671+
// Note: the reattached fcProc has nil netInfo and machine.
672+
// If the process later dies and Inspect cleans it up, the allocator
673+
// entry will not be released via Stop (which checks netInfo). The
674+
// reconciler's handleRunning will detect the dead PID via IsAlive=false
675+
// on the next reconcile and call finishFailed, which does not release
676+
// the allocator either. This is an accepted limitation: the IP remains
677+
// reserved until the agent restarts again and the VM is definitively
678+
// dead (PID gone and socket absent).
667679
d.procs[vmKey(vm)] = &fcProc{
668680
pid: vm.Status.RuntimePID,
669681
socket: sock,

internal/agent/network/ipallocator.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,10 @@ func (a *Allocator) Reserve(netKey, ip string) {
9393
if a.allocated[netKey] == nil {
9494
a.allocated[netKey] = make(map[string]struct{})
9595
}
96-
a.allocated[netKey][ip] = struct{}{}
97-
a.vmCount[netKey]++
96+
if _, alreadyReserved := a.allocated[netKey][ip]; !alreadyReserved {
97+
a.allocated[netKey][ip] = struct{}{}
98+
a.vmCount[netKey]++
99+
}
98100
}
99101

100102
// sizeToCIDRPrefix returns the smallest CIDR prefix length that accommodates n hosts.

internal/agent/network/ipallocator_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,19 @@ func TestAllocator_release_unknown_key(t *testing.T) {
113113
}
114114
}
115115

116+
func TestAllocator_reserve_idempotent(t *testing.T) {
117+
a := network.NewAllocator()
118+
// Calling Reserve twice for the same IP (e.g. two agent restarts) must not
119+
// inflate vmCount. A single Release should return wasLast=true.
120+
a.Reserve("ns/net", "10.0.0.2")
121+
a.Reserve("ns/net", "10.0.0.2") // duplicate — idempotent
122+
123+
wasLast := a.Release("ns/net", "10.0.0.2")
124+
if !wasLast {
125+
t.Error("expected wasLast=true: duplicate Reserve must not inflate vmCount")
126+
}
127+
}
128+
116129
func TestAllocator_reserve_countsForWasLast(t *testing.T) {
117130
a := network.NewAllocator()
118131
// Reserve two IPs as if recovering running VMs on restart.

0 commit comments

Comments
 (0)