[PR #14] [MERGED] Phase 4b: node OS update + manager self-update Python flows #14

Closed
opened 2026-06-02 22:21:39 +08:00 by ivenator1 · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/ivenator1/proxmox-management/pull/14
Author: @ivenator1
Created: 6/2/2026
Status: Merged
Merged: 6/2/2026
Merged by: @ivenator1

Base: mainHead: phase-4-vm-remote-node-flows


📝 Commits (3)

  • aa1d723 feat: port Phase 2+3 (node OS update + manager self-update) to Python
  • b01287e test: add driver + settings tests for Phase 4b; fix reboot_host check_mode
  • 13b3365 docs: update CLAUDE.md and roadmap for Phase 4b completion

📊 Changes

13 files changed (+1170 additions, -48 deletions)

View changed files

📝 CLAUDE.md (+23 -8)
📝 ansible/primitives/reboot_host.yml (+1 -0)
📝 docs/migration-roadmap.md (+71 -15)
📝 fleet-update.yml (+49 -20)
📝 proxmox_fleet/cli.py (+22 -2)
📝 proxmox_fleet/driver.py (+57 -0)
proxmox_fleet/flows/node.py (+196 -0)
📝 proxmox_fleet/models/settings.py (+7 -0)
📝 proxmox_fleet/status.py (+46 -0)
📝 tests/unit/test_driver.py (+215 -3)
tests/unit/test_flow_node.py (+378 -0)
📝 tests/unit/test_settings.py (+26 -0)
tests/unit/test_status_node.py (+79 -0)

📄 Description

Summary

  • Ports Phase 2 (serial node OS update + reboot loop) and Phase 3 (manager LXC self-update) from fleet-update.yml into flows/node.py, completing the migration of all five update phases to Python
  • run_node_update(): is_manager check via pct list, apt dist-upgrade with 5-retry loop, robust reboot check (reboot-required file OR kernel mismatch), proxy wait + 15 s settle post-reboot, node_status() status strings matching the Phase 2 Jinja tree byte-for-byte
  • run_manager_update(): apt on localhost with ignore_errors, reboot-required stat, never reboots
  • Wired behind --use-node-flow flag following the same pattern as all prior phases; legacy Phase 2/3 stays in fleet-update.yml gated by skip_phase_2/3 until real-run parity is retired
  • reboot_host.yml: added check_mode: false — Python owns the dry-run decision by passing either apt-get -s or the real command; Ansible check mode is bypassed at the primitive level
  • Parity verified on live cluster: fleet-update --use-node-flow --check -e fleet_dry_run=true produced identical fleet_node_data to the legacy Ansible path (all 5 nodes + Ansible-Manager, all OK)
  • Found and documented a legacy vm_update role bug: in dry-run mode the skipped "Update VM packages" task overwrites vm_apt_res with {skipped: true, changed: false}, silently dropping VMs from the Discord notification. Unaffected in real runs; Python driver (--use-vm-flow) is immune

New files

  • proxmox_fleet/flows/node.pyNodeFlowOutcome, run_node_update(), run_manager_update()
  • tests/unit/test_status_node.py — 15 parity tests for node_status(), manager_status(), node_should_report()
  • tests/unit/test_flow_node.py — 16 flow tests: normal, reboot, manager-host skip, idle, rescue, dry-run, apt retry, proxy wait, manager variants

Modified files

  • proxmox_fleet/status.pynode_status(), manager_status(), node_should_report()
  • proxmox_fleet/models/settings.pymanager_lxc_id, apt_proxy_ip, apt_proxy_port, node_dry_run, node_auto_reboot
  • proxmox_fleet/driver.py_fold_node_outcome(), run_node_phase() (serial abort-on-failure; manager always runs)
  • proxmox_fleet/cli.py--use-node-flow flag
  • fleet-update.yml — "Merge Python node state" play; skip_phase_2/3 gates
  • ansible/primitives/reboot_host.ymlcheck_mode: false
  • tests/unit/test_driver.py — 6 new run_node_phase() tests; ScriptedExecutor gains default= param
  • tests/unit/test_settings.py — 2 new tests for node/manager fields
  • CLAUDE.md, docs/migration-roadmap.md — updated throughout

Test plan

  • pytest tests/unit/ -q → 541 passed
  • python -m mypy proxmox_fleet/ → no issues
  • fleet-update --use-node-flow --check -e fleet_dry_run=true on live cluster → all nodes OK, Phase 2/3 skipped in Ansible, Discord notification sent
  • Compare fleet_node_data with and without flag → byte-identical

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/ivenator1/proxmox-management/pull/14 **Author:** [@ivenator1](https://github.com/ivenator1) **Created:** 6/2/2026 **Status:** ✅ Merged **Merged:** 6/2/2026 **Merged by:** [@ivenator1](https://github.com/ivenator1) **Base:** `main` ← **Head:** `phase-4-vm-remote-node-flows` --- ### 📝 Commits (3) - [`aa1d723`](https://github.com/ivenator1/proxmox-management/commit/aa1d72329b134a2eb656201bb7daaf1125681fc6) feat: port Phase 2+3 (node OS update + manager self-update) to Python - [`b01287e`](https://github.com/ivenator1/proxmox-management/commit/b01287e24d3fdc33de6e712babab66bdbe79dd6d) test: add driver + settings tests for Phase 4b; fix reboot_host check_mode - [`13b3365`](https://github.com/ivenator1/proxmox-management/commit/13b3365e2ca3733b468c1c2415b5ce027fbfc10a) docs: update CLAUDE.md and roadmap for Phase 4b completion ### 📊 Changes **13 files changed** (+1170 additions, -48 deletions) <details> <summary>View changed files</summary> 📝 `CLAUDE.md` (+23 -8) 📝 `ansible/primitives/reboot_host.yml` (+1 -0) 📝 `docs/migration-roadmap.md` (+71 -15) 📝 `fleet-update.yml` (+49 -20) 📝 `proxmox_fleet/cli.py` (+22 -2) 📝 `proxmox_fleet/driver.py` (+57 -0) ➕ `proxmox_fleet/flows/node.py` (+196 -0) 📝 `proxmox_fleet/models/settings.py` (+7 -0) 📝 `proxmox_fleet/status.py` (+46 -0) 📝 `tests/unit/test_driver.py` (+215 -3) ➕ `tests/unit/test_flow_node.py` (+378 -0) 📝 `tests/unit/test_settings.py` (+26 -0) ➕ `tests/unit/test_status_node.py` (+79 -0) </details> ### 📄 Description ## Summary - Ports Phase 2 (serial node OS update + reboot loop) and Phase 3 (manager LXC self-update) from `fleet-update.yml` into `flows/node.py`, completing the migration of all five update phases to Python - `run_node_update()`: is_manager check via `pct list`, apt dist-upgrade with 5-retry loop, robust reboot check (reboot-required file OR kernel mismatch), proxy wait + 15 s settle post-reboot, `node_status()` status strings matching the Phase 2 Jinja tree byte-for-byte - `run_manager_update()`: apt on localhost with `ignore_errors`, reboot-required stat, never reboots - Wired behind `--use-node-flow` flag following the same pattern as all prior phases; legacy Phase 2/3 stays in `fleet-update.yml` gated by `skip_phase_2/3` until real-run parity is retired - `reboot_host.yml`: added `check_mode: false` — Python owns the dry-run decision by passing either `apt-get -s` or the real command; Ansible check mode is bypassed at the primitive level - Parity verified on live cluster: `fleet-update --use-node-flow --check -e fleet_dry_run=true` produced identical `fleet_node_data` to the legacy Ansible path (all 5 nodes + Ansible-Manager, all OK) - Found and documented a legacy `vm_update` role bug: in dry-run mode the skipped "Update VM packages" task overwrites `vm_apt_res` with `{skipped: true, changed: false}`, silently dropping VMs from the Discord notification. Unaffected in real runs; Python driver (`--use-vm-flow`) is immune ## New files - `proxmox_fleet/flows/node.py` — `NodeFlowOutcome`, `run_node_update()`, `run_manager_update()` - `tests/unit/test_status_node.py` — 15 parity tests for `node_status()`, `manager_status()`, `node_should_report()` - `tests/unit/test_flow_node.py` — 16 flow tests: normal, reboot, manager-host skip, idle, rescue, dry-run, apt retry, proxy wait, manager variants ## Modified files - `proxmox_fleet/status.py` — `node_status()`, `manager_status()`, `node_should_report()` - `proxmox_fleet/models/settings.py` — `manager_lxc_id`, `apt_proxy_ip`, `apt_proxy_port`, `node_dry_run`, `node_auto_reboot` - `proxmox_fleet/driver.py` — `_fold_node_outcome()`, `run_node_phase()` (serial abort-on-failure; manager always runs) - `proxmox_fleet/cli.py` — `--use-node-flow` flag - `fleet-update.yml` — "Merge Python node state" play; `skip_phase_2/3` gates - `ansible/primitives/reboot_host.yml` — `check_mode: false` - `tests/unit/test_driver.py` — 6 new `run_node_phase()` tests; `ScriptedExecutor` gains `default=` param - `tests/unit/test_settings.py` — 2 new tests for node/manager fields - `CLAUDE.md`, `docs/migration-roadmap.md` — updated throughout ## Test plan - [x] `pytest tests/unit/ -q` → 541 passed - [x] `python -m mypy proxmox_fleet/` → no issues - [x] `fleet-update --use-node-flow --check -e fleet_dry_run=true` on live cluster → all nodes OK, Phase 2/3 skipped in Ansible, Discord notification sent - [x] Compare `fleet_node_data` with and without flag → byte-identical 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
ivenator1 2026-06-02 22:21:39 +08:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
ivenator1/proxmox-management#14
No description provided.