Skip to content
This repository was archived by the owner on Mar 26, 2020. It is now read-only.

Commit

Permalink
BlockVolume: Input block host volume properties in block create request
Browse files Browse the repository at this point in the history
Signed-off-by: Poornima G <[email protected]>
  • Loading branch information
Poornima G authored and Madhu-1 committed Feb 21, 2019
1 parent a94bec2 commit 2869f88
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 57 deletions.
20 changes: 2 additions & 18 deletions glustercli/cmd/volume-create.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"strings"

"github.com/gluster/glusterd2/glusterd2/volume"
"github.com/gluster/glusterd2/pkg/api"

log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -315,7 +316,7 @@ func volumeCreateCmdRun(cmd *cobra.Command, args []string) {
fmt.Println("Thin arbiter can only be enabled for replica count 2")
return
}
if err := addThinArbiter(&req, cmd.Flag("thin-arbiter").Value.String()); err != nil {
if err := volume.AddThinArbiter(&req, cmd.Flag("thin-arbiter").Value.String()); err != nil {
fmt.Println(err)
return
}
Expand All @@ -331,20 +332,3 @@ func volumeCreateCmdRun(cmd *cobra.Command, args []string) {
fmt.Printf("%s Volume created successfully\n", vol.Name)
fmt.Println("Volume ID: ", vol.ID)
}

func addThinArbiter(req *api.VolCreateReq, thinArbiter string) error {

s := strings.Split(thinArbiter, ":")
if len(s) != 2 && len(s) != 3 {
return fmt.Errorf("thin arbiter brick must be of the form <host>:<brick> or <host>:<brick>:<port>")
}

// TODO: If required, handle this in a generic way, just like other
// volume set options that we're going to allow to be set during
// volume create.
req.Options = map[string]string{
"replicate.thin-arbiter": thinArbiter,
}
req.AllowAdvanced = true
return nil
}
24 changes: 24 additions & 0 deletions glusterd2/volume/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,30 @@ func ApplyCustomFilters(volumes []*Volinfo, filters ...Filter) []*Volinfo {
return volumes
}

// FilterThinArbiterVolumes filters out volumes that are thin arbiter volumes
func FilterThinArbiterVolumes(volumes []*Volinfo) []*Volinfo {
var volInfos []*Volinfo
for _, volume := range volumes {
_, exists := volume.Options["cluster/replicate.thin-arbiter"]
if exists {
volInfos = append(volInfos, volume)
}
}
return volInfos
}

//FilterShardVolumes filters out volumes that are shard enabled
func FilterShardVolumes(volumes []*Volinfo) []*Volinfo {
var volInfos []*Volinfo
for _, volume := range volumes {
_, exists := volume.Options["features/shard"]
if exists {
volInfos = append(volInfos, volume)
}
}
return volInfos
}

// FilterBlockHostedVolumes filters out volume which are suitable for hosting block volume
func FilterBlockHostedVolumes(volumes []*Volinfo) []*Volinfo {
var volInfos []*Volinfo
Expand Down
26 changes: 26 additions & 0 deletions glusterd2/volume/volume-utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"syscall"

Expand Down Expand Up @@ -399,3 +400,28 @@ func CleanBricksLoop(volinfo *Volinfo) error {
}
return nil
}

//AddThinArbiter adds thin arbiter option to the volume create request
func AddThinArbiter(req *api.VolCreateReq, thinArbiter string) error {

s := strings.Split(thinArbiter, ":")
if len(s) != 2 && len(s) != 3 {
return errors.New("thin arbiter brick must be of the form <host>:<brick> or <host>:<brick>:<port>")
}

// TODO: If required, handle this in a generic way, just like other
// volume set options that we're going to allow to be set during
// volume create.
req.Options["replicate.thin-arbiter"] = thinArbiter
req.AllowAdvanced = true
return nil
}

//AddShard adds shard options to the volume create request
func AddShard(req *api.VolCreateReq, shardSize uint64) {

req.Options["features/shard"] = "on"
req.Options["features/shard.shard-block-size"] = strconv.FormatUint(shardSize, 10)
req.AllowAdvanced = true
return
}
18 changes: 16 additions & 2 deletions plugins/blockvolume/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,25 @@ type BlockVolumeInfo struct {
HaCount int `json:"hacount,omitempty"`
}

// HostVolumeInfo represents block volume info
type HostVolumeInfo struct {
// HostVolReplicaCnt represents the replica count of the block hosting volume
HostVolReplicaCnt int `json:"hostvolreplicacnt,omitempty"`
// HostVolThinArbPath represents the thin arbiter path
HostVolThinArbPath string `json:"hostvolthinarbpath,omitempty"`
// HostVolShardSize represents the shard size of the block hosting volume
HostVolShardSize uint64 `json:"hostvolshardsize,omitempty"`
// Size represents Block Hosting Volume size in bytes
HostVolSize uint64 `json:"hostvolsize,omitempty"`
}

// BlockVolumeCreateRequest represents req Body for Block vol create req
type BlockVolumeCreateRequest struct {
*BlockVolumeInfo
Clusters []string `json:"clusters,omitempty"`
Auth bool `json:"auth,omitempty"`
HostVolumeInfo
BlockType string `json:"blocktype,omitempty"`
Clusters []string `json:"clusters,omitempty"`
Auth bool `json:"auth,omitempty"`
}

// BlockVolumeCreateResp represents resp body for a Block Vol Create req
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/gluster/glusterd2/glusterd2/volume"
"github.com/gluster/glusterd2/pkg/size"
"github.com/gluster/glusterd2/plugins/blockvolume/blockprovider"
"github.com/gluster/glusterd2/plugins/blockvolume/utils"
"github.com/gluster/glusterd2/plugins/blockvolume/hostvol"
"time"

"github.com/gluster/gluster-block-restapi/client"
Expand Down Expand Up @@ -79,7 +79,7 @@ func (g *GlusterBlock) CreateBlockVolume(name string, size uint64, hostVolume st
}

resizeFunc := func(blockHostingAvailableSize, blockSize uint64) uint64 { return blockHostingAvailableSize - blockSize }
if err = utils.ResizeBlockHostingVolume(hostVolume, size, resizeFunc); err != nil {
if err = hostvol.ResizeBlockHostingVolume(hostVolume, size, resizeFunc); err != nil {
logger.WithError(err).Error("failed in updating hostvolume _block-hosting-available-size metadata")
}

Expand Down Expand Up @@ -133,7 +133,7 @@ func (g *GlusterBlock) DeleteBlockVolume(name string, options ...blockprovider.B

resizeFunc := func(blockHostingAvailableSize, blockSize uint64) uint64 { return blockHostingAvailableSize + blockSize }

if err = utils.ResizeBlockHostingVolume(hostVol, blockInfo.Size, resizeFunc); err != nil {
if err = hostvol.ResizeBlockHostingVolume(hostVol, blockInfo.Size, resizeFunc); err != nil {
log.WithFields(log.Fields{
"error": err,
"size": blockInfo.Size,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/gluster/glusterd2/pkg/errors"
"github.com/gluster/glusterd2/pkg/utils"
"github.com/gluster/glusterd2/plugins/blockvolume/blockprovider"
blkUtils "github.com/gluster/glusterd2/plugins/blockvolume/utils"
"github.com/gluster/glusterd2/plugins/blockvolume/hostvol"

log "github.com/sirupsen/logrus"
config "github.com/spf13/viper"
Expand Down Expand Up @@ -95,18 +95,21 @@ func (g *GlusterVirtBlk) CreateBlockVolume(name string, size uint64, hostVolume
blockFileName := hostDir + "/" + name
err = utils.ExecuteCommandRun("truncate", fmt.Sprintf("-s %d", size), blockFileName) //nolint: gosec
if err != nil {
logger.WithError(err).Errorf("failed to truncate block file" + blockFileName)
logger.WithError(err).Errorf("failed to truncate block file %s", blockFileName)
return nil, err
}

err = utils.ExecuteCommandRun("mkfs.xfs", "-f", blockFileName) //nolint: gosec
if err != nil {
logger.WithError(err).Errorf("failed to format block file " + blockFileName)
return nil, err
if blockVolOpts.BlockType != "raw" {
fsType := blockVolOpts.BlockType
err = utils.ExecuteCommandRun(fmt.Sprintf("mkfs.%s", fsType), "-f", blockFileName) //nolint: gosec
if err != nil {
logger.WithError(err).Errorf("failed to format block file %s with filesystem %s", blockFileName, fsType)
return nil, err
}
}

resizeFunc := func(blockHostingAvailableSize, blockSize uint64) uint64 { return blockHostingAvailableSize - blockSize }
if err = blkUtils.ResizeBlockHostingVolume(hostVolume, size, resizeFunc); err != nil {
if err = hostvol.ResizeBlockHostingVolume(hostVolume, size, resizeFunc); err != nil {
logger.WithError(err).Error("failed in updating hostvolume _block-hosting-available-size metadata")
return nil, err
}
Expand All @@ -119,7 +122,7 @@ func (g *GlusterVirtBlk) CreateBlockVolume(name string, size uint64, hostVolume

volInfo, err := volume.GetVolume(hostVolume)
if err != nil {
logger.WithError(err).Errorf("failed to get host volume info " + hostVolume)
logger.WithError(err).Errorf("failed to get host volume info %s", hostVolume)
return nil, err
}
key := volume.BlockPrefix + name
Expand Down Expand Up @@ -181,14 +184,14 @@ func (g *GlusterVirtBlk) DeleteBlockVolume(name string, options ...blockprovider

hostDir, err := mountHost(g, blkVol.HostVolume())
if err != nil {
log.WithError(err).Errorf("error mounting block hosting volume :" + blkVol.HostVolume())
log.WithError(err).Errorf("error mounting block hosting volume :%s", blkVol.HostVolume())
return err
}

blockFileName := hostDir + "/" + name
err = os.Remove(blockFileName)
if err != nil {
log.WithError(err).Errorf("error removing block :" + blockFileName)
log.WithError(err).Errorf("error removing block :%s", blockFileName)
return err
}

Expand All @@ -199,7 +202,7 @@ func (g *GlusterVirtBlk) DeleteBlockVolume(name string, options ...blockprovider
}

resizeFunc := func(blockHostingAvailableSize, blockSize uint64) uint64 { return blockHostingAvailableSize + blockSize }
if err = blkUtils.ResizeBlockHostingVolume(blkVol.HostVolume(), blkVol.Size(), resizeFunc); err != nil {
if err = hostvol.ResizeBlockHostingVolume(blkVol.HostVolume(), blkVol.Size(), resizeFunc); err != nil {
log.WithFields(log.Fields{
"error": err,
"size": blkVol.Size(),
Expand Down
12 changes: 12 additions & 0 deletions plugins/blockvolume/blockprovider/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type BlockVolumeOptions struct {
ForceDelete bool
UnlinkStorage bool
Hosts []string
BlockType string
}

// ApplyOpts applies configured optional parameters on BlockVolumeOptions
Expand Down Expand Up @@ -69,3 +70,14 @@ func WithHosts(hosts []string) BlockVolOption {
options.Hosts = hosts
}
}

// WithBlockType configures the block type
func WithBlockType(blockType string) BlockVolOption {
return func(options *BlockVolumeOptions) {
if blockType == "" {
options.BlockType = "xfs"
} else {
options.BlockType = blockType
}
}
}
3 changes: 2 additions & 1 deletion plugins/blockvolume/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func (b *BlockVolume) CreateVolume(w http.ResponseWriter, r *http.Request) {
opts = append(opts,
blockprovider.WithHaCount(req.HaCount),
blockprovider.WithHosts(req.Clusters),
blockprovider.WithBlockType(req.BlockType),
)

if req.Auth {
Expand All @@ -39,7 +40,7 @@ func (b *BlockVolume) CreateVolume(w http.ResponseWriter, r *http.Request) {
return
}

hostVolInfo, err := b.hostVolManager.GetOrCreateHostingVolume(req.HostingVolume, req.Size)
hostVolInfo, err := b.hostVolManager.GetOrCreateHostingVolume(req.HostingVolume, req.Size, &req.HostVolumeInfo)
if err != nil {
utils.SendHTTPError(r.Context(), w, http.StatusInternalServerError, err)
return
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package blockvolume
package hostvol

import (
"context"
Expand All @@ -11,7 +11,7 @@ import (

"github.com/gluster/glusterd2/glusterd2/transaction"
"github.com/gluster/glusterd2/glusterd2/volume"
"github.com/gluster/glusterd2/plugins/blockvolume/utils"
"github.com/gluster/glusterd2/plugins/blockvolume/api"

log "github.com/sirupsen/logrus"
)
Expand All @@ -23,25 +23,25 @@ const (
// HostingVolumeManager provides methods for host volume management
type HostingVolumeManager interface {
GetHostingVolumesInUse() []*volume.Volinfo
GetOrCreateHostingVolume(name string, minSizeLimit uint64) (*volume.Volinfo, error)
GetOrCreateHostingVolume(name string, minSizeLimit uint64, hostVolumeInfo *api.HostVolumeInfo) (*volume.Volinfo, error)
}

// glusterVolManager is a concrete implementation of HostingVolumeManager
type glusterVolManager struct {
// GlusterVolManager is a concrete implementation of HostingVolumeManager
type GlusterVolManager struct {
hostVolOpts *HostingVolumeOptions
}

// newGlusterVolManager returns a glusterVolManager instance
func newGlusterVolManager() *glusterVolManager {
g := &glusterVolManager{
// NewGlusterVolManager returns a glusterVolManager instance
func NewGlusterVolManager() *GlusterVolManager {
g := &GlusterVolManager{
hostVolOpts: newHostingVolumeOptions(),
}

return g
}

// GetHostingVolumesInUse lists all volumes which used in hosting block-vols
func (g *glusterVolManager) GetHostingVolumesInUse() []*volume.Volinfo {
func (g *GlusterVolManager) GetHostingVolumesInUse() []*volume.Volinfo {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()

Expand All @@ -55,7 +55,7 @@ func (g *glusterVolManager) GetHostingVolumesInUse() []*volume.Volinfo {

// GetOrCreateHostingVolume will returns volume details for a given volume name and having a minimum size of `minSizeLimit`.
// If volume name is not provided then it will create a gluster volume with default size for hosting gluster block.
func (g *glusterVolManager) GetOrCreateHostingVolume(name string, minSizeLimit uint64) (*volume.Volinfo, error) {
func (g *GlusterVolManager) GetOrCreateHostingVolume(name string, minSizeLimit uint64, hostVolumeInfo *api.HostVolumeInfo) (*volume.Volinfo, error) {
var (
volInfo *volume.Volinfo
clusterLocks = transaction.Locks{}
Expand All @@ -67,9 +67,14 @@ func (g *glusterVolManager) GetOrCreateHostingVolume(name string, minSizeLimit u
defer clusterLocks.UnLock(context.Background())

g.hostVolOpts.SetFromClusterOptions()
volCreateReq := g.hostVolOpts.PrepareVolumeCreateReq()
g.hostVolOpts.SetFromReq(hostVolumeInfo)
volCreateReq, err := g.hostVolOpts.PrepareVolumeCreateReq()
if err != nil {
log.WithError(err).Error("failed to create block volume create request")
return nil, err
}

// ERROR if If HostingVolume is not specified and auto-create-block-hosting-volumes is false
// ERROR if HostingVolume is not specified and auto-create-block-hosting-volumes is false
if name == "" && !g.hostVolOpts.AutoCreate {
err := errors.New("host volume is not provided and auto creation is not enabled")
log.WithError(err).Error("failed in creating block volume")
Expand All @@ -91,7 +96,7 @@ func (g *glusterVolManager) GetOrCreateHostingVolume(name string, minSizeLimit u
// If HostingVolume is not specified. List all available volumes and see if any volume is
// available with Metadata:block-hosting=yes
if name == "" {
vInfo, err := utils.GetExistingBlockHostingVolume(minSizeLimit)
vInfo, err := GetExistingBlockHostingVolume(minSizeLimit, g.hostVolOpts)
if err != nil {
log.WithError(err).Debug("no block hosting volumes present")
}
Expand All @@ -102,7 +107,7 @@ func (g *glusterVolManager) GetOrCreateHostingVolume(name string, minSizeLimit u
// volumes(Metadata:block-hosting-available-size is less than request size), then try to create a new
// block hosting Volume with generated name with default size and volume type configured.
if name == "" && volInfo == nil {
vInfo, err := utils.CreateAndStartHostingVolume(volCreateReq)
vInfo, err := CreateAndStartHostingVolume(volCreateReq)
if err != nil {
log.WithError(err).Error("error in auto creation of block hosting volume")
return nil, err
Expand Down
Loading

0 comments on commit 2869f88

Please sign in to comment.