diff --git a/home/conf/xonsh/xonshrc b/home/conf/xonsh/xonshrc index c589184..2b0b2c3 100644 --- a/home/conf/xonsh/xonshrc +++ b/home/conf/xonsh/xonshrc @@ -1,7 +1,7 @@ ## ALIASES ## # home network utils aliases["tsla-fan"] = "ipmitool -H 10.30.0.3 -U ADMIN -P ADMIN raw 0x30 0x70 0x66 0x01 0x0" -aliases["weboot"] = "bash -c 'nix shell nixpkgs#efibootmgr -c sudo efibootmgr -n 0000 && reboot'" +aliases["weboot"] = "sudo efibootmgr -n 0000 && reboot" # nixos helpers aliases["nixoss"] = "sudo nixos-rebuild switch --flake @('.#' + $(hostname))" diff --git a/hosts/electra/configuration.nix b/hosts/electra/configuration.nix index 14ac524..9e97c89 100644 --- a/hosts/electra/configuration.nix +++ b/hosts/electra/configuration.nix @@ -4,7 +4,9 @@ imports = [ ./hardware-configuration.nix ]; networking.hostName = "electra"; - + environment.systemPackages = with pkgs; [ + wakeonlan + ]; boot = { loader.systemd-boot.enable = true; loader.efi.canTouchEfiVariables = true; diff --git a/hosts/inuc/configuration.nix b/hosts/inuc/configuration.nix index 5d7320a..55f72b6 100644 --- a/hosts/inuc/configuration.nix +++ b/hosts/inuc/configuration.nix @@ -1,6 +1,9 @@ { config, pkgs, lib, ... }: { + environment.systemPackages = with pkgs; [ + wakeonlan + ]; security.sudo.wheelNeedsPassword = false; imports = [ ./hardware-configuration.nix ]; diff --git a/hosts/tower/configuration.nix b/hosts/tower/configuration.nix index 4ce5da8..f8d9813 100644 --- a/hosts/tower/configuration.nix +++ b/hosts/tower/configuration.nix @@ -52,10 +52,15 @@ xserver.videoDrivers = [ "nvidia" ]; openssh.enable = true; }; # end services - environment.variables = { - GBM_BACKEND = "nvidia-drm"; - __GLX_VENDOR_LIBRARY_NAME = "nvidia"; - MOZ_DISABLE_RDD_SANDBOX= "1" ; - LIBVA_DRIVER_NAME = "nvidia"; + environment = { + variables = { + GBM_BACKEND = "nvidia-drm"; + __GLX_VENDOR_LIBRARY_NAME = "nvidia"; + MOZ_DISABLE_RDD_SANDBOX= "1" ; + LIBVA_DRIVER_NAME = "nvidia"; + }; + systemPackages = [ + pkgs.efibootmgr + ] }; } # end file diff --git a/util/wol_man.py b/util/wol_man.py new file mode 100644 index 0000000..cd178f5 --- /dev/null +++ b/util/wol_man.py @@ -0,0 +1,153 @@ +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): + response = subprocess.run(f"ssh tower '{command}", shell=True, capture_output=True, text=True) + return (response.returncode, response.stdout, response.stderr) + +def weboot(): + code, stdout, stderr = remote_cmd("sudo efibootmgr -n 0000") + if code == 0: + code, stdout, stderr = remote_cmd("sudo reboot") + time.sleep(60) + if code != 0: + raise RuntimeError(f"weboot failed {stderr}") + return code, stdout, stderr + +def send_wol(): + response = subprocess.run(f"wakeonlan {TARGET_LINK}", shell=True, capture_output=True, text=True) + return (response.returncode, response.stdout, response.stderr) + +def get_os(): + code, stdout, stderr = remote_cmd("whoami") + if code == 255 and "No route to host" in stderr: + return "offline" + elif code != 0: + raise RuntimeError(f"win_or_linux failed {stderr}") + if "Windows" in stdout: + return "windows" + + else: + 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(): + match get_os(): + case "windows": + return False + case "linux": + return True + case "offline": + send_wol() + time.sleep(60) + return True + +def boot_windows(): + match get_os(): + case "windows": + return True + case "linux": + return False + case "offline": + boot_linux() + weboot() + if get_os() == "windows": + return True + else: + return False + +def reboot(): + 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": + return False + +def shutdown(): + match get_os(): + case "windows": + code, stdout, stderr = remote_cmd("shutdown /s") + return True + case "linux": + code, stdout, stderr = remote_cmd("sudo shutdown -h now") + return True + case "offline": + return False + +def action_do(action): + match action: + 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": + if get_os() != "offline": + print("Target is in use, belaying update 1h") + time.sleep(3600) + action_do("winupdate") + code, stdout, stderr = remote_cmd("powershell -Command \"& {Install-WindowsUpdate -AcceptAll -AutoReboot}\"") + 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() + +def main():: + parser = argparse.ArgumentParser(description="WOL and reboot utility") + parser.add_argument("action", choices=["boot_linux", "boot_windows", "swap_os", "reboot", "shutdown", "winupdate"], help="Action to perform") + action_do(parser.parse_args().action) +