github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/worker/storageprovisioner/common.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storageprovisioner 5 6 import ( 7 "path/filepath" 8 9 "github.com/juju/errors" 10 "github.com/juju/names" 11 12 "github.com/juju/juju/apiserver/params" 13 "github.com/juju/juju/environs/config" 14 "github.com/juju/juju/storage" 15 "github.com/juju/juju/storage/provider/registry" 16 ) 17 18 // storageEntityLife queries the lifecycle state of each specified 19 // storage entity (volume or filesystem), and then partitions the 20 // tags by them. 21 func storageEntityLife(ctx *context, tags []names.Tag) (alive, dying, dead []names.Tag, _ error) { 22 lifeResults, err := ctx.life.Life(tags) 23 if err != nil { 24 return nil, nil, nil, errors.Annotate(err, "getting storage entity life") 25 } 26 for i, result := range lifeResults { 27 if result.Error != nil { 28 return nil, nil, nil, errors.Annotatef( 29 result.Error, "getting life of %s", 30 names.ReadableString(tags[i]), 31 ) 32 } 33 switch result.Life { 34 case params.Alive: 35 alive = append(alive, tags[i]) 36 case params.Dying: 37 dying = append(dying, tags[i]) 38 case params.Dead: 39 dead = append(dead, tags[i]) 40 } 41 } 42 return alive, dying, dead, nil 43 } 44 45 // attachmentLife queries the lifecycle state of each specified 46 // attachment, and then partitions the IDs by them. 47 func attachmentLife(ctx *context, ids []params.MachineStorageId) ( 48 alive, dying, dead []params.MachineStorageId, _ error, 49 ) { 50 lifeResults, err := ctx.life.AttachmentLife(ids) 51 if err != nil { 52 return nil, nil, nil, errors.Annotate(err, "getting machine attachment life") 53 } 54 for i, result := range lifeResults { 55 if result.Error != nil { 56 return nil, nil, nil, errors.Annotatef( 57 result.Error, "getting life of %s attached to %s", 58 ids[i].AttachmentTag, ids[i].MachineTag, 59 ) 60 } 61 switch result.Life { 62 case params.Alive: 63 alive = append(alive, ids[i]) 64 case params.Dying: 65 dying = append(dying, ids[i]) 66 case params.Dead: 67 dead = append(dead, ids[i]) 68 } 69 } 70 return alive, dying, dead, nil 71 } 72 73 // removeEntities removes each specified Dead entity from state. 74 func removeEntities(ctx *context, tags []names.Tag) error { 75 logger.Debugf("removing entities: %v", tags) 76 errorResults, err := ctx.life.Remove(tags) 77 if err != nil { 78 return errors.Annotate(err, "removing storage entities") 79 } 80 for i, result := range errorResults { 81 if result.Error != nil { 82 return errors.Annotatef(result.Error, "removing %s from state", names.ReadableString(tags[i])) 83 } 84 } 85 return nil 86 } 87 88 // removeAttachments removes each specified attachment from state. 89 func removeAttachments(ctx *context, ids []params.MachineStorageId) error { 90 errorResults, err := ctx.life.RemoveAttachments(ids) 91 if err != nil { 92 return errors.Annotate(err, "removing attachments") 93 } 94 for i, result := range errorResults { 95 if result.Error != nil { 96 return errors.Annotatef( 97 result.Error, "removing attachment of %s to %s from state", 98 ids[i].AttachmentTag, ids[i].MachineTag, 99 ) 100 } 101 } 102 return nil 103 } 104 105 var errNonDynamic = errors.New("non-dynamic storage provider") 106 107 // volumeSource returns a volume source given a name, provider type, 108 // environment config and storage directory. 109 // 110 // TODO(axw) move this to the main storageprovisioner, and have 111 // it watch for changes to storage source configurations, updating 112 // a map in-between calls to the volume/filesystem/attachment 113 // event handlers. 114 func volumeSource( 115 environConfig *config.Config, 116 baseStorageDir string, 117 sourceName string, 118 providerType storage.ProviderType, 119 ) (storage.VolumeSource, error) { 120 provider, sourceConfig, err := sourceParams(providerType, sourceName, baseStorageDir) 121 if err != nil { 122 return nil, errors.Annotatef(err, "getting storage source %q params", sourceName) 123 } 124 if !provider.Dynamic() { 125 return nil, errNonDynamic 126 } 127 source, err := provider.VolumeSource(environConfig, sourceConfig) 128 if err != nil { 129 return nil, errors.Annotatef(err, "getting storage source %q", sourceName) 130 } 131 return source, nil 132 } 133 134 // filesystemSource returns a filesystem source given a name, provider type, 135 // environment config and storage directory. 136 // 137 // TODO(axw) move this to the main storageprovisioner, and have 138 // it watch for changes to storage source configurations, updating 139 // a map in-between calls to the volume/filesystem/attachment 140 // event handlers. 141 func filesystemSource( 142 environConfig *config.Config, 143 baseStorageDir string, 144 sourceName string, 145 providerType storage.ProviderType, 146 ) (storage.FilesystemSource, error) { 147 provider, sourceConfig, err := sourceParams(providerType, sourceName, baseStorageDir) 148 if err != nil { 149 return nil, errors.Annotatef(err, "getting storage source %q params", sourceName) 150 } 151 source, err := provider.FilesystemSource(environConfig, sourceConfig) 152 if err != nil { 153 return nil, errors.Annotatef(err, "getting storage source %q", sourceName) 154 } 155 return source, nil 156 } 157 158 func sourceParams(providerType storage.ProviderType, sourceName, baseStorageDir string) (storage.Provider, *storage.Config, error) { 159 provider, err := registry.StorageProvider(providerType) 160 if err != nil { 161 return nil, nil, errors.Annotate(err, "getting provider") 162 } 163 attrs := make(map[string]interface{}) 164 if baseStorageDir != "" { 165 storageDir := filepath.Join(baseStorageDir, sourceName) 166 attrs[storage.ConfigStorageDir] = storageDir 167 } 168 sourceConfig, err := storage.NewConfig(sourceName, providerType, attrs) 169 if err != nil { 170 return nil, nil, errors.Annotate(err, "getting config") 171 } 172 return provider, sourceConfig, nil 173 }