resources: Improve the state/cache system
Refactor the state cache into the engine. This makes resource writing less error prone, and paves the way for better notifications.
This commit is contained in:
@@ -129,19 +129,35 @@ func (g *Graph) Process(v *Vertex) error {
|
||||
if changed, err := obj.SendRecv(obj); err != nil {
|
||||
return errwrap.Wrapf(err, "could not SendRecv in Process")
|
||||
} else if changed {
|
||||
obj.StateOK(false) // invalidate cache
|
||||
obj.StateOK(false) // invalidate cache, mark as dirty
|
||||
}
|
||||
|
||||
// if this fails, don't UpdateTimestamp()
|
||||
checkok, err := obj.CheckApply(!obj.Meta().Noop)
|
||||
if checkok && err != nil { // should never return this way
|
||||
log.Fatalf("%s[%s]: CheckApply(): %t, %+v", obj.Kind(), obj.GetName(), checkok, err)
|
||||
if global.DEBUG {
|
||||
log.Printf("%s[%s]: CheckApply(%t)", obj.Kind(), obj.GetName(), !obj.Meta().Noop)
|
||||
}
|
||||
|
||||
var checkOK bool
|
||||
var err error
|
||||
if obj.IsStateOK() { // check cached state, to skip CheckApply
|
||||
checkOK, err = true, nil
|
||||
} else {
|
||||
// if this fails, don't UpdateTimestamp()
|
||||
checkOK, err = obj.CheckApply(!obj.Meta().Noop)
|
||||
}
|
||||
|
||||
if checkOK && err != nil { // should never return this way
|
||||
log.Fatalf("%s[%s]: CheckApply(): %t, %+v", obj.Kind(), obj.GetName(), checkOK, err)
|
||||
}
|
||||
if global.DEBUG {
|
||||
log.Printf("%s[%s]: CheckApply(): %t, %v", obj.Kind(), obj.GetName(), checkok, err)
|
||||
log.Printf("%s[%s]: CheckApply(): %t, %v", obj.Kind(), obj.GetName(), checkOK, err)
|
||||
}
|
||||
|
||||
if !checkok { // if state *was* not ok, we had to have apply'ed
|
||||
// if CheckApply ran without noop and without error, state should be good
|
||||
if !obj.Meta().Noop && err == nil { // aka !obj.Meta().Noop || checkOK
|
||||
obj.StateOK(true) // reset
|
||||
}
|
||||
|
||||
if !checkOK { // if state *was* not ok, we had to have apply'ed
|
||||
if err != nil { // error during check or apply
|
||||
ok = false
|
||||
} else {
|
||||
@@ -189,7 +205,7 @@ func (g *Graph) Worker(v *Vertex) error {
|
||||
// the Watch() function about which graph it is
|
||||
// running on, which isolates things nicely...
|
||||
obj := v.Res
|
||||
chanProcess := make(chan event.Event)
|
||||
processChan := make(chan event.Event)
|
||||
go func() {
|
||||
running := false
|
||||
var timer = time.NewTimer(time.Duration(math.MaxInt64)) // longest duration
|
||||
@@ -205,14 +221,14 @@ func (g *Graph) Worker(v *Vertex) error {
|
||||
// event loop will keep running and change state,
|
||||
// causing the converged timeout to fire!
|
||||
select {
|
||||
case event, ok := <-chanProcess: // must use like this
|
||||
case event, ok := <-processChan: // must use like this
|
||||
if running && ok {
|
||||
// we got an event that wasn't a close,
|
||||
// while we were waiting for the timer!
|
||||
// if this happens, it might be a bug:(
|
||||
log.Fatalf("%s[%s]: Worker: Unexpected event: %+v", v.Kind(), v.GetName(), event)
|
||||
}
|
||||
if !ok { // chanProcess closed, let's exit
|
||||
if !ok { // processChan closed, let's exit
|
||||
break Loop // no event, so no ack!
|
||||
}
|
||||
|
||||
@@ -245,7 +261,7 @@ func (g *Graph) Worker(v *Vertex) error {
|
||||
running = false
|
||||
log.Printf("%s[%s]: CheckApply delay expired!", v.Kind(), v.GetName())
|
||||
// re-send this failed event, to trigger a CheckApply()
|
||||
go func() { chanProcess <- saved }()
|
||||
go func() { processChan <- saved }()
|
||||
// TODO: should we send a fake event instead?
|
||||
//saved = nil
|
||||
}
|
||||
@@ -308,14 +324,14 @@ func (g *Graph) Worker(v *Vertex) error {
|
||||
// NOTE: we can avoid the send if running Watch guarantees
|
||||
// one CheckApply event on startup!
|
||||
//if pendingSendEvent { // TODO: should this become a list in the future?
|
||||
// if exit, err := obj.DoSend(chanProcess, ""); exit || err != nil {
|
||||
// if exit, err := obj.DoSend(processChan, ""); exit || err != nil {
|
||||
// return err // we exit or bubble up a NACK...
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
// TODO: reset the watch retry count after some amount of success
|
||||
e := v.Res.Watch(chanProcess)
|
||||
e := v.Res.Watch(processChan)
|
||||
if e == nil { // exit signal
|
||||
err = nil // clean exit
|
||||
break
|
||||
@@ -339,7 +355,7 @@ func (g *Graph) Worker(v *Vertex) error {
|
||||
// by getting the Watch resource to send one event once it's up!
|
||||
//v.SendEvent(eventPoke, false, false)
|
||||
}
|
||||
close(chanProcess)
|
||||
close(processChan)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ func (obj *ExecRes) Watch(processChan chan event.Event) error {
|
||||
startup = true // startup finished
|
||||
send = false
|
||||
// it is okay to invalidate the clean state on poke too
|
||||
obj.isStateOK = false // something made state dirty
|
||||
obj.StateOK(false) // something made state dirty
|
||||
if exit, err := obj.DoSend(processChan, ""); exit || err != nil {
|
||||
return err // we exit or bubble up a NACK...
|
||||
}
|
||||
@@ -221,12 +221,11 @@ func (obj *ExecRes) Watch(processChan chan event.Event) error {
|
||||
// CheckApply checks the resource state and applies the resource if the bool
|
||||
// input is true. It returns error info and if the state check passed or not.
|
||||
// TODO: expand the IfCmd to be a list of commands
|
||||
func (obj *ExecRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
log.Printf("%s[%s]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
||||
func (obj *ExecRes) CheckApply(apply bool) (checkOK bool, err error) {
|
||||
|
||||
// if there is a watch command, but no if command, run based on state
|
||||
if obj.WatchCmd != "" && obj.IfCmd == "" {
|
||||
if obj.isStateOK {
|
||||
if obj.IsStateOK() { // FIXME: this is done by engine now...
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -264,7 +263,7 @@ func (obj *ExecRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
// if there is no watcher and no onlyif check, assume we should run
|
||||
} else { // if obj.WatchCmd == "" && obj.IfCmd == "" {
|
||||
// just run if state is dirty
|
||||
if obj.isStateOK {
|
||||
if obj.IsStateOK() { // FIXME: this is done by engine now...
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
@@ -331,12 +330,12 @@ func (obj *ExecRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
}
|
||||
// XXX: return based on exit value!!
|
||||
|
||||
// the state tracking is for exec resources that can't "detect" their
|
||||
// The state tracking is for exec resources that can't "detect" their
|
||||
// state, and assume it's invalid when the Watch() function triggers.
|
||||
// if we apply state successfully, we should reset it here so that we
|
||||
// If we apply state successfully, we should reset it here so that we
|
||||
// know that we have applied since the state was set not ok by event!
|
||||
obj.isStateOK = true // reset
|
||||
return false, nil // success
|
||||
// This now happens automatically after the engine runs CheckApply().
|
||||
return false, nil // success
|
||||
}
|
||||
|
||||
// ExecUID is the UID struct for ExecRes.
|
||||
|
||||
@@ -169,7 +169,6 @@ func (obj *FileRes) Watch(processChan chan event.Event) error {
|
||||
|
||||
var send = false // send event?
|
||||
var exit = false
|
||||
var dirty = false
|
||||
|
||||
for {
|
||||
if global.DEBUG {
|
||||
@@ -190,14 +189,14 @@ func (obj *FileRes) Watch(processChan chan event.Event) error {
|
||||
log.Printf("%s[%s]: Event(%s): %v", obj.Kind(), obj.GetName(), event.Body.Name, event.Body.Op)
|
||||
}
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
|
||||
case event := <-obj.Events():
|
||||
cuid.SetConverged(false)
|
||||
if exit, send = obj.ReadEvent(&event); exit {
|
||||
return nil // exit
|
||||
}
|
||||
//dirty = false // these events don't invalidate state
|
||||
//obj.StateOK(false) // dirty // these events don't invalidate state
|
||||
|
||||
case <-cuid.ConvergedTimer():
|
||||
cuid.SetConverged(true) // converged!
|
||||
@@ -206,18 +205,13 @@ func (obj *FileRes) Watch(processChan chan event.Event) error {
|
||||
case <-Startup(startup):
|
||||
cuid.SetConverged(false)
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
}
|
||||
|
||||
// do all our event sending all together to avoid duplicate msgs
|
||||
if send {
|
||||
startup = true // startup finished
|
||||
send = false
|
||||
// only invalid state on certain types of events
|
||||
if dirty {
|
||||
dirty = false
|
||||
obj.isStateOK = false // something made state dirty
|
||||
}
|
||||
if exit, err := obj.DoSend(processChan, ""); exit || err != nil {
|
||||
return err // we exit or bubble up a NACK...
|
||||
}
|
||||
@@ -645,11 +639,6 @@ func (obj *FileRes) contentCheckApply(apply bool) (checkOK bool, _ error) {
|
||||
// CheckApply checks the resource state and applies the resource if the bool
|
||||
// input is true. It returns error info and if the state check passed or not.
|
||||
func (obj *FileRes) CheckApply(apply bool) (checkOK bool, _ error) {
|
||||
log.Printf("%s[%s]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
||||
|
||||
if obj.isStateOK { // cache the state
|
||||
return true, nil
|
||||
}
|
||||
|
||||
checkOK = true
|
||||
|
||||
@@ -673,10 +662,6 @@ func (obj *FileRes) CheckApply(apply bool) (checkOK bool, _ error) {
|
||||
// checkOK = false
|
||||
//}
|
||||
|
||||
// if we did work successfully, or are in a good state, then state is ok
|
||||
if apply || checkOK {
|
||||
obj.isStateOK = true
|
||||
}
|
||||
return checkOK, nil // w00t
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,6 @@ func (obj *HostnameRes) Watch(processChan chan event.Event) error {
|
||||
bus.Signal(signals)
|
||||
|
||||
var send = false // send event?
|
||||
var dirty = false
|
||||
|
||||
for {
|
||||
obj.SetState(ResStateWatching) // reset
|
||||
@@ -151,7 +150,7 @@ func (obj *HostnameRes) Watch(processChan chan event.Event) error {
|
||||
case <-signals:
|
||||
cuid.SetConverged(false)
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
|
||||
case event := <-obj.Events():
|
||||
cuid.SetConverged(false)
|
||||
@@ -160,7 +159,7 @@ func (obj *HostnameRes) Watch(processChan chan event.Event) error {
|
||||
return nil // exit
|
||||
}
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
|
||||
case <-cuid.ConvergedTimer():
|
||||
cuid.SetConverged(true) // converged!
|
||||
@@ -175,11 +174,7 @@ func (obj *HostnameRes) Watch(processChan chan event.Event) error {
|
||||
if send {
|
||||
startup = true // startup finished
|
||||
send = false
|
||||
if dirty {
|
||||
dirty = false
|
||||
obj.isStateOK = false // something made state dirty
|
||||
}
|
||||
// only do this on certain types of events
|
||||
|
||||
if exit, err := obj.DoSend(processChan, ""); exit || err != nil {
|
||||
return err // we exit or bubble up a NACK...
|
||||
}
|
||||
@@ -223,12 +218,6 @@ func updateHostnameProperty(object dbus.BusObject, expectedValue, property, sett
|
||||
|
||||
// CheckApply method for Hostname resource.
|
||||
func (obj *HostnameRes) CheckApply(apply bool) (checkOK bool, err error) {
|
||||
log.Printf("%v[%v]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
||||
|
||||
if obj.isStateOK { // cached state
|
||||
return true, nil
|
||||
}
|
||||
|
||||
conn, err := util.SystemBusPrivateUsable()
|
||||
if err != nil {
|
||||
return false, errwrap.Wrap(err, "Failed to connect to the private system bus")
|
||||
@@ -260,10 +249,6 @@ func (obj *HostnameRes) CheckApply(apply bool) (checkOK bool, err error) {
|
||||
checkOK = checkOK && propertyCheckOK
|
||||
}
|
||||
|
||||
if apply || checkOK {
|
||||
obj.isStateOK = true
|
||||
}
|
||||
|
||||
return checkOK, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -125,16 +125,15 @@ func (obj *MsgRes) Watch(processChan chan event.Event) error {
|
||||
return nil // exit
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO: invalidate cached state on poke events
|
||||
obj.logStateOK = false
|
||||
if obj.Journal {
|
||||
obj.journalStateOK = false
|
||||
}
|
||||
if obj.Syslog {
|
||||
obj.syslogStateOK = false
|
||||
}
|
||||
*/
|
||||
// TODO: invalidate cached state on poke events
|
||||
//obj.logStateOK = false
|
||||
//if obj.Journal {
|
||||
// obj.journalStateOK = false
|
||||
//}
|
||||
//if obj.Syslog {
|
||||
// obj.syslogStateOK = false
|
||||
//}
|
||||
//obj.updateStateOK()
|
||||
send = true
|
||||
|
||||
case <-cuid.ConvergedTimer():
|
||||
@@ -205,7 +204,7 @@ func (obj *MsgRes) Compare(res Res) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsAllStateOK derives a compound state from all internal cache flags that apply to this resource.
|
||||
// isAllStateOK derives a compound state from all internal cache flags that apply to this resource.
|
||||
func (obj *MsgRes) isAllStateOK() bool {
|
||||
if obj.Journal && !obj.journalStateOK {
|
||||
return false
|
||||
@@ -216,6 +215,11 @@ func (obj *MsgRes) isAllStateOK() bool {
|
||||
return obj.logStateOK
|
||||
}
|
||||
|
||||
// updateStateOK sets the global state so it can be read by the engine.
|
||||
func (obj *MsgRes) updateStateOK() {
|
||||
obj.StateOK(obj.isAllStateOK())
|
||||
}
|
||||
|
||||
// JournalPriority converts a string description to a numeric priority.
|
||||
// XXX: Have Validate() make sure it actually is one of these.
|
||||
func (obj *MsgRes) journalPriority() journal.Priority {
|
||||
@@ -243,15 +247,16 @@ func (obj *MsgRes) journalPriority() journal.Priority {
|
||||
// CheckApply method for Msg resource.
|
||||
// Every check leads to an apply, meaning that the message is flushed to the journal.
|
||||
func (obj *MsgRes) CheckApply(apply bool) (bool, error) {
|
||||
log.Printf("%s[%s]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
||||
|
||||
if obj.isAllStateOK() {
|
||||
return true, nil
|
||||
}
|
||||
// isStateOK() done by engine, so we updateStateOK() to pass in value
|
||||
//if obj.isAllStateOK() {
|
||||
// return true, nil
|
||||
//}
|
||||
|
||||
if !obj.logStateOK {
|
||||
log.Printf("%s[%s]: Body: %s", obj.Kind(), obj.GetName(), obj.Body)
|
||||
obj.logStateOK = true
|
||||
obj.updateStateOK()
|
||||
}
|
||||
|
||||
if !apply {
|
||||
@@ -262,10 +267,12 @@ func (obj *MsgRes) CheckApply(apply bool) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
obj.journalStateOK = true
|
||||
obj.updateStateOK()
|
||||
}
|
||||
if obj.Syslog && !obj.syslogStateOK {
|
||||
// TODO: implement syslog client
|
||||
obj.syslogStateOK = true
|
||||
obj.updateStateOK()
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package resources
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/purpleidea/mgmt/event"
|
||||
@@ -102,8 +101,6 @@ func (obj *NoopRes) Watch(processChan chan event.Event) error {
|
||||
if send {
|
||||
startup = true // startup finished
|
||||
send = false
|
||||
// only do this on certain types of events
|
||||
//obj.isStateOK = false // something made state dirty
|
||||
if exit, err := obj.DoSend(processChan, ""); exit || err != nil {
|
||||
return err // we exit or bubble up a NACK...
|
||||
}
|
||||
@@ -112,8 +109,7 @@ func (obj *NoopRes) Watch(processChan chan event.Event) error {
|
||||
}
|
||||
|
||||
// CheckApply method for Noop resource. Does nothing, returns happy!
|
||||
func (obj *NoopRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
log.Printf("%s[%s]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
||||
func (obj *NoopRes) CheckApply(apply bool) (checkOK bool, err error) {
|
||||
return true, nil // state is always okay
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,6 @@ func (obj *NspawnRes) Watch(processChan chan event.Event) error {
|
||||
|
||||
var send = false
|
||||
var exit = false
|
||||
var dirty = false
|
||||
|
||||
for {
|
||||
obj.SetState(ResStateWatching)
|
||||
@@ -155,7 +154,7 @@ func (obj *NspawnRes) Watch(processChan chan event.Event) error {
|
||||
return fmt.Errorf("Unknown event: %s", event.Name)
|
||||
}
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
}
|
||||
|
||||
case event := <-obj.Events():
|
||||
@@ -171,18 +170,13 @@ func (obj *NspawnRes) Watch(processChan chan event.Event) error {
|
||||
case <-Startup(startup):
|
||||
cuid.SetConverged(false)
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
}
|
||||
|
||||
// do all our event sending all together to avoid duplicate msgs
|
||||
if send || !obj.isStateOK {
|
||||
if send {
|
||||
startup = true // startup finished
|
||||
send = false
|
||||
// only invalid state on certain types of events
|
||||
if dirty {
|
||||
dirty = false
|
||||
obj.isStateOK = false // something made state dirty
|
||||
}
|
||||
if exit, err := obj.DoSend(processChan, ""); exit || err != nil {
|
||||
return err // we exit or bubble up a NACK...
|
||||
}
|
||||
@@ -193,15 +187,7 @@ func (obj *NspawnRes) Watch(processChan chan event.Event) error {
|
||||
// CheckApply is run to check the state and, if apply is true, to apply the
|
||||
// necessary changes to reach the desired state. this is run before Watch and
|
||||
// again if watch finds a change occurring to the state
|
||||
func (obj *NspawnRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
if global.DEBUG {
|
||||
log.Printf("%s[%s]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
||||
}
|
||||
|
||||
if obj.isStateOK { // cache the state
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (obj *NspawnRes) CheckApply(apply bool) (checkOK bool, err error) {
|
||||
// this resource depends on systemd ensure that it's running
|
||||
if !systemdUtil.IsRunningSystemd() {
|
||||
return false, errors.New("Systemd is not running.")
|
||||
@@ -241,11 +227,10 @@ func (obj *NspawnRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
if global.DEBUG {
|
||||
log.Printf("%s[%s]: CheckApply() in valid state", obj.Kind(), obj.GetName())
|
||||
}
|
||||
obj.isStateOK = true // state is ok
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// end of state checking. if we're here, checkok is false
|
||||
// end of state checking. if we're here, checkOK is false
|
||||
if !apply {
|
||||
return false, nil
|
||||
}
|
||||
@@ -271,7 +256,6 @@ func (obj *NspawnRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
obj.isStateOK = true // state is now good
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
"os"
|
||||
"path"
|
||||
@@ -239,8 +238,6 @@ func (obj *PasswordRes) Watch(processChan chan event.Event) error {
|
||||
if send {
|
||||
startup = true // startup finished
|
||||
send = false
|
||||
// only do this on certain types of events
|
||||
//obj.isStateOK = false // something made state dirty
|
||||
if exit, err := obj.DoSend(processChan, ""); exit || err != nil {
|
||||
return err // we exit or bubble up a NACK...
|
||||
}
|
||||
@@ -249,9 +246,7 @@ func (obj *PasswordRes) Watch(processChan chan event.Event) error {
|
||||
}
|
||||
|
||||
// CheckApply method for Password resource. Does nothing, returns happy!
|
||||
func (obj *PasswordRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
log.Printf("%s[%s]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
||||
|
||||
func (obj *PasswordRes) CheckApply(apply bool) (checkOK bool, err error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,6 @@ func (obj *PkgRes) Watch(processChan chan event.Event) error {
|
||||
|
||||
var send = false // send event?
|
||||
var exit = false
|
||||
var dirty = false
|
||||
|
||||
for {
|
||||
if global.DEBUG {
|
||||
@@ -165,14 +164,14 @@ func (obj *PkgRes) Watch(processChan chan event.Event) error {
|
||||
}
|
||||
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
|
||||
case event := <-obj.Events():
|
||||
cuid.SetConverged(false)
|
||||
if exit, send = obj.ReadEvent(&event); exit {
|
||||
return nil // exit
|
||||
}
|
||||
dirty = false // these events don't invalidate state
|
||||
//obj.StateOK(false) // these events don't invalidate state
|
||||
|
||||
case <-cuid.ConvergedTimer():
|
||||
cuid.SetConverged(true) // converged!
|
||||
@@ -181,18 +180,13 @@ func (obj *PkgRes) Watch(processChan chan event.Event) error {
|
||||
case <-Startup(startup):
|
||||
cuid.SetConverged(false)
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
}
|
||||
|
||||
// do all our event sending all together to avoid duplicate msgs
|
||||
if send {
|
||||
startup = true // startup finished
|
||||
send = false
|
||||
// only invalid state on certain types of events
|
||||
if dirty {
|
||||
dirty = false
|
||||
obj.isStateOK = false // something made state dirty
|
||||
}
|
||||
if exit, err := obj.DoSend(processChan, ""); exit || err != nil {
|
||||
return err // we exit or bubble up a NACK...
|
||||
}
|
||||
@@ -264,16 +258,8 @@ func (obj *PkgRes) pkgMappingHelper(bus *packagekit.Conn) (map[string]*packageki
|
||||
|
||||
// CheckApply checks the resource state and applies the resource if the bool
|
||||
// input is true. It returns error info and if the state check passed or not.
|
||||
func (obj *PkgRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
log.Printf("%s: CheckApply(%t)", obj.fmtNames(obj.getNames()), apply)
|
||||
|
||||
if obj.State == "" { // TODO: Validate() should replace this check!
|
||||
log.Fatalf("%s: Package state is undefined!", obj.fmtNames(obj.getNames()))
|
||||
}
|
||||
|
||||
if obj.isStateOK { // cache the state
|
||||
return true, nil
|
||||
}
|
||||
func (obj *PkgRes) CheckApply(apply bool) (checkOK bool, err error) {
|
||||
log.Printf("%s: Check", obj.fmtNames(obj.getNames()))
|
||||
|
||||
bus := packagekit.NewBus()
|
||||
if bus == nil {
|
||||
@@ -309,12 +295,10 @@ func (obj *PkgRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
fallthrough
|
||||
case "newest":
|
||||
if validState {
|
||||
obj.isStateOK = true // reset
|
||||
return true, nil // state is correct, exit!
|
||||
return true, nil // state is correct, exit!
|
||||
}
|
||||
default: // version string
|
||||
if obj.State == data.Version && data.Version != "" {
|
||||
obj.isStateOK = true // reset
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
@@ -358,8 +342,7 @@ func (obj *PkgRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
return false, err // fail
|
||||
}
|
||||
log.Printf("%s: Set: %v success!", obj.fmtNames(util.StrListIntersection(applyPackages, obj.getNames())), obj.State)
|
||||
obj.isStateOK = true // reset
|
||||
return false, nil // success
|
||||
return false, nil // success
|
||||
}
|
||||
|
||||
// PkgUID is the UID struct for PkgRes.
|
||||
|
||||
@@ -221,7 +221,7 @@ func (obj *BaseRes) Init() error {
|
||||
if obj.kind == "" {
|
||||
return fmt.Errorf("Resource did not set kind!")
|
||||
}
|
||||
obj.events = make(chan event.Event) // unbuffered chan size to avoid stale events
|
||||
obj.events = make(chan event.Event) // unbuffered chan to avoid stale events
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,6 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
|
||||
var svc = fmt.Sprintf("%s.service", obj.Name) // systemd name
|
||||
var send = false // send event?
|
||||
var exit = false
|
||||
var dirty = false
|
||||
var invalid = false // does the svc exist or not?
|
||||
var previous bool // previous invalid value
|
||||
set := conn.NewSubscriptionSet() // no error should be returned
|
||||
@@ -150,7 +149,7 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
|
||||
|
||||
if previous != invalid { // if invalid changed, send signal
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
}
|
||||
|
||||
if invalid {
|
||||
@@ -173,7 +172,7 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
|
||||
return nil // exit
|
||||
}
|
||||
if event.GetActivity() {
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
}
|
||||
|
||||
case <-cuid.ConvergedTimer():
|
||||
@@ -183,7 +182,7 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
|
||||
case <-Startup(startup):
|
||||
cuid.SetConverged(false)
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
}
|
||||
} else {
|
||||
if !activeSet {
|
||||
@@ -216,7 +215,7 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
|
||||
log.Printf("Svc[%s]->Stopped", svc)
|
||||
}
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
|
||||
case err := <-subErrors:
|
||||
cuid.SetConverged(false)
|
||||
@@ -228,7 +227,7 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
|
||||
return nil // exit
|
||||
}
|
||||
if event.GetActivity() {
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
}
|
||||
|
||||
case <-cuid.ConvergedTimer():
|
||||
@@ -238,17 +237,13 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
|
||||
case <-Startup(startup):
|
||||
cuid.SetConverged(false)
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
}
|
||||
}
|
||||
|
||||
if send {
|
||||
startup = true // startup finished
|
||||
send = false
|
||||
if dirty {
|
||||
dirty = false
|
||||
obj.isStateOK = false // something made state dirty
|
||||
}
|
||||
if exit, err := obj.DoSend(processChan, ""); exit || err != nil {
|
||||
return err // we exit or bubble up a NACK...
|
||||
}
|
||||
@@ -258,13 +253,7 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
|
||||
|
||||
// CheckApply checks the resource state and applies the resource if the bool
|
||||
// input is true. It returns error info and if the state check passed or not.
|
||||
func (obj *SvcRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
log.Printf("%s[%s]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
||||
|
||||
if obj.isStateOK { // cache the state
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (obj *SvcRes) CheckApply(apply bool) (checkOK bool, err error) {
|
||||
if !systemdUtil.IsRunningSystemd() {
|
||||
return false, fmt.Errorf("Systemd is not running.")
|
||||
}
|
||||
@@ -301,7 +290,6 @@ func (obj *SvcRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
var startupOK = true // XXX: DETECT AND SET
|
||||
|
||||
if stateOK && startupOK {
|
||||
obj.isStateOK = true
|
||||
return true, nil // we are in the correct state
|
||||
}
|
||||
|
||||
@@ -349,7 +337,6 @@ func (obj *SvcRes) CheckApply(apply bool) (checkok bool, err error) {
|
||||
|
||||
// XXX: also set enabled on boot
|
||||
|
||||
obj.isStateOK = true
|
||||
return false, nil // success
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,6 @@ func (obj *TimerRes) Watch(processChan chan event.Event) error {
|
||||
if send {
|
||||
startup = true // startup finished
|
||||
send = false
|
||||
//obj.isStateOK = false
|
||||
if exit, err := obj.DoSend(processChan, "timer ticked"); exit || err != nil {
|
||||
return err // we exit or bubble up a NACK...
|
||||
}
|
||||
@@ -162,6 +161,5 @@ func (obj *TimerRes) Compare(res Res) bool {
|
||||
|
||||
// CheckApply method for Timer resource. Does nothing, returns happy!
|
||||
func (obj *TimerRes) CheckApply(apply bool) (bool, error) {
|
||||
log.Printf("%s[%s]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
||||
return true, nil // state is always okay
|
||||
}
|
||||
|
||||
@@ -206,7 +206,6 @@ func (obj *VirtRes) Watch(processChan chan event.Event) error {
|
||||
|
||||
var send = false
|
||||
var exit = false
|
||||
var dirty = false
|
||||
|
||||
for {
|
||||
select {
|
||||
@@ -215,37 +214,37 @@ func (obj *VirtRes) Watch(processChan chan event.Event) error {
|
||||
switch event {
|
||||
case libvirt.VIR_DOMAIN_EVENT_DEFINED:
|
||||
if obj.Transient {
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
send = true
|
||||
}
|
||||
case libvirt.VIR_DOMAIN_EVENT_UNDEFINED:
|
||||
if !obj.Transient {
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
send = true
|
||||
}
|
||||
case libvirt.VIR_DOMAIN_EVENT_STARTED:
|
||||
fallthrough
|
||||
case libvirt.VIR_DOMAIN_EVENT_RESUMED:
|
||||
if obj.State != "running" {
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
send = true
|
||||
}
|
||||
case libvirt.VIR_DOMAIN_EVENT_SUSPENDED:
|
||||
if obj.State != "paused" {
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
send = true
|
||||
}
|
||||
case libvirt.VIR_DOMAIN_EVENT_STOPPED:
|
||||
fallthrough
|
||||
case libvirt.VIR_DOMAIN_EVENT_SHUTDOWN:
|
||||
if obj.State != "shutoff" {
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
send = true
|
||||
}
|
||||
case libvirt.VIR_DOMAIN_EVENT_PMSUSPENDED:
|
||||
fallthrough
|
||||
case libvirt.VIR_DOMAIN_EVENT_CRASHED:
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
send = true
|
||||
}
|
||||
|
||||
@@ -266,17 +265,12 @@ func (obj *VirtRes) Watch(processChan chan event.Event) error {
|
||||
case <-Startup(startup):
|
||||
cuid.SetConverged(false)
|
||||
send = true
|
||||
dirty = true
|
||||
obj.StateOK(false) // dirty
|
||||
}
|
||||
|
||||
if send {
|
||||
startup = true // startup finished
|
||||
send = false
|
||||
// only invalid state on certain types of events
|
||||
if dirty {
|
||||
dirty = false
|
||||
obj.isStateOK = false // something made state dirty
|
||||
}
|
||||
if exit, err := obj.DoSend(processChan, ""); exit || err != nil {
|
||||
return err // we exit or bubble up a NACK...
|
||||
}
|
||||
@@ -379,12 +373,6 @@ func (obj *VirtRes) domainCreate() (libvirt.VirDomain, bool, error) {
|
||||
// CheckApply checks the resource state and applies the resource if the bool
|
||||
// input is true. It returns error info and if the state check passed or not.
|
||||
func (obj *VirtRes) CheckApply(apply bool) (bool, error) {
|
||||
log.Printf("%s[%s]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
||||
|
||||
if obj.isStateOK { // cache the state
|
||||
return true, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
obj.conn, err = obj.connect()
|
||||
if err != nil {
|
||||
@@ -399,7 +387,6 @@ func (obj *VirtRes) CheckApply(apply bool) (bool, error) {
|
||||
} else if virErr, ok := err.(libvirt.VirError); ok && virErr.Code == libvirt.VIR_ERR_NO_DOMAIN {
|
||||
// domain not found
|
||||
if obj.absent {
|
||||
obj.isStateOK = true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -538,9 +525,6 @@ func (obj *VirtRes) CheckApply(apply bool) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if apply || checkOK {
|
||||
obj.isStateOK = true
|
||||
}
|
||||
return checkOK, nil // w00t
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user