package serveractions import ( "context" "fmt" "net" "os/exec" "time" "golang.org/x/crypto/ssh" ) func WakeServer(name string, servers []Server) { for _, s := range servers { if s.Name == name { fmt.Printf("Sending Wake-on-LAN packet to %s (%s)...\n", s.Name, s.Mac) err := sendMagicPacket(s.Mac) if err != nil { fmt.Printf("Error sending packet: %v\n", err) } else { fmt.Println("Packet sent successfully.") } return } } fmt.Printf("Server '%s' not found in configuration.\n", name) } func WakeAllServers(servers []Server) { fmt.Println("Waking all servers...") for _, s := range servers { fmt.Printf("Sending Wake-on-LAN packet to %s (%s)...\n", s.Name, s.Mac) err := sendMagicPacket(s.Mac) if err != nil { fmt.Printf(" - Error for %s: %v\n", s.Name, err) } else { fmt.Printf(" - Packet sent to %s.\n", s.Name) } } } func CheckServersStatus(servers []Server) { fmt.Println("Checking server status...") for _, s := range servers { if s.IP == "" { fmt.Printf(" - %-20s [SKIPPED] (No IP configured)\n", s.Name) continue } online := PingHost(s.IP) status := "Offline" if online { status = "Online" } fmt.Printf(" - %-20s [%s]\n", s.Name, status) } } func PingHost(host string) bool { ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() cmd := exec.CommandContext(ctx, "ping", "-c", "1", "-W", "1", host) err := cmd.Run() return err == nil } // Creates and sends a magic packet to the specified MAC address. func sendMagicPacket(macAddr string) error { hwAddr, err := net.ParseMAC(macAddr) if err != nil { return fmt.Errorf("invalid mac address '%s': %w", macAddr, err) } magicPacket := make([]byte, 102) for i := 0; i < 6; i++ { magicPacket[i] = 0xFF } for i := 1; i <= 16; i++ { copy(magicPacket[i*6:], hwAddr) } conn, err := net.Dial("udp", "255.255.255.255:9") if err != nil { return err } defer conn.Close() _, err = conn.Write(magicPacket) return err } func ShutdownServer(name string, servers []Server) { for _, s := range servers { if s.Name == name { fmt.Printf("Attempting to shutdown %s...\n", s.Name) err := executeSSHCommand(s, "sudo shutdown -h now") if err != nil { fmt.Printf("Error shutting down %s: %v\n", s.Name, err) } else { fmt.Printf("%s is shutting down.\n", s.Name) } return } } fmt.Printf("Server '%s' not found in configuration.\n", name) } func RebootServer(name string, servers []Server) { for _, s := range servers { if s.Name == name { fmt.Printf("Attempting to reboot %s...\n", s.Name) err := executeSSHCommand(s, "sudo reboot") if err != nil { fmt.Printf("Error rebooting %s: %v\n", s.Name, err) } else { fmt.Printf("%s is rebooting.\n", s.Name) } return } } fmt.Printf("Server '%s' not found in configuration.\n", name) } func executeSSHCommand(server Server, command string) error { config := &ssh.ClientConfig{ User: server.SSHUser, Auth: []ssh.AuthMethod{ ssh.Password(server.SSHPass), }, HostKeyCallback: ssh.InsecureIgnoreHostKey(), Timeout: 10 * time.Second, } client, err := ssh.Dial("tcp", server.IP+":22", config) if err != nil { return fmt.Errorf("failed to dial: %w", err) } defer client.Close() session, err := client.NewSession() if err != nil { return fmt.Errorf("failed to create session: %w", err) } defer session.Close() _, err = session.CombinedOutput(command) if err != nil { return fmt.Errorf("failed to run command: %w", err) } return nil }