safing-portbase/modules/subsystems/subsystem.go
2020-04-14 16:27:43 +02:00

116 lines
2.6 KiB
Go

package subsystems
import (
"sync"
"github.com/safing/portbase/config"
"github.com/safing/portbase/database/record"
"github.com/safing/portbase/log"
"github.com/safing/portbase/modules"
)
// Subsystem describes a subset of modules that represent a part of a service or program to the user.
type Subsystem struct { //nolint:maligned // not worth the effort
record.Base
sync.Mutex
ID string
Name string
Description string
module *modules.Module
Modules []*ModuleStatus
FailureStatus uint8 // summary: worst status
ToggleOptionKey string
toggleOption *config.Option
toggleValue func() bool
ExpertiseLevel uint8 // copied from toggleOption
ReleaseLevel uint8 // copied from toggleOption
ConfigKeySpace string
}
// ModuleStatus describes the status of a module.
type ModuleStatus struct {
Name string
module *modules.Module
// status mgmt
Enabled bool
Status uint8
// failure status
FailureStatus uint8
FailureID string
FailureMsg string
}
// Save saves the Subsystem Status to the database.
func (sub *Subsystem) Save() {
if databaseKeySpace != "" {
if !sub.KeyIsSet() {
sub.SetKey(databaseKeySpace + sub.ID)
}
err := db.Put(sub)
if err != nil {
log.Errorf("subsystems: could not save subsystem status to database: %s", err)
}
}
}
func statusFromModule(module *modules.Module) *ModuleStatus {
status := &ModuleStatus{
Name: module.Name,
module: module,
Enabled: module.Enabled(),
Status: module.Status(),
}
status.FailureStatus, status.FailureID, status.FailureMsg = module.FailureStatus()
return status
}
func compareAndUpdateStatus(module *modules.Module, status *ModuleStatus) (changed bool) {
// check if enabled
enabled := module.Enabled()
if status.Enabled != enabled {
status.Enabled = enabled
changed = true
}
// check status
statusLvl := module.Status()
if status.Status != statusLvl {
status.Status = statusLvl
changed = true
}
// check failure status
failureStatus, failureID, failureMsg := module.FailureStatus()
if status.FailureStatus != failureStatus ||
status.FailureID != failureID {
status.FailureStatus = failureStatus
status.FailureID = failureID
status.FailureMsg = failureMsg
changed = true
}
return
}
func (sub *Subsystem) makeSummary() {
// find worst failing module
worstFailing := &ModuleStatus{}
for _, depStatus := range sub.Modules {
if depStatus.FailureStatus > worstFailing.FailureStatus {
worstFailing = depStatus
}
}
if worstFailing != nil {
sub.FailureStatus = worstFailing.FailureStatus
} else {
sub.FailureStatus = 0
}
}