Skip to content

Commit cc4c519

Browse files
author
Oshank Kumar
committed
gd2 plugin: added a plugin for block volume management
- added APIs for creation,deleting and listing block volumes. - added pluggable interface for block volume providers. Refer Design Doc: gluster#1319 Signed-off-by: Oshank Kumar <[email protected]>
1 parent e432ed3 commit cc4c519

File tree

17 files changed

+1386
-73
lines changed

17 files changed

+1386
-73
lines changed

Gopkg.lock

Lines changed: 26 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949
[[constraint]]
5050
name = "github.com/sirupsen/logrus"
51-
version = "~1.0.3"
51+
version = "~1.2.0"
5252

5353
[[constraint]]
5454
name = "github.com/cockroachdb/cmux"

glusterd2/commands/volumes/volume-create.go

Lines changed: 45 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package volumecommands
22

33
import (
4+
"context"
45
"errors"
56
"net/http"
67
"path/filepath"
@@ -102,9 +103,6 @@ func registerVolCreateStepFuncs() {
102103
func volumeCreateHandler(w http.ResponseWriter, r *http.Request) {
103104

104105
ctx := r.Context()
105-
ctx, span := trace.StartSpan(ctx, "/volumeCreateHandler")
106-
defer span.End()
107-
108106
logger := gdctx.GetReqLogger(ctx)
109107
var err error
110108

@@ -114,45 +112,68 @@ func volumeCreateHandler(w http.ResponseWriter, r *http.Request) {
114112
return
115113
}
116114

117-
if err := validateVolCreateReq(&req); err != nil {
118-
restutils.SendHTTPError(ctx, w, http.StatusBadRequest, err)
115+
if status, err := CreateVolume(ctx, req); err != nil {
116+
restutils.SendHTTPError(ctx, w, status, err)
119117
return
120118
}
121119

122-
if containsReservedGroupProfile(req.Options) {
123-
restutils.SendHTTPError(ctx, w, http.StatusBadRequest, gderrors.ErrReservedGroupProfile)
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)
124126
return
125127
}
126128

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 creates a volume
142+
func CreateVolume(ctx context.Context, req api.VolCreateReq) (status int, err error) {
143+
ctx, span := trace.StartSpan(ctx, "/volumeCreateHandler")
144+
defer span.End()
145+
146+
if err := validateVolCreateReq(&req); err != nil {
147+
return http.StatusBadRequest, err
148+
}
149+
150+
if containsReservedGroupProfile(req.Options) {
151+
return http.StatusBadRequest, gderrors.ErrReservedGroupProfile
152+
}
153+
127154
if req.Size > 0 {
128155
applyDefaults(&req)
129156

130157
if req.SnapshotReserveFactor < 1 {
131-
restutils.SendHTTPError(ctx, w, http.StatusBadRequest,
132-
errors.New("invalid snapshot reserve factor"))
133-
return
158+
return http.StatusBadRequest, errors.New("invalid snapshot reserve factor")
134159
}
135160

136161
if err := bricksplanner.PlanBricks(&req); err != nil {
137-
restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, err)
138-
return
162+
return http.StatusInternalServerError, err
139163
}
140164
} else {
141165
if err := checkDupBrickEntryVolCreate(req); err != nil {
142-
restutils.SendHTTPError(ctx, w, http.StatusBadRequest, err)
143-
return
166+
return http.StatusBadRequest, err
144167
}
145168
}
146169

147170
req.Options, err = expandGroupOptions(req.Options)
148171
if err != nil {
149-
restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, err)
150-
return
172+
return http.StatusInternalServerError, err
151173
}
152174

153175
if err := validateOptions(req.Options, req.VolOptionFlags); err != nil {
154-
restutils.SendHTTPError(ctx, w, http.StatusBadRequest, err)
155-
return
176+
return http.StatusBadRequest, err
156177
}
157178

158179
// Include default Volume Options profile
@@ -171,21 +192,17 @@ func volumeCreateHandler(w http.ResponseWriter, r *http.Request) {
171192

172193
nodes, err := req.Nodes()
173194
if err != nil {
174-
restutils.SendHTTPError(ctx, w, http.StatusBadRequest, err)
175-
return
195+
return http.StatusBadRequest, err
176196
}
177197

178198
txn, err := transactionv2.NewTxnWithLocks(ctx, req.Name)
179199
if err != nil {
180-
status, err := restutils.ErrToStatusCode(err)
181-
restutils.SendHTTPError(ctx, w, status, err)
182-
return
200+
return restutils.ErrToStatusCode(err)
183201
}
184202
defer txn.Done()
185203

186204
if volume.Exists(req.Name) {
187-
restutils.SendHTTPError(ctx, w, http.StatusBadRequest, gderrors.ErrVolExists)
188-
return
205+
return http.StatusBadRequest, gderrors.ErrVolExists
189206
}
190207

191208
txn.Steps = []*transaction.Step{
@@ -219,8 +236,7 @@ func volumeCreateHandler(w http.ResponseWriter, r *http.Request) {
219236
}
220237

221238
if err := txn.Ctx.Set("req", &req); err != nil {
222-
restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, err)
223-
return
239+
return http.StatusInternalServerError, err
224240
}
225241

226242
// Add attributes to the span with info that can be viewed along with traces.
@@ -231,28 +247,8 @@ func volumeCreateHandler(w http.ResponseWriter, r *http.Request) {
231247
)
232248

233249
if err := txn.Do(); err != nil {
234-
status, err := restutils.ErrToStatusCode(err)
235-
restutils.SendHTTPError(ctx, w, status, err)
236-
return
250+
return restutils.ErrToStatusCode(err)
237251
}
238252

239-
volinfo, err := volume.GetVolume(req.Name)
240-
if err != nil {
241-
// FIXME: If volume was created successfully in the txn above and
242-
// then the store goes down by the time we reach here, what do
243-
// we return to the client ?
244-
restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, err)
245-
return
246-
}
247-
248-
logger.WithField("volume-name", volinfo.Name).Info("new volume created")
249-
events.Broadcast(volume.NewEvent(volume.EventVolumeCreated, volinfo))
250-
251-
resp := createVolumeCreateResp(volinfo)
252-
restutils.SetLocationHeader(r, w, volinfo.Name)
253-
restutils.SendHTTPResponse(ctx, w, http.StatusCreated, resp)
254-
}
255-
256-
func createVolumeCreateResp(v *volume.Volinfo) *api.VolumeCreateResp {
257-
return (*api.VolumeCreateResp)(volume.CreateVolumeInfoResp(v))
253+
return http.StatusCreated, nil
258254
}

glusterd2/commands/volumes/volume-start.go

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,6 @@ func registerVolStartStepFuncs() {
128128
func volumeStartHandler(w http.ResponseWriter, r *http.Request) {
129129

130130
ctx := r.Context()
131-
ctx, span := trace.StartSpan(ctx, "/volumeStartHandler")
132-
defer span.End()
133-
134131
logger := gdctx.GetReqLogger(ctx)
135132
volname := mux.Vars(r)["volname"]
136133
var req api.VolumeStartReq
@@ -141,24 +138,40 @@ func volumeStartHandler(w http.ResponseWriter, r *http.Request) {
141138
return
142139
}
143140

144-
txn, err := transaction.NewTxnWithLocks(ctx, volname)
141+
volinfo, status, err := StartVolume(ctx, volname, req)
145142
if err != nil {
146-
status, err := restutils.ErrToStatusCode(err)
147143
restutils.SendHTTPError(ctx, w, status, err)
148144
return
149145
}
146+
147+
logger.WithField("volume-name", volinfo.Name).Info("volume started")
148+
events.Broadcast(volume.NewEvent(volume.EventVolumeStarted, volinfo))
149+
150+
resp := createVolumeStartResp(volinfo)
151+
restutils.SendHTTPResponse(ctx, w, http.StatusOK, resp)
152+
}
153+
154+
// StartVolume starts a volume
155+
func StartVolume(ctx context.Context, volname string, req api.VolumeStartReq) (volInfo *volume.Volinfo, status int, err error) {
156+
logger := gdctx.GetReqLogger(ctx)
157+
ctx, span := trace.StartSpan(ctx, "/volumeStartHandler")
158+
defer span.End()
159+
160+
txn, err := transaction.NewTxnWithLocks(ctx, volname)
161+
if err != nil {
162+
status, err := restutils.ErrToStatusCode(err)
163+
return nil, status, err
164+
}
150165
defer txn.Done()
151166

152167
volinfo, err := volume.GetVolume(volname)
153168
if err != nil {
154169
status, err := restutils.ErrToStatusCode(err)
155-
restutils.SendHTTPError(ctx, w, status, err)
156-
return
170+
return nil, status, err
157171
}
158172

159173
if volinfo.State == volume.VolStarted && !req.ForceStartBricks {
160-
restutils.SendHTTPError(ctx, w, http.StatusBadRequest, errors.ErrVolAlreadyStarted)
161-
return
174+
return nil, http.StatusBadRequest, errors.ErrVolAlreadyStarted
162175
}
163176

164177
txn.Steps = []*transaction.Step{
@@ -181,15 +194,13 @@ func volumeStartHandler(w http.ResponseWriter, r *http.Request) {
181194
}
182195

183196
if err := txn.Ctx.Set("oldvolinfo", volinfo); err != nil {
184-
restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, err)
185-
return
197+
return nil, http.StatusInternalServerError, err
186198
}
187199

188200
volinfo.State = volume.VolStarted
189201

190202
if err := txn.Ctx.Set("volinfo", volinfo); err != nil {
191-
restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, err)
192-
return
203+
return nil, http.StatusInternalServerError, err
193204
}
194205

195206
span.AddAttributes(
@@ -200,15 +211,10 @@ func volumeStartHandler(w http.ResponseWriter, r *http.Request) {
200211
if err := txn.Do(); err != nil {
201212
logger.WithError(err).WithField(
202213
"volume", volname).Error("transaction to start volume failed")
203-
restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, err)
204-
return
214+
return nil, http.StatusInternalServerError, err
205215
}
206216

207-
logger.WithField("volume-name", volinfo.Name).Info("volume started")
208-
events.Broadcast(volume.NewEvent(volume.EventVolumeStarted, volinfo))
209-
210-
resp := createVolumeStartResp(volinfo)
211-
restutils.SendHTTPResponse(ctx, w, http.StatusOK, resp)
217+
return volinfo, http.StatusOK, nil
212218
}
213219

214220
func createVolumeStartResp(v *volume.Volinfo) *api.VolumeStartResp {

glusterd2/plugin/plugins.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package plugin
44

55
import (
66
"github.com/gluster/glusterd2/plugins/bitrot"
7+
"github.com/gluster/glusterd2/plugins/blockvolume"
78
"github.com/gluster/glusterd2/plugins/device"
89
"github.com/gluster/glusterd2/plugins/events"
910
"github.com/gluster/glusterd2/plugins/georeplication"
@@ -25,4 +26,5 @@ var PluginsList = []GlusterdPlugin{
2526
&glustershd.Plugin{},
2627
&device.Plugin{},
2728
&rebalance.Plugin{},
29+
&blockvolume.BlockVolume{},
2830
}

0 commit comments

Comments
 (0)