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 }