@@ -3,6 +3,7 @@ package driver
3
3
import (
4
4
"fmt"
5
5
"os"
6
+ "sort"
6
7
"strconv"
7
8
"strings"
8
9
"sync"
@@ -30,6 +31,8 @@ type Driver struct {
30
31
sync.Mutex
31
32
}
32
33
34
+ var AllowedOptions = []string {"size" , "sparse" , "fs" , "uid" , "gid" , "mode" }
35
+
33
36
func NewDriver (cfg Config ) (d Driver , err error ) {
34
37
if cfg .DefaultSize == "" {
35
38
err = errors .Errorf ("DefaultSize must be specified" )
@@ -64,6 +67,26 @@ func (d Driver) Create(req *v.CreateRequest) error {
64
67
Str ("opts-size" , req .Options ["size" ]).
65
68
Logger ()
66
69
70
+ // 1st - let's validate incoming option names
71
+ allowedOptionsSet := make (map [string ]struct {})
72
+ for _ , option := range AllowedOptions {
73
+ allowedOptionsSet [option ] = struct {}{}
74
+ }
75
+ var wrongOptions []string
76
+ for k := range req .Options {
77
+ _ , allowed := allowedOptionsSet [k ]
78
+ if ! allowed {
79
+ wrongOptions = append (wrongOptions , k )
80
+ }
81
+ }
82
+ if len (wrongOptions ) > 0 {
83
+ sort .Strings (wrongOptions )
84
+ return errors .Errorf (
85
+ "options '%s' are not among supported ones: %s" ,
86
+ strings .Join (wrongOptions , ", " ), strings .Join (AllowedOptions , ", " ))
87
+ }
88
+
89
+ // 2nd - parse 'size' option if present
67
90
size , sizePresent := req .Options ["size" ]
68
91
69
92
if ! sizePresent {
@@ -75,22 +98,20 @@ func (d Driver) Create(req *v.CreateRequest) error {
75
98
76
99
sizeInBytes , err := FromHumanSize (size )
77
100
if err != nil {
78
- return errors .Errorf (
79
- "couldn't convert specified size [%s] into bytes" ,
80
- size )
101
+ return errors .Errorf ("cannot convert 'size' option value '%s' into bytes" , size )
81
102
}
82
103
104
+ // 3rd - parse 'sparse' option if present
83
105
sparse := false
84
106
sparseStr , sparsePresent := req .Options ["sparse" ]
85
107
if sparsePresent {
86
108
sparse , err = strconv .ParseBool (sparseStr )
87
109
if err != nil {
88
- return errors .Wrapf (err ,
89
- "Error creating volume '%s' - cannot parse 'sparse' option value '%s' as bool" ,
90
- req .Name , sparseStr )
110
+ return errors .Wrapf (err , "cannot parse 'sparse' option value '%s' as bool" , sparseStr )
91
111
}
92
112
}
93
113
114
+ // 4th - parse 'fs' option if present
94
115
var fs string
95
116
fsInput , fsPresent := req .Options ["fs" ]
96
117
if fsPresent && len (fsInput ) > 0 {
@@ -102,46 +123,41 @@ func (d Driver) Create(req *v.CreateRequest) error {
102
123
Msg ("no fs opt found, using default" )
103
124
}
104
125
126
+ // 5th - parse 'uid' option if present
105
127
uid := - 1
106
128
uidStr , uidPresent := req .Options ["uid" ]
107
129
if uidPresent && len (uidStr ) > 0 {
108
130
uid , err = strconv .Atoi (uidStr )
109
131
if err != nil {
110
- return errors .Wrapf (err ,
111
- "Error creating volume '%s' - cannot parse 'uid' option value '%s' as an integer" ,
112
- req .Name , uidStr )
132
+ return errors .Wrapf (err , "cannot parse 'uid' option value '%s' as an integer" , uidStr )
113
133
}
114
134
if uid < 0 {
115
- return errors .Errorf (
116
- "Error creating volume '%s' - 'uid' option should be >= 0 but received '%d'" ,
117
- req .Name , uid )
135
+ return errors .Errorf ("'uid' option should be >= 0 but received '%d'" , uid )
118
136
}
119
137
120
138
logger .Debug ().
121
139
Int ("uid" , uid ).
122
140
Msg ("set volume root uid" )
123
141
}
124
142
143
+ // 6th - parse 'gid' option if present
125
144
gid := - 1
126
145
gidStr , gidPresent := req .Options ["gid" ]
127
146
if gidPresent && len (gidStr ) > 0 {
128
147
gid , err = strconv .Atoi (gidStr )
129
148
if err != nil {
130
- return errors .Wrapf (err ,
131
- "Error creating volume '%s' - cannot parse 'gid' option value '%s' as an integer" ,
132
- req .Name , gidStr )
149
+ return errors .Wrapf (err , "cannot parse 'gid' option value '%s' as an integer" , gidStr )
133
150
}
134
151
if gid < 0 {
135
- return errors .Errorf (
136
- "Error creating volume '%s' - 'gid' option should be >= 0 but received '%d'" ,
137
- req .Name , gid )
152
+ return errors .Errorf ("'gid' option should be >= 0 but received '%d'" , gid )
138
153
}
139
154
140
155
logger .Debug ().
141
156
Int ("gid" , gid ).
142
157
Msg ("set volume root gid" )
143
158
}
144
159
160
+ // 7th - parse 'mode' option if present
145
161
var mode uint32
146
162
modeStr , modePresent := req .Options ["mode" ]
147
163
if modePresent && len (modeStr ) > 0 {
@@ -151,32 +167,30 @@ func (d Driver) Create(req *v.CreateRequest) error {
151
167
152
168
modeParsed , err := strconv .ParseUint (modeStr , 8 , 32 )
153
169
if err != nil {
154
- return errors .Wrapf (err ,
155
- "Error creating volume '%s' - cannot parse mode '%s' as positive 4-position octal" ,
156
- req .Name , modeStr )
170
+ return errors .Wrapf (err , "cannot parse mode '%s' as positive 4-position octal" , modeStr )
157
171
}
158
172
159
173
if modeParsed <= 0 || modeParsed > 07777 {
160
- return errors .Errorf (
161
- "Error creating volume '%s' - mode value '%s' does not fall between 0 and 7777 in octal encoding" ,
162
- req .Name , modeStr )
174
+ return errors .Errorf ("mode value '%s' does not fall between 0 and 7777 in octal encoding" , modeStr )
163
175
}
164
176
165
177
mode = uint32 (modeParsed )
166
178
}
167
179
180
+ // Finally - attempt creating a volume
181
+
168
182
d .Lock ()
169
183
defer d .Unlock ()
170
184
171
185
logger .Debug ().Msg ("starting creation" )
172
186
173
187
err = d .manager .Create (req .Name , sizeInBytes , sparse , fs , uid , gid , mode )
174
188
if err != nil {
189
+ logger .Debug ().Msg ("failed creating volume" )
175
190
return err
176
191
}
177
192
178
193
logger .Debug ().Msg ("finished creating volume" )
179
-
180
194
return nil
181
195
}
182
196
0 commit comments