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  }