github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/common/environdestroy.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/names"
     9  
    10  	"github.com/juju/juju/apiserver/metricsender"
    11  	"github.com/juju/juju/environs"
    12  	"github.com/juju/juju/instance"
    13  	"github.com/juju/juju/state"
    14  )
    15  
    16  var sendMetrics = func(st *state.State) error {
    17  	err := metricsender.SendMetrics(st, metricsender.DefaultMetricSender(), metricsender.DefaultMaxBatchesPerSend())
    18  	return errors.Trace(err)
    19  }
    20  
    21  // DestroyEnvironment destroys all services and non-manager machine
    22  // instances in the specified environment. This function assumes that all
    23  // necessary authentication checks have been done.
    24  func DestroyEnvironment(st *state.State, environTag names.EnvironTag) error {
    25  	var err error
    26  	if environTag != st.EnvironTag() {
    27  		if st, err = st.ForEnviron(environTag); err != nil {
    28  			return errors.Trace(err)
    29  		}
    30  		defer st.Close()
    31  	}
    32  
    33  	check := NewBlockChecker(st)
    34  	if err = check.DestroyAllowed(); err != nil {
    35  		return errors.Trace(err)
    36  	}
    37  
    38  	env, err := st.Environment()
    39  	if err != nil {
    40  		return errors.Trace(err)
    41  	}
    42  
    43  	if err = env.Destroy(); err != nil {
    44  		return errors.Trace(err)
    45  	}
    46  
    47  	machines, err := st.AllMachines()
    48  	if err != nil {
    49  		return errors.Trace(err)
    50  	}
    51  
    52  	err = sendMetrics(st)
    53  	if err != nil {
    54  		logger.Warningf("failed to send leftover metrics: %v", err)
    55  	}
    56  
    57  	// We must destroy instances server-side to support JES (Juju Environment
    58  	// Server), as there's no CLI to fall back on. In that case, we only ever
    59  	// destroy non-state machines; we leave destroying state servers in non-
    60  	// hosted environments to the CLI, as otherwise the API server may get cut
    61  	// off.
    62  	if err := destroyNonManagerMachines(st, machines); err != nil {
    63  		return errors.Trace(err)
    64  	}
    65  
    66  	// If this is not the state server environment, remove all documents from
    67  	// state associated with the environment.
    68  	if env.EnvironTag() != env.ServerTag() {
    69  		return errors.Trace(st.RemoveAllEnvironDocs())
    70  	}
    71  
    72  	// Return to the caller. If it's the CLI, it will finish up
    73  	// by calling the provider's Destroy method, which will
    74  	// destroy the state servers, any straggler instances, and
    75  	// other provider-specific resources.
    76  	return nil
    77  }
    78  
    79  // destroyNonManagerMachines directly destroys all non-manager, non-manual
    80  // machine instances.
    81  func destroyNonManagerMachines(st *state.State, machines []*state.Machine) error {
    82  	var ids []instance.Id
    83  	for _, m := range machines {
    84  		if m.IsManager() {
    85  			continue
    86  		}
    87  		if _, isContainer := m.ParentId(); isContainer {
    88  			continue
    89  		}
    90  		manual, err := m.IsManual()
    91  		if err != nil {
    92  			return err
    93  		} else if manual {
    94  			continue
    95  		}
    96  		// There is a possible race here if a machine is being
    97  		// provisioned, but hasn't yet come up.
    98  		id, err := m.InstanceId()
    99  		if err != nil {
   100  			continue
   101  		}
   102  		ids = append(ids, id)
   103  	}
   104  	if len(ids) == 0 {
   105  		return nil
   106  	}
   107  	envcfg, err := st.EnvironConfig()
   108  	if err != nil {
   109  		return err
   110  	}
   111  	env, err := environs.New(envcfg)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	return env.StopInstances(ids...)
   116  }