Refactor: Rename NanoKVM to BatchuKVM and update server URL

This commit is contained in:
2025-12-09 20:35:38 +09:00
commit 8cf674c9e5
396 changed files with 54380 additions and 0 deletions

View File

@@ -0,0 +1,223 @@
package network
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"NanoKVM-Server/proto"
)
const (
WolMacFile = "/etc/kvm/cache/wol"
)
func (s *Service) WakeOnLAN(c *gin.Context) {
var req proto.WakeOnLANReq
var rsp proto.Response
if err := proto.ParseFormRequest(c, &req); err != nil {
rsp.ErrRsp(c, -1, "invalid arguments")
return
}
mac, err := parseMAC(req.Mac)
if err != nil {
rsp.ErrRsp(c, -2, "invalid MAC address")
return
}
command := fmt.Sprintf("ether-wake -b %s", mac)
cmd := exec.Command("sh", "-c", command)
output, err := cmd.CombinedOutput()
if err != nil {
log.Errorf("failed to wake on lan: %s", err)
rsp.ErrRsp(c, -3, string(output))
return
}
go saveMac(mac)
rsp.OkRsp(c)
log.Debugf("wake on lan: %s", mac)
}
func (s *Service) GetMac(c *gin.Context) {
var rsp proto.Response
content, err := os.ReadFile(WolMacFile)
if err != nil {
rsp.ErrRsp(c, -2, "open file error")
return
}
data := &proto.GetMacRsp{
Macs: strings.Split(string(content), "\n"),
}
rsp.OkRspWithData(c, data)
}
func (s *Service) SetMacName(c *gin.Context) {
var req proto.SetMacNameReq // Mac:string Name:string
var rsp proto.Response
if err := proto.ParseFormRequest(c, &req); err != nil {
rsp.ErrRsp(c, -1, "invalid arguments")
return
}
content, err := os.ReadFile(WolMacFile)
if err != nil {
log.Errorf("failed to open %s: %s", WolMacFile, err)
rsp.ErrRsp(c, -2, "read failed")
return
}
macs := strings.Split(string(content), "\n")
var newLines []string
macFound := false
for _, line := range macs {
parts := strings.Split(line, " ")
if req.Mac != parts[0] {
newLines = append(newLines, line)
continue
}
newLines = append(newLines, parts[0]+" "+req.Name)
macFound = true
}
if !macFound {
log.Errorf("failed to found mac %s: %s", req.Mac, err)
rsp.ErrRsp(c, -3, "write failed")
return
}
data := strings.Join(newLines, "\n")
err = os.WriteFile(WolMacFile, []byte(data), 0o644)
if err != nil {
log.Errorf("failed to write %s: %s", WolMacFile, err)
rsp.ErrRsp(c, -3, "write failed")
return
}
rsp.OkRsp(c)
log.Debugf("set wol mac name: %s %s", req.Mac, req.Name)
}
func (s *Service) DeleteMac(c *gin.Context) {
var req proto.DeleteMacReq
var rsp proto.Response
if err := proto.ParseFormRequest(c, &req); err != nil {
rsp.ErrRsp(c, -1, "invalid arguments")
return
}
content, err := os.ReadFile(WolMacFile)
if err != nil {
log.Errorf("failed to open %s: %s", WolMacFile, err)
rsp.ErrRsp(c, -2, "read failed")
return
}
macs := strings.Split(string(content), "\n")
var newMacs []string
for _, mac := range macs {
parts := strings.Split(mac, " ")
if req.Mac != parts[0] {
newMacs = append(newMacs, mac)
}
}
data := strings.Join(newMacs, "\n")
err = os.WriteFile(WolMacFile, []byte(data), 0o644)
if err != nil {
log.Errorf("failed to write %s: %s", WolMacFile, err)
rsp.ErrRsp(c, -3, "write failed")
return
}
rsp.OkRsp(c)
log.Debugf("delete wol mac: %s", req.Mac)
}
func parseMAC(mac string) (string, error) {
mac = strings.ToUpper(strings.TrimSpace(mac))
mac = strings.ReplaceAll(mac, "-", "")
mac = strings.ReplaceAll(mac, ":", "")
mac = strings.ReplaceAll(mac, ".", "")
matched, err := regexp.MatchString("^[0-9A-F]{12}$", mac)
if err != nil {
return "", err
}
if !matched {
return "", fmt.Errorf("invalid MAC address: %s", mac)
}
var result strings.Builder
for i := 0; i < 12; i += 2 {
if i > 0 {
result.WriteString(":")
}
result.WriteString(mac[i : i+2])
}
return result.String(), nil
}
func saveMac(mac string) {
if isMacExist(mac) {
return
}
err := os.MkdirAll(filepath.Dir(WolMacFile), 0o644)
if err != nil {
log.Errorf("failed to create dir: %s", err)
return
}
file, err := os.OpenFile(WolMacFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
log.Errorf("failed to open %s: %s", WolMacFile, err)
return
}
defer func() {
_ = file.Close()
}()
content := fmt.Sprintf("%s\n", mac)
_, err = file.WriteString(content)
if err != nil {
log.Errorf("failed to write %s: %s", WolMacFile, err)
return
}
}
func isMacExist(mac string) bool {
content, err := os.ReadFile(WolMacFile)
if err != nil {
return false
}
macs := strings.Split(string(content), "\n")
for _, item := range macs {
parts := strings.Split(item, " ")
if mac == parts[0] {
return true
}
}
return false
}