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  }