Destroy model: watch better suited collection for changes. #7218

Merged
merged 7 commits into from Apr 10, 2017

Conversation

Projects
None yet
4 participants
Member

anastasiamac commented Apr 10, 2017

Description of change

When destroying models, we used to watch only applications and machines collections. However, when we were determining if model is ready to be destroyed, we'd check collection that stored model entities references.

This introduced 2 problems:

  1. If we were to identify new entities that model should worry about before self-destructing, we would miss them as we were not watching their collections.
  2. There was a potential for a race - which was observed fairly reliably - between when a specific entity collection would change and when the reference for that collection would be dealt with.

This PR changes undertaker behavior to watch for changes on collection that references model entities rather than said entities collections.

We are also now surfacing errors that we've encountered during the attempts to destroy model as well as log them.
Drive-by fixes:

QA steps

There are several scenarios where destroy-model would chase its own tail.
The most commonly encountered one that I have used:

  1. bootstrap;
  2. add model;
  3. deploy an application with one unit - wait for dust to settle;
  4. remove that one unit - wait for dust to settle;
    [you would have an empty deployed app]
  5. destroy this model.
    Model gets destroyed successfully.

Previously, model destruction would get into infinite loop and only eventual kill-controller will get rid of it.
Note that if you are running 'watch juju status' during model destruction, you may not observe failure to destroy.

Documentation changes

n/a - internal change

Bug reference

https://bugs.launchpad.net/juju/+bug/1672549
https://bugs.launchpad.net/juju/+bug/1661930

apiserver/undertaker/state.go
// ModelConfig retrieves the model configuration.
ModelConfig() (*config.Config, error)
+
+ // WatchModelEntitiesReferences gets a watcher capable of monitoring
@axw

axw Apr 10, 2017

Member

s/Entities/Entity/

@anastasiamac

anastasiamac Apr 10, 2017

Member

Changed :D nice pick-up! I was, of course thinking of model entities as a concept.

apiserver/undertaker/undertaker.go
- watch := common.NewMultiNotifyWatcher(watchers...)
+ // (anastasiamac 2017-04-10) I do not know what watcher is best suited here.
+ // Keeping multi-notify watcher for historical reasons for now.
+ watch := common.NewMultiNotifyWatcher(u.st.WatchModelEntitiesReferences(m.UUID()))
@axw

axw Apr 10, 2017

Member

Drop the multi and use the entity references watcher directly. There is now and for the foreseeable future should only be one.

@anastasiamac

anastasiamac Apr 10, 2017

Member

Dropped. Thank you for advice!

state/application.go
@@ -272,10 +272,6 @@ func (a *Application) removeOps(asserts bson.D) ([]txn.Op, error) {
Id: a.doc.DocID,
Assert: asserts,
Remove: true,
- }, {
@axw

axw Apr 10, 2017

Member

please move this to another PR if it is still relevant

@anastasiamac

anastasiamac Apr 10, 2017

Member

Removed this and the other related bits. Will propose separately :) I do not think that it is particularly hurtful but was very surprising to examine a transaction where several exact same operations appeared...

state/application.go
@@ -290,7 +286,6 @@ func (a *Application) removeOps(asserts bson.D) ([]txn.Op, error) {
return nil, errors.Trace(err)
}
ops = append(ops, charmOps...)
- ops = append(ops, finalAppCharmRemoveOps(name, curl)...)
@axw

axw Apr 10, 2017

Member

and this

state/charm_test.go
@@ -256,12 +256,10 @@ func (s *CharmSuite) TestDestroyFinalUnitReference(c *gc.C) {
app := s.Factory.MakeApplication(c, &factory.ApplicationParams{
Charm: s.charm,
})
- unit := s.Factory.MakeUnit(c, &factory.UnitParams{
@axw

axw Apr 10, 2017

Member

and these

state/model.go
@@ -1040,16 +1046,22 @@ func (m *Model) checkEmpty() error {
}
return errors.Annotatef(err, "getting entity references for model %s", m.UUID())
}
+ // These errors could be potentially swallowed as we re-try to destroy model.
+ // Let's, at least, log them for observations.
@jameinel

jameinel Apr 10, 2017

Owner

observation.

@anastasiamac

anastasiamac Apr 10, 2017

Member

Nice :) With my English, both plural and singular work here but I appreciate your feedback! Changed :)

worker/undertaker/undertaker.go
- // Yes, we ignore the error. See comment above.
+ // Yes, we ignore the error. See comment above. But let's at least
+ // surface it in status.
+ u.setStatus(status.Destroying, fmt.Sprintf("%d attempt to destroy model: %v", attempt, err))
@jameinel

jameinel Apr 10, 2017

Owner

2 attempt to destroy model: error
would probably read better as:
"attempt %d to destroy model failed (will retry): %v"

moving the counter helps readability, and some indication as to what we are doing about this failure.
These are going to be shown in "juju status", so making them legible is important.

@anastasiamac

anastasiamac Apr 10, 2017

Member

Great idea! Reads better indeed. Thank you :D

axw approved these changes Apr 10, 2017

apiserver/undertaker/state.go
// ModelConfig retrieves the model configuration.
ModelConfig() (*config.Config, error)
+
+ // WatchModelEntityReferences gets a watcher capable of monitoring
+ // model entities references changes.
@axw

axw Apr 10, 2017

Member

s/entities/entity/

@anastasiamac

anastasiamac Apr 10, 2017

Member

Of course, I'll change here and in other comments..

apiserver/undertaker/undertaker.go
- }
- services, err := u.st.AllApplications()
+
+ m, err := u.st.Model()
@axw

axw Apr 10, 2017

Member

just call state.ModelUUID instead? no need to hit the db just to get the UUID

@anastasiamac

anastasiamac Apr 10, 2017

Member

oh k.. I was looking at other code in the area. I'll take a look to see what state.ModelUUID actually gives here :)

@anastasiamac

anastasiamac Apr 10, 2017

Member

done \o/ so much neater!

Member

anastasiamac commented Apr 10, 2017

$$merge$$

Contributor

jujubot commented Apr 10, 2017

Status: merge request accepted. Url: http://juju-ci.vapour.ws:8080/job/github-merge-juju

@jujubot jujubot merged commit b7fbd80 into juju:develop Apr 10, 2017

@anastasiamac anastasiamac deleted the anastasiamac:destroy-model-watch-entities branch Apr 10, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment