github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/undertaker.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state 5 6 import ( 7 "github.com/juju/errors" 8 "gopkg.in/mgo.v2/bson" 9 "gopkg.in/mgo.v2/txn" 10 ) 11 12 var ErrModelNotDying = errors.New("model is not dying") 13 14 // ProcessDyingModel checks if there are any machines or services left in 15 // state. If there are none, the model's life is changed from dying to dead. 16 func (st *State) ProcessDyingModel() (err error) { 17 buildTxn := func(attempt int) ([]txn.Op, error) { 18 model, err := st.Model() 19 if err != nil { 20 return nil, errors.Trace(err) 21 } 22 23 if model.Life() != Dying { 24 return nil, errors.Trace(ErrModelNotDying) 25 } 26 27 if st.IsController() { 28 models, err := st.AllModels() 29 if err != nil { 30 return nil, errors.Trace(err) 31 } 32 for _, model := range models { 33 if model.UUID() != st.ModelUUID() && model.Life() != Dead { 34 return nil, errors.Errorf("one or more hosted models are not yet dead") 35 } 36 } 37 } 38 39 if err := model.checkEmpty(); err != nil { 40 return nil, errors.Trace(err) 41 } 42 43 ops := []txn.Op{{ 44 C: modelsC, 45 Id: st.ModelUUID(), 46 Assert: isDyingDoc, 47 Update: bson.M{"$set": bson.M{ 48 "life": Dead, 49 "time-of-death": st.NowToTheSecond(), 50 }}, 51 }} 52 return ops, nil 53 } 54 55 if err = st.run(buildTxn); err != nil { 56 return errors.Trace(err) 57 } 58 return nil 59 }