github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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/clock" 8 "github.com/juju/errors" 9 10 "github.com/juju/juju/apiserver/facades/agent/metricsender" 11 "github.com/juju/juju/state" 12 ) 13 14 var sendMetrics = func(st metricsender.ModelBackend) error { 15 ccfg, err := st.ControllerConfig() 16 if err != nil { 17 return errors.Annotate(err, "failed to get controller config") 18 } 19 meteringURL := ccfg.MeteringURL() 20 cfg, err := st.ModelConfig() 21 if err != nil { 22 return errors.Annotatef(err, "failed to get model config for %s", st.ModelTag()) 23 } 24 25 err = metricsender.SendMetrics( 26 st, 27 metricsender.DefaultSenderFactory()(meteringURL), 28 clock.WallClock, 29 metricsender.DefaultMaxBatchesPerSend(), 30 cfg.TransmitVendorMetrics(), 31 ) 32 return errors.Trace(err) 33 } 34 35 // DestroyController sets the controller model to Dying and, if requested, 36 // schedules cleanups so that all of the hosted models are destroyed, or 37 // otherwise returns an error indicating that there are hosted models 38 // remaining. 39 func DestroyController( 40 st ModelManagerBackend, 41 destroyHostedModels bool, 42 destroyStorage *bool, 43 ) error { 44 modelTag := st.ModelTag() 45 controllerModelTag := st.ControllerModelTag() 46 if modelTag != controllerModelTag { 47 return errors.Errorf( 48 "expected state for controller model UUID %v, got %v", 49 controllerModelTag.Id(), 50 modelTag.Id(), 51 ) 52 } 53 if destroyHostedModels { 54 uuids, err := st.AllModelUUIDs() 55 if err != nil { 56 return errors.Trace(err) 57 } 58 for _, uuid := range uuids { 59 modelSt, release, err := st.GetBackend(uuid) 60 if err != nil { 61 if errors.IsNotFound(err) { 62 // Model is already in the process of being destroyed. 63 continue 64 } 65 return errors.Trace(err) 66 } 67 defer release() 68 69 check := NewBlockChecker(modelSt) 70 if err = check.DestroyAllowed(); err != nil { 71 return errors.Trace(err) 72 } 73 err = sendMetrics(modelSt) 74 if err != nil { 75 logger.Errorf("failed to send leftover metrics: %v", err) 76 } 77 } 78 } 79 return destroyModel(st, state.DestroyModelParams{ 80 DestroyHostedModels: destroyHostedModels, 81 DestroyStorage: destroyStorage, 82 }) 83 } 84 85 // DestroyModel sets the model to Dying, such that the model's resources will 86 // be destroyed and the model removed from the controller. 87 func DestroyModel( 88 st ModelManagerBackend, 89 destroyStorage *bool, 90 ) error { 91 return destroyModel(st, state.DestroyModelParams{ 92 DestroyStorage: destroyStorage, 93 }) 94 } 95 96 func destroyModel(st ModelManagerBackend, args state.DestroyModelParams) error { 97 check := NewBlockChecker(st) 98 if err := check.DestroyAllowed(); err != nil { 99 return errors.Trace(err) 100 } 101 102 model, err := st.Model() 103 if err != nil { 104 return errors.Trace(err) 105 } 106 if err := model.Destroy(args); err != nil { 107 return errors.Trace(err) 108 } 109 110 err = sendMetrics(st) 111 if err != nil { 112 logger.Errorf("failed to send leftover metrics: %v", err) 113 } 114 115 // Return to the caller. If it's the CLI, it will finish up by calling the 116 // provider's Destroy method, which will destroy the controllers, any 117 // straggler instances, and other provider-specific resources. Once all 118 // resources are torn down, the Undertaker worker handles the removal of 119 // the model. 120 return nil 121 }