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