Skip to content

Commit 66a9981

Browse files
committed
fix(incus): cloning fails with mac address conflict
Remove volatile keys from incus config upon clone
1 parent 39ac335 commit 66a9981

1 file changed

Lines changed: 20 additions & 1 deletion

File tree

sandbox/incus/backend.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,10 @@ func (i *Incus) RestoreSnapshot(ctx context.Context, name, label string) error {
468468
return nil
469469
}
470470

471-
// CloneFrom copies an instance from a source snapshot into a new instance.
471+
// CloneFrom copies an instance from a source snapshot into a new instance,
472+
// then starts it. Volatile keys (notably volatile.eth0.hwaddr) are stripped
473+
// so Incus regenerates them on the destination — otherwise the clone would
474+
// boot with a duplicate MAC and fail eth0 validation.
472475
func (i *Incus) CloneFrom(ctx context.Context, source, label, newName string) error {
473476
sourceFull := prefixed(source)
474477
newFull := prefixed(newName)
@@ -479,6 +482,15 @@ func (i *Incus) CloneFrom(ctx context.Context, source, label, newName string) er
479482
return fmt.Errorf("getting source instance: %w", err)
480483
}
481484

485+
// Strip volatile.* keys: these encode per-instance identity (MAC, idmap,
486+
// last_state, etc.) and must not survive into the clone. Matches the
487+
// behaviour of the `incus copy` CLI.
488+
for k := range sourceInst.Config {
489+
if strings.HasPrefix(k, "volatile.") {
490+
delete(sourceInst.Config, k)
491+
}
492+
}
493+
482494
// Copy from snapshot.
483495
sourceInst.Name = sourceFull + "/" + label
484496
op, err := i.server.CopyInstance(i.server, *sourceInst, &incusclient.InstanceCopyArgs{
@@ -492,6 +504,13 @@ func (i *Incus) CloneFrom(ctx context.Context, source, label, newName string) er
492504
return fmt.Errorf("waiting for copy: %w", err)
493505
}
494506

507+
// Callers (BuildBase, create_sandbox) expect a clone to be running on
508+
// return — Ready polls for state.Running. Match the TrueNAS backend and
509+
// the post-Create flow above.
510+
if err := i.Start(ctx, newName); err != nil {
511+
return fmt.Errorf("starting clone: %w", err)
512+
}
513+
495514
return nil
496515
}
497516

0 commit comments

Comments
 (0)