154 lines
3.5 KiB
Go
154 lines
3.5 KiB
Go
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
|
|
}
|