github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/storage/poolmanager/poolmanager.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package poolmanager 5 6 import ( 7 "github.com/juju/errors" 8 9 "github.com/juju/juju/storage" 10 "github.com/juju/juju/storage/provider" 11 ) 12 13 const ( 14 // Pool configuration attribute names. 15 Name = "name" 16 Type = "type" 17 ) 18 19 var ( 20 MissingTypeError = errors.New("provider type is missing") 21 MissingNameError = errors.New("pool name is missing") 22 ) 23 24 // New returns a PoolManager implementation using the specified state. 25 func New(settings SettingsManager, registry storage.ProviderRegistry) PoolManager { 26 return &poolManager{settings, registry} 27 } 28 29 var _ PoolManager = (*poolManager)(nil) 30 31 type poolManager struct { 32 settings SettingsManager 33 registry storage.ProviderRegistry 34 } 35 36 const globalKeyPrefix = "pool#" 37 38 func globalKey(name string) string { 39 return globalKeyPrefix + name 40 } 41 42 // Create is defined on PoolManager interface. 43 func (pm *poolManager) Create(name string, providerType storage.ProviderType, attrs map[string]interface{}) (*storage.Config, error) { 44 if name == "" { 45 return nil, MissingNameError 46 } 47 if providerType == "" { 48 return nil, MissingTypeError 49 } 50 51 cfg, err := storage.NewConfig(name, providerType, attrs) 52 if err != nil { 53 return nil, errors.Trace(err) 54 } 55 p, err := pm.registry.StorageProvider(providerType) 56 if err != nil { 57 return nil, errors.Trace(err) 58 } 59 if err := provider.ValidateConfig(p, cfg); err != nil { 60 return nil, errors.Annotate(err, "validating storage provider config") 61 } 62 63 poolAttrs := cfg.Attrs() 64 poolAttrs[Name] = name 65 poolAttrs[Type] = string(providerType) 66 if err := pm.settings.CreateSettings(globalKey(name), poolAttrs); err != nil { 67 return nil, errors.Annotatef(err, "creating pool %q", name) 68 } 69 return cfg, nil 70 } 71 72 // Delete is defined on PoolManager interface. 73 func (pm *poolManager) Delete(name string) error { 74 err := pm.settings.RemoveSettings(globalKey(name)) 75 if err == nil || errors.IsNotFound(err) { 76 return nil 77 } 78 return errors.Annotatef(err, "deleting pool %q", name) 79 } 80 81 // Get is defined on PoolManager interface. 82 func (pm *poolManager) Get(name string) (*storage.Config, error) { 83 settings, err := pm.settings.ReadSettings(globalKey(name)) 84 if err != nil { 85 if errors.IsNotFound(err) { 86 return nil, errors.NotFoundf("pool %q", name) 87 } else { 88 return nil, errors.Annotatef(err, "reading pool %q", name) 89 } 90 } 91 return pm.configFromSettings(settings) 92 } 93 94 // List is defined on PoolManager interface. 95 func (pm *poolManager) List() ([]*storage.Config, error) { 96 settings, err := pm.settings.ListSettings(globalKeyPrefix) 97 if err != nil { 98 return nil, errors.Annotate(err, "listing pool settings") 99 } 100 var result []*storage.Config 101 for _, attrs := range settings { 102 cfg, err := pm.configFromSettings(attrs) 103 if err != nil { 104 return nil, errors.Trace(err) 105 } 106 result = append(result, cfg) 107 } 108 return result, nil 109 } 110 111 func (pm *poolManager) configFromSettings(settings map[string]interface{}) (*storage.Config, error) { 112 providerType := storage.ProviderType(settings[Type].(string)) 113 name := settings[Name].(string) 114 // Ensure returned attributes are stripped of name and type, 115 // as these are not user-specified attributes. 116 delete(settings, Name) 117 delete(settings, Type) 118 cfg, err := storage.NewConfig(name, providerType, settings) 119 if err != nil { 120 return nil, errors.Trace(err) 121 } 122 p, err := pm.registry.StorageProvider(providerType) 123 if err != nil { 124 return nil, errors.Trace(err) 125 } 126 if err := provider.ValidateConfig(p, cfg); err != nil { 127 return nil, errors.Trace(err) 128 } 129 return cfg, nil 130 }