github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/apiserver/common/modeldestroy.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/utils/clock" 9 "gopkg.in/juju/names.v2" 10 11 "github.com/juju/juju/apiserver/metricsender" 12 ) 13 14 var sendMetrics = func(st metricsender.ModelBackend) error { 15 cfg, err := st.ModelConfig() 16 if err != nil { 17 return errors.Annotatef(err, "failed to get model config for %s", st.ModelTag()) 18 } 19 20 err = metricsender.SendMetrics(st, metricsender.DefaultMetricSender(), clock.WallClock, metricsender.DefaultMaxBatchesPerSend(), cfg.TransmitVendorMetrics()) 21 return errors.Trace(err) 22 } 23 24 // DestroyModelIncludingHosted sets the model to dying. Cleanup jobs then destroy 25 // all services and non-manager, non-manual machine instances in the specified 26 // model. This function assumes that all necessary authentication checks 27 // have been done. If the model is a controller hosting other 28 // models, they will also be destroyed. 29 func DestroyModelIncludingHosted(st ModelManagerBackend, systemTag names.ModelTag) error { 30 return destroyModel(st, systemTag, true) 31 } 32 33 // DestroyModel sets the environment to dying. Cleanup jobs then destroy 34 // all services and non-manager, non-manual machine instances in the specified 35 // model. This function assumes that all necessary authentication checks 36 // have been done. An error will be returned if this model is a 37 // controller hosting other model. 38 func DestroyModel(st ModelManagerBackend, modelTag names.ModelTag) error { 39 return destroyModel(st, modelTag, false) 40 } 41 42 func destroyModel(st ModelManagerBackend, modelTag names.ModelTag, destroyHostedModels bool) error { 43 var err error 44 if modelTag != st.ModelTag() { 45 if st, err = st.ForModel(modelTag); err != nil { 46 return errors.Trace(err) 47 } 48 defer st.Close() 49 } 50 51 if destroyHostedModels { 52 // Check we are operating on the controller state. 53 controllerModel, err := st.ControllerModel() 54 if err != nil { 55 return errors.Trace(err) 56 } 57 if modelTag != controllerModel.ModelTag() { 58 return errors.Errorf("expected controller model UUID %v, got %v", modelTag.Id(), controllerModel.ModelTag().Id()) 59 } 60 models, err := st.AllModels() 61 if err != nil { 62 return errors.Trace(err) 63 } 64 for _, model := range models { 65 modelSt, err := st.ForModel(model.ModelTag()) 66 defer modelSt.Close() 67 if err != nil { 68 return errors.Trace(err) 69 } 70 check := NewBlockChecker(modelSt) 71 if err = check.DestroyAllowed(); err != nil { 72 return errors.Trace(err) 73 } 74 err = sendMetrics(modelSt) 75 if err != nil { 76 logger.Errorf("failed to send leftover metrics: %v", err) 77 } 78 79 } 80 } else { 81 check := NewBlockChecker(st) 82 if err = check.DestroyAllowed(); err != nil { 83 return errors.Trace(err) 84 } 85 } 86 87 model, err := st.Model() 88 if err != nil { 89 return errors.Trace(err) 90 } 91 92 if destroyHostedModels { 93 if err := model.DestroyIncludingHosted(); err != nil { 94 return err 95 } 96 } else { 97 if err = model.Destroy(); err != nil { 98 return errors.Trace(err) 99 } 100 } 101 err = sendMetrics(st) 102 if err != nil { 103 logger.Errorf("failed to send leftover metrics: %v", err) 104 } 105 106 // Return to the caller. If it's the CLI, it will finish up by calling the 107 // provider's Destroy method, which will destroy the controllers, any 108 // straggler instances, and other provider-specific resources. Once all 109 // resources are torn down, the Undertaker worker handles the removal of 110 // the environment. 111 return nil 112 }