---
phase: "07"
plan: "02"
subsystem: net
tags: [net-partition, iptables, fault-injection, fault-registry, tdd]
dependency_graph:
  requires: [vmcluster_mcp/net/fault_registry.py, vmcluster_mcp/models.py, vmcluster_mcp/topology/schema.py]
  provides: [vmcluster_mcp/net/fault.py, vmcluster_mcp/net/__init__.py]
  affects: [07-03 net_heal, 07-04 net_heal_all/net_fault_list, server.py tool registry]
tech_stack:
  added: [iptables subprocess via _run_host_cmd (asyncio.create_subprocess_exec)]
  patterns: [symmetric rule pairs, comment-tag cleanup (D-07), TDD red-green, structured_tool_handler (D-14)]
key_files:
  created:
    - vmcluster_mcp/net/fault.py
    - tests/test_net_partition.py
  modified:
    - vmcluster_mcp/net/__init__.py
    - vmcluster_mcp/server.py
decisions:
  - "build_partition_rules returns list[list[str]] — pure data, no I/O — enabling straightforward unit testing without subprocess mocks"
  - "apply_partition_rules returns deduplicated comment tags (list[str]) as rule_identifiers for FaultRegistry storage"
  - "remove_rules_by_comment parses iptables -L --line-numbers output and deletes in reverse order to avoid index shifting"
  - "net_partition not idempotent by design — each call creates a new handle per plan spec"
metrics:
  duration_s: 191
  completed_date: "2026-03-24"
  tasks: 2
  files: 4
requirements-completed: [FAULT-01]
---

# Phase 07 Plan 02: net_partition Tool Summary

**One-liner:** `net_partition` MCP tool with iptables symmetric DROP rules tagged `vmcluster:<cluster>:<handle_id>` and FaultRegistry persistence.

## What Was Built

`net_partition` is the first fault injection tool. It installs symmetric iptables FORWARD DROP rules between two node groups on the libvirt bridge, tags every rule with `vmcluster:<cluster>:<handle_id>` per D-07, and persists a `NetFaultHandle` in the `FaultRegistry` for cleanup by future `net_heal` / `net_heal_all` tools.

### Files Created / Modified

| File | Change |
|------|--------|
| `vmcluster_mcp/net/fault.py` | New — `build_partition_rules`, `apply_partition_rules`, `remove_rules_by_comment` (145 lines) |
| `vmcluster_mcp/net/__init__.py` | New — `net_partition` tool registration with FaultRegistry wiring (97 lines) |
| `vmcluster_mcp/server.py` | Modified — added `net` to tool registration import block |
| `tests/test_net_partition.py` | New — 15 unit tests for rule generation, apply, and remove functions (207 lines) |

### Commit History

| Commit | Type | Description |
|--------|------|-------------|
| `61a8d27` | `test(07-02)` | RED — failing tests for iptables rule builder, apply, and remove |
| `1693445` | `feat(07-02)` | GREEN — iptables rule builder, apply_partition_rules, remove_rules_by_comment |
| `7f5665c` | `feat(07-02)` | net_partition tool registered on MCP server with FaultRegistry persistence |

## Tasks Completed

### Task 1: iptables rule builder and host-side apply/remove (TDD) ✅

- `build_partition_rules(cluster_name, handle_id, bridge, ips_a, ips_b)` — generates symmetric A→B + B→A DROP rules with `vmcluster:<cluster>:<handle>` comment tag (D-07), targeting `-i/-o <bridge>` on FORWARD chain
- `apply_partition_rules(rules)` — dispatches each rule via `_run_host_cmd`, raises `RuntimeError` on failure, returns deduplicated comment tag identifiers
- `remove_rules_by_comment(comment_tag)` — lists FORWARD chain, finds matching line numbers, deletes in descending order (prevents index shifting), returns count removed; handles no-match gracefully

### Task 2: Wire net_partition tool to MCP server ✅

- `vmcluster_mcp/net/__init__.py` — `FaultRegistry` singleton loaded at import, `net_partition` decorated with `@mcp.tool()` + `@structured_tool_handler` (D-14). Resolves node names to IPs from topology, generates handle UUID, applies rules, persists to registry
- `vmcluster_mcp/server.py` — added `net` to module import block so tool registration fires at server startup

## Verification

```
$ python -m pytest tests/test_net_partition.py tests/test_fault_registry.py -v
37 passed in 1.16s

$ ruff check vmcluster_mcp/net/
All checks passed!
```

## Deviations from Plan

None — plan executed exactly as written.

## Known Stubs

None — `net_partition` is fully wired: topology resolution, rule application, and FaultRegistry persistence all operational.

## Self-Check: PASSED

- `vmcluster_mcp/net/fault.py` — FOUND
- `vmcluster_mcp/net/__init__.py` — FOUND
- `vmcluster_mcp/server.py` — FOUND (net import added)
- `tests/test_net_partition.py` — FOUND
- Commit `61a8d27` — FOUND
- Commit `1693445` — FOUND
- Commit `7f5665c` — FOUND
