From 0df715dda16f91f5d4a7ef1658a8461b41f2c242 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Wed, 27 Aug 2025 15:57:56 +0300 Subject: [PATCH] Move service enable/disable functionality to esvm --- src/ectl/go.mod | 2 - src/ectl/go.sum | 4 -- src/ectl/main.go | 100 +------------------------------------------- src/esvm/service.go | 62 +++++++++++++++++++++++++++ src/esvm/socket.go | 64 ++++++++++++++++++++++++++++ 5 files changed, 127 insertions(+), 105 deletions(-) diff --git a/src/ectl/go.mod b/src/ectl/go.mod index 28b0013..56db4d6 100644 --- a/src/ectl/go.mod +++ b/src/ectl/go.mod @@ -1,5 +1,3 @@ module ectl go 1.23.4 - -require gopkg.in/yaml.v3 v3.0.1 diff --git a/src/ectl/go.sum b/src/ectl/go.sum index a62c313..e69de29 100644 --- a/src/ectl/go.sum +++ b/src/ectl/go.sum @@ -1,4 +0,0 @@ -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/src/ectl/main.go b/src/ectl/main.go index 3af2f70..27a7fda 100644 --- a/src/ectl/main.go +++ b/src/ectl/main.go @@ -13,8 +13,6 @@ import ( "strings" "syscall" "time" - - "gopkg.in/yaml.v3" ) // Build-time variables @@ -88,7 +86,7 @@ func main() { } else if len(flag.Args()) <= 2 { fmt.Printf("Usage: ectl service %s \n", flag.Args()[1]) return - } else if flag.Arg(1) == "start" || flag.Arg(1) == "stop" || flag.Arg(1) == "restart" { + } else if flag.Arg(1) == "start" || flag.Arg(1) == "stop" || flag.Arg(1) == "restart" || flag.Arg(1) == "enable" || flag.Arg(1) == "disable" { type ServiceCommandJsonStruct struct { Command string `json:"command"` Service string `json:"service"` @@ -136,102 +134,6 @@ func main() { log.Fatal("Connection returned empty string!") } - return - } else if flag.Args()[1] == "enable" { - // Check if service exists - found := false - entries, err := os.ReadDir(path.Join(sysconfdir, "esvm/services/")) - if err != nil { - log.Fatalf("Could not enable service! Error: %s\n", err) - } - type minimalServiceStruct struct { - Name string `yaml:"name"` - } - for _, entry := range entries { - if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".esv") { - continue - } - - bytes, err := os.ReadFile(path.Join(sysconfdir, "esvm/services", entry.Name())) - if err != nil { - log.Fatalf("Could not enable service! Error: %s\n", err) - } - - sv := minimalServiceStruct{Name: ""} - err = yaml.Unmarshal(bytes, &sv) - if err != nil { - log.Fatalf("Could not enable service! Error: %s\n", err) - } - - if sv.Name == flag.Args()[2] { - found = true - break - } - } - if !found { - log.Fatalf("Service does not exist!") - } - - if _, err := os.Stat(path.Join(sysconfdir, "esvm/enabled_services")); err != nil { - err := os.WriteFile(path.Join(sysconfdir, "esvm/enabled_services"), []byte(flag.Args()[2]+"\n"), 0644) - if err != nil { - log.Fatalf("Could not enable service! Error: %s\n", err) - } - return - } - - file, err := os.ReadFile(path.Join(sysconfdir, "esvm/enabled_services")) - if err != nil { - log.Fatalf("Could not enable service! Error: %s\n", err) - } - for _, line := range strings.Split(string(file), "\n") { - if strings.TrimSpace(line) == flag.Args()[2] { - fmt.Println("Service is already enabled!") - return - } - } - - err = os.WriteFile(path.Join(sysconfdir, "esvm/enabled_services"), []byte(string(file)+flag.Args()[2]+"\n"), 0644) - if err != nil { - log.Fatalf("Could not enable service! Error: %s\n", err) - } - - fmt.Printf("Service (%s) has been enabled!\n", flag.Args()[2]) - return - } else if flag.Args()[1] == "disable" { - if _, err := os.Stat(path.Join(sysconfdir, "esvm/enabled_services")); err != nil { - fmt.Println("Service is already disabled!") - return - } - - file, err := os.ReadFile(path.Join(sysconfdir, "esvm/enabled_services")) - if err != nil { - log.Fatalf("Could not disable service! Error: %s\n", err) - } - - lines := strings.Split(string(file), "\n") - found := false - for i := len(lines) - 1; i >= 0; i-- { - line := strings.TrimSpace(lines[i]) - if strings.TrimSpace(line) == flag.Args()[2] { - lines = append(lines[:i], lines[i+1:]...) - found = true - } else if strings.TrimSpace(line) == "" { - lines = append(lines[:i], lines[i+1:]...) - } - } - - if !found { - fmt.Println("Service is already disabled!") - return - } - - err = os.WriteFile(path.Join(sysconfdir, "esvm/enabled_services"), []byte(strings.Join(lines, "\n")+"\n"), 0644) - if err != nil { - log.Fatalf("Could not disable service! Error: %s\n", err) - } - - fmt.Printf("Service (%s) has been disabled!\n", flag.Args()[2]) return } else if flag.Args()[1] == "status" { if _, err := os.Stat(path.Join(runstatedir, "esvm", flag.Args()[2])); err != nil { diff --git a/src/esvm/service.go b/src/esvm/service.go index b67c2ec..a89dd3f 100644 --- a/src/esvm/service.go +++ b/src/esvm/service.go @@ -1,6 +1,7 @@ package main import ( + "io" "os" "os/exec" "path" @@ -308,3 +309,64 @@ func (service *EnitService) RestartService() error { return nil } + +// Functions will be rewritten at some point to allow enabling unloaded services + +func (service *EnitService) isEnabled() bool { + contents, err := os.ReadFile(path.Join(serviceConfigDir, "enabled_services")) + if err != nil { + return false + } + + for _, line := range strings.Split(string(contents), "\n") { + line = strings.TrimSpace(line) + if line == "" { + continue + } + + if line == service.Name { + return true + } + } + + return false +} + +func (service *EnitService) SetEnabled(isEnabled bool) error { + // Return if service is already in correct state + if service.isEnabled() == isEnabled { + return nil + } + + // Create or open enabled_services file + file, err := os.OpenFile(path.Join(serviceConfigDir, "enabled_services"), os.O_CREATE|os.O_RDWR, 0644) + if err != nil { + return err + } + defer file.Close() + + // Get enabled_services file contents + contents, err := io.ReadAll(file) + if err != nil { + return err + } + + // Modify contents + strContents := string(contents) + if isEnabled { + strContents += service.Name + "\n" + } else { + strContents = strings.ReplaceAll(strContents, service.Name+"\n", "") + } + + // Write new contents to file + file.Truncate(0) + file.Seek(0, 0) + _, err = file.WriteString(strContents) + if err != nil { + return err + } + file.Sync() + + return nil +} diff --git a/src/esvm/socket.go b/src/esvm/socket.go index f409c3d..8c94a55 100644 --- a/src/esvm/socket.go +++ b/src/esvm/socket.go @@ -20,6 +20,8 @@ func initSocket() (socket net.Listener, err error) { commandHandlers["start"] = handleStartServiceCommand commandHandlers["stop"] = handleStopServiceCommand commandHandlers["restart"] = handleRestartServiceCommand + commandHandlers["enable"] = handleEnableServiceCommand + commandHandlers["disable"] = handleDisableServiceCommand return socket, nil } @@ -143,6 +145,68 @@ func handleRestartServiceCommand(conn net.Conn, jsonData map[string]any) { conn.Write(wrapSuccessMsgInJson(fmt.Sprintf("Service (%s) has restarted sucessfully", serviceName.(string)))) } +func handleEnableServiceCommand(conn net.Conn, jsonData map[string]any) { + // Get service name from json data + serviceName, ok := jsonData["service"] + if !ok { + conn.Write(wrapErrorInJson(fmt.Errorf("'service' field missing"))) + return + } + + // Ensure service exists + service := GetServiceByName(serviceName.(string)) + if service == nil { + conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) not found", serviceName.(string)))) + return + } + + // Check if service is already enabled + if service.isEnabled() { + conn.Write(wrapSuccessMsgInJson(fmt.Sprintf("Service (%s) is already enabled", serviceName.(string)))) + return + } + + // Enable service + err := service.SetEnabled(true) + if err != nil { + conn.Write(wrapErrorInJson(fmt.Errorf("Could not enable service! Error: %s", err))) + return + } + + conn.Write(wrapSuccessMsgInJson(fmt.Sprintf("Service (%s) was enabled sucessfully", serviceName.(string)))) +} + +func handleDisableServiceCommand(conn net.Conn, jsonData map[string]any) { + // Get service name from json data + serviceName, ok := jsonData["service"] + if !ok { + conn.Write(wrapErrorInJson(fmt.Errorf("'service' field missing"))) + return + } + + // Ensure service exists + service := GetServiceByName(serviceName.(string)) + if service == nil { + conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) not found", serviceName.(string)))) + return + } + + // Check if service is already disabled + if !service.isEnabled() { + conn.Write(wrapSuccessMsgInJson(fmt.Sprintf("Service (%s) is already disabled", serviceName.(string)))) + return + } + + // Disable service + err := service.SetEnabled(false) + if err != nil { + conn.Write(wrapErrorInJson(fmt.Errorf("Could not disable service! Error: %s", err))) + return + } + + conn.Write(wrapSuccessMsgInJson(fmt.Sprintf("Service (%s) was disabled sucessfully", serviceName.(string)))) +} + func wrapErrorInJson(err error) []byte { // Wrap error in struct type jsonErrorStruct struct {