Compare commits

..

4 Commits

2 changed files with 101 additions and 13 deletions

View File

@ -55,10 +55,43 @@ func main() {
func mountVirtualFilesystems() {
fmt.Print("Mounting virtual filesystems... ")
commonFlags := uintptr(0 | syscall.MS_NOSUID | syscall.MS_RELATIME)
// Mount /proc
if err := syscall.Mount("proc", "/proc", "proc", commonFlags|syscall.MS_NODEV|syscall.MS_NOEXEC|syscall.MS_REMOUNT, ""); err != nil {
panic(err)
}
// Mount /sys
if err := syscall.Mount("sys", "/sys", "sysfs", commonFlags|syscall.MS_NODEV|syscall.MS_NOEXEC|syscall.MS_REMOUNT, ""); err != nil {
panic(err)
}
// Mount /dev
if err := syscall.Mount("dev", "/dev", "devtmpfs", commonFlags|syscall.MS_REMOUNT, "mode=755,inode64"); err != nil {
panic(err)
}
// Mount /run
if err := syscall.Mount("run", "/run", "tmpfs", commonFlags|syscall.MS_NODEV|syscall.MS_REMOUNT, "mode=755,inode64"); err != nil {
panic(err)
}
// Mount /dev/pts
if err := os.Mkdir("/dev/pts", 0755); err != nil {
panic(err)
}
if err := syscall.Mount("none", "/dev/pts", "devpts", syscall.MS_NOSUID|syscall.MS_NOEXEC, ""); err != nil {
if err := syscall.Mount("devpts", "/dev/pts", "devpts", commonFlags, "gid=5,mode=620,ptmxmode=000"); err != nil {
panic(err)
}
// Mount /dev/shm
if err := os.Mkdir("/dev/shm", 0755); err != nil {
panic(err)
}
if err := syscall.Mount("shm", "/dev/shm", "tmpfs", commonFlags|syscall.MS_NODEV, "inode64"); err != nil {
panic(err)
}
// Mount securityfs
if err := syscall.Mount("securityfs", "/sys/kernel/security", "securityfs", commonFlags, ""); err != nil {
panic(err)
}
// Mount cgroups v2
if err := syscall.Mount("cgroup2", "/sys/fs/cgroup", "cgroup2", commonFlags|syscall.MS_NOEXEC, ""); err != nil {
panic(err)
}

View File

@ -31,12 +31,14 @@ const (
type EnitService struct {
Name string `yaml:"name"`
Description string `yaml:"description,omitempty"`
Dependencies []string `yaml:"dependencies,omitempty"`
Type string `yaml:"type"`
StartCmd string `yaml:"start_cmd"`
ExitMethod string `yaml:"exit_method"`
StopCmd string `yaml:"stop_cmd,omitempty"`
Restart bool `yaml:"restart,omitempty"`
ServiceRunPath string
restartCount int
stopChannel chan bool
}
@ -124,6 +126,7 @@ func Init() {
logger.Fatalf("Could not initialize ESVM! Error: %s", err)
}
// Read and initialize service files
for _, entry := range dirEntries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".esv") {
logger.Printf("Initializing service (%s)...\n", entry.Name())
@ -136,12 +139,14 @@ func Init() {
service := EnitService{
Name: "",
Description: "",
Dependencies: make([]string, 0),
Type: "",
StartCmd: "",
ExitMethod: "",
StopCmd: "",
Restart: false,
ServiceRunPath: "",
restartCount: 0,
stopChannel: make(chan bool),
}
if err := yaml.Unmarshal(bytes, &service); err != nil {
@ -176,11 +181,46 @@ func Init() {
Services = append(Services, service)
if err := service.StartService(); err != nil {
logger.Printf("Could not start service %s: %s\n", service.Name, err)
logger.Printf("Service (%s) has been initialized!\n", service.Name)
}
}
logger.Printf("Service (%s) has been initialized!\n", service.Name)
// Get services that meet their dependencies
servicesWithMetDepends := make([]EnitService, 0)
for _, service := range Services {
if len(service.GetUnmetDependencies()) == 0 {
servicesWithMetDepends = append(servicesWithMetDepends, service)
}
}
// Loop until all services have started or timed out
for start := time.Now(); time.Since(start) < 60*time.Second; {
if len(servicesWithMetDepends) == 0 {
break
}
for i := len(servicesWithMetDepends) - 1; i >= 0; i-- {
service := servicesWithMetDepends[i]
canStart := true
for _, dependency := range service.Dependencies {
if GetServiceByName(dependency).GetCurrentState() != EnitServiceRunning && GetServiceByName(dependency).GetCurrentState() != EnitServiceCompleted {
canStart = false
break
}
}
if canStart {
err := service.StartService()
if err != nil {
logger.Printf("Could not start service (%s)! Error: %s", service.Name, err)
}
servicesWithMetDepends = append(servicesWithMetDepends[:i], servicesWithMetDepends[i+1:]...)
}
}
}
if len(servicesWithMetDepends) > 0 {
for _, service := range servicesWithMetDepends {
logger.Printf("Could not start service (%s)! Error: dependencies not met", service.Name)
}
}
@ -206,6 +246,17 @@ func GetServiceByName(name string) *EnitService {
return nil
}
func (service *EnitService) GetUnmetDependencies() (missingDependencies []string) {
for _, dependency := range service.Dependencies {
depService := GetServiceByName(dependency)
if depService == nil {
missingDependencies = append(missingDependencies, dependency)
}
}
return missingDependencies
}
func (service *EnitService) GetProcess() *os.Process {
bytes, err := os.ReadFile(path.Join(service.ServiceRunPath, "process"))
if err != nil {
@ -281,15 +332,19 @@ func (service *EnitService) StartService() error {
err := cmd.Wait()
select {
case <-service.stopChannel:
service.restartCount = 0
_ = service.setCurrentState(EnitServiceStopped)
default:
if service.Type == "simple" && err == nil {
service.restartCount = 0
_ = service.setCurrentState(EnitServiceCompleted)
return
}
logger.Printf("Service (%s) has crashed!\n", service.Name)
_ = service.setCurrentState(EnitServiceCrashed)
if service.Restart {
if service.Restart && service.restartCount < 5 {
service.restartCount++
_ = service.StartService()
}
}