fix(reboot): add windows99 vmx backup search package
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m14s
CD Pipeline / build-and-deploy (push) Successful in 4m45s
CD Pipeline / post-deploy-checks (push) Successful in 1m57s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m14s
CD Pipeline / build-and-deploy (push) Successful in 4m45s
CD Pipeline / post-deploy-checks (push) Successful in 1m57s
This commit is contained in:
@@ -2987,6 +2987,9 @@ def _enrich_from_current_readbacks(
|
||||
from src.services.windows99_vmx_source_locator_readback import (
|
||||
build_windows99_vmx_source_locator_readback,
|
||||
)
|
||||
from src.services.windows99_vmx_source_backup_search_package import (
|
||||
build_windows99_vmx_source_backup_search_package,
|
||||
)
|
||||
from src.services.windows99_vmware_autostart_check_mode_package import (
|
||||
build_windows99_vmware_autostart_check_mode_package,
|
||||
)
|
||||
@@ -3044,6 +3047,12 @@ def _enrich_from_current_readbacks(
|
||||
repair_package=windows99_vmx_source_repair_package,
|
||||
)
|
||||
)
|
||||
windows99_vmx_source_backup_search_package = (
|
||||
build_windows99_vmx_source_backup_search_package(
|
||||
reboot_slo,
|
||||
locator_readback=windows99_vmx_source_locator_readback,
|
||||
)
|
||||
)
|
||||
windows99_vmx_source_repair_action_chain = _dict(
|
||||
windows99_vmx_source_repair_package.get("action_chain")
|
||||
)
|
||||
@@ -3818,6 +3827,74 @@ def _enrich_from_current_readbacks(
|
||||
state["windows99_vmx_source_locator_vm_power_change_performed"] = bool(
|
||||
windows99_vmx_source_locator_readback.get("vm_power_change_performed") is True
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_package_status"] = str(
|
||||
windows99_vmx_source_backup_search_package.get("status") or "unknown"
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_package_ready"] = bool(
|
||||
windows99_vmx_source_backup_search_package.get("package_ready") is True
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_target_aliases"] = _strings(
|
||||
windows99_vmx_source_backup_search_package.get("target_vm_aliases")
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_next_executable_step"] = str(
|
||||
windows99_vmx_source_backup_search_package.get("next_executable_step") or ""
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_safe_next_step"] = str(
|
||||
windows99_vmx_source_backup_search_package.get("safe_next_step") or ""
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_receipt_readback_present"] = bool(
|
||||
windows99_vmx_source_backup_search_package.get("receipt_readback_present")
|
||||
is True
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_host_count"] = _int(
|
||||
windows99_vmx_source_backup_search_package.get("search_host_count")
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_searched_host_count"] = _int(
|
||||
windows99_vmx_source_backup_search_package.get("searched_host_count")
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_blocked_host_count"] = _int(
|
||||
windows99_vmx_source_backup_search_package.get("blocked_host_count")
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_pending_host_count"] = _int(
|
||||
windows99_vmx_source_backup_search_package.get("pending_host_count")
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_blocked_host_aliases"] = _strings(
|
||||
windows99_vmx_source_backup_search_package.get("blocked_host_aliases")
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_candidate_source_count"] = _int(
|
||||
windows99_vmx_source_backup_search_package.get("candidate_source_count")
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_candidate_fingerprint_count"] = _int(
|
||||
windows99_vmx_source_backup_search_package.get(
|
||||
"candidate_source_fingerprint_count"
|
||||
)
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_candidate_source_found"] = bool(
|
||||
windows99_vmx_source_backup_search_package.get("candidate_source_found")
|
||||
is True
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_apply_allowed_by_this_package"] = bool(
|
||||
windows99_vmx_source_backup_search_package.get("apply_allowed_by_this_package")
|
||||
is True
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_raw_path_output"] = bool(
|
||||
windows99_vmx_source_backup_search_package.get("raw_path_output") is True
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_path_fingerprint_only"] = bool(
|
||||
windows99_vmx_source_backup_search_package.get("path_fingerprint_only")
|
||||
is True
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_file_content_read"] = bool(
|
||||
windows99_vmx_source_backup_search_package.get("file_content_read") is True
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_remote_write_performed"] = bool(
|
||||
windows99_vmx_source_backup_search_package.get("remote_write_performed")
|
||||
is True
|
||||
)
|
||||
state["windows99_vmx_source_backup_search_vm_power_change_performed"] = bool(
|
||||
windows99_vmx_source_backup_search_package.get("vm_power_change_performed")
|
||||
is True
|
||||
)
|
||||
state["stale_snapshot_or_old_cd_runs_must_not_reopen_closed_work"] = True
|
||||
state["p0_004_template_copy_apply_gate_production_http_status"] = 200
|
||||
state["p0_004_template_copy_apply_gate_runtime_readback_state"] = (
|
||||
@@ -4404,6 +4481,66 @@ def _enrich_from_current_readbacks(
|
||||
evidence["windows99_vmx_source_locator_vm_power_change_performed"] = state[
|
||||
"windows99_vmx_source_locator_vm_power_change_performed"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_package_status"] = state[
|
||||
"windows99_vmx_source_backup_search_package_status"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_package_ready"] = state[
|
||||
"windows99_vmx_source_backup_search_package_ready"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_target_aliases"] = state[
|
||||
"windows99_vmx_source_backup_search_target_aliases"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_next_executable_step"] = state[
|
||||
"windows99_vmx_source_backup_search_next_executable_step"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_safe_next_step"] = state[
|
||||
"windows99_vmx_source_backup_search_safe_next_step"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_receipt_readback_present"] = (
|
||||
state["windows99_vmx_source_backup_search_receipt_readback_present"]
|
||||
)
|
||||
evidence["windows99_vmx_source_backup_search_host_count"] = state[
|
||||
"windows99_vmx_source_backup_search_host_count"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_searched_host_count"] = state[
|
||||
"windows99_vmx_source_backup_search_searched_host_count"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_blocked_host_count"] = state[
|
||||
"windows99_vmx_source_backup_search_blocked_host_count"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_pending_host_count"] = state[
|
||||
"windows99_vmx_source_backup_search_pending_host_count"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_blocked_host_aliases"] = state[
|
||||
"windows99_vmx_source_backup_search_blocked_host_aliases"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_candidate_source_count"] = state[
|
||||
"windows99_vmx_source_backup_search_candidate_source_count"
|
||||
]
|
||||
evidence[
|
||||
"windows99_vmx_source_backup_search_candidate_fingerprint_count"
|
||||
] = state["windows99_vmx_source_backup_search_candidate_fingerprint_count"]
|
||||
evidence["windows99_vmx_source_backup_search_candidate_source_found"] = state[
|
||||
"windows99_vmx_source_backup_search_candidate_source_found"
|
||||
]
|
||||
evidence[
|
||||
"windows99_vmx_source_backup_search_apply_allowed_by_this_package"
|
||||
] = state["windows99_vmx_source_backup_search_apply_allowed_by_this_package"]
|
||||
evidence["windows99_vmx_source_backup_search_raw_path_output"] = state[
|
||||
"windows99_vmx_source_backup_search_raw_path_output"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_path_fingerprint_only"] = state[
|
||||
"windows99_vmx_source_backup_search_path_fingerprint_only"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_file_content_read"] = state[
|
||||
"windows99_vmx_source_backup_search_file_content_read"
|
||||
]
|
||||
evidence["windows99_vmx_source_backup_search_remote_write_performed"] = state[
|
||||
"windows99_vmx_source_backup_search_remote_write_performed"
|
||||
]
|
||||
evidence[
|
||||
"windows99_vmx_source_backup_search_vm_power_change_performed"
|
||||
] = state["windows99_vmx_source_backup_search_vm_power_change_performed"]
|
||||
evidence["drill_preflight_status"] = str(reboot_preflight.get("status") or "")
|
||||
evidence["drill_preflight_ready"] = (
|
||||
reboot_preflight_rollups.get("preflight_ready") is True
|
||||
@@ -4684,11 +4821,29 @@ def _refresh_rollups_after_stockplatform_overlay(
|
||||
rollups.get("active_p0_event_gated_by_fresh_reboot_window_only") is True
|
||||
and not stock_blocked
|
||||
)
|
||||
rollups["windows99_vmx_source_backup_search_status"] = str(
|
||||
state.get("windows99_vmx_source_backup_search_package_status") or "unknown"
|
||||
)
|
||||
rollups["windows99_vmx_source_backup_search_candidate_source_count"] = _int(
|
||||
state.get("windows99_vmx_source_backup_search_candidate_source_count")
|
||||
)
|
||||
rollups["windows99_vmx_source_backup_search_blocked_host_count"] = _int(
|
||||
state.get("windows99_vmx_source_backup_search_blocked_host_count")
|
||||
)
|
||||
|
||||
summary = _dict(payload.setdefault("summary", {}))
|
||||
summary["status"] = str(payload.get("status") or "")
|
||||
summary["active_p0_state"] = str(state.get("active_p0_state") or "")
|
||||
summary["active_p0_live_active_blockers"] = active_blockers
|
||||
summary["windows99_vmx_source_backup_search_status"] = str(
|
||||
state.get("windows99_vmx_source_backup_search_package_status") or "unknown"
|
||||
)
|
||||
summary["windows99_vmx_source_backup_search_candidate_source_count"] = _int(
|
||||
state.get("windows99_vmx_source_backup_search_candidate_source_count")
|
||||
)
|
||||
summary["windows99_vmx_source_backup_search_safe_next_step"] = str(
|
||||
state.get("windows99_vmx_source_backup_search_safe_next_step") or ""
|
||||
)
|
||||
summary["stockplatform_public_api_runtime_status"] = str(
|
||||
state.get("stockplatform_public_api_runtime_status") or "unknown"
|
||||
)
|
||||
@@ -5309,6 +5464,33 @@ def _set_rollups_and_summary(
|
||||
state.get("windows99_vmx_source_locator_vm_power_change_performed")
|
||||
is True
|
||||
),
|
||||
"windows99_vmx_source_backup_search_status": str(
|
||||
state.get("windows99_vmx_source_backup_search_package_status")
|
||||
or "unknown"
|
||||
),
|
||||
"windows99_vmx_source_backup_search_package_ready": (
|
||||
state.get("windows99_vmx_source_backup_search_package_ready") is True
|
||||
),
|
||||
"windows99_vmx_source_backup_search_candidate_source_count": _int(
|
||||
state.get("windows99_vmx_source_backup_search_candidate_source_count")
|
||||
),
|
||||
"windows99_vmx_source_backup_search_blocked_host_count": _int(
|
||||
state.get("windows99_vmx_source_backup_search_blocked_host_count")
|
||||
),
|
||||
"windows99_vmx_source_backup_search_apply_allowed_by_this_package": (
|
||||
state.get(
|
||||
"windows99_vmx_source_backup_search_apply_allowed_by_this_package"
|
||||
)
|
||||
is True
|
||||
),
|
||||
"windows99_vmx_source_backup_search_remote_write_performed": (
|
||||
state.get("windows99_vmx_source_backup_search_remote_write_performed")
|
||||
is True
|
||||
),
|
||||
"windows99_vmx_source_backup_search_vm_power_change_performed": (
|
||||
state.get("windows99_vmx_source_backup_search_vm_power_change_performed")
|
||||
is True
|
||||
),
|
||||
"p0_004_runtime_readback_ready": p0_004_ready,
|
||||
"reboot_drill_preflight_runtime_readback_ready": (
|
||||
state.get("reboot_drill_preflight_runtime_readback_state") == "ready"
|
||||
@@ -5744,6 +5926,36 @@ def _set_rollups_and_summary(
|
||||
state.get("windows99_vmx_source_locator_vm_power_change_performed")
|
||||
is True
|
||||
),
|
||||
"windows99_vmx_source_backup_search_status": str(
|
||||
state.get("windows99_vmx_source_backup_search_package_status")
|
||||
or "unknown"
|
||||
),
|
||||
"windows99_vmx_source_backup_search_package_ready": (
|
||||
state.get("windows99_vmx_source_backup_search_package_ready") is True
|
||||
),
|
||||
"windows99_vmx_source_backup_search_candidate_source_count": _int(
|
||||
state.get("windows99_vmx_source_backup_search_candidate_source_count")
|
||||
),
|
||||
"windows99_vmx_source_backup_search_blocked_host_count": _int(
|
||||
state.get("windows99_vmx_source_backup_search_blocked_host_count")
|
||||
),
|
||||
"windows99_vmx_source_backup_search_safe_next_step": str(
|
||||
state.get("windows99_vmx_source_backup_search_safe_next_step") or ""
|
||||
),
|
||||
"windows99_vmx_source_backup_search_apply_allowed_by_this_package": (
|
||||
state.get(
|
||||
"windows99_vmx_source_backup_search_apply_allowed_by_this_package"
|
||||
)
|
||||
is True
|
||||
),
|
||||
"windows99_vmx_source_backup_search_remote_write_performed": (
|
||||
state.get("windows99_vmx_source_backup_search_remote_write_performed")
|
||||
is True
|
||||
),
|
||||
"windows99_vmx_source_backup_search_vm_power_change_performed": (
|
||||
state.get("windows99_vmx_source_backup_search_vm_power_change_performed")
|
||||
is True
|
||||
),
|
||||
"windows99_winrm_http_open": (
|
||||
state.get("windows99_winrm_http_open") is True
|
||||
),
|
||||
|
||||
@@ -0,0 +1,323 @@
|
||||
"""Windows99 VMX source backup-search check-mode package.
|
||||
|
||||
This readback turns "111 VMX source not found" into a fixed no-secret search
|
||||
contract across backup/source hosts. It does not SSH from the API, read VMX
|
||||
contents, expose raw paths, write Windows state, start VMs, stop VMs, restart
|
||||
services, or reboot hosts.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from src.services.reboot_auto_recovery_slo_scorecard import (
|
||||
_taipei_now_iso,
|
||||
load_latest_reboot_auto_recovery_slo_scorecard,
|
||||
)
|
||||
from src.services.snapshot_paths import default_operations_dir
|
||||
from src.services.windows99_vmx_source_locator_readback import (
|
||||
build_windows99_vmx_source_locator_readback,
|
||||
)
|
||||
from src.services.windows99_vmx_source_repair_package import (
|
||||
build_windows99_vmx_source_repair_package,
|
||||
)
|
||||
|
||||
_DEFAULT_OPERATIONS_DIR = default_operations_dir(Path(__file__))
|
||||
_SCHEMA_VERSION = "windows99_vmx_source_backup_search_package_v1"
|
||||
_RECEIPT_SCHEMA_VERSION = "windows99_vmx_source_backup_search_receipt_v1"
|
||||
_RECEIPT_FILE = "windows99-vmx-source-backup-search-receipt.snapshot.json"
|
||||
_COLLECTOR_SCRIPT_PATH = (
|
||||
"scripts/reboot-recovery/collect-windows99-vmx-source-backup-search.sh"
|
||||
)
|
||||
_DEFAULT_SEARCH_HOSTS = ["99", "110", "120", "121", "188", "112", "local"]
|
||||
_FORBIDDEN_ACTIONS = [
|
||||
"read_windows_password_or_secret",
|
||||
"read_vmx_file_contents",
|
||||
"emit_raw_internal_paths_on_public_endpoint",
|
||||
"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",
|
||||
"destructive_restore",
|
||||
]
|
||||
|
||||
|
||||
def _dict(value: Any) -> dict[str, Any]:
|
||||
return value if isinstance(value, dict) else {}
|
||||
|
||||
|
||||
def _list(value: Any) -> list[Any]:
|
||||
return value if isinstance(value, list) else []
|
||||
|
||||
|
||||
def _strings(value: Any) -> list[str]:
|
||||
if isinstance(value, list):
|
||||
return [str(item).strip() for item in value if str(item).strip()]
|
||||
if isinstance(value, str):
|
||||
return [part.strip() for part in value.split(",") if part.strip()]
|
||||
return []
|
||||
|
||||
|
||||
def _int(value: Any, default: int = 0) -> int:
|
||||
if isinstance(value, bool):
|
||||
return default
|
||||
if isinstance(value, int):
|
||||
return value
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
return int(value.strip())
|
||||
except ValueError:
|
||||
return default
|
||||
return default
|
||||
|
||||
|
||||
def _load_backup_search_receipt(operations_dir: Path | None = None) -> dict[str, Any]:
|
||||
path = (operations_dir or _DEFAULT_OPERATIONS_DIR) / _RECEIPT_FILE
|
||||
if not path.exists():
|
||||
return {}
|
||||
payload = json.loads(path.read_text(encoding="utf-8"))
|
||||
if not isinstance(payload, dict):
|
||||
raise ValueError(f"{path}: expected JSON object")
|
||||
if payload.get("schema_version") != _RECEIPT_SCHEMA_VERSION:
|
||||
raise ValueError(f"{path}: unexpected schema_version")
|
||||
serialized = json.dumps(payload, ensure_ascii=False)
|
||||
forbidden = ["192.168.0.", "D:\\", "C:\\", "E:\\", "/Users/", "/Volumes/"]
|
||||
leaked = [fragment for fragment in forbidden if fragment in serialized]
|
||||
if leaked:
|
||||
raise ValueError(f"{path}: unsafe backup-search receipt fragments: {leaked}")
|
||||
return payload
|
||||
|
||||
|
||||
def _receipt_applies(receipt: dict[str, Any], target_aliases: list[str]) -> bool:
|
||||
receipt_aliases = _strings(receipt.get("target_vm_aliases"))
|
||||
return bool(
|
||||
receipt.get("collector_readback_present") is True
|
||||
and receipt.get("target_host_alias") == "99"
|
||||
and receipt_aliases
|
||||
and set(receipt_aliases).issubset(set(target_aliases or receipt_aliases))
|
||||
)
|
||||
|
||||
|
||||
def _default_host_rows(locator_readback: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
locator_candidate_count = _int(locator_readback.get("candidate_source_count"), 0)
|
||||
locator_known = locator_readback.get("candidate_source_count_known") is True
|
||||
rows = [
|
||||
{
|
||||
"host_alias": "99",
|
||||
"search_role": "windows_vmware_roots_via_locator",
|
||||
"status": str(locator_readback.get("locate_status") or "not_collected"),
|
||||
"candidate_source_count": locator_candidate_count if locator_known else 0,
|
||||
"candidate_source_count_known": locator_known,
|
||||
"collector": "windows99-vmx-source-locator-readback",
|
||||
}
|
||||
]
|
||||
for alias in ["110", "120", "121", "188", "112", "local"]:
|
||||
rows.append(
|
||||
{
|
||||
"host_alias": alias,
|
||||
"search_role": "linux_or_local_backup_roots",
|
||||
"status": "check_mode_pending",
|
||||
"candidate_source_count": 0,
|
||||
"candidate_source_count_known": False,
|
||||
"collector": _COLLECTOR_SCRIPT_PATH,
|
||||
}
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
def _host_rows_from_receipt(
|
||||
receipt: dict[str, Any],
|
||||
locator_readback: dict[str, Any],
|
||||
) -> list[dict[str, Any]]:
|
||||
rows = _list(receipt.get("host_rows"))
|
||||
if rows:
|
||||
return [dict(row) for row in rows if isinstance(row, dict)]
|
||||
return _default_host_rows(locator_readback)
|
||||
|
||||
|
||||
def build_windows99_vmx_source_backup_search_package(
|
||||
scorecard: dict[str, Any],
|
||||
*,
|
||||
locator_readback: dict[str, Any] | None = None,
|
||||
collector_receipt: dict[str, Any] | None = None,
|
||||
operations_dir: Path | None = None,
|
||||
generated_at: str | None = None,
|
||||
) -> dict[str, Any]:
|
||||
repair_package = build_windows99_vmx_source_repair_package(scorecard)
|
||||
locator = locator_readback or build_windows99_vmx_source_locator_readback(
|
||||
scorecard,
|
||||
repair_package=repair_package,
|
||||
operations_dir=operations_dir,
|
||||
)
|
||||
missing_aliases = _strings(repair_package.get("missing_vmx_aliases"))
|
||||
target_aliases = missing_aliases or _strings(locator.get("target_vm_aliases"))
|
||||
receipt = (
|
||||
_dict(collector_receipt)
|
||||
if collector_receipt is not None
|
||||
else _load_backup_search_receipt(operations_dir)
|
||||
)
|
||||
receipt_applies = _receipt_applies(receipt, target_aliases)
|
||||
host_rows = (
|
||||
_host_rows_from_receipt(receipt, locator)
|
||||
if receipt_applies
|
||||
else _default_host_rows(locator)
|
||||
)
|
||||
searched_rows = [
|
||||
row for row in host_rows if row.get("status") in {"searched", "not_matched"}
|
||||
]
|
||||
blocked_rows = [
|
||||
row
|
||||
for row in host_rows
|
||||
if str(row.get("status") or "").startswith("blocked_")
|
||||
or row.get("status") == "transport_intermittent"
|
||||
]
|
||||
pending_rows = [
|
||||
row
|
||||
for row in host_rows
|
||||
if row.get("candidate_source_count_known") is not True
|
||||
and row not in blocked_rows
|
||||
]
|
||||
candidate_count = sum(_int(row.get("candidate_source_count"), 0) for row in host_rows)
|
||||
candidate_fingerprint_count = sum(
|
||||
_int(row.get("candidate_source_fingerprint_count"), 0) for row in host_rows
|
||||
)
|
||||
locator_candidate_count = _int(locator.get("candidate_source_count"), 0)
|
||||
locator_no_candidate = bool(
|
||||
locator.get("candidate_source_count_known") is True
|
||||
and locator_candidate_count == 0
|
||||
)
|
||||
search_required = bool(missing_aliases)
|
||||
|
||||
if not search_required:
|
||||
status = "ready_no_windows99_vmx_backup_search_required"
|
||||
next_step = "rerun_no_secret_vmware_verify_collector"
|
||||
safe_next_step = "rerun_no_secret_collector_and_reboot_slo_scorecard_verify_only"
|
||||
elif candidate_count > 0:
|
||||
status = "candidate_fingerprint_found_requires_internal_path_resolution"
|
||||
next_step = "resolve_candidate_fingerprint_to_authorized_internal_path"
|
||||
safe_next_step = (
|
||||
"resolve_candidate_fingerprint_to_authorized_internal_path_then_"
|
||||
"build_scoped_relink_dry_run_no_write"
|
||||
)
|
||||
elif receipt_applies and blocked_rows:
|
||||
status = "blocked_windows99_vmx_backup_source_not_found_some_hosts_unsearched"
|
||||
next_step = "rerun_backup_search_for_blocked_hosts_or_offline_inventory"
|
||||
safe_next_step = (
|
||||
"rerun_windows99_vmx_source_backup_search_check_mode_for_blocked_hosts_"
|
||||
"then_update_receipt_no_write"
|
||||
)
|
||||
elif receipt_applies:
|
||||
status = "blocked_windows99_vmx_backup_source_not_found"
|
||||
next_step = "continue_verified_backup_inventory_search_or_console_source_path"
|
||||
safe_next_step = (
|
||||
"recover_verified_external_backup_artifact_or_authorized_console_path_"
|
||||
"then_build_scoped_relink_dry_run_no_write"
|
||||
)
|
||||
elif locator_no_candidate:
|
||||
status = "check_mode_package_ready_windows99_vmx_backup_search_required"
|
||||
next_step = "run_windows99_vmx_source_backup_search_check_mode"
|
||||
safe_next_step = (
|
||||
"bash scripts/reboot-recovery/collect-windows99-vmx-source-backup-"
|
||||
"search.sh --timeout 35"
|
||||
)
|
||||
else:
|
||||
status = "check_mode_package_ready_windows99_vmx_identity_or_backup_search_required"
|
||||
next_step = "run_locator_confirmation_or_backup_search_check_mode"
|
||||
safe_next_step = (
|
||||
"confirm_locator_candidate_identity_or_run_backup_search_check_mode_"
|
||||
"before_scoped_relink_dry_run"
|
||||
)
|
||||
|
||||
return {
|
||||
"schema_version": _SCHEMA_VERSION,
|
||||
"generated_at": generated_at
|
||||
or str(scorecard.get("generated_at") or _taipei_now_iso()),
|
||||
"status": status,
|
||||
"package_ready": search_required,
|
||||
"target_host_alias": "99",
|
||||
"target_vm_aliases": target_aliases,
|
||||
"missing_vmx_aliases": missing_aliases,
|
||||
"next_executable_step": next_step,
|
||||
"safe_next_step": safe_next_step,
|
||||
"collector_script_path": _COLLECTOR_SCRIPT_PATH,
|
||||
"collector_schema_version": "windows99_vmx_source_backup_search_collector_v1",
|
||||
"collector_command": (
|
||||
"bash scripts/reboot-recovery/collect-windows99-vmx-source-backup-"
|
||||
"search.sh --timeout 35"
|
||||
),
|
||||
"receipt_readback_present": receipt_applies,
|
||||
"receipt_ref": str(receipt.get("receipt_ref") or "") if receipt_applies else "",
|
||||
"receipt_generated_at": str(receipt.get("generated_at") or "")
|
||||
if receipt_applies
|
||||
else "",
|
||||
"source_locator_status": str(locator.get("status") or "unknown"),
|
||||
"source_locator_candidate_source_count": locator_candidate_count,
|
||||
"source_locator_candidate_source_count_known": bool(
|
||||
locator.get("candidate_source_count_known") is True
|
||||
),
|
||||
"search_host_aliases": _DEFAULT_SEARCH_HOSTS,
|
||||
"host_rows": host_rows,
|
||||
"search_host_count": len(host_rows),
|
||||
"searched_host_count": len(searched_rows),
|
||||
"blocked_host_count": len(blocked_rows),
|
||||
"pending_host_count": len(pending_rows),
|
||||
"blocked_host_aliases": _strings(
|
||||
[row.get("host_alias") for row in blocked_rows]
|
||||
),
|
||||
"candidate_source_count": candidate_count,
|
||||
"candidate_source_fingerprint_count": candidate_fingerprint_count,
|
||||
"candidate_source_found": candidate_count > 0,
|
||||
"internal_path_resolution_required": candidate_count > 0,
|
||||
"public_lan_topology_redacted": True,
|
||||
"redacted_public_display_only": True,
|
||||
"raw_path_output": False,
|
||||
"path_fingerprint_only": True,
|
||||
"file_content_read": False,
|
||||
"secret_value_read": False,
|
||||
"password_prompt_allowed": False,
|
||||
"remote_write_performed": False,
|
||||
"host_reboot_performed": False,
|
||||
"vm_power_change_performed": False,
|
||||
"windows_service_restart_performed": False,
|
||||
"windows_registry_apply_performed": False,
|
||||
"scheduled_task_write_performed": False,
|
||||
"vm_power_change_allowed": False,
|
||||
"destructive_restore_allowed": False,
|
||||
"apply_allowed_by_this_package": False,
|
||||
"forbidden_actions": _FORBIDDEN_ACTIONS,
|
||||
"operation_boundaries": {
|
||||
"secret_value_read": False,
|
||||
"password_prompt_allowed": False,
|
||||
"file_content_read": False,
|
||||
"raw_path_output": False,
|
||||
"path_fingerprint_only": True,
|
||||
"remote_write_performed": False,
|
||||
"host_reboot_performed": False,
|
||||
"vm_power_change_performed": False,
|
||||
"windows_service_restart_performed": False,
|
||||
"windows_registry_apply_performed": False,
|
||||
"scheduled_task_write_performed": False,
|
||||
},
|
||||
"post_search_verifier": [
|
||||
"GET /api/v1/agents/windows99-vmx-source-backup-search-package",
|
||||
"GET /api/v1/agents/windows99-vmx-source-locator-readback",
|
||||
"GET /api/v1/agents/reboot-auto-recovery-slo-scorecard",
|
||||
"GET /api/v1/agents/awoooi-priority-work-order-readback",
|
||||
],
|
||||
"km_writeback_ref": "km://awoooi/reboot-slo/windows99-vmx-source-backup-search-111",
|
||||
"playbook_trust_writeback_ref": (
|
||||
"playbook://awoooi/windows99-vmx-source-backup-search/"
|
||||
"windows99-vmx-source-backup-search-111"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def load_latest_windows99_vmx_source_backup_search_package() -> dict[str, Any]:
|
||||
return build_windows99_vmx_source_backup_search_package(
|
||||
load_latest_reboot_auto_recovery_slo_scorecard()
|
||||
)
|
||||
Reference in New Issue
Block a user