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

Commit

Permalink
Merge branch 'master' of https://github.com/gluster/glusterd2 into re…
Browse files Browse the repository at this point in the history
…balance
  • Loading branch information
rishubhjain committed Jul 13, 2018
2 parents 68f8011 + 94b631c commit 599085b
Show file tree
Hide file tree
Showing 17 changed files with 426 additions and 111 deletions.
14 changes: 11 additions & 3 deletions e2e/glustershd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/require"
)

func TestSelfHealInfo(t *testing.T) {
func TestSelfHeal(t *testing.T) {
r := require.New(t)

gds, err := setupCluster("./config/1.toml")
Expand Down Expand Up @@ -55,9 +55,17 @@ func TestSelfHealInfo(t *testing.T) {
_, err = client.SelfHealInfo(vol1.Name, "split-brain-info")
r.Nil(err)

var optionReq api.VolOptionReq

optionReq.Options = map[string]string{"replicate.self-heal-daemon": "on"}
optionReq.Advanced = true

r.Nil(client.VolumeSet(vol1.Name, optionReq))
r.Nil(client.SelfHeal(vol1.Name, "index"))
r.Nil(client.SelfHeal(vol1.Name, "full"))

// Stop Volume
r.Nil(client.VolumeStop(vol1.Name), "Volume stop failed")
// delete volume
err = client.VolumeDelete(vol1.Name)
r.Nil(err)
r.Nil(client.VolumeDelete(vol1.Name))
}
34 changes: 34 additions & 0 deletions glustercli/cmd/glustershd.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ func init() {
selfHealInfoCmd.Flags().BoolVar(&flagSummaryInfo, "info-summary", false, "Heal Info Summary")
selfHealInfoCmd.Flags().BoolVar(&flagSplitBrainInfo, "split-brain-info", false, "Heal Split Brain Info")
selfHealCmd.AddCommand(selfHealInfoCmd)
selfHealCmd.AddCommand(selfHealIndexCmd)
selfHealCmd.AddCommand(selfHealFullCmd)

volumeCmd.AddCommand(selfHealCmd)
}
Expand Down Expand Up @@ -82,3 +84,35 @@ var selfHealInfoCmd = &cobra.Command{
}
},
}

var selfHealIndexCmd = &cobra.Command{
Use: "index <volname>",
Short: "Index Heal",
Long: "CLI command to trigger index heal on a volume",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
var err error
volname := args[0]
err = client.SelfHeal(volname, "index")
if err != nil {
failure(fmt.Sprintf("Failed to run heal for volume %s\n", volname), err, 1)
}
fmt.Println("Heal on volume has been successfully launched. Use heal info to check status")
},
}

var selfHealFullCmd = &cobra.Command{
Use: "full <volname>",
Short: "Full Heal",
Long: "CLI command to trigger full heal on a volume",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
var err error
volname := args[0]
err = client.SelfHeal(volname, "full")
if err != nil {
failure(fmt.Sprintf("Failed to run heal for volume %s\n", volname), err, 1)
}
fmt.Println("Heal on volume has been successfully launched. Use heal info to check status")
},
}
6 changes: 6 additions & 0 deletions glusterd2/commands/volumes/grouped-options.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ var defaultGroupOptions = map[string]*api.OptionGroup{
{Name: "features.shard", OnValue: "on"},
{Name: "user.cifs", OnValue: "off"}},
"Enable this profile, if the Gluster Volume is used to store virtual machines"},
"tls": {"tls",
[]api.VolumeOption{
{Name: "server.transport.socket.ssl-enabled", OnValue: "on"},
{Name: "client.transport.socket.ssl-enabled", OnValue: "on"},
},
"Enable TLS for the volume for both bricks and clients"},
"profile.test": {"profile.test",
[]api.VolumeOption{{Name: "afr.eager-lock", OnValue: "on"},
{Name: "gfproxy.afr.eager-lock", OnValue: "on"}},
Expand Down
6 changes: 3 additions & 3 deletions glusterd2/commands/volumes/volume-option.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@ func optionSetValidate(c transaction.TxnCtx) error {
// validateOptions.

if err := validateOptions(options, req.Advanced, req.Experimental, req.Deprecated); err != nil {
return fmt.Errorf("Validation failed for volume option: %s", err.Error())
return fmt.Errorf("validation failed for volume option: %s", err.Error())
}

var volinfo volume.Volinfo
if err := c.Get("volinfo", &volinfo); err != nil {
return err
}

if err := validateXlatorOptions(req.Options, &volinfo); err != nil {
return fmt.Errorf("Validation failed for volume option:: %s", err.Error())
if err := validateXlatorOptions(options, &volinfo); err != nil {
return fmt.Errorf("validation failed for volume option:: %s", err.Error())
}

for k, v := range options {
Expand Down
35 changes: 35 additions & 0 deletions glusterd2/xlator/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func Load() (err error) {
}
xlMap = xls

injectTransportOptions()
loadOptions()
return
}
Expand All @@ -57,3 +58,37 @@ func loadOptions() {
}
}
}

// injectTransportOptions injects options present in transport layer (socket.so
// and rdma.so) into list of options loaded from protocol layer (server.so and
// client.so)
func injectTransportOptions() {

var transportNames = [...]string{"socket", "rdma"}
transports := make([]*Xlator, 0, 2)
for _, name := range transportNames {
if xl, ok := xlMap[name]; ok {
transports = append(transports, xl)
}
}

if len(transports) == 0 {
panic("socket.so or rdma.so not found. Please install glusterfs-server package")
}

for _, transport := range transports {
for _, option := range transport.Options {
// TODO:
// remove this once proper settable flags are set for
// these transport options in glusterfs source
option.Flags = option.Flags | options.OptionFlagSettable
if xl, ok := xlMap["server"]; ok {
xl.Options = append(xl.Options, option)
}
if xl, ok := xlMap["client"]; ok {
option.Flags = option.Flags | options.OptionFlagClientOpt
xl.Options = append(xl.Options, option)
}
}
}
}
6 changes: 6 additions & 0 deletions glusterd2/xlator/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ func structifyOption(cOpt *C.volume_option_t) *options.Option {
opt.SetKey = C.GoString(cOpt.setkey)
opt.Level = options.OptionLevel(cOpt.level)

// For boolean options, default value isn't set in xlator's option
// table as glusterfs code treats that case as false by default.
if opt.Type == options.OptionTypeBool && opt.DefaultValue == "" {
opt.DefaultValue = "off"
}

return &opt
}

Expand Down
19 changes: 10 additions & 9 deletions glusterd2/xlator/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,16 +247,17 @@ func ValidateInternetAddress(o *Option, val string) error {
if len(val) == 0 {
return ErrInvalidArg
}
if !(validate.IsHost(val)) {
return ErrInvalidArg
} else if !(validate.IsIP(val)) {
return ErrInvalidArg
} else if !(validate.IsCIDR(val)) {
return ErrInvalidArg
} else if !(strings.ContainsAny(val, "* & # & ? & ^")) {
return ErrInvalidArg
if validate.IsHost(val) {
return nil
} else if validate.IsIP(val) {
return nil
} else if validate.IsCIDR(val) {
return nil
} else if strings.ContainsAny(val, "* & # & ? & ^") {
return nil
}
return nil

return ErrInvalidArg
}

// ValidateInternetAddressList validates the Internet Address List
Expand Down
43 changes: 34 additions & 9 deletions glusterd2/xlator/options/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,51 @@ package options
import (
"fmt"
"strings"

"github.com/gluster/glusterd2/pkg/utils"
)

// InvalidKeyError is returned by SplitKey if key is not of the correct form.
type InvalidKeyError string

func (e InvalidKeyError) Error() string {
return fmt.Sprintf("option key not in <graph>.<xlator>.<name> form: %s", string(e))
return fmt.Sprintf("option key not in [<graph>.]<xlator>.<option-name> form: %s", string(e))
}

var validGraphs = [...]string{
"brick",
"fuse",
"gfproxy",
"nfs",
}

// SplitKey returns three strings by breaking key of the form
// [<graph>].<xlator>.<name> into its constituents. <graph> is optional.
// [<graph>].<xlator>.<option-name> into its constituents. <graph> is optional.
// Returns an InvalidKeyError if key is not of correcf form.
func SplitKey(k string) (string, string, string, error) {
var graph, xlator, optName string

tmp := strings.Split(strings.TrimSpace(k), ".")
switch len(tmp) {
case 2:
return "", tmp[0], tmp[1], nil
case 3:
return tmp[0], tmp[1], tmp[2], nil
default:
return "", "", "", InvalidKeyError(k)
if len(tmp) < 2 {
// must at least be of the form <xlator>.<name>
return graph, xlator, optName, InvalidKeyError(k)
}

if utils.StringInSlice(tmp[0], validGraphs[:]) {
// valid graph present
if len(tmp) < 3 {
// must be of the form <graph>.<xlator>.<name>
return graph, xlator, optName, InvalidKeyError(k)
}
graph = tmp[0]
xlator = tmp[1]
optName = strings.Join(tmp[2:], ".")
} else {
// key is of the format <xlator>.<name> where <name> itself
// may contain dots. For example: transport.socket.ssl-enabled
xlator = tmp[0]
optName = k[len(xlator)+1:]
}

return graph, xlator, optName, nil
}
15 changes: 15 additions & 0 deletions pkg/restclient/glustershd.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,18 @@ func (c *Client) SelfHealInfo(params ...string) ([]glustershdapi.BrickHealInfo,
err := c.get(url, nil, http.StatusOK, &output)
return output, err
}

// SelfHeal sends request to start the heal process on the specified volname
func (c *Client) SelfHeal(volname string, healType string) error {
var url string
switch healType {
case "index":
url = fmt.Sprintf("/v1/volumes/%s/heal", volname)
case "full":
url = fmt.Sprintf("/v1/volumes/%s/heal?type=%s", volname, healType)
default:
return errors.New("invalid parameters")
}

return c.post(url, nil, http.StatusOK, nil)
}
10 changes: 3 additions & 7 deletions plugins/dht/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,13 @@ import (

var names = [...]string{"distribute", "dht"}

func validateOptions(v *volume.Volinfo, key string, value string) error {
var err error
func validateOptions(v *volume.Volinfo, key, value string) error {
if strings.Contains(key, "readdirplus-for-dir") {
if value == "on" {
val, exists := v.Options["features.cache-invalidation"]
if exists && val == "on" {
if v, ok := v.Options["features.cache-invalidation"]; ok && v == "on" {
return nil
}
err = fmt.Errorf("Enable \"features.cache-invalidation\" before enabling %s",
key)
return err
return fmt.Errorf("Enable \"features.cache-invalidation\" before enabling %s", key)
}
}
return nil
Expand Down
Loading

0 comments on commit 599085b

Please sign in to comment.