From 074b450827a117b90cacf142879969c403a937fe Mon Sep 17 00:00:00 2001 From: ogt Date: Tue, 14 Jul 2026 09:06:21 +0800 Subject: [PATCH] fix(recovery): include host112 ssh readiness --- .../host112-guest-readiness.sh | 37 ++++++++++++++++++- .../test_reboot_p0_operational_contract.py | 4 ++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/scripts/reboot-recovery/host112-guest-readiness.sh b/scripts/reboot-recovery/host112-guest-readiness.sh index 1269b4c89..1a0a50ffb 100755 --- a/scripts/reboot-recovery/host112-guest-readiness.sh +++ b/scripts/reboot-recovery/host112-guest-readiness.sh @@ -16,7 +16,7 @@ Usage: host112-guest-readiness.sh [--check|--apply] --check emits a bounded no-secret guest readiness row. --apply performs only allowlisted idempotent recovery for graphical.target, -LightDM, open-vm-tools and a cooldown-guarded Wazuh Indexer start retry. +LightDM, open-vm-tools, SSH and a cooldown-guarded Wazuh Indexer start retry. USAGE } @@ -65,6 +65,19 @@ start_if_inactive() { fi } +enable_if_disabled() { + local unit="$1" action="$2" state + state="$(unit_enabled "$unit")" + if [ "$state" = "enabled" ] || [ "$state" = "static" ]; then + return 0 + fi + if systemctl enable "$unit" >/dev/null; then + record_action "$action" + else + record_action "${action}_failed" + fi +} + if [ "$MODE" = "apply" ]; then if [ "${EUID:-$(id -u)}" -ne 0 ]; then echo "BLOCKER host112_apply_requires_root" >&2 @@ -83,6 +96,12 @@ if [ "$MODE" = "apply" ]; then start_if_inactive graphical.target start_graphical_target start_if_inactive open-vm-tools.service start_vmware_tools start_if_inactive lightdm.service start_lightdm + if unit_loaded ssh.service; then + enable_if_disabled ssh.service enable_ssh + start_if_inactive ssh.service start_ssh + else + record_action "ssh_service_missing" + fi uptime_for_retry="$(awk '{print int($1)}' /proc/uptime 2>/dev/null || echo 0)" indexer_state="$(unit_active wazuh-indexer.service)" @@ -126,9 +145,22 @@ wazuh_indexer="$(unit_active wazuh-indexer.service)" wazuh_manager="$(unit_active wazuh-manager.service)" wazuh_dashboard="$(unit_active wazuh-dashboard.service)" filebeat="$(unit_active filebeat.service)" +ssh_service="$(unit_active ssh.service)" +ssh_enabled="$(unit_enabled ssh.service)" startup_enabled="$(unit_enabled awoooi-host112-guest-recovery.timer)" startup_active="$(unit_active awoooi-host112-guest-recovery.timer)" +ssh_port_listening=0 +if ss -H -ltn 2>/dev/null | awk '{print $4}' | grep -Eq '(^|:)22$'; then + ssh_port_listening=1 +fi +ssh_ready=0 +if [ "$ssh_service" = "active" ] \ + && { [ "$ssh_enabled" = "enabled" ] || [ "$ssh_enabled" = "static" ]; } \ + && [ "$ssh_port_listening" -eq 1 ]; then + ssh_ready=1 +fi + xorg="inactive" if pgrep -x Xorg >/dev/null 2>&1 || pgrep -x Xwayland >/dev/null 2>&1; then xorg="active" @@ -160,6 +192,7 @@ fi guest_ready=0 if [ "$console_ready" -eq 1 ] \ && [ "$services_ready" -eq 1 ] \ + && [ "$ssh_ready" -eq 1 ] \ && [ "$recovery_timer_ready" -eq 1 ] \ && [ "$systemd_state" = "running" ]; then guest_ready=1 @@ -170,7 +203,7 @@ if [ "${#actions[@]}" -gt 0 ]; then action_text="$(IFS=,; printf '%s' "${actions[*]}")" fi -readback="boot_id=$boot_id uptime_seconds=$uptime_seconds systemd_state=$systemd_state startup_enabled=$startup_enabled startup_active=$startup_active default_target=$default_target graphical_target=$graphical_target display_manager=$display_manager lightdm=$lightdm vmware_tools=$vmware_tools xorg=$xorg wazuh_indexer=$wazuh_indexer wazuh_manager=$wazuh_manager wazuh_dashboard=$wazuh_dashboard filebeat=$filebeat console_ready=$console_ready services_ready=$services_ready recovery_timer_ready=$recovery_timer_ready guest_ready=$guest_ready action_count=${#actions[@]} actions=$action_text" +readback="boot_id=$boot_id uptime_seconds=$uptime_seconds systemd_state=$systemd_state startup_enabled=$startup_enabled startup_active=$startup_active default_target=$default_target graphical_target=$graphical_target display_manager=$display_manager lightdm=$lightdm vmware_tools=$vmware_tools xorg=$xorg wazuh_indexer=$wazuh_indexer wazuh_manager=$wazuh_manager wazuh_dashboard=$wazuh_dashboard filebeat=$filebeat ssh_service=$ssh_service ssh_enabled=$ssh_enabled ssh_port_listening=$ssh_port_listening ssh_ready=$ssh_ready console_ready=$console_ready services_ready=$services_ready recovery_timer_ready=$recovery_timer_ready guest_ready=$guest_ready action_count=${#actions[@]} actions=$action_text" printf '%s\n' "$readback" if [ "$MODE" = "apply" ]; then diff --git a/scripts/reboot-recovery/tests/test_reboot_p0_operational_contract.py b/scripts/reboot-recovery/tests/test_reboot_p0_operational_contract.py index a7db9299b..56b76c6cf 100644 --- a/scripts/reboot-recovery/tests/test_reboot_p0_operational_contract.py +++ b/scripts/reboot-recovery/tests/test_reboot_p0_operational_contract.py @@ -97,6 +97,10 @@ def test_reboot_p0_contract_covers_all_required_hosts_and_vmware_autostart() -> assert "systemctl set-default graphical.target" in host112_readiness assert "start_if_inactive lightdm.service" in host112_readiness assert "start_if_inactive open-vm-tools.service" in host112_readiness + assert "enable_if_disabled ssh.service enable_ssh" in host112_readiness + assert "start_if_inactive ssh.service start_ssh" in host112_readiness + assert "ssh_port_listening=$ssh_port_listening" in host112_readiness + assert "ssh_ready=$ssh_ready" in host112_readiness assert "INDEXER_RETRY_COOLDOWN_SECONDS" in host112_readiness assert "console_ready=$console_ready" in host112_readiness assert "guest_ready=$guest_ready" in host112_readiness