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  }