From b0a8fc165c67e64434e53675bb0cf82a7a18b191 Mon Sep 17 00:00:00 2001 From: James Shubin Date: Fri, 25 Nov 2016 12:30:29 -0500 Subject: [PATCH] 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. --- pgraph/actions.go | 44 ++++++++++++++++++++++++++++-------------- resources/exec.go | 17 ++++++++-------- resources/file.go | 21 +++----------------- resources/hostname.go | 21 +++----------------- resources/msg.go | 37 +++++++++++++++++++++-------------- resources/noop.go | 6 +----- resources/nspawn.go | 26 +++++-------------------- resources/password.go | 7 +------ resources/pkg.go | 31 +++++++---------------------- resources/resources.go | 2 +- resources/svc.go | 27 +++++++------------------- resources/timer.go | 2 -- resources/virt.go | 30 +++++++--------------------- 13 files changed, 95 insertions(+), 176 deletions(-) diff --git a/pgraph/actions.go b/pgraph/actions.go index 461dab47..2bfcef90 100644 --- a/pgraph/actions.go +++ b/pgraph/actions.go @@ -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 } diff --git a/resources/exec.go b/resources/exec.go index d2768c7d..10576754 100644 --- a/resources/exec.go +++ b/resources/exec.go @@ -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. diff --git a/resources/file.go b/resources/file.go index 88e3909e..f73e3ca3 100644 --- a/resources/file.go +++ b/resources/file.go @@ -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 } diff --git a/resources/hostname.go b/resources/hostname.go index 60cc7714..737a30f4 100644 --- a/resources/hostname.go +++ b/resources/hostname.go @@ -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 } diff --git a/resources/msg.go b/resources/msg.go index a499b1b4..88a72297 100644 --- a/resources/msg.go +++ b/resources/msg.go @@ -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 } diff --git a/resources/noop.go b/resources/noop.go index a444cd81..1c6f33be 100644 --- a/resources/noop.go +++ b/resources/noop.go @@ -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 } diff --git a/resources/nspawn.go b/resources/nspawn.go index 3d18eb34..05929f02 100644 --- a/resources/nspawn.go +++ b/resources/nspawn.go @@ -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 } diff --git a/resources/password.go b/resources/password.go index 2affa2d9..d0412bcd 100644 --- a/resources/password.go +++ b/resources/password.go @@ -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 } diff --git a/resources/pkg.go b/resources/pkg.go index b38c3564..822519a9 100644 --- a/resources/pkg.go +++ b/resources/pkg.go @@ -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. diff --git a/resources/resources.go b/resources/resources.go index b3893a8a..07825e9a 100644 --- a/resources/resources.go +++ b/resources/resources.go @@ -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 } diff --git a/resources/svc.go b/resources/svc.go index f680941f..4d6aedbc 100644 --- a/resources/svc.go +++ b/resources/svc.go @@ -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 } diff --git a/resources/timer.go b/resources/timer.go index 2ef5bd9f..5b392f96 100644 --- a/resources/timer.go +++ b/resources/timer.go @@ -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 } diff --git a/resources/virt.go b/resources/virt.go index a355d988..c095e295 100644 --- a/resources/virt.go +++ b/resources/virt.go @@ -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 }