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