fix(reboot): expose windows99 vmx repair package readback
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m34s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled

This commit is contained in:
Your Name
2026-07-03 11:00:29 +08:00
parent aed26bae84
commit 44a308d4e5
6 changed files with 245 additions and 6 deletions

View File

@@ -112,6 +112,34 @@ _WINDOWS99_POWERED_OFF_NEXT_SAFE_ACTION = (
"build_windows99_vmware_autostart_check_mode_package_for_powered_off_aliases_"
"then_rerun_no_secret_collector_no_vm_power_change"
)
_WINDOWS99_REQUIRED_VM_ALIASES = ["111", "188", "120", "121", "112"]
_WINDOWS99_EXPECTED_VMX_CANDIDATES = {
"111": [
r"D:\Documents\Virtual Machines\192.168.0.111_Ubuntu_64-bit\192.168.0.111_Ubuntu_64-bit.vmx",
],
"188": [
r"D:\Documents\Virtual Machines\Ollama_Ubuntu_64-bit\Ollama_Ubuntu_64-bit.vmx",
],
"120": [
r"D:\Documents\Virtual Machines\192.168.0.120_Ubuntu_64-bit\192.168.0.120_Ubuntu_64-bit.vmx",
],
"121": [
r"D:\Documents\Virtual Machines\192.168.0.121_Ubuntu_64-bit\192.168.0.121_Ubuntu_64-bit.vmx",
],
"112": [
r"D:\Downloads\kali-linux-2025.4-vmware-amd64\kali-linux-2025.4-vmware-amd64.vmwarevm\kali-linux-2025.4-vmware-amd64.vmx",
],
}
_WINDOWS99_VMX_REPAIR_FORBIDDEN_ACTIONS = [
"read_windows_password_or_secret",
"vm_power_change",
"vmrun_start_or_stop",
"host_reboot",
"windows_service_restart",
"windows_registry_apply",
"scheduled_task_register_or_modify",
"docker_nginx_k3s_db_firewall_restart",
]
def load_latest_reboot_auto_recovery_slo_scorecard(
@@ -771,6 +799,12 @@ def _apply_prometheus_windows99_vmware_readback(
rollups["windows99_verify_collection_blocker_count"] = len(
_strings(collection.get("collection_blockers"))
)
_sync_windows99_vmx_source_repair_package(
payload,
generated_at=str(
payload.get("runtime_readback_generated_at") or _taipei_now_iso()
),
)
def _reconcile_prometheus_metric_active_blockers_with_source_controls(
@@ -1643,6 +1677,12 @@ def _build_payload(scorecard: dict[str, Any], path: Path) -> dict[str, Any]:
windows99_management=windows99_management,
windows99_collector=windows99_collector,
)
windows99_vmx_source_repair_package = (
_build_windows99_vmx_source_repair_package(
windows99,
generated_at=runtime_readback_generated_at,
)
)
blocked_by_fresh_reboot_window_only = active_blockers == [
"host_boot_observation_older_than_target_window"
]
@@ -1769,6 +1809,22 @@ def _build_payload(scorecard: dict[str, Any], path: Path) -> dict[str, Any]:
"windows99_vmware_powered_off_count": len(
_strings(windows99.get("powered_off_aliases"))
),
"windows99_vmx_source_repair_package_ready": (
windows99_vmx_source_repair_package["package_ready"] is True
),
"windows99_vmx_source_repair_package_status": str(
windows99_vmx_source_repair_package["status"]
),
"windows99_vmx_source_repair_package_safe_next_step": str(
windows99_vmx_source_repair_package["safe_next_step"]
),
"windows99_vmx_source_repair_package_apply_allowed": (
windows99_vmx_source_repair_package["apply_allowed_by_this_package"]
is True
),
"windows99_vmx_source_repair_missing_vmx_aliases": _strings(
windows99_vmx_source_repair_package.get("missing_vmx_aliases")
),
"windows99_verify_collection_status": windows99_verify_collection["status"],
"windows99_verify_collection_can_collect_no_secret": (
windows99_verify_collection["can_collect_no_secret_verify"] is True
@@ -1960,6 +2016,21 @@ def _build_payload(scorecard: dict[str, Any], path: Path) -> dict[str, Any]:
"windows99_update_no_auto_reboot_ready": rollups[
"windows99_update_no_auto_reboot_ready"
],
"windows99_vmx_source_repair_package_ready": rollups[
"windows99_vmx_source_repair_package_ready"
],
"windows99_vmx_source_repair_package_status": rollups[
"windows99_vmx_source_repair_package_status"
],
"windows99_vmx_source_repair_package_safe_next_step": rollups[
"windows99_vmx_source_repair_package_safe_next_step"
],
"windows99_vmx_source_repair_package_apply_allowed": rollups[
"windows99_vmx_source_repair_package_apply_allowed"
],
"windows99_vmx_source_repair_missing_vmx_aliases": rollups[
"windows99_vmx_source_repair_missing_vmx_aliases"
],
"windows99_verify_collection_status": rollups[
"windows99_verify_collection_status"
],
@@ -2015,6 +2086,7 @@ def _build_payload(scorecard: dict[str, Any], path: Path) -> dict[str, Any]:
"public_maintenance_fallback": public_maintenance,
"windows99_vmware_autostart": windows99,
"windows99_vmware_verify_collector": windows99_collector,
"windows99_vmx_source_repair_package": windows99_vmx_source_repair_package,
"windows99_verify_collection": windows99_verify_collection,
"windows99_management_channel": windows99_management,
"source_controls": source_controls,
@@ -2357,6 +2429,132 @@ def _build_windows99_verify_collection_packet(
}
def _powershell_test_path(path: str) -> str:
escaped = path.replace("'", "''")
return f"Test-Path -LiteralPath '{escaped}'"
def _build_windows99_vmx_source_repair_package(
windows99: dict[str, Any],
*,
generated_at: str,
) -> dict[str, Any]:
missing_vmx_aliases = _unique_strings(
_strings(windows99.get("missing_vmx_aliases"))
)
powered_off_aliases = _unique_strings(
_strings(windows99.get("powered_off_aliases"))
)
required_aliases = _unique_strings(
_strings(windows99.get("required_vm_aliases"))
or _WINDOWS99_REQUIRED_VM_ALIASES
)
package_ready = bool(missing_vmx_aliases or powered_off_aliases)
if missing_vmx_aliases:
status = "check_mode_package_ready_windows99_vmx_source_repair_required"
safe_next_step = _WINDOWS99_MISSING_VMX_NEXT_SAFE_ACTION
elif powered_off_aliases:
status = "check_mode_package_ready_windows99_power_check_required"
safe_next_step = _WINDOWS99_POWERED_OFF_NEXT_SAFE_ACTION
else:
status = "ready_no_windows99_vmx_source_repair_required"
safe_next_step = "rerun_no_secret_collector_and_reboot_slo_scorecard_verify_only"
rows: list[dict[str, Any]] = []
for alias in required_aliases:
candidates = _WINDOWS99_EXPECTED_VMX_CANDIDATES.get(alias, [])
rows.append(
{
"alias": alias,
"missing_vmx_source": alias in missing_vmx_aliases,
"powered_off": alias in powered_off_aliases,
"expected_vmx_candidates": candidates,
"check_mode_probe_commands": [
_powershell_test_path(candidate) for candidate in candidates
],
"controlled_restore_required": alias in missing_vmx_aliases,
"controlled_restore_hint": (
"restore_or_relink_existing_vmx_source_to_expected_path_then_verify"
if alias in missing_vmx_aliases
else ""
),
}
)
return {
"schema_version": "windows99_vmx_source_repair_check_mode_package_v1",
"generated_at": generated_at,
"status": status,
"package_ready": package_ready,
"target_host_alias": "99",
"missing_vmx_aliases": missing_vmx_aliases,
"powered_off_aliases": powered_off_aliases,
"required_vm_aliases": required_aliases,
"vm_rows": rows,
"safe_next_step": safe_next_step,
"controlled_apply_mode": "check_mode_package_only_no_windows_or_vm_write",
"apply_allowed_by_this_package": False,
"post_verifier": [
"bash scripts/reboot-recovery/collect-windows99-vmware-verify.sh --collect",
"bash scripts/reboot-recovery/install-reboot-auto-recovery-slo-110.sh --verify-only",
"GET /api/v1/agents/reboot-auto-recovery-slo-scorecard",
],
"forbidden_actions": _WINDOWS99_VMX_REPAIR_FORBIDDEN_ACTIONS,
"operation_boundaries": {
"secret_value_read": False,
"remote_write_performed": False,
"vm_power_change_performed": False,
"windows_service_restart_performed": False,
"windows_registry_apply_performed": False,
"host_reboot_performed": False,
},
}
def _sync_windows99_vmx_source_repair_package(
payload: dict[str, Any],
*,
generated_at: str,
) -> dict[str, Any]:
windows99 = _dict(payload.get("windows99_vmware_autostart"))
package = _build_windows99_vmx_source_repair_package(
windows99,
generated_at=generated_at,
)
payload["windows99_vmx_source_repair_package"] = package
readback = _dict(payload.setdefault("readback", {}))
readback["windows99_vmx_source_repair_package_ready"] = (
package["package_ready"] is True
)
readback["windows99_vmx_source_repair_package_status"] = str(package["status"])
readback["windows99_vmx_source_repair_package_safe_next_step"] = str(
package["safe_next_step"]
)
readback["windows99_vmx_source_repair_package_apply_allowed"] = (
package["apply_allowed_by_this_package"] is True
)
readback["windows99_vmx_source_repair_missing_vmx_aliases"] = _strings(
package.get("missing_vmx_aliases")
)
rollups = _dict(payload.setdefault("rollups", {}))
rollups["windows99_vmx_source_repair_package_ready"] = (
package["package_ready"] is True
)
rollups["windows99_vmx_source_repair_package_status"] = str(package["status"])
rollups["windows99_vmx_source_repair_package_safe_next_step"] = str(
package["safe_next_step"]
)
rollups["windows99_vmx_source_repair_package_apply_allowed"] = (
package["apply_allowed_by_this_package"] is True
)
rollups["windows99_vmx_source_repair_missing_vmx_aliases"] = _strings(
package.get("missing_vmx_aliases")
)
return package
def _host_row_by_alias(
host_boot_detection: dict[str, Any],
alias: str,

View File

@@ -440,6 +440,30 @@ def test_reboot_auto_recovery_slo_scorecard_overlays_prometheus_runtime_metrics(
== WINDOWS99_RUNTIME_READBACK_ADDED_BLOCKERS
)
assert payload["runtime_metric_runtime_readback_added_blocker_count"] == 2
package = payload["windows99_vmx_source_repair_package"]
assert package["schema_version"] == (
"windows99_vmx_source_repair_check_mode_package_v1"
)
assert package["package_ready"] is True
assert package["apply_allowed_by_this_package"] is False
assert package["missing_vmx_aliases"] == ["111"]
assert package["safe_next_step"] == EXPECTED_WINDOWS99_MISSING_VMX_NEXT_STEP
vm_rows = {row["alias"]: row for row in package["vm_rows"]}
assert vm_rows["111"]["controlled_restore_required"] is True
assert vm_rows["111"]["check_mode_probe_commands"] == [
(
"Test-Path -LiteralPath 'D:\\Documents\\Virtual Machines\\"
"192.168.0.111_Ubuntu_64-bit\\192.168.0.111_Ubuntu_64-bit.vmx'"
)
]
assert payload["readback"]["windows99_vmx_source_repair_package_ready"] is True
assert (
payload["readback"]["windows99_vmx_source_repair_package_apply_allowed"]
is False
)
assert payload["rollups"]["windows99_vmx_source_repair_missing_vmx_aliases"] == [
"111"
]
assert payload["service_green"] is True
assert payload["backup_core_green"] is True
assert payload["product_data_green"] is True