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

Commit 599085b

Browse files
committed
Merge branch 'master' of https://github.com/gluster/glusterd2 into rebalance
2 parents 68f8011 + 94b631c commit 599085b

File tree

17 files changed

+426
-111
lines changed

17 files changed

+426
-111
lines changed

e2e/glustershd_test.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/stretchr/testify/require"
1010
)
1111

12-
func TestSelfHealInfo(t *testing.T) {
12+
func TestSelfHeal(t *testing.T) {
1313
r := require.New(t)
1414

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

58+
var optionReq api.VolOptionReq
59+
60+
optionReq.Options = map[string]string{"replicate.self-heal-daemon": "on"}
61+
optionReq.Advanced = true
62+
63+
r.Nil(client.VolumeSet(vol1.Name, optionReq))
64+
r.Nil(client.SelfHeal(vol1.Name, "index"))
65+
r.Nil(client.SelfHeal(vol1.Name, "full"))
66+
5867
// Stop Volume
5968
r.Nil(client.VolumeStop(vol1.Name), "Volume stop failed")
6069
// delete volume
61-
err = client.VolumeDelete(vol1.Name)
62-
r.Nil(err)
70+
r.Nil(client.VolumeDelete(vol1.Name))
6371
}

glustercli/cmd/glustershd.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ func init() {
2626
selfHealInfoCmd.Flags().BoolVar(&flagSummaryInfo, "info-summary", false, "Heal Info Summary")
2727
selfHealInfoCmd.Flags().BoolVar(&flagSplitBrainInfo, "split-brain-info", false, "Heal Split Brain Info")
2828
selfHealCmd.AddCommand(selfHealInfoCmd)
29+
selfHealCmd.AddCommand(selfHealIndexCmd)
30+
selfHealCmd.AddCommand(selfHealFullCmd)
2931

3032
volumeCmd.AddCommand(selfHealCmd)
3133
}
@@ -82,3 +84,35 @@ var selfHealInfoCmd = &cobra.Command{
8284
}
8385
},
8486
}
87+
88+
var selfHealIndexCmd = &cobra.Command{
89+
Use: "index <volname>",
90+
Short: "Index Heal",
91+
Long: "CLI command to trigger index heal on a volume",
92+
Args: cobra.ExactArgs(1),
93+
Run: func(cmd *cobra.Command, args []string) {
94+
var err error
95+
volname := args[0]
96+
err = client.SelfHeal(volname, "index")
97+
if err != nil {
98+
failure(fmt.Sprintf("Failed to run heal for volume %s\n", volname), err, 1)
99+
}
100+
fmt.Println("Heal on volume has been successfully launched. Use heal info to check status")
101+
},
102+
}
103+
104+
var selfHealFullCmd = &cobra.Command{
105+
Use: "full <volname>",
106+
Short: "Full Heal",
107+
Long: "CLI command to trigger full heal on a volume",
108+
Args: cobra.ExactArgs(1),
109+
Run: func(cmd *cobra.Command, args []string) {
110+
var err error
111+
volname := args[0]
112+
err = client.SelfHeal(volname, "full")
113+
if err != nil {
114+
failure(fmt.Sprintf("Failed to run heal for volume %s\n", volname), err, 1)
115+
}
116+
fmt.Println("Heal on volume has been successfully launched. Use heal info to check status")
117+
},
118+
}

glusterd2/commands/volumes/grouped-options.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ var defaultGroupOptions = map[string]*api.OptionGroup{
129129
{Name: "features.shard", OnValue: "on"},
130130
{Name: "user.cifs", OnValue: "off"}},
131131
"Enable this profile, if the Gluster Volume is used to store virtual machines"},
132+
"tls": {"tls",
133+
[]api.VolumeOption{
134+
{Name: "server.transport.socket.ssl-enabled", OnValue: "on"},
135+
{Name: "client.transport.socket.ssl-enabled", OnValue: "on"},
136+
},
137+
"Enable TLS for the volume for both bricks and clients"},
132138
"profile.test": {"profile.test",
133139
[]api.VolumeOption{{Name: "afr.eager-lock", OnValue: "on"},
134140
{Name: "gfproxy.afr.eager-lock", OnValue: "on"}},

glusterd2/commands/volumes/volume-option.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,16 @@ func optionSetValidate(c transaction.TxnCtx) error {
3535
// validateOptions.
3636

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

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

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

5050
for k, v := range options {

glusterd2/xlator/global.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func Load() (err error) {
3535
}
3636
xlMap = xls
3737

38+
injectTransportOptions()
3839
loadOptions()
3940
return
4041
}
@@ -57,3 +58,37 @@ func loadOptions() {
5758
}
5859
}
5960
}
61+
62+
// injectTransportOptions injects options present in transport layer (socket.so
63+
// and rdma.so) into list of options loaded from protocol layer (server.so and
64+
// client.so)
65+
func injectTransportOptions() {
66+
67+
var transportNames = [...]string{"socket", "rdma"}
68+
transports := make([]*Xlator, 0, 2)
69+
for _, name := range transportNames {
70+
if xl, ok := xlMap[name]; ok {
71+
transports = append(transports, xl)
72+
}
73+
}
74+
75+
if len(transports) == 0 {
76+
panic("socket.so or rdma.so not found. Please install glusterfs-server package")
77+
}
78+
79+
for _, transport := range transports {
80+
for _, option := range transport.Options {
81+
// TODO:
82+
// remove this once proper settable flags are set for
83+
// these transport options in glusterfs source
84+
option.Flags = option.Flags | options.OptionFlagSettable
85+
if xl, ok := xlMap["server"]; ok {
86+
xl.Options = append(xl.Options, option)
87+
}
88+
if xl, ok := xlMap["client"]; ok {
89+
option.Flags = option.Flags | options.OptionFlagClientOpt
90+
xl.Options = append(xl.Options, option)
91+
}
92+
}
93+
}
94+
}

glusterd2/xlator/load.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ func structifyOption(cOpt *C.volume_option_t) *options.Option {
6666
opt.SetKey = C.GoString(cOpt.setkey)
6767
opt.Level = options.OptionLevel(cOpt.level)
6868

69+
// For boolean options, default value isn't set in xlator's option
70+
// table as glusterfs code treats that case as false by default.
71+
if opt.Type == options.OptionTypeBool && opt.DefaultValue == "" {
72+
opt.DefaultValue = "off"
73+
}
74+
6975
return &opt
7076
}
7177

glusterd2/xlator/options/options.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -247,16 +247,17 @@ func ValidateInternetAddress(o *Option, val string) error {
247247
if len(val) == 0 {
248248
return ErrInvalidArg
249249
}
250-
if !(validate.IsHost(val)) {
251-
return ErrInvalidArg
252-
} else if !(validate.IsIP(val)) {
253-
return ErrInvalidArg
254-
} else if !(validate.IsCIDR(val)) {
255-
return ErrInvalidArg
256-
} else if !(strings.ContainsAny(val, "* & # & ? & ^")) {
257-
return ErrInvalidArg
250+
if validate.IsHost(val) {
251+
return nil
252+
} else if validate.IsIP(val) {
253+
return nil
254+
} else if validate.IsCIDR(val) {
255+
return nil
256+
} else if strings.ContainsAny(val, "* & # & ? & ^") {
257+
return nil
258258
}
259-
return nil
259+
260+
return ErrInvalidArg
260261
}
261262

262263
// ValidateInternetAddressList validates the Internet Address List

glusterd2/xlator/options/utils.go

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,51 @@ package options
33
import (
44
"fmt"
55
"strings"
6+
7+
"github.com/gluster/glusterd2/pkg/utils"
68
)
79

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

1113
func (e InvalidKeyError) Error() string {
12-
return fmt.Sprintf("option key not in <graph>.<xlator>.<name> form: %s", string(e))
14+
return fmt.Sprintf("option key not in [<graph>.]<xlator>.<option-name> form: %s", string(e))
15+
}
16+
17+
var validGraphs = [...]string{
18+
"brick",
19+
"fuse",
20+
"gfproxy",
21+
"nfs",
1322
}
1423

1524
// SplitKey returns three strings by breaking key of the form
16-
// [<graph>].<xlator>.<name> into its constituents. <graph> is optional.
25+
// [<graph>].<xlator>.<option-name> into its constituents. <graph> is optional.
1726
// Returns an InvalidKeyError if key is not of correcf form.
1827
func SplitKey(k string) (string, string, string, error) {
28+
var graph, xlator, optName string
29+
1930
tmp := strings.Split(strings.TrimSpace(k), ".")
20-
switch len(tmp) {
21-
case 2:
22-
return "", tmp[0], tmp[1], nil
23-
case 3:
24-
return tmp[0], tmp[1], tmp[2], nil
25-
default:
26-
return "", "", "", InvalidKeyError(k)
31+
if len(tmp) < 2 {
32+
// must at least be of the form <xlator>.<name>
33+
return graph, xlator, optName, InvalidKeyError(k)
2734
}
35+
36+
if utils.StringInSlice(tmp[0], validGraphs[:]) {
37+
// valid graph present
38+
if len(tmp) < 3 {
39+
// must be of the form <graph>.<xlator>.<name>
40+
return graph, xlator, optName, InvalidKeyError(k)
41+
}
42+
graph = tmp[0]
43+
xlator = tmp[1]
44+
optName = strings.Join(tmp[2:], ".")
45+
} else {
46+
// key is of the format <xlator>.<name> where <name> itself
47+
// may contain dots. For example: transport.socket.ssl-enabled
48+
xlator = tmp[0]
49+
optName = k[len(xlator)+1:]
50+
}
51+
52+
return graph, xlator, optName, nil
2853
}

pkg/restclient/glustershd.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,18 @@ func (c *Client) SelfHealInfo(params ...string) ([]glustershdapi.BrickHealInfo,
2222
err := c.get(url, nil, http.StatusOK, &output)
2323
return output, err
2424
}
25+
26+
// SelfHeal sends request to start the heal process on the specified volname
27+
func (c *Client) SelfHeal(volname string, healType string) error {
28+
var url string
29+
switch healType {
30+
case "index":
31+
url = fmt.Sprintf("/v1/volumes/%s/heal", volname)
32+
case "full":
33+
url = fmt.Sprintf("/v1/volumes/%s/heal?type=%s", volname, healType)
34+
default:
35+
return errors.New("invalid parameters")
36+
}
37+
38+
return c.post(url, nil, http.StatusOK, nil)
39+
}

plugins/dht/validate.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,13 @@ import (
1010

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

13-
func validateOptions(v *volume.Volinfo, key string, value string) error {
14-
var err error
13+
func validateOptions(v *volume.Volinfo, key, value string) error {
1514
if strings.Contains(key, "readdirplus-for-dir") {
1615
if value == "on" {
17-
val, exists := v.Options["features.cache-invalidation"]
18-
if exists && val == "on" {
16+
if v, ok := v.Options["features.cache-invalidation"]; ok && v == "on" {
1917
return nil
2018
}
21-
err = fmt.Errorf("Enable \"features.cache-invalidation\" before enabling %s",
22-
key)
23-
return err
19+
return fmt.Errorf("Enable \"features.cache-invalidation\" before enabling %s", key)
2420
}
2521
}
2622
return nil

0 commit comments

Comments
 (0)