feat: Initial commit of the server management tool

This commit is contained in:
Matthias
2025-09-08 20:36:50 +02:00
commit 75406bd56c
8 changed files with 474 additions and 0 deletions
+153
View File
@@ -0,0 +1,153 @@
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
}