diff --git a/pkg/volume/glusterfs/glusterfs.go b/pkg/volume/glusterfs/glusterfs.go index 732d9e9630..28a7104aa1 100644 --- a/pkg/volume/glusterfs/glusterfs.go +++ b/pkg/volume/glusterfs/glusterfs.go @@ -397,18 +397,19 @@ func (plugin *glusterfsPlugin) newProvisionerInternal(options volume.VolumeOptio } type provisionerConfig struct { - url string - user string - userKey string - secretNamespace string - secretName string - secretValue string - clusterID string - gidMin int - gidMax int - volumeType gapi.VolumeDurabilityInfo - volumeOptions []string - volumeNamePrefix string + url string + user string + userKey string + secretNamespace string + secretName string + secretValue string + clusterID string + gidMin int + gidMax int + volumeType gapi.VolumeDurabilityInfo + volumeOptions []string + volumeNamePrefix string + thinPoolSnapFactor float32 } type glusterfsVolumeProvisioner struct { @@ -760,7 +761,15 @@ func (p *glusterfsVolumeProvisioner) CreateVolume(gid int) (r *v1.GlusterfsVolum } gid64 := int64(gid) - volumeReq := &gapi.VolumeCreateRequest{Size: sz, Name: customVolumeName, Clusters: clusterIDs, Gid: gid64, Durability: p.volumeType, GlusterVolumeOptions: p.volumeOptions} + snaps := struct { + Enable bool `json:"enable"` + Factor float32 `json:"factor"` + }{ + true, + p.provisionerConfig.thinPoolSnapFactor, + } + + volumeReq := &gapi.VolumeCreateRequest{Size: sz, Name: customVolumeName, Clusters: clusterIDs, Gid: gid64, Durability: p.volumeType, GlusterVolumeOptions: p.volumeOptions, Snapshot: snaps} volume, err := cli.VolumeCreate(volumeReq) if err != nil { glog.Errorf("failed to create volume: %v", err) @@ -927,6 +936,10 @@ func parseClassParameters(params map[string]string, kubeClient clientset.Interfa parseVolumeType := "" parseVolumeOptions := "" parseVolumeNamePrefix := "" + parseThinPoolSnapFactor := "" + + //thin pool snap factor default to 1.0 + cfg.thinPoolSnapFactor = float32(1.0) for k, v := range params { switch dstrings.ToLower(k) { @@ -981,6 +994,11 @@ func parseClassParameters(params map[string]string, kubeClient clientset.Interfa if len(v) != 0 { parseVolumeNamePrefix = v } + case "snapfactor": + if len(v) != 0 { + parseThinPoolSnapFactor = v + } + default: return nil, fmt.Errorf("invalid option %q for volume plugin %s", k, glusterfsPluginName) } @@ -1068,6 +1086,17 @@ func parseClassParameters(params map[string]string, kubeClient clientset.Interfa } cfg.volumeNamePrefix = parseVolumeNamePrefix } + + if len(parseThinPoolSnapFactor) != 0 { + thinPoolSnapFactor, err := strconv.ParseFloat(parseThinPoolSnapFactor, 32) + if err != nil { + return nil, fmt.Errorf("failed to convert snapfactor %v to float: %v", parseThinPoolSnapFactor, err) + } + if thinPoolSnapFactor < 1.0 || thinPoolSnapFactor > 100.0 { + return nil, fmt.Errorf("invalid snapshot factor %v, the value must be between 1 to 100", thinPoolSnapFactor) + } + cfg.thinPoolSnapFactor = float32(thinPoolSnapFactor) + } return &cfg, nil } diff --git a/pkg/volume/glusterfs/glusterfs_test.go b/pkg/volume/glusterfs/glusterfs_test.go index 8c25a07158..266e69bda5 100644 --- a/pkg/volume/glusterfs/glusterfs_test.go +++ b/pkg/volume/glusterfs/glusterfs_test.go @@ -253,13 +253,14 @@ func TestParseClassParameters(t *testing.T) { nil, // secret false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - user: "admin", - userKey: "password", - secretValue: "password", - gidMin: 2000, - gidMax: 2147483647, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + user: "admin", + userKey: "password", + secretValue: "password", + gidMin: 2000, + gidMax: 2147483647, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, { @@ -273,14 +274,15 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - user: "admin", - secretName: "mysecret", - secretNamespace: "default", - secretValue: "mypassword", - gidMin: 2000, - gidMax: 2147483647, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + user: "admin", + secretName: "mysecret", + secretNamespace: "default", + secretValue: "mypassword", + gidMin: 2000, + gidMax: 2147483647, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, { @@ -292,10 +294,11 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 2000, - gidMax: 2147483647, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + gidMin: 2000, + gidMax: 2147483647, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, { @@ -429,10 +432,11 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 4000, - gidMax: 2147483647, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + gidMin: 4000, + gidMax: 2147483647, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, { @@ -445,10 +449,11 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 2000, - gidMax: 5000, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + gidMin: 2000, + gidMax: 5000, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, { @@ -462,10 +467,11 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 4000, - gidMax: 5000, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + gidMin: 4000, + gidMax: 5000, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, @@ -481,10 +487,11 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 4000, - gidMax: 5000, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 4}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + gidMin: 4000, + gidMax: 5000, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 4}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, @@ -500,10 +507,31 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 4000, - gidMax: 5000, - volumeType: gapi.VolumeDurabilityInfo{Type: "disperse", Replicate: gapi.ReplicaDurability{Replica: 0}, Disperse: gapi.DisperseDurability{Data: 4, Redundancy: 2}}, + url: "https://localhost:8080", + gidMin: 4000, + gidMax: 5000, + volumeType: gapi.VolumeDurabilityInfo{Type: "disperse", Replicate: gapi.ReplicaDurability{Replica: 0}, Disperse: gapi.DisperseDurability{Data: 4, Redundancy: 2}}, + thinPoolSnapFactor: float32(1.0), + }, + }, + { + "valid snapfactor: 50", + map[string]string{ + "resturl": "https://localhost:8080", + "restauthenabled": "false", + "gidMin": "4000", + "gidMax": "5000", + "volumetype": "disperse:4:2", + "snapfactor": "50", + }, + &secret, + false, // expect error + &provisionerConfig{ + url: "https://localhost:8080", + gidMin: 4000, + gidMax: 5000, + volumeType: gapi.VolumeDurabilityInfo{Type: "disperse", Replicate: gapi.ReplicaDurability{Replica: 0}, Disperse: gapi.DisperseDurability{Data: 4, Redundancy: 2}}, + thinPoolSnapFactor: float32(50), }, }, { @@ -550,6 +578,28 @@ func TestParseClassParameters(t *testing.T) { true, // expect error nil, }, + { + "invalid thinPoolSnapFactor: value out of range", + map[string]string{ + "resturl": "https://localhost:8080", + "restauthenabled": "false", + "snapfactor": "0.5", + }, + &secret, + true, // expect error + nil, + }, + { + "invalid thinPoolSnapFactor: value out of range", + map[string]string{ + "resturl": "https://localhost:8080", + "restauthenabled": "false", + "snapfactor": "120", + }, + &secret, + true, // expect error + nil, + }, } for _, test := range tests {