nixos_config/util/wol_man.py

213 lines
6.8 KiB
Python
Raw Normal View History

2026-01-27 15:44:52 +01:00
from time import time
import subprocess
from _socket import socket
import argparse
import time
import socket
import subprocess
TARGET_LINK = "f0:2f:74:30:0c:d0"
TARGET_HOSTNAME = "tower.home.the.malice.zone"
TARGET_IP = socket.gethostbyname(TARGET_HOSTNAME)
def remote_cmd(command):
print(f"Executing: ssh alisceon@tower.home.the.malice.zone '{command}'")
2026-01-30 18:56:08 +01:00
response = subprocess.run(f"ssh tower -o 'StrictHostKeyChecking no' '{command}'", shell=True, capture_output=True, text=True)
2026-01-27 15:44:52 +01:00
return (response.returncode, response.stdout, response.stderr)
def weboot():
2026-01-27 16:00:34 +01:00
print("Rebooting to windows")
2026-01-27 15:44:52 +01:00
code, stdout, stderr = remote_cmd("sudo efibootmgr -n 0000")
if code == 0:
code, stdout, stderr = remote_cmd("sudo reboot")
time.sleep(120)
2026-01-27 15:44:52 +01:00
if code != 0:
raise RuntimeError(f"weboot failed {stderr}")
return code, stdout, stderr
def send_wol():
2026-01-27 16:00:34 +01:00
print(f"Broadcasting WOL packet to {TARGET_LINK}")
2026-01-27 15:44:52 +01:00
response = subprocess.run(f"wakeonlan {TARGET_LINK}", shell=True, capture_output=True, text=True)
return (response.returncode, response.stdout, response.stderr)
def get_os():
2026-01-27 16:00:34 +01:00
print("Determining target OS")
2026-01-27 15:44:52 +01:00
code, stdout, stderr = remote_cmd("whoami")
if code == 255 and "No route to host" in stderr:
2026-01-27 16:00:34 +01:00
print("Target is offline")
2026-01-27 15:44:52 +01:00
return "offline"
elif code != 0:
raise RuntimeError(f"win_or_linux failed {stderr}")
if "tower\\alisceon" in stdout.lower():
2026-01-27 16:00:34 +01:00
print("Target is running Windows")
2026-01-27 15:44:52 +01:00
return "windows"
else:
2026-01-27 16:00:34 +01:00
print("Target is running Linux")
2026-01-27 15:44:52 +01:00
return "linux"
def swap_os():
match get_os():
case "windows":
code, stdout, stderr = remote_cmd("shutdown /r")
case "linux":
code, stdout, stderr = weboot()
case "offline":
return False
return True
def boot_linux():
2026-01-27 16:00:34 +01:00
print("Booting Linux")
2026-01-27 15:44:52 +01:00
match get_os():
case "windows":
2026-01-27 16:00:34 +01:00
print("Tower is busy")
2026-01-27 15:44:52 +01:00
return False
case "linux":
2026-01-27 16:00:34 +01:00
print("Linux is already running")
2026-01-27 15:44:52 +01:00
return True
case "offline":
2026-01-27 16:00:34 +01:00
print("Booting via WOL")
2026-01-27 15:44:52 +01:00
send_wol()
time.sleep(60)
return True
def boot_windows():
2026-01-27 16:00:34 +01:00
print("Booting Windows")
2026-01-27 15:44:52 +01:00
match get_os():
case "windows":
2026-01-27 16:00:34 +01:00
print("Windows is already running")
2026-01-27 15:44:52 +01:00
return True
case "linux":
2026-01-27 16:00:34 +01:00
print("Tower is busy")
2026-01-27 15:44:52 +01:00
return False
case "offline":
2026-01-27 16:00:34 +01:00
print("Booting via WOL")
2026-01-27 15:44:52 +01:00
boot_linux()
weboot()
if get_os() == "windows":
return True
else:
return False
def reboot():
2026-01-27 16:00:34 +01:00
print("Rebooting target")
2026-01-27 15:44:52 +01:00
orig_os = get_os()
match orig_os:
case "windows":
code, stdout, stderr = remote_cmd("shutdown /r")
time.sleep(60)
weboot()
return True
case "linux":
code, stdout, stderr = remote_cmd("sudo reboot")
return True
case "offline":
2026-01-27 16:00:34 +01:00
print("Target is offline, cannot reboot")
2026-01-27 15:44:52 +01:00
return False
def shutdown():
2026-01-27 16:00:34 +01:00
print("Shutting down target")
2026-01-27 15:44:52 +01:00
match get_os():
case "windows":
code, stdout, stderr = remote_cmd("shutdown /s /t 0")
2026-01-27 16:00:34 +01:00
time.sleep(30)
2026-01-27 15:44:52 +01:00
case "linux":
code, stdout, stderr = remote_cmd("sudo shutdown -h now")
2026-01-27 16:00:34 +01:00
time.sleep(30)
2026-01-27 15:44:52 +01:00
case "offline":
2026-01-27 16:00:34 +01:00
print("Target is already offline")
2026-01-27 15:44:52 +01:00
return False
if get_os() == "offline":
print("Target is now offline")
return True
else:
print("Failed to shut down target")
return False
2026-01-27 15:44:52 +01:00
2026-01-30 18:56:08 +01:00
def winupdate() :
print("Starting Windows Update process")
if get_os() != "windows":
print("Target is not running Windows, cannot update")
return False
code, stdout, stderr = remote_cmd('powershell -Command "Start-Service wuauserv"')
if code != 0:
raise RuntimeError(f"Failed to start Windows Update service: {stderr}")
time.sleep(30)
code, stdout, stderr = remote_cmd('powershell -Command "UsoClient StartScan"')
if code != 0:
raise RuntimeError(f"Failed to start Windows Update scan: {stderr}")
time.sleep(300)
code, stdout, stderr = remote_cmd('powershell -Command "UsoClient StartDownload"')
if code != 0:
raise RuntimeError(f"Failed to start Windows Update download: {stderr}")
time.sleep(600)
code, stdout, stderr = remote_cmd('powershell -Command "UsoClient StartInstall"')
if code != 0:
raise RuntimeError(f"Failed to start Windows Update installation: {stderr}")
time.sleep(1800)
return True
2026-01-27 15:44:52 +01:00
def action_do(action):
match action:
2026-01-27 16:00:34 +01:00
case "get_os":
os = get_os()
print(f"Current OS: {os}")
2026-01-27 15:44:52 +01:00
case "boot_linux":
if boot_linux():
print("Linux is now running")
else:
print("Failed to boot Linux")
case "boot_windows":
if boot_windows():
print("Windows is now running")
else:
print("Failed to boot Windows")
case "swap_os":
if swap_os():
print("OS swapped successfully")
else:
print("Failed to swap OS")
case "reboot":
if reboot():
print("Reboot command sent successfully")
else:
print("Failed to reboot")
case "shutdown":
if shutdown():
print("Shutdown command sent successfully")
else:
print("Failed to shutdown")
case "winupdate":
2026-01-30 18:56:08 +01:00
if winupdate():
print("Windows update commands sent successfully")
case "autowin":
2026-01-27 15:44:52 +01:00
if get_os() != "offline":
print("Target is in use, belaying update 1h")
time.sleep(3600)
action_do("winupdate")
2026-01-27 16:00:34 +01:00
if boot_windows():
print("Initiating Windows update")
else:
print("Failed to boot Windows for update")
return
2026-01-30 18:56:08 +01:00
winupdate()
2026-01-27 15:44:52 +01:00
if code == 0:
print("Windows update initiated successfully")
else:
print(f"Failed to initiate Windows update: {stderr}")
#first reboot to windows
time.sleep(300)
weboot()
#second reboot after update
time.sleep(600)
reboot()
#shutdown
time.sleep(300)
shutdown()
2026-01-27 16:00:34 +01:00
def main():
2026-01-27 15:44:52 +01:00
parser = argparse.ArgumentParser(description="WOL and reboot utility")
2026-01-30 18:56:08 +01:00
parser.add_argument("action", choices=["get_os", "boot_linux", "boot_windows", "swap_os", "reboot", "shutdown", "winupdate", "autowin"], help="Action to perform")
2026-01-27 15:44:52 +01:00
action_do(parser.parse_args().action)
2026-01-27 16:00:34 +01:00
if __name__ == "__main__":
main()