1
1
package volumecommands
2
2
3
3
import (
4
+ "context"
4
5
"errors"
5
6
"net/http"
6
7
"path/filepath"
@@ -99,67 +100,93 @@ func registerVolCreateStepFuncs() {
99
100
}
100
101
101
102
func volumeCreateHandler (w http.ResponseWriter , r * http.Request ) {
103
+ var (
104
+ err error
105
+ req api.VolCreateReq
106
+ ctx = r .Context ()
107
+ logger = gdctx .GetReqLogger (ctx )
108
+ )
102
109
103
- ctx := r .Context ()
104
- ctx , span := trace .StartSpan (ctx , "/volumeCreateHandler" )
105
- defer span .End ()
106
-
107
- logger := gdctx .GetReqLogger (ctx )
108
- var err error
109
-
110
- var req api.VolCreateReq
111
110
if err := restutils .UnmarshalRequest (r , & req ); err != nil {
112
111
restutils .SendHTTPError (ctx , w , http .StatusBadRequest , gderrors .ErrJSONParsingFailed )
113
112
return
114
113
}
115
114
116
- if err := validateVolCreateReq (& req ); err != nil {
117
- restutils .SendHTTPError (ctx , w , http .StatusBadRequest , err )
115
+ if status , err := CreateVolume (ctx , req ); err != nil {
116
+ restutils .SendHTTPError (ctx , w , status , err )
117
+ return
118
+ }
119
+
120
+ volinfo , err := volume .GetVolume (req .Name )
121
+ if err != nil {
122
+ // FIXME: If volume was created successfully in the txn above and
123
+ // then the store goes down by the time we reach here, what do
124
+ // we return to the client ?
125
+ restutils .SendHTTPError (ctx , w , http .StatusInternalServerError , err )
118
126
return
119
127
}
120
128
129
+ logger .WithField ("volume-name" , volinfo .Name ).Info ("new volume created" )
130
+ events .Broadcast (volume .NewEvent (volume .EventVolumeCreated , volinfo ))
131
+
132
+ resp := createVolumeCreateResp (volinfo )
133
+ restutils .SetLocationHeader (r , w , volinfo .Name )
134
+ restutils .SendHTTPResponse (ctx , w , http .StatusCreated , resp )
135
+ }
136
+
137
+ func createVolumeCreateResp (v * volume.Volinfo ) * api.VolumeCreateResp {
138
+ return (* api .VolumeCreateResp )(volume .CreateVolumeInfoResp (v ))
139
+ }
140
+
141
+ // CreateVolume will create a volume. It returns http StatusCode to be sent to client
142
+ // and any error if occurred.
143
+ func CreateVolume (ctx context.Context , req api.VolCreateReq ) (status int , err error ) {
144
+ ctx , span := trace .StartSpan (ctx , "/volumeCreateHandler" )
145
+ defer span .End ()
146
+
147
+ if err := validateVolCreateReq (& req ); err != nil {
148
+ return http .StatusBadRequest , err
149
+ }
150
+
121
151
if req .Size > 0 {
122
152
applyDefaults (& req )
123
153
124
154
if req .SnapshotReserveFactor < 1 {
125
- restutils .SendHTTPError (ctx , w , http .StatusBadRequest ,
126
- errors .New ("invalid snapshot reserve factor" ))
127
- return
155
+ return http .StatusBadRequest , errors .New ("invalid snapshot reserve factor" )
156
+
128
157
}
129
158
130
159
if err := bricksplanner .PlanBricks (& req ); err != nil {
131
- restutils . SendHTTPError ( ctx , w , http .StatusInternalServerError , err )
132
- return
160
+ return http .StatusInternalServerError , err
161
+
133
162
}
134
163
} else {
135
164
if err := checkDupBrickEntryVolCreate (req ); err != nil {
136
- restutils . SendHTTPError ( ctx , w , http .StatusBadRequest , err )
137
- return
165
+ return http .StatusBadRequest , err
166
+
138
167
}
139
168
}
140
169
141
170
req .Options , err = expandGroupOptions (req .Options )
142
171
if err != nil {
143
- restutils . SendHTTPError ( ctx , w , http .StatusInternalServerError , err )
144
- return
172
+ return http .StatusInternalServerError , err
173
+
145
174
}
146
175
147
176
if err := validateOptions (req .Options , req .VolOptionFlags ); err != nil {
148
- restutils . SendHTTPError ( ctx , w , http .StatusBadRequest , err )
149
- return
177
+ return http .StatusBadRequest , err
178
+
150
179
}
151
180
152
181
nodes , err := req .Nodes ()
153
182
if err != nil {
154
- restutils . SendHTTPError ( ctx , w , http .StatusBadRequest , err )
155
- return
183
+ return http .StatusBadRequest , err
184
+
156
185
}
157
186
158
187
txn , err := transaction .NewTxnWithLocks (ctx , req .Name )
159
188
if err != nil {
160
- status , err := restutils .ErrToStatusCode (err )
161
- restutils .SendHTTPError (ctx , w , status , err )
162
- return
189
+ return restutils .ErrToStatusCode (err )
163
190
}
164
191
defer txn .Done ()
165
192
@@ -191,8 +218,8 @@ func volumeCreateHandler(w http.ResponseWriter, r *http.Request) {
191
218
}
192
219
193
220
if err := txn .Ctx .Set ("req" , & req ); err != nil {
194
- restutils . SendHTTPError ( ctx , w , http .StatusInternalServerError , err )
195
- return
221
+ return http .StatusInternalServerError , err
222
+
196
223
}
197
224
198
225
// Add attributes to the span with info that can be viewed along with traces.
@@ -203,28 +230,8 @@ func volumeCreateHandler(w http.ResponseWriter, r *http.Request) {
203
230
)
204
231
205
232
if err := txn .Do (); err != nil {
206
- status , err := restutils .ErrToStatusCode (err )
207
- restutils .SendHTTPError (ctx , w , status , err )
208
- return
233
+ return restutils .ErrToStatusCode (err )
209
234
}
210
235
211
- volinfo , err := volume .GetVolume (req .Name )
212
- if err != nil {
213
- // FIXME: If volume was created successfully in the txn above and
214
- // then the store goes down by the time we reach here, what do
215
- // we return to the client ?
216
- restutils .SendHTTPError (ctx , w , http .StatusInternalServerError , err )
217
- return
218
- }
219
-
220
- logger .WithField ("volume-name" , volinfo .Name ).Info ("new volume created" )
221
- events .Broadcast (volume .NewEvent (volume .EventVolumeCreated , volinfo ))
222
-
223
- resp := createVolumeCreateResp (volinfo )
224
- restutils .SetLocationHeader (r , w , volinfo .Name )
225
- restutils .SendHTTPResponse (ctx , w , http .StatusCreated , resp )
226
- }
227
-
228
- func createVolumeCreateResp (v * volume.Volinfo ) * api.VolumeCreateResp {
229
- return (* api .VolumeCreateResp )(volume .CreateVolumeInfoResp (v ))
236
+ return http .StatusCreated , nil
230
237
}
0 commit comments