From 31f8290f7bbfe4f1623a1be067c3cd126e30c190 Mon Sep 17 00:00:00 2001 From: Aravinda VK Date: Mon, 11 Jun 2018 10:45:30 -0400 Subject: [PATCH] Auto generate Volume Name if not specified in Request Updates: #851 Signed-off-by: Aravinda VK --- doc/quick-start-user-guide.md | 2 +- e2e/smartvol_ops_test.go | 13 +++++++++ e2e/volume_ops_test.go | 30 +++++++++++++++++++++ glustercli/cmd/volume-create.go | 23 ++++++++-------- glusterd2/commands/volumes/volume-create.go | 5 ++++ glusterd2/volume/volume-utils.go | 5 ++++ pkg/api/volume_req.go | 2 +- plugins/smartvol/api/req_resp.go | 28 +++++++++---------- plugins/smartvol/rest.go | 5 ++++ 9 files changed, 85 insertions(+), 28 deletions(-) diff --git a/doc/quick-start-user-guide.md b/doc/quick-start-user-guide.md index 9d0f4e928..a16a406fc 100644 --- a/doc/quick-start-user-guide.md +++ b/doc/quick-start-user-guide.md @@ -172,7 +172,7 @@ $ curl -X POST http://192.168.56.101:24007/v1/volumes --data @volcreate.json -H Send the volume create request using glustercli: - $ glustercli volume create testvol :/export/brick1/data :/export/brick2/data :/export/brick3/data :/export/brick4/data --replica 2 + $ glustercli volume create --name testvol :/export/brick1/data :/export/brick2/data :/export/brick3/data :/export/brick4/data --replica 2 ## Start the volume diff --git a/e2e/smartvol_ops_test.go b/e2e/smartvol_ops_test.go index 3ca534954..1a1a33c21 100644 --- a/e2e/smartvol_ops_test.go +++ b/e2e/smartvol_ops_test.go @@ -213,6 +213,18 @@ func testSmartVolumeDistributeDisperse(t *testing.T) { r.Nil(client.VolumeDelete(smartvolname)) } +func testSmartVolumeWithoutName(t *testing.T) { + r := require.New(t) + + createReq := smartvolapi.VolCreateReq{ + Size: 20, + } + volinfo, err := client.SmartVolumeCreate(createReq) + r.Nil(err) + + r.Nil(client.VolumeDelete(volinfo.Name)) +} + // TestSmartVolume creates a volume and starts it, runs further tests on it and // finally deletes the volume func TestSmartVolume(t *testing.T) { @@ -252,6 +264,7 @@ func TestSmartVolume(t *testing.T) { t.Run("Smartvol Disperse Volume", testSmartVolumeDisperse) t.Run("Smartvol Distributed-Replicate Volume", testSmartVolumeDistributeReplicate) t.Run("Smartvol Distributed-Disperse Volume", testSmartVolumeDistributeDisperse) + t.Run("Smartvol Without Name", testSmartVolumeWithoutName) // // Device Cleanup r.Nil(loopDevicesCleanup(t)) diff --git a/e2e/volume_ops_test.go b/e2e/volume_ops_test.go index 89ce9f62b..60785da68 100644 --- a/e2e/volume_ops_test.go +++ b/e2e/volume_ops_test.go @@ -46,6 +46,8 @@ func TestVolume(t *testing.T) { t.Logf("Using temp dir: %s", tmpDir) //defer os.RemoveAll(tmpDir) + t.Run("CreateWithoutName", testVolumeCreateWithoutName) + // Create the volume t.Run("Create", testVolumeCreate) // Expand the volume @@ -68,6 +70,34 @@ func TestVolume(t *testing.T) { t.Run("Disperse", testDisperse) } +func testVolumeCreateWithoutName(t *testing.T) { + r := require.New(t) + + var brickPaths []string + for i := 1; i <= 2; i++ { + brickPath, err := ioutil.TempDir(tmpDir, "brick") + r.Nil(err) + brickPaths = append(brickPaths, brickPath) + } + + // create 2x2 dist-rep volume + createReq := api.VolCreateReq{ + Subvols: []api.SubvolReq{ + { + Bricks: []api.BrickReq{ + {PeerID: gds[0].PeerID(), Path: brickPaths[0]}, + {PeerID: gds[1].PeerID(), Path: brickPaths[1]}, + }, + }, + }, + Force: true, + } + volinfo, err := client.VolumeCreate(createReq) + r.Nil(err) + + r.Nil(client.VolumeDelete(volinfo.Name)) +} + func testVolumeCreate(t *testing.T) { r := require.New(t) diff --git a/glustercli/cmd/volume-create.go b/glustercli/cmd/volume-create.go index 492ee60bb..cffc55055 100644 --- a/glustercli/cmd/volume-create.go +++ b/glustercli/cmd/volume-create.go @@ -17,6 +17,7 @@ const ( ) var ( + flagCreateVolumeName string flagCreateStripeCount int flagCreateReplicaCount int flagCreateArbiterCount int @@ -42,15 +43,16 @@ var ( flagCreateSubvolZoneOverlap bool volumeCreateCmd = &cobra.Command{ - Use: "create [ []...|--size ]", + Use: "create [--name ] [ []...|--size ]", Short: volumeCreateHelpShort, Long: volumeCreateHelpLong, - Args: cobra.MinimumNArgs(1), + Args: cobra.MinimumNArgs(0), Run: volumeCreateCmdRun, } ) func init() { + volumeCreateCmd.Flags().StringVar(&flagCreateVolumeName, "name", "", "Volume Name") volumeCreateCmd.Flags().IntVar(&flagCreateStripeCount, "stripe", 0, "Stripe Count") volumeCreateCmd.Flags().IntVar(&flagCreateReplicaCount, "replica", 0, "Replica Count") volumeCreateCmd.Flags().IntVar(&flagCreateArbiterCount, "arbiter", 0, "Arbiter Count") @@ -91,10 +93,8 @@ func smartVolumeCreate(cmd *cobra.Command, args []string) { failure("Invalid Volume Size specified", nil, 1) } - volname := args[0] - req := smartvolapi.VolCreateReq{ - Name: volname, + Name: flagCreateVolumeName, Transport: flagCreateTransport, Size: size, ReplicaCount: flagCreateReplicaCount, @@ -117,7 +117,7 @@ func smartVolumeCreate(cmd *cobra.Command, args []string) { if err != nil { if verbose { log.WithFields(log.Fields{ - "volume": volname, + "volume": flagCreateVolumeName, "error": err.Error(), }).Error("volume creation failed") } @@ -133,17 +133,16 @@ func volumeCreateCmdRun(cmd *cobra.Command, args []string) { return } - if len(args) < 2 { + if len(args) < 1 { failure("Bricks not specified", nil, 1) } - volname := args[0] - bricks, err := bricksAsUUID(args[1:]) + bricks, err := bricksAsUUID(args) if err != nil { if verbose { log.WithFields(log.Fields{ "error": err.Error(), - "volume": volname, + "volume": flagCreateVolumeName, }).Error("error getting brick UUIDs") } failure("Error getting brick UUIDs", err, 1) @@ -243,7 +242,7 @@ func volumeCreateCmdRun(cmd *cobra.Command, args []string) { } req := api.VolCreateReq{ - Name: volname, + Name: flagCreateVolumeName, Subvols: subvols, Force: flagCreateForce, Options: options, @@ -269,7 +268,7 @@ func volumeCreateCmdRun(cmd *cobra.Command, args []string) { if err != nil { if verbose { log.WithFields(log.Fields{ - "volume": volname, + "volume": flagCreateVolumeName, "error": err.Error(), }).Error("volume creation failed") } diff --git a/glusterd2/commands/volumes/volume-create.go b/glusterd2/commands/volumes/volume-create.go index 534df1e99..5768fe63f 100644 --- a/glusterd2/commands/volumes/volume-create.go +++ b/glusterd2/commands/volumes/volume-create.go @@ -88,6 +88,11 @@ func volumeCreateHandler(w http.ResponseWriter, r *http.Request) { return } + // Generate Volume name if not provided + if req.Name == "" { + req.Name = volume.GenerateVolumeName() + } + if err := validateVolCreateReq(&req); err != nil { restutils.SendHTTPError(ctx, w, http.StatusBadRequest, err) return diff --git a/glusterd2/volume/volume-utils.go b/glusterd2/volume/volume-utils.go index 237a969e8..37d892d05 100644 --- a/glusterd2/volume/volume-utils.go +++ b/glusterd2/volume/volume-utils.go @@ -22,6 +22,11 @@ var ( volumeNameRE = regexp.MustCompile("^[a-zA-Z0-9_-]+$") ) +// GenerateVolumeName generates volume name as vol_ +func GenerateVolumeName() string { + return "vol_" + uuid.NewRandom().String() +} + // IsValidName validates Volume name func IsValidName(name string) bool { return volumeNameRE.MatchString(name) diff --git a/pkg/api/volume_req.go b/pkg/api/volume_req.go index 30a55d46e..1ef03d378 100644 --- a/pkg/api/volume_req.go +++ b/pkg/api/volume_req.go @@ -27,7 +27,7 @@ type SubvolReq struct { "create-brick-dir" : if brick dir is not present, create it */ type VolCreateReq struct { - Name string `json:"name"` + Name string `json:"name,omitempty"` Transport string `json:"transport,omitempty"` Subvols []SubvolReq `json:"subvols"` Options map[string]string `json:"options,omitempty"` diff --git a/plugins/smartvol/api/req_resp.go b/plugins/smartvol/api/req_resp.go index 3fbce17a9..348d7fb09 100644 --- a/plugins/smartvol/api/req_resp.go +++ b/plugins/smartvol/api/req_resp.go @@ -2,23 +2,23 @@ package api // VolCreateReq represents a Volume Create Request type VolCreateReq struct { - Name string `json:"name"` + Name string `json:"name,omitempty"` Transport string `json:"transport,omitempty"` Force bool `json:"force,omitempty"` Size uint64 `json:"size"` - DistributeCount int `json:"distribute"` - ReplicaCount int `json:"replica"` - ArbiterCount int `json:"arbiter"` - DisperseCount int `json:"disperse"` - DisperseRedundancyCount int `json:"disperse-redundancy"` - DisperseDataCount int `json:"disperse-data"` - SnapshotEnabled bool `json:"snapshot"` - SnapshotReserveFactor float64 `json:"snapshot-reserve-factor"` - LimitPeers []string `json:"limit-peers"` - LimitZones []string `json:"limit-zones"` - ExcludePeers []string `json:"exclude-peers"` - ExcludeZones []string `json:"exclude-zones"` - SubvolZonesOverlap bool `json:"subvolume-zones-overlap"` + DistributeCount int `json:"distribute,omitempty"` + ReplicaCount int `json:"replica,omitempty"` + ArbiterCount int `json:"arbiter,omitempty"` + DisperseCount int `json:"disperse,omitempty"` + DisperseRedundancyCount int `json:"disperse-redundancy,omitempty"` + DisperseDataCount int `json:"disperse-data,omitempty"` + SnapshotEnabled bool `json:"snapshot,omitempty"` + SnapshotReserveFactor float64 `json:"snapshot-reserve-factor,omitempty"` + LimitPeers []string `json:"limit-peers,omitempty"` + LimitZones []string `json:"limit-zones,omitempty"` + ExcludePeers []string `json:"exclude-peers,omitempty"` + ExcludeZones []string `json:"exclude-zones,omitempty"` + SubvolZonesOverlap bool `json:"subvolume-zones-overlap,omitempty"` } // Brick represents Brick Request diff --git a/plugins/smartvol/rest.go b/plugins/smartvol/rest.go index 0bc86233e..d631b8fbc 100644 --- a/plugins/smartvol/rest.go +++ b/plugins/smartvol/rest.go @@ -92,6 +92,11 @@ func smartVolumeCreateHandler(w http.ResponseWriter, r *http.Request) { return } + // Generate Volume name if not provided + if req.Name == "" { + req.Name = volume.GenerateVolumeName() + } + if err := validateVolCreateReq(&req); err != nil { restutils.SendHTTPError(ctx, w, http.StatusBadRequest, err) return