fix(reboot): expose windows99 autostart task run state
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m0s
CD Pipeline / build-and-deploy (push) Failing after 1m1s
CD Pipeline / post-deploy-checks (push) Has been skipped

This commit is contained in:
Your Name
2026-07-03 16:11:33 +08:00
parent 344862b71a
commit 37dda358a3
11 changed files with 447 additions and 9 deletions

View File

@@ -461,6 +461,13 @@ def gauge(name: str, value: bool) -> None:
print(f'{name}{{scope="windows99"}} {1 if value else 0}')
def int_value(value: object, default: int = -1) -> int:
try:
return int(str(value), 0)
except (TypeError, ValueError):
return default
gauge(
"awoooi_windows99_vmware_readback_present",
windows99.get("readback_present") is True,
@@ -477,6 +484,28 @@ gauge(
"awoooi_windows99_vmware_windows_update_no_auto_reboot_ready",
windows99.get("windows_update_no_auto_reboot_ready") is True,
)
task = windows99.get("scheduled_task") or windows99.get("autostart_task") or {}
if task:
start_script_present = task.get("start_script_present") is True
task_last_result = int_value(task.get("last_task_result"))
task_last_result_hex = hex(task_last_result) if task_last_result >= 0 else "unknown"
task_last_run_time = str(task.get("last_run_time") or "unknown")
task_never_ran = task.get("never_ran") is True
gauge(
"awoooi_windows99_vmware_autostart_task_start_script_present",
start_script_present,
)
if task_last_result >= 0:
print(
"awoooi_windows99_vmware_autostart_task_last_result"
f'{{scope="windows99",result_hex="{label(task_last_result_hex)}",'
f'last_run_time="{label(task_last_run_time)}"}} {task_last_result}'
)
print(
"awoooi_windows99_vmware_autostart_task_never_ran"
f'{{scope="windows99",result_hex="{label(task_last_result_hex)}",'
f'last_run_time="{label(task_last_run_time)}"}} {1 if task_never_ran else 0}'
)
for alias in windows99.get("missing_vmx_aliases") or []:
if alias:
print(
@@ -607,6 +636,12 @@ awoooi_public_maintenance_edge_fallback_ready{scope="public_routes"} $public_edg
# TYPE awoooi_windows99_vmware_autostart_config_ready gauge
# HELP awoooi_windows99_vmware_windows_update_no_auto_reboot_ready Whether Windows Update no-auto-reboot policy is verified.
# TYPE awoooi_windows99_vmware_windows_update_no_auto_reboot_ready gauge
# HELP awoooi_windows99_vmware_autostart_task_start_script_present Whether the Windows99 VMware autostart scheduled task target script exists.
# TYPE awoooi_windows99_vmware_autostart_task_start_script_present gauge
# HELP awoooi_windows99_vmware_autostart_task_last_result Windows Scheduled Task last task result for VMware autostart.
# TYPE awoooi_windows99_vmware_autostart_task_last_result gauge
# HELP awoooi_windows99_vmware_autostart_task_never_ran Whether the VMware autostart task appears never to have run.
# TYPE awoooi_windows99_vmware_autostart_task_never_ran gauge
# HELP awoooi_windows99_vmware_missing_vmx_alias Missing required Windows99 VMX aliases.
# TYPE awoooi_windows99_vmware_missing_vmx_alias gauge
# HELP awoooi_windows99_vmware_powered_off_alias Required Windows99 VMware guests observed powered off.

View File

@@ -202,6 +202,31 @@ def parse_windows99_vmware_readback(text: str) -> dict[str, Any]:
"ok": match.group(7) == "1",
}
continue
match = re.match(
r"^VMWARE_AUTOSTART_TASK_DETAIL name=(\S+) principal_user=(\S+) "
r"run_level=(\S+) logon_type=(\S+) start_script_present=([01]) "
r"last_run_time=(\S+) last_task_result=(\S+) next_run_time=(\S+)$",
line,
)
if match:
task.setdefault("name", match.group(1))
task["principal_user"] = match.group(2)
task["run_level"] = match.group(3)
task["logon_type"] = match.group(4)
task["start_script_present"] = match.group(5) == "1"
task["last_run_time"] = match.group(6)
task["last_task_result"] = match.group(7)
task["next_run_time"] = match.group(8)
continue
match = re.match(
r"^VMWARE_AUTOSTART_TASK_ACTION name=(\S+) execute=(\S+) argument=(\S+)$",
line,
)
if match:
task.setdefault("name", match.group(1))
task["action_execute"] = match.group(2)
task["action_argument"] = match.group(3)
continue
match = re.match(
r"^WINDOWS_UPDATE_POLICY name=(\S+) value=(\S+) expected=(\S+) ok=([01])$",
line,
@@ -259,6 +284,13 @@ def parse_windows99_vmware_readback(text: str) -> dict[str, Any]:
power_ready = not powered_off_aliases
if "VMWARE_AUTOSTART_VERIFY_READY" not in kv:
verify_ready = config_ready and power_ready
task_last_result = str(task.get("last_task_result") or "")
task_last_run_time = str(task.get("last_run_time") or "")
task_never_ran = task_last_result in {"267011", "0x41303"} or (
task_last_run_time.startswith("1999-11-30")
)
if task:
task["never_ran"] = task_never_ran
blockers: list[str] = []
if not vmrun_present:
@@ -269,6 +301,8 @@ def parse_windows99_vmware_readback(text: str) -> dict[str, Any]:
blockers.append("windows99_vmware_autostart_config_not_ready")
if powered_off_aliases:
blockers.append("windows99_vmware_guest_power_not_ready")
if powered_off_aliases and task_never_ran:
blockers.append("windows99_vmware_autostart_task_never_ran")
if not update_ready:
blockers.append("windows99_update_no_auto_reboot_policy_not_ready")
if not verify_ready and not blockers:
@@ -1213,6 +1247,8 @@ def build_windows99_verify_collection_packet(
"VMX alias=<alias> present=<0|1>",
"VMWARE_SERVICE name=<name> ok=<0|1>",
"VMWARE_AUTOSTART_TASK name=AWOOOI-Start-VMware-VMs ok=<0|1>",
"VMWARE_AUTOSTART_TASK_DETAIL last_task_result=<code>",
"VMWARE_AUTOSTART_TASK_ACTION execute=<path>",
"WINDOWS_UPDATE_POLICY name=<name> ok=<0|1>",
"VM_POWER alias=<alias> running=<0|1>",
"VMWARE_AUTOSTART_CONFIG_READY",
@@ -1460,6 +1496,7 @@ def reboot_sop_current_phase(active_blockers: list[str], can_claim: bool) -> str
"windows99_vmrun_missing",
"windows99_vmware_vmx_missing",
"windows99_vmware_autostart_config_not_ready",
"windows99_vmware_autostart_task_never_ran",
"windows99_vmware_guest_power_not_ready",
"windows99_update_no_auto_reboot_policy_not_ready",
"windows99_console_clipboard_unreliable",
@@ -1514,6 +1551,7 @@ def reboot_sop_primary_blocker(active_blockers: list[str]) -> str:
"windows99_vmrun_missing",
"windows99_vmware_vmx_missing",
"windows99_vmware_autostart_config_not_ready",
"windows99_vmware_autostart_task_never_ran",
"windows99_vmware_guest_power_not_ready",
"windows99_update_no_auto_reboot_policy_not_ready",
"windows99_console_clipboard_unreliable",
@@ -1671,7 +1709,10 @@ def active_blocker_action_row(
"restore_windows99_missing_vmx_source_for_aliases_then_rerun_"
"no_secret_collector_and_scorecard_no_vm_power_change"
)
elif blocker == "windows99_vmware_guest_power_not_ready":
elif blocker in {
"windows99_vmware_guest_power_not_ready",
"windows99_vmware_autostart_task_never_ran",
}:
next_safe_action = (
"run_windows99_vmware_autostart_check_mode_package_for_powered_"
"off_aliases_then_rerun_no_secret_collector_no_vm_power_change"

View File

@@ -73,6 +73,8 @@ VMX alias=112 path=D:\\VMs\\112.vmx present=1
VMWARE_SERVICE name=VMAuthdService present=1 status=Running startup_type=Auto ok=1
VMWARE_SERVICE name=VMnetDHCP present=1 status=Running startup_type=Auto ok=1
VMWARE_AUTOSTART_TASK name=AWOOOI-Start-VMware-VMs present=1 enabled=1 state=Ready trigger_count=1 action_count=1 ok=1
VMWARE_AUTOSTART_TASK_DETAIL name=AWOOOI-Start-VMware-VMs principal_user=SYSTEM run_level=Highest logon_type=ServiceAccount start_script_present=1 last_run_time=2026-07-03T15:10:00 last_task_result=0 next_run_time=never
VMWARE_AUTOSTART_TASK_ACTION name=AWOOOI-Start-VMware-VMs execute=powershell.exe argument=-NoProfile_-ExecutionPolicy_Bypass_-File_C:\\ProgramData\\AWOOOI\\Start-AWOOOI-VMs.ps1
WINDOWS_UPDATE_POLICY name=NoAutoRebootWithLoggedOnUsers value=1 expected=1 ok=1
WINDOWS_UPDATE_POLICY name=AlwaysAutoRebootAtScheduledTime value=0 expected=0 ok=1
WINDOWS_UPDATE_POLICY name=AUOptions value=3 expected=3 ok=1
@@ -527,6 +529,12 @@ def test_green_summary_and_recent_all_host_probe_can_claim_slo(tmp_path: Path) -
"188",
]
assert payload["windows99_vmware_autostart"]["verify_ready"] is True
task = payload["windows99_vmware_autostart"]["scheduled_task"]
assert task["principal_user"] == "SYSTEM"
assert task["run_level"] == "Highest"
assert task["start_script_present"] is True
assert task["last_task_result"] == "0"
assert task["action_execute"] == "powershell.exe"
assert payload["windows99_verify_collection"]["collection_blockers"] == []
assert payload["active_blocker_action_matrix"]["item_count"] == 0
assert payload["active_blocker_action_matrix"]["items"] == []
@@ -540,6 +548,52 @@ def test_green_summary_and_recent_all_host_probe_can_claim_slo(tmp_path: Path) -
] is True
def test_windows99_autostart_task_never_ran_blocks_powered_off_guests(
tmp_path: Path,
) -> None:
windows99 = WINDOWS99_VMWARE_GREEN
for alias in ["111", "188", "120", "121", "112"]:
windows99 = windows99.replace(
f"VM_POWER alias={alias} vmx_present=1 running=1",
f"VM_POWER alias={alias} vmx_present=1 running=0",
)
windows99 = (
windows99.replace(
"last_run_time=2026-07-03T15:10:00 last_task_result=0",
"last_run_time=1999-11-30T00:00:00 last_task_result=267011",
)
.replace("VMWARE_AUTOSTART_POWER_READY=1", "VMWARE_AUTOSTART_POWER_READY=0")
.replace("VMWARE_AUTOSTART_VERIFY_READY=1", "VMWARE_AUTOSTART_VERIFY_READY=0")
)
payload = run_scorecard(tmp_path, GREEN_SUMMARY, windows99=windows99)
assert payload["status"] == "blocked_reboot_auto_recovery_slo_not_ready"
assert payload["windows99_vmware_autostart"]["powered_off_aliases"] == [
"111",
"112",
"120",
"121",
"188",
]
task = payload["windows99_vmware_autostart"]["scheduled_task"]
assert task["last_task_result"] == "267011"
assert task["last_run_time"] == "1999-11-30T00:00:00"
assert task["never_ran"] is True
assert "windows99_vmware_guest_power_not_ready" in payload["active_blockers"]
assert "windows99_vmware_autostart_task_never_ran" in payload["active_blockers"]
action_by_blocker = {
item["blocker"]: item
for item in payload["active_blocker_action_matrix"]["items"]
}
assert action_by_blocker["windows99_vmware_autostart_task_never_ran"][
"next_safe_action"
] == (
"run_windows99_vmware_autostart_check_mode_package_for_powered_off_"
"aliases_then_rerun_no_secret_collector_no_vm_power_change"
)
def test_missing_public_maintenance_runtime_readback_fails_closed(tmp_path: Path) -> None:
payload = run_scorecard(
tmp_path,

View File

@@ -94,6 +94,10 @@ def test_reboot_p0_contract_covers_all_required_hosts_and_vmware_autostart() ->
assert "WINDOWS_UPDATE_POLICY" in windows99
assert "VM_POWER alias=$alias" in windows99
assert "VM_ALREADY_RUNNING" in windows99
assert "VMWARE_AUTOSTART_TASK_DETAIL" in windows99
assert "last_task_result" in windows99
assert "start_script_present" in windows99
assert "VMWARE_AUTOSTART_TASK_ACTION" in windows99
def test_reboot_p0_contract_has_maintenance_and_telegram_alerts() -> None:

View File

@@ -191,26 +191,72 @@ function Get-VmwareServiceReadback {
}
}
function Format-ReadbackValue {
param([object]$Value)
if ($null -eq $Value) {
return "unknown"
}
$text = "$Value"
if ([string]::IsNullOrWhiteSpace($text)) {
return "unknown"
}
return ($text -replace "\s+", "_")
}
function Get-AutostartTaskReadback {
$task = $null
$taskInfo = $null
try {
$task = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue
} catch {
$task = $null
}
try {
$taskInfo = Get-ScheduledTaskInfo -TaskName $TaskName -ErrorAction SilentlyContinue
} catch {
$taskInfo = $null
}
$present = [int][bool]$task
$enabled = 0
$state = "missing"
$triggerCount = 0
$actionCount = 0
$principalUser = "missing"
$runLevel = "missing"
$logonType = "missing"
$lastRunTime = "never"
$lastTaskResult = "unknown"
$nextRunTime = "unknown"
$actionExecute = "missing"
$actionArgument = "missing"
if ($task) {
$enabled = [int]($task.State -ne "Disabled")
$state = "$($task.State)"
$triggerCount = @($task.Triggers).Count
$actionCount = @($task.Actions).Count
if ($task.Principal) {
$principalUser = "$($task.Principal.UserId)"
$runLevel = "$($task.Principal.RunLevel)"
$logonType = "$($task.Principal.LogonType)"
}
$actionExecute = (@($task.Actions) | ForEach-Object { "$($_.Execute)" }) -join "|"
$actionArgument = (@($task.Actions) | ForEach-Object { "$($_.Arguments)" }) -join "|"
}
if ($taskInfo) {
if ($taskInfo.LastRunTime) {
$lastRunTime = $taskInfo.LastRunTime.ToString("s")
}
$lastTaskResult = "$($taskInfo.LastTaskResult)"
if ($taskInfo.NextRunTime) {
$nextRunTime = $taskInfo.NextRunTime.ToString("s")
}
}
$startScriptPresent = [int](Test-Path -LiteralPath $StartScript)
$ok = [int]($task -and $enabled -eq 1 -and $triggerCount -gt 0 -and $actionCount -gt 0)
Write-Output "VMWARE_AUTOSTART_TASK name=$TaskName present=$present enabled=$enabled state=$state trigger_count=$triggerCount action_count=$actionCount ok=$ok"
Write-Output "VMWARE_AUTOSTART_TASK_DETAIL name=$TaskName principal_user=$(Format-ReadbackValue $principalUser) run_level=$(Format-ReadbackValue $runLevel) logon_type=$(Format-ReadbackValue $logonType) start_script_present=$startScriptPresent last_run_time=$(Format-ReadbackValue $lastRunTime) last_task_result=$(Format-ReadbackValue $lastTaskResult) next_run_time=$(Format-ReadbackValue $nextRunTime)"
Write-Output "VMWARE_AUTOSTART_TASK_ACTION name=$TaskName execute=$(Format-ReadbackValue $actionExecute) argument=$(Format-ReadbackValue $actionArgument)"
}
function Get-WindowsUpdatePolicyReadback {