Move service enable/disable functionality to esvm

This commit is contained in:
2025-08-27 15:57:56 +03:00
parent d344347782
commit 0df715dda1
5 changed files with 127 additions and 105 deletions
-2
View File
@@ -1,5 +1,3 @@
module ectl module ectl
go 1.23.4 go 1.23.4
require gopkg.in/yaml.v3 v3.0.1
-4
View File
@@ -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=
+1 -99
View File
@@ -13,8 +13,6 @@ import (
"strings" "strings"
"syscall" "syscall"
"time" "time"
"gopkg.in/yaml.v3"
) )
// Build-time variables // Build-time variables
@@ -88,7 +86,7 @@ func main() {
} else if len(flag.Args()) <= 2 { } else if len(flag.Args()) <= 2 {
fmt.Printf("Usage: ectl service %s <service>\n", flag.Args()[1]) fmt.Printf("Usage: ectl service %s <service>\n", flag.Args()[1])
return 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 { type ServiceCommandJsonStruct struct {
Command string `json:"command"` Command string `json:"command"`
Service string `json:"service"` Service string `json:"service"`
@@ -136,102 +134,6 @@ func main() {
log.Fatal("Connection returned empty string!") 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 return
} else if flag.Args()[1] == "status" { } else if flag.Args()[1] == "status" {
if _, err := os.Stat(path.Join(runstatedir, "esvm", flag.Args()[2])); err != nil { if _, err := os.Stat(path.Join(runstatedir, "esvm", flag.Args()[2])); err != nil {
+62
View File
@@ -1,6 +1,7 @@
package main package main
import ( import (
"io"
"os" "os"
"os/exec" "os/exec"
"path" "path"
@@ -308,3 +309,64 @@ func (service *EnitService) RestartService() error {
return nil 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
}
+64
View File
@@ -20,6 +20,8 @@ func initSocket() (socket net.Listener, err error) {
commandHandlers["start"] = handleStartServiceCommand commandHandlers["start"] = handleStartServiceCommand
commandHandlers["stop"] = handleStopServiceCommand commandHandlers["stop"] = handleStopServiceCommand
commandHandlers["restart"] = handleRestartServiceCommand commandHandlers["restart"] = handleRestartServiceCommand
commandHandlers["enable"] = handleEnableServiceCommand
commandHandlers["disable"] = handleDisableServiceCommand
return socket, nil 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)))) 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 { func wrapErrorInJson(err error) []byte {
// Wrap error in struct // Wrap error in struct
type jsonErrorStruct struct { type jsonErrorStruct struct {