Files
warewulf/internal/pkg/warewulfd/daemon.go
2022-01-24 00:32:02 +00:00

180 lines
3.7 KiB
Go

package warewulfd
import (
"fmt"
"io/ioutil"
"log"
"log/syslog"
"os"
"os/exec"
"strconv"
"syscall"
"time"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/version"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
"github.com/pkg/errors"
)
const (
WAREWULFD_PIDFILE = "/var/run/warewulfd.pid"
WAREWULFD_LOGFILE = "/var/log/warewulfd.log"
)
var logwriter *syslog.Writer
var loginit bool
func daemonLogf(message string, a ...interface{}) {
conf, err := warewulfconf.New()
if err != nil {
fmt.Printf("ERROR: Could not read Warewulf configuration file: %s\n", err)
return
}
if conf.Warewulf.Syslog {
if !loginit {
var err error
logwriter, err = syslog.New(syslog.LOG_NOTICE, "warewulfd")
if err != nil {
return
}
log.SetOutput(logwriter)
loginit = true
log.SetFlags(0)
log.SetPrefix("")
}
log.Printf(message, a...)
} else {
prefix := fmt.Sprintf("[%s] ", time.Now().Format(time.UnixDate))
fmt.Printf(prefix+message, a...)
}
}
func DaemonStart() error {
if os.Getenv("WAREWULFD_BACKGROUND") == "1" {
err := RunServer()
if err != nil {
return errors.Wrap(err, "failed to run server")
}
} else {
if util.IsFile(WAREWULFD_PIDFILE) {
return errors.New("process is already running")
}
os.Setenv("WAREWULFD_BACKGROUND", "1")
f, err := os.OpenFile(WAREWULFD_LOGFILE, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
return err
}
p, err := os.OpenFile(WAREWULFD_PIDFILE, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer p.Close()
cmd := exec.Command(os.Args[0], "server", "start")
cmd.Stdout = f
cmd.Stderr = f
err = cmd.Start()
if err != nil {
return errors.Wrap(err, "failed to start command")
}
pid := cmd.Process.Pid
fmt.Fprintf(p, "%d", pid)
fmt.Printf("Started Warewulf (%s) server at PID: %d\n", version.GetVersion(), pid)
}
return nil
}
func DaemonStatus() error {
if !util.IsFile(WAREWULFD_PIDFILE) {
return errors.New("Warewulf server is not running")
}
dat, err := ioutil.ReadFile(WAREWULFD_PIDFILE)
if err != nil {
return errors.Wrap(err, "could not read Warewulfd PID file")
}
pid, _ := strconv.Atoi(string(dat))
process, err := os.FindProcess(pid)
if err != nil {
return errors.Wrap(err, "failed to find running PID")
} else {
err := process.Signal(syscall.Signal(0))
if err != nil {
return errors.Wrap(err, "failed to send process SIGCONT")
} else {
fmt.Printf("Warewulf server is running at PID: %d\n", pid)
}
}
return nil
}
func DaemonReload() error {
if !util.IsFile(WAREWULFD_PIDFILE) {
return errors.New("Warewulf server is not running")
}
dat, err := ioutil.ReadFile(WAREWULFD_PIDFILE)
if err != nil {
return errors.Wrap(err, "could not read Warewulfd PID file")
}
pid, _ := strconv.Atoi(string(dat))
process, err := os.FindProcess(pid)
if err != nil {
return errors.Wrap(err, "failed to find running PID")
} else {
err := process.Signal(syscall.Signal(syscall.SIGHUP))
if err != nil {
return errors.Wrap(err, "failed to send process SIGHUP")
}
}
return nil
}
func DaemonStop() error {
if !util.IsFile(WAREWULFD_PIDFILE) {
fmt.Printf("Warewulf daemon process not running\n")
return nil
}
dat, err := ioutil.ReadFile(WAREWULFD_PIDFILE)
if err != nil {
return err
}
_ = os.Remove(WAREWULFD_PIDFILE)
pid, _ := strconv.Atoi(string(dat))
process, err := os.FindProcess(pid)
if err != nil {
return errors.Wrap(err, "failed to find running PID")
} else {
err := process.Signal(syscall.Signal(15))
if err != nil {
return errors.Wrap(err, "failed to send process SIGTERM")
} else {
fmt.Printf("Terminated Warewulf server at PID: %d\n", pid)
}
}
return nil
}