/
poolcreate.go
148 lines (125 loc) · 4.48 KB
/
poolcreate.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package storage
import (
"strings"
"github.com/juju/cmd/v3"
"github.com/juju/errors"
"github.com/juju/utils/v3/keyvalues"
k8sconstants "github.com/juju/juju/caas/kubernetes/provider/constants"
jujucmd "github.com/juju/juju/cmd"
"github.com/juju/juju/cmd/modelcmd"
"github.com/juju/juju/core/model"
)
// PoolCreateAPI defines the API methods that pool create command uses.
type PoolCreateAPI interface {
Close() error
CreatePool(pname, ptype string, pconfig map[string]interface{}) error
}
const poolCreateCommandDoc = `
Pools are a mechanism for administrators to define sources of storage that
they will use to satisfy application storage requirements.
A single pool might be used for storage from units of many different applications -
it is a resource from which different stores may be drawn.
A pool describes provider-specific parameters for creating storage,
such as performance (e.g. IOPS), media type (e.g. magnetic vs. SSD),
or durability.
For many providers, there will be a shared resource
where storage can be requested (e.g. EBS in amazon).
Creating pools there maps provider specific settings
into named resources that can be used during deployment.
Pools defined at the model level are easily reused across applications.
Pool creation requires a pool name, the provider type and attributes for
configuration as space-separated pairs, e.g. tags, size, path, etc.
For Kubernetes models, the provider type defaults to "kubernetes"
unless otherwise specified.
`
const poolCreateCommandExamples = `
juju create-storage-pool ebsrotary ebs volume-type=standard
juju create-storage-pool gcepd storage-provisioner=kubernetes.io/gce-pd [storage-mode=RWX|RWO|ROX] parameters.type=pd-standard
`
// NewPoolCreateCommand returns a command that creates or defines a storage pool
func NewPoolCreateCommand() cmd.Command {
cmd := &poolCreateCommand{}
cmd.newAPIFunc = func() (PoolCreateAPI, error) {
return cmd.NewStorageAPI()
}
return modelcmd.Wrap(cmd)
}
// poolCreateCommand lists storage pools.
type poolCreateCommand struct {
PoolCommandBase
newAPIFunc func() (PoolCreateAPI, error)
poolName string
// TODO(anastasiamac 2015-01-29) type will need to become optional
// if type is unspecified, use the environment's default provider type
provider string
attrs map[string]interface{}
}
// Init implements Command.Init.
func (c *poolCreateCommand) Init(args []string) (err error) {
modelType, err := c.ModelType()
if err != nil {
return errors.Trace(err)
}
if modelType == model.CAAS && len(args) > 0 {
if len(args) == 1 {
args = []string{args[0], string(k8sconstants.StorageProviderType)}
}
if strings.Contains(args[1], "=") {
newArgs := []string{args[0], string(k8sconstants.StorageProviderType)}
args = append(newArgs, args[1:]...)
}
}
if len(args) < 2 {
return errors.New("pool creation requires names, provider type and optional attributes for configuration")
}
c.poolName = args[0]
c.provider = args[1]
// poolName and provider can contain any character, except for '='.
// However, the last arguments are always expected to be key=value pairs.
// Since it's possible for users to mistype, we want to check here for cases
// such as:
// $ juju create-storage-pool poolName key=value
// $ juju create-storage-pool key=value poolName
// as either a provider or a pool name are missing.
if strings.Contains(c.poolName, "=") || strings.Contains(c.provider, "=") {
return errors.New("pool creation requires names and provider type before optional attributes for configuration")
}
options, err := keyvalues.Parse(args[2:], false)
if err != nil {
return err
}
c.attrs = make(map[string]interface{})
if len(options) == 0 {
return nil
}
for key, value := range options {
c.attrs[key] = value
}
return nil
}
// Info implements Command.Info.
func (c *poolCreateCommand) Info() *cmd.Info {
return jujucmd.Info(&cmd.Info{
Name: "create-storage-pool",
Args: "<name> <provider> [<key>=<value> [<key>=<value>...]]",
Purpose: "Create or define a storage pool.",
Doc: poolCreateCommandDoc,
Examples: poolCreateCommandExamples,
SeeAlso: []string{
"remove-storage-pool",
"update-storage-pool",
"storage-pools",
},
})
}
// Run implements Command.Run.
func (c *poolCreateCommand) Run(ctx *cmd.Context) (err error) {
api, err := c.newAPIFunc()
if err != nil {
return err
}
defer api.Close()
return api.CreatePool(c.poolName, c.provider, c.attrs)
}