update... work pending
This commit is contained in:
21
daemon/consts.go
Normal file
21
daemon/consts.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
`os`
|
||||
`syscall`
|
||||
|
||||
sysdUtil `github.com/coreos/go-systemd/util`
|
||||
)
|
||||
|
||||
// Signal traps
|
||||
var (
|
||||
stopSigs []os.Signal = []os.Signal{
|
||||
syscall.SIGQUIT,
|
||||
os.Interrupt,
|
||||
syscall.SIGTERM,
|
||||
}
|
||||
reloadSigs []os.Signal = []os.Signal{
|
||||
syscall.SIGHUP,
|
||||
}
|
||||
isSystemd bool = sysdUtil.IsRunningSystemd()
|
||||
)
|
||||
34
daemon/funcs.go
Normal file
34
daemon/funcs.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
`os`
|
||||
`time`
|
||||
|
||||
`r00t2.io/gobroke/conf`
|
||||
`r00t2.io/goutils/logging`
|
||||
)
|
||||
|
||||
// NewUpdater returns a new Updater.
|
||||
func NewUpdater(cfg *conf.Config, log logging.Logger) (updater *Updater, err error) {
|
||||
|
||||
var u Updater = Updater{
|
||||
cfg: cfg,
|
||||
log: log,
|
||||
doneChan: make(chan bool, 1),
|
||||
stopChan: make(chan os.Signal),
|
||||
reloadChan: make(chan os.Signal),
|
||||
isStopping: false,
|
||||
}
|
||||
|
||||
log.Debug("daemon.NewUpdater: Initializing new Updater.")
|
||||
|
||||
// This will start the timer immediately, but we restart it at the beginning of Updater.Start().
|
||||
// It just shouldn't be nil.
|
||||
u.timer = time.NewTimer(cfg.Freq)
|
||||
|
||||
updater = &u
|
||||
|
||||
log.Debug("daemon.NewUpdater: Updater initialized.")
|
||||
|
||||
return
|
||||
}
|
||||
177
daemon/funcs_updater.go
Normal file
177
daemon/funcs_updater.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
`bytes`
|
||||
`os`
|
||||
`time`
|
||||
|
||||
sysd "github.com/coreos/go-systemd/daemon"
|
||||
`github.com/davecgh/go-spew/spew`
|
||||
`r00t2.io/gobroke/conf`
|
||||
`r00t2.io/gobroke/runner`
|
||||
`r00t2.io/goutils/multierr`
|
||||
)
|
||||
|
||||
// Start starts an Updater. This blocks.
|
||||
func (u *Updater) Start() (err error) {
|
||||
|
||||
var sig os.Signal
|
||||
var t time.Time
|
||||
var tunResults []*runner.TunnelResult
|
||||
var tunsChanged bool
|
||||
var tunsUpdated bool
|
||||
var mErr *multierr.MultiError = multierr.NewMultiError(nil)
|
||||
|
||||
u.log.Debug("daemon.Updater.Start: Starting persistent Updater.")
|
||||
|
||||
u.timer.Reset(u.cfg.Freq)
|
||||
|
||||
if isSystemd {
|
||||
var supported bool
|
||||
|
||||
// https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
||||
if supported, err = sysd.SdNotify(false, sysd.SdNotifyReady); err != nil {
|
||||
u.log.Err(
|
||||
"daemon.Updater.Start: Error encountered when notifying systemd of changestate to READY (supported: %v): %v",
|
||||
supported, err,
|
||||
)
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
|
||||
breakLoop:
|
||||
for !u.isStopping {
|
||||
if u.isStopping {
|
||||
break
|
||||
}
|
||||
select {
|
||||
case t = <-u.timer.C:
|
||||
u.log.Debug("daemon.Updater.Start: Tick at %s; running check/update.", t.String())
|
||||
if tunResults, tunsChanged, tunsUpdated, err = runner.Run(u.cfg, u.log); err != nil {
|
||||
u.log.Err("daemon.Updater.Start: Received error running check/update: %v", err)
|
||||
mErr.AddError(err)
|
||||
err = nil
|
||||
} else {
|
||||
u.log.Debug(
|
||||
"daemon.Updater.Start: Check/update finished at %s; waiting %s. Changed: %v, Updated: %v, Results:\n%s",
|
||||
t.String(), u.cfg.Freq.String(), tunsChanged, tunsUpdated, spew.Sdump(tunResults),
|
||||
)
|
||||
}
|
||||
u.timer.Reset(u.cfg.Freq)
|
||||
case sig = <-u.reloadChan:
|
||||
u.log.Debug("daemon.Updater.Start: Received reload signal %v (%#v): %v", sig, sig, sig.String())
|
||||
if u.isStopping {
|
||||
break breakLoop
|
||||
}
|
||||
if err = u.Reload(); err != nil {
|
||||
u.log.Err("daemon.Updater.Start: Received error running reload: %v", err)
|
||||
mErr.AddError(err)
|
||||
err = nil
|
||||
}
|
||||
case sig = <-u.stopChan:
|
||||
u.isStopping = true
|
||||
u.log.Debug("daemon.Updater.Start: Received stop signal %v (%#v): %v", sig, sig, sig.String())
|
||||
if err = u.Stop(); err != nil {
|
||||
u.log.Err("daemon.Updater.Start: Received error stopping: %v", err)
|
||||
mErr.AddError(err)
|
||||
err = nil
|
||||
}
|
||||
break breakLoop
|
||||
}
|
||||
}
|
||||
|
||||
if !mErr.IsEmpty() {
|
||||
err = mErr
|
||||
return
|
||||
}
|
||||
|
||||
u.log.Debug("daemon.Updater.Start: Persistent updater stopped.")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Stop stops an Updater. This is called by signal handlers in Start, and will close Start's block.
|
||||
func (u *Updater) Stop() (err error) {
|
||||
|
||||
u.log.Debug("daemon.Updater.Stop: Stopping persistent Updater.")
|
||||
|
||||
if isSystemd {
|
||||
// https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
||||
if _, err = sysd.SdNotify(false, sysd.SdNotifyStopping); err != nil {
|
||||
u.log.Err("daemon.Updater.Stop: Received error notifying systemd of stop: %v", err)
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
|
||||
u.isStopping = true
|
||||
u.timer.Stop()
|
||||
close(u.stopChan)
|
||||
close(u.reloadChan)
|
||||
|
||||
u.log.Debug("daemon.Updater.Stop: Stopped persistent Updater.")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Reload reloads the configuration if it was originally set via a file.
|
||||
func (u *Updater) Reload() (err error) {
|
||||
|
||||
var prevCfg *conf.Config
|
||||
var supported bool
|
||||
var newCksum []byte
|
||||
|
||||
u.log.Debug("daemon.Updater.Reload: Reloading persistent Updater.")
|
||||
|
||||
if isSystemd {
|
||||
// https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
||||
if _, err = sysd.SdNotify(false, sysd.SdNotifyReloading); err != nil {
|
||||
u.log.Err("daemon.Updater.Reload: Received error notifying systemd of reload: %v", err)
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
|
||||
if u.cfg.Path() != "" {
|
||||
if newCksum, err = conf.ChecksumPath(u.cfg.Path()); err != nil {
|
||||
u.log.Err(
|
||||
"daemon.Updater.Reload: Received error getting checksum of defined conf path '%s'; skipping reload: %v",
|
||||
u.cfg.Path(), err,
|
||||
)
|
||||
err = nil
|
||||
} else {
|
||||
if bytes.Equal(newCksum, u.cfg.Checksum()) {
|
||||
u.log.Warning("daemon.Updater.Reload: Config path '%s' checksum unchanged; skipping reload", u.cfg.Path())
|
||||
} else {
|
||||
prevCfg = new(conf.Config)
|
||||
*prevCfg = *u.cfg
|
||||
if u.cfg, err = conf.NewConfig(u.cfg.Path(), u.cfg.IsDebug(), u.log); err != nil {
|
||||
u.log.Err("daemon.Updater.Reload: Received error parsing new config; reverting to previous configuration: %v", err)
|
||||
err = nil
|
||||
u.cfg = prevCfg
|
||||
} else {
|
||||
u.log.Debug(
|
||||
"daemon.Updater.Reload: New configuration loaded from '%s'; restarting timer for '%s'.",
|
||||
u.cfg.Path(), u.cfg.Freq.String(),
|
||||
)
|
||||
u.timer.Reset(u.cfg.Freq)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
u.log.Debug("daemon.Updater.Reload: No config filepath specified; NO-OP.")
|
||||
}
|
||||
|
||||
if isSystemd {
|
||||
// https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
||||
if supported, err = sysd.SdNotify(false, sysd.SdNotifyReady); err != nil {
|
||||
u.log.Err(
|
||||
"daemon.Updater.Reload: Error encountered when notifying systemd of changestate to READY (supported: %v): %v",
|
||||
supported, err,
|
||||
)
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
|
||||
u.log.Debug("daemon.Updater.Reload: Finished Updater reload.")
|
||||
|
||||
return
|
||||
}
|
||||
20
daemon/types.go
Normal file
20
daemon/types.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
`os`
|
||||
`time`
|
||||
|
||||
`r00t2.io/gobroke/conf`
|
||||
`r00t2.io/goutils/logging`
|
||||
)
|
||||
|
||||
// Updater runs a persistent checker/updater as a service/daemon.
|
||||
type Updater struct {
|
||||
cfg *conf.Config
|
||||
log logging.Logger
|
||||
timer *time.Timer
|
||||
doneChan chan bool
|
||||
stopChan chan os.Signal
|
||||
reloadChan chan os.Signal
|
||||
isStopping bool
|
||||
}
|
||||
Reference in New Issue
Block a user