github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/provider/common/destroy.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common
     5  
     6  import (
     7  	"strings"
     8  
     9  	"github.com/juju/errors"
    10  
    11  	"github.com/juju/juju/environs"
    12  	"github.com/juju/juju/environs/config"
    13  	"github.com/juju/juju/instance"
    14  	"github.com/juju/juju/storage"
    15  	"github.com/juju/juju/storage/provider/registry"
    16  )
    17  
    18  // Destroy is a common implementation of the Destroy method defined on
    19  // environs.Environ; we strongly recommend that this implementation be
    20  // used when writing a new provider.
    21  func Destroy(env environs.Environ) error {
    22  	logger.Infof("destroying model %q", env.Config().Name())
    23  	if err := destroyInstances(env); err != nil {
    24  		return errors.Annotate(err, "destroying instances")
    25  	}
    26  	if err := destroyStorage(env); err != nil {
    27  		return errors.Annotate(err, "destroying storage")
    28  	}
    29  	return nil
    30  }
    31  
    32  func destroyInstances(env environs.Environ) error {
    33  	logger.Infof("destroying instances")
    34  	instances, err := env.AllInstances()
    35  	switch err {
    36  	case nil:
    37  		ids := make([]instance.Id, len(instances))
    38  		for i, inst := range instances {
    39  			ids[i] = inst.Id()
    40  		}
    41  		if err := env.StopInstances(ids...); err != nil {
    42  			return err
    43  		}
    44  		fallthrough
    45  	case environs.ErrNoInstances:
    46  		return nil
    47  	default:
    48  		return err
    49  	}
    50  }
    51  
    52  func destroyStorage(env environs.Environ) error {
    53  	logger.Infof("destroying storage")
    54  	environConfig := env.Config()
    55  	storageProviderTypes, ok := registry.EnvironStorageProviders(environConfig.Type())
    56  	if !ok {
    57  		return nil
    58  	}
    59  	for _, storageProviderType := range storageProviderTypes {
    60  		storageProvider, err := registry.StorageProvider(storageProviderType)
    61  		if err != nil {
    62  			return errors.Trace(err)
    63  		}
    64  		if !storageProvider.Dynamic() {
    65  			continue
    66  		}
    67  		if storageProvider.Scope() != storage.ScopeEnviron {
    68  			continue
    69  		}
    70  		if err := destroyVolumes(environConfig, storageProviderType, storageProvider); err != nil {
    71  			return errors.Trace(err)
    72  		}
    73  		// TODO(axw) destroy env-level filesystems when we have them.
    74  	}
    75  	return nil
    76  }
    77  
    78  func destroyVolumes(
    79  	environConfig *config.Config,
    80  	storageProviderType storage.ProviderType,
    81  	storageProvider storage.Provider,
    82  ) error {
    83  	if !storageProvider.Supports(storage.StorageKindBlock) {
    84  		return nil
    85  	}
    86  
    87  	storageConfig, err := storage.NewConfig(
    88  		string(storageProviderType),
    89  		storageProviderType,
    90  		map[string]interface{}{},
    91  	)
    92  	if err != nil {
    93  		return errors.Trace(err)
    94  	}
    95  
    96  	volumeSource, err := storageProvider.VolumeSource(environConfig, storageConfig)
    97  	if err != nil {
    98  		return errors.Annotate(err, "getting volume source")
    99  	}
   100  
   101  	volumeIds, err := volumeSource.ListVolumes()
   102  	if err != nil {
   103  		return errors.Annotate(err, "listing volumes")
   104  	}
   105  
   106  	var errStrings []string
   107  	errs, err := volumeSource.DestroyVolumes(volumeIds)
   108  	if err != nil {
   109  		return errors.Annotate(err, "destroying volumes")
   110  	}
   111  	for _, err := range errs {
   112  		if err != nil {
   113  			errStrings = append(errStrings, err.Error())
   114  		}
   115  	}
   116  	if len(errStrings) > 0 {
   117  		return errors.Errorf("destroying volumes: %s", strings.Join(errStrings, ", "))
   118  	}
   119  	return nil
   120  }