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

Refactoring for Intelligent Volume Provisioning #782

Merged
merged 1 commit into from
May 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions glusterd2/commands/volumes/events.go

This file was deleted.

16 changes: 1 addition & 15 deletions glusterd2/commands/volumes/volume-create-disperse.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,6 @@ import (
"github.com/gluster/glusterd2/pkg/api"
)

func getRedundancy(disperse uint) uint {
var temp, l, mask uint
temp = disperse
l = 0
for temp = temp >> 1; temp != 0; temp = temp >> 1 {
l = l + 1
}
mask = ^(1 << l)
if red := disperse & mask; red != 0 {
return red
}
return 1
}

func checkDisperseParams(req *api.SubvolReq, s *volume.Subvol) error {
count := len(req.Bricks)

Expand Down Expand Up @@ -50,7 +36,7 @@ func checkDisperseParams(req *api.SubvolReq, s *volume.Subvol) error {
}

if req.DisperseRedundancy <= 0 {
req.DisperseRedundancy = int(getRedundancy(uint(req.DisperseCount)))
req.DisperseRedundancy = volume.GetRedundancy(uint(req.DisperseCount))
}

if req.DisperseCount != count {
Expand Down
4 changes: 2 additions & 2 deletions glusterd2/commands/volumes/volume-create.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func volumeCreateHandler(w http.ResponseWriter, r *http.Request) {
return
}

nodes, err := nodesFromVolumeCreateReq(&req)
nodes, err := req.Nodes()
if err != nil {
restutils.SendHTTPError(ctx, w, http.StatusBadRequest, err)
return
Expand Down Expand Up @@ -172,7 +172,7 @@ func volumeCreateHandler(w http.ResponseWriter, r *http.Request) {
}

logger.WithField("volume-name", volinfo.Name).Info("new volume created")
events.Broadcast(newVolumeEvent(eventVolumeCreated, volinfo))
events.Broadcast(volume.NewEvent(volume.EventVolumeCreated, volinfo))

resp := createVolumeCreateResp(volinfo)
restutils.SendHTTPResponse(ctx, w, http.StatusCreated, resp)
Expand Down
2 changes: 1 addition & 1 deletion glusterd2/commands/volumes/volume-delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func volumeDeleteHandler(w http.ResponseWriter, r *http.Request) {
}

logger.WithField("volume-name", volinfo.Name).Info("volume deleted")
events.Broadcast(newVolumeEvent(eventVolumeDeleted, volinfo))
events.Broadcast(volume.NewEvent(volume.EventVolumeDeleted, volinfo))

restutils.SendHTTPResponse(ctx, w, http.StatusOK, nil)
}
4 changes: 2 additions & 2 deletions glusterd2/commands/volumes/volume-expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func volumeExpandHandler(w http.ResponseWriter, r *http.Request) {
txn := transaction.NewTxn(ctx)
defer txn.Cleanup()

nodes, err := nodesFromVolumeExpandReq(&req)
nodes, err := req.Nodes()
if err != nil {
logger.WithError(err).Error("could not prepare node list")
restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, err)
Expand Down Expand Up @@ -170,7 +170,7 @@ func volumeExpandHandler(w http.ResponseWriter, r *http.Request) {
}

logger.WithField("volume-name", volinfo.Name).Info("volume expanded")
events.Broadcast(newVolumeEvent(eventVolumeExpanded, volinfo))
events.Broadcast(volume.NewEvent(volume.EventVolumeExpanded, volinfo))

resp := createVolumeExpandResp(volinfo)
restutils.SendHTTPResponse(ctx, w, http.StatusOK, resp)
Expand Down
2 changes: 1 addition & 1 deletion glusterd2/commands/volumes/volume-start.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func volumeStartHandler(w http.ResponseWriter, r *http.Request) {
}

logger.WithField("volume-name", volinfo.Name).Info("volume started")
events.Broadcast(newVolumeEvent(eventVolumeStarted, volinfo))
events.Broadcast(volume.NewEvent(volume.EventVolumeStarted, volinfo))

resp := createVolumeStartResp(volinfo)
restutils.SendHTTPResponse(ctx, w, http.StatusOK, resp)
Expand Down
2 changes: 1 addition & 1 deletion glusterd2/commands/volumes/volume-stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func volumeStopHandler(w http.ResponseWriter, r *http.Request) {
}

logger.WithField("volume-name", volinfo.Name).Info("volume stopped")
events.Broadcast(newVolumeEvent(eventVolumeStopped, volinfo))
events.Broadcast(volume.NewEvent(volume.EventVolumeStopped, volinfo))

resp := createVolumeStopResp(volinfo)
restutils.SendHTTPResponse(ctx, w, http.StatusOK, resp)
Expand Down
32 changes: 32 additions & 0 deletions glusterd2/volume/events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package volume

import (
"github.com/gluster/glusterd2/glusterd2/events"
"github.com/gluster/glusterd2/pkg/api"
)

// Event represents Volume life cycle events
type Event string

const (
// EventVolumeCreated represents Volume Create event
EventVolumeCreated Event = "volume.created"
// EventVolumeExpanded represents Volume Expand event
EventVolumeExpanded = "volume.expanded"
// EventVolumeStarted represents Volume Start event
EventVolumeStarted = "volume.started"
// EventVolumeStopped represents Volume Stop event
EventVolumeStopped = "volume.stopped"
// EventVolumeDeleted represents Volume Delete event
EventVolumeDeleted = "volume.deleted"
)

// NewEvent adds required details to event based on Volume info
func NewEvent(e Event, v *Volinfo) *api.Event {
data := map[string]string{
"volume.name": v.Name,
"volume.id": v.ID.String(),
}

return events.New(string(e), data, true)
}
14 changes: 14 additions & 0 deletions glusterd2/volume/volume-utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ import (
log "github.com/sirupsen/logrus"
)

// GetRedundancy calculates redundancy count based on disperse count
func GetRedundancy(disperse uint) int {
var temp, l, mask uint
temp = disperse
for temp = temp >> 1; temp != 0; temp = temp >> 1 {
l = l + 1
}
mask = ^(1 << l)
if red := disperse & mask; red != 0 {
return int(red)
}
return 1
}

// isBrickPathAvailable validates whether the brick is consumed by other
// volume
func isBrickPathAvailable(peerID uuid.UUID, brickPath string) error {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package volumecommands
package api

import (
"fmt"

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

"github.com/pborman/uuid"
)

func nodesFromVolumeCreateReq(req *api.VolCreateReq) ([]uuid.UUID, error) {
// Nodes extracts the list of nodes from Volume Create request
func (req *VolCreateReq) Nodes() ([]uuid.UUID, error) {
var nodesMap = make(map[string]bool)
var nodes []uuid.UUID
for _, subvol := range req.Subvols {
Expand All @@ -26,7 +25,8 @@ func nodesFromVolumeCreateReq(req *api.VolCreateReq) ([]uuid.UUID, error) {
return nodes, nil
}

func nodesFromVolumeExpandReq(req *api.VolExpandReq) ([]uuid.UUID, error) {
// Nodes extracts list of Peer IDs from Volume Expand request
func (req *VolExpandReq) Nodes() ([]uuid.UUID, error) {
var nodesMap = make(map[string]bool)
var nodes []uuid.UUID
for _, brick := range req.Bricks {
Expand Down
8 changes: 6 additions & 2 deletions plugins/device/api/resp.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import (

// Info represents structure in which devices are to be store in Peer Metadata
type Info struct {
Name string `json:"name"`
State string `json:"state"`
Name string `json:"name"`
State string `json:"state"`
VgName string `json:"vg-name"`
AvailableSize uint64 `json:"available-size"`
ExtentSize uint64 `json:"extent-size"`
Used bool `json:"used"`
}

// AddDeviceResp is the success response sent to a AddDeviceReq request
Expand Down
168 changes: 168 additions & 0 deletions plugins/device/deviceutils/fstab.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package deviceutils

import (
"errors"
"fmt"
"io/ioutil"
"os"
"strings"
"syscall"
)

// FstabMount represents entry in Fstab file
type FstabMount struct {
Device string
MountPoint string
FilesystemFormat string
MountOptions string
DumpValue string
FsckOption string
}

// Fstab represents Fstab entries
type Fstab struct {
Filename string
Mounts []FstabMount
}

func lock(filename string) (*os.File, error) {
lockfile, err := os.Create(filename + ".lock")
if err != nil {
return nil, err
}

err = syscall.Flock(int(lockfile.Fd()), syscall.LOCK_EX)
if err != nil {
return nil, err
}
return lockfile, nil
}

func (f *Fstab) save() error {
data := "\n"
for _, mnt := range f.Mounts {
data += fmt.Sprintf("%s %s %s %s %s %s\n",
mnt.Device,
mnt.MountPoint,
mnt.FilesystemFormat,
mnt.MountOptions,
mnt.DumpValue,
mnt.FsckOption,
)
}
err := ioutil.WriteFile(f.Filename+".tmp", []byte(data), 0600)
if err != nil {
return err
}
return os.Rename(f.Filename+".tmp", f.Filename)
}

func (f *Fstab) load() error {
out, err := ioutil.ReadFile(f.Filename)
if os.IsNotExist(err) {
return nil
}

if err != nil {
return err
}
lines := strings.Split(string(out), "\n")
for _, line := range lines {
if line == "" || strings.HasPrefix(line, "#") {
continue
}

var parts []string
for _, p := range strings.Split(line, " ") {
if p != "" {
parts = append(parts, p)
}
}

if len(parts) != 6 {
return errors.New("Invalid mount entry: " + line)
}
f.Mounts = append(f.Mounts, FstabMount{
Device: parts[0],
MountPoint: parts[1],
FilesystemFormat: parts[2],
MountOptions: parts[3],
DumpValue: parts[4],
FsckOption: parts[5],
})
}
return nil
}

func (f *Fstab) mountExists(mountpoint string) bool {
for _, mnt := range f.Mounts {
if mnt.MountPoint == mountpoint {
return true
}
}
return false
}

// FstabAddMount adds mount point entry to fstab
func FstabAddMount(filename string, mnt FstabMount) error {
fstab := Fstab{Filename: filename}

file, err := lock(fstab.Filename)
if err != nil {
return err
}

defer file.Close()

err = fstab.load()
if err != nil {
return err
}

if mnt.FilesystemFormat == "" {
mnt.FilesystemFormat = "xfs"
}

if mnt.DumpValue == "" {
mnt.DumpValue = "0"
}

if mnt.FsckOption == "" {
mnt.FsckOption = "0"
}

if mnt.MountOptions == "" {
mnt.MountOptions = "defaults"
}

if !fstab.mountExists(mnt.MountPoint) {
fstab.Mounts = append(fstab.Mounts, mnt)
}
return fstab.save()
}

// FstabRemoveMount removes mountpoint from fstab
func FstabRemoveMount(filename, mountpoint string) error {
fstab := Fstab{Filename: filename}
file, err := lock(fstab.Filename)
if err != nil {
return err
}

defer file.Close()

err = fstab.load()
if err != nil {
return err
}

var mounts []FstabMount
for _, mnt := range fstab.Mounts {
if mnt.MountPoint != mountpoint {
mounts = append(mounts, mnt)
}
}
fstab.Mounts = mounts

return fstab.save()
}
Loading