# Phase 4: Snapshot Management - Discussion Log

> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.

**Date:** 2026-03-23
**Phase:** 04-snapshot-management
**Mode:** `--auto` (all areas auto-resolved with recommended defaults)
**Areas discussed:** Snapshot Strategy, Partial Revert Failure Handling, Snapshot File Storage Layout, Concurrency Model

---

## Snapshot Strategy

| Option | Description | Selected |
|--------|-------------|----------|
| External disk-only | libvirt external snapshot mechanism — fast, no memory overhead, creates backing-chain overlay | ✓ |
| Internal QEMU snapshot | virDomainSnapshotCreateXML internal — slower, stored in image file | |
| Full memory + disk | Captures in-flight state via memory dump — slowest, needed for live state restore | |

**Auto-selected:** External disk-only  
**Rationale:** Design doc §4 explicitly states "Optimize for speed first" for snapshot strategy. External disk-only snapshots are the fastest option and align with the design doc's `include_memory=False` default — memory capture is available as opt-in via the `include_memory` parameter.

---

## Partial Revert Failure Handling

| Option | Description | Selected |
|--------|-------------|----------|
| All-or-nothing (strict) | Any node failure returns success=False with per-node status; no silent partial state | ✓ |
| Best-effort | Continue reverting remaining nodes even if one fails; report partial success | |

**Auto-selected:** All-or-nothing (strict)  
**Rationale:** Consistent with D-04 from Phase 2 (cluster_start with wait_for_ssh is strict all-or-nothing). Silent partial-revert would leave the cluster in an undefined mixed state, making it unreliable for test resets — the primary use case.

**Note:** `snapshot_delete` uses best-effort semantics (per D-08) since deletion failures don't invalidate cluster state.

---

## Snapshot File Storage Layout

| Option | Description | Selected |
|--------|-------------|----------|
| `{overlay_dir}/{cluster_name}/snapshots/{snapshot_name}/{node_name}.qcow2` | Cluster-namespaced, snapshot-scoped paths — consistent with D-10 pattern | ✓ |
| `{overlay_dir}/snapshots/{cluster_name}/{snapshot_name}/{node_name}.qcow2` | Snapshots at top level, then cluster-nested | |
| Alongside overlay disks | Same directory as overlay disks — flat layout | |

**Auto-selected:** `{overlay_dir}/{cluster_name}/snapshots/{snapshot_name}/{node_name}.qcow2`  
**Rationale:** Consistent with D-10 cluster-namespaced layout from Phase 2. Snapshot-scoped subdirectory makes per-snapshot cleanup straightforward. All cluster artifacts live under `{overlay_dir}/{cluster_name}/`.

---

## Concurrency Model

| Option | Description | Selected |
|--------|-------------|----------|
| asyncio.gather + existing libvirt executor | Per-node operations run concurrently; libvirt calls serialized via single-worker executor | ✓ |
| Sequential per node | One node at a time — simple but slow for large clusters | |
| Native threads per node | Spawn a thread per node — bypasses libvirt thread-safety requirement | |

**Auto-selected:** asyncio.gather + existing libvirt executor  
**Rationale:** Consistent with D-08 (libvirt not thread-safe, single ThreadPoolExecutor) and the async fan-out pattern established in Phase 3 node_exec_all. Per-node disk stat queries and qcow2 path operations can run fully concurrently; libvirt domain API calls are the only serialization point.

---

## Agent's Discretion

The following areas were identified as implementation decisions deferred to researcher/planner:
- Exact libvirt virDomainSnapshot XML format and flags for external disk-only snapshots
- Whether to use virDomainSnapshotCreateXML or qemu-img externally
- Return type definition for `snapshot_create` (currently `SnapshotStatus` in design doc, not in models.py)
- Disk size reporting (allocated vs virtual size)
- Graceful vs. forced VM shutdown sequence during snapshot_revert

## Deferred Ideas

None — discussion stayed within phase scope.
