Commit bdb051c7 authored by Humble Chirammal's avatar Humble Chirammal

Refactor GlusterFS PV spec.

This patch introduces glusterfsPersistentVolumeSource addition to glusterfsVolumeSource. All fields remains same as glusterfsVolumeSource with an addition of a new field called `EndpointsNamespace` to define namespace of endpoint in the spec. Signed-off-by: 's avatarHumble Chirammal <hchiramm@redhat.com>
parent 808557e4
......@@ -4,6 +4,7 @@ API rule violation: names_match,k8s.io/api/core/v1,ContainerStatus,LastTerminati
API rule violation: names_match,k8s.io/api/core/v1,DaemonEndpoint,Port
API rule violation: names_match,k8s.io/api/core/v1,Event,ReportingController
API rule violation: names_match,k8s.io/api/core/v1,FCVolumeSource,WWIDs
API rule violation: names_match,k8s.io/api/core/v1,GlusterfsPersistentVolumeSource,EndpointsName
API rule violation: names_match,k8s.io/api/core/v1,GlusterfsVolumeSource,EndpointsName
API rule violation: names_match,k8s.io/api/core/v1,ISCSIPersistentVolumeSource,DiscoveryCHAPAuth
API rule violation: names_match,k8s.io/api/core/v1,ISCSIPersistentVolumeSource,SessionCHAPAuth
......
......@@ -84125,6 +84125,31 @@
}
}
},
"io.k8s.api.core.v1.GlusterfsPersistentVolumeSource": {
"description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"required": [
"endpoints",
"path"
],
"properties": {
"endpoints": {
"description": "EndpointsName is the endpoint name that details Glusterfs topology. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"type": "string"
},
"endpointsNamespace": {
"description": "EndpointsNamespace is the namespace that contains Glusterfs endpoint. If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"type": "string"
},
"path": {
"description": "Path is the Glusterfs volume path. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"type": "string"
},
"readOnly": {
"description": "ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"type": "boolean"
}
}
},
"io.k8s.api.core.v1.GlusterfsVolumeSource": {
"description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"required": [
......@@ -85424,7 +85449,7 @@
},
"glusterfs": {
"description": "Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md",
"$ref": "#/definitions/io.k8s.api.core.v1.GlusterfsVolumeSource"
"$ref": "#/definitions/io.k8s.api.core.v1.GlusterfsPersistentVolumeSource"
},
"hostPath": {
"description": "HostPath represents a directory on the host. Provisioned by a developer or tester. This is useful for single-node development and testing only! On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath",
......@@ -20217,7 +20217,7 @@
"description": "HostPath represents a directory on the host. Provisioned by a developer or tester. This is useful for single-node development and testing only! On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
},
"glusterfs": {
"$ref": "v1.GlusterfsVolumeSource",
"$ref": "v1.GlusterfsPersistentVolumeSource",
"description": "Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md"
},
"nfs": {
......@@ -20401,8 +20401,8 @@
"id": "v1.HostPathType",
"properties": {}
},
"v1.GlusterfsVolumeSource": {
"id": "v1.GlusterfsVolumeSource",
"v1.GlusterfsPersistentVolumeSource": {
"id": "v1.GlusterfsPersistentVolumeSource",
"description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"required": [
"endpoints",
......@@ -20420,6 +20420,10 @@
"readOnly": {
"type": "boolean",
"description": "ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod"
},
"endpointsNamespace": {
"type": "string",
"description": "EndpointsNamespace is the namespace that contains Glusterfs endpoint. If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod"
}
}
},
......@@ -21568,6 +21572,28 @@
}
}
},
"v1.GlusterfsVolumeSource": {
"id": "v1.GlusterfsVolumeSource",
"description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"required": [
"endpoints",
"path"
],
"properties": {
"endpoints": {
"type": "string",
"description": "EndpointsName is the endpoint name that details Glusterfs topology. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod"
},
"path": {
"type": "string",
"description": "Path is the Glusterfs volume path. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod"
},
"readOnly": {
"type": "boolean",
"description": "ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod"
}
}
},
"v1.PersistentVolumeClaimVolumeSource": {
"id": "v1.PersistentVolumeClaimVolumeSource",
"description": "PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace. This volume finds the bound PV and mounts that volume for the pod. A PersistentVolumeClaimVolumeSource is, essentially, a wrapper around another type of volume that is owned by someone else (the system).",
......@@ -175,7 +175,7 @@ type PersistentVolumeSource struct {
HostPath *HostPathVolumeSource
// Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod
// +optional
Glusterfs *GlusterfsVolumeSource
Glusterfs *GlusterfsPersistentVolumeSource
// NFS represents an NFS mount on the host that shares a pod's lifetime
// +optional
NFS *NFSVolumeSource
......@@ -935,6 +935,30 @@ type GlusterfsVolumeSource struct {
ReadOnly bool
}
// Represents a Glusterfs mount that lasts the lifetime of a pod.
// Glusterfs volumes do not support ownership management or SELinux relabeling.
type GlusterfsPersistentVolumeSource struct {
// EndpointsName is the endpoint name that details Glusterfs topology.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
EndpointsName string
// Path is the Glusterfs volume path.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
Path string
// ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions.
// Defaults to false.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
ReadOnly bool
// EndpointsNamespace is the namespace that contains Glusterfs endpoint.
// If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
EndpointsNamespace *string
}
// Represents a Rados Block Device mount that lasts the lifetime of a pod.
// RBD volumes support ownership management and SELinux relabeling.
type RBDVolumeSource struct {
......
......@@ -610,6 +610,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.GlusterfsPersistentVolumeSource)(nil), (*core.GlusterfsPersistentVolumeSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_GlusterfsPersistentVolumeSource_To_core_GlusterfsPersistentVolumeSource(a.(*v1.GlusterfsPersistentVolumeSource), b.(*core.GlusterfsPersistentVolumeSource), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*core.GlusterfsPersistentVolumeSource)(nil), (*v1.GlusterfsPersistentVolumeSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_core_GlusterfsPersistentVolumeSource_To_v1_GlusterfsPersistentVolumeSource(a.(*core.GlusterfsPersistentVolumeSource), b.(*v1.GlusterfsPersistentVolumeSource), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.GlusterfsVolumeSource)(nil), (*core.GlusterfsVolumeSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_GlusterfsVolumeSource_To_core_GlusterfsVolumeSource(a.(*v1.GlusterfsVolumeSource), b.(*core.GlusterfsVolumeSource), scope)
}); err != nil {
......@@ -3602,6 +3612,32 @@ func Convert_core_GitRepoVolumeSource_To_v1_GitRepoVolumeSource(in *core.GitRepo
return autoConvert_core_GitRepoVolumeSource_To_v1_GitRepoVolumeSource(in, out, s)
}
func autoConvert_v1_GlusterfsPersistentVolumeSource_To_core_GlusterfsPersistentVolumeSource(in *v1.GlusterfsPersistentVolumeSource, out *core.GlusterfsPersistentVolumeSource, s conversion.Scope) error {
out.EndpointsName = in.EndpointsName
out.Path = in.Path
out.ReadOnly = in.ReadOnly
out.EndpointsNamespace = (*string)(unsafe.Pointer(in.EndpointsNamespace))
return nil
}
// Convert_v1_GlusterfsPersistentVolumeSource_To_core_GlusterfsPersistentVolumeSource is an autogenerated conversion function.
func Convert_v1_GlusterfsPersistentVolumeSource_To_core_GlusterfsPersistentVolumeSource(in *v1.GlusterfsPersistentVolumeSource, out *core.GlusterfsPersistentVolumeSource, s conversion.Scope) error {
return autoConvert_v1_GlusterfsPersistentVolumeSource_To_core_GlusterfsPersistentVolumeSource(in, out, s)
}
func autoConvert_core_GlusterfsPersistentVolumeSource_To_v1_GlusterfsPersistentVolumeSource(in *core.GlusterfsPersistentVolumeSource, out *v1.GlusterfsPersistentVolumeSource, s conversion.Scope) error {
out.EndpointsName = in.EndpointsName
out.Path = in.Path
out.ReadOnly = in.ReadOnly
out.EndpointsNamespace = (*string)(unsafe.Pointer(in.EndpointsNamespace))
return nil
}
// Convert_core_GlusterfsPersistentVolumeSource_To_v1_GlusterfsPersistentVolumeSource is an autogenerated conversion function.
func Convert_core_GlusterfsPersistentVolumeSource_To_v1_GlusterfsPersistentVolumeSource(in *core.GlusterfsPersistentVolumeSource, out *v1.GlusterfsPersistentVolumeSource, s conversion.Scope) error {
return autoConvert_core_GlusterfsPersistentVolumeSource_To_v1_GlusterfsPersistentVolumeSource(in, out, s)
}
func autoConvert_v1_GlusterfsVolumeSource_To_core_GlusterfsVolumeSource(in *v1.GlusterfsVolumeSource, out *core.GlusterfsVolumeSource, s conversion.Scope) error {
out.EndpointsName = in.EndpointsName
out.Path = in.Path
......@@ -4932,7 +4968,7 @@ func autoConvert_v1_PersistentVolumeSource_To_core_PersistentVolumeSource(in *v1
out.GCEPersistentDisk = (*core.GCEPersistentDiskVolumeSource)(unsafe.Pointer(in.GCEPersistentDisk))
out.AWSElasticBlockStore = (*core.AWSElasticBlockStoreVolumeSource)(unsafe.Pointer(in.AWSElasticBlockStore))
out.HostPath = (*core.HostPathVolumeSource)(unsafe.Pointer(in.HostPath))
out.Glusterfs = (*core.GlusterfsVolumeSource)(unsafe.Pointer(in.Glusterfs))
out.Glusterfs = (*core.GlusterfsPersistentVolumeSource)(unsafe.Pointer(in.Glusterfs))
out.NFS = (*core.NFSVolumeSource)(unsafe.Pointer(in.NFS))
out.RBD = (*core.RBDPersistentVolumeSource)(unsafe.Pointer(in.RBD))
out.ISCSI = (*core.ISCSIPersistentVolumeSource)(unsafe.Pointer(in.ISCSI))
......@@ -4963,7 +4999,7 @@ func autoConvert_core_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *co
out.GCEPersistentDisk = (*v1.GCEPersistentDiskVolumeSource)(unsafe.Pointer(in.GCEPersistentDisk))
out.AWSElasticBlockStore = (*v1.AWSElasticBlockStoreVolumeSource)(unsafe.Pointer(in.AWSElasticBlockStore))
out.HostPath = (*v1.HostPathVolumeSource)(unsafe.Pointer(in.HostPath))
out.Glusterfs = (*v1.GlusterfsVolumeSource)(unsafe.Pointer(in.Glusterfs))
out.Glusterfs = (*v1.GlusterfsPersistentVolumeSource)(unsafe.Pointer(in.Glusterfs))
out.NFS = (*v1.NFSVolumeSource)(unsafe.Pointer(in.NFS))
out.RBD = (*v1.RBDPersistentVolumeSource)(unsafe.Pointer(in.RBD))
out.Quobyte = (*v1.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte))
......
......@@ -903,6 +903,26 @@ func validateGlusterfsVolumeSource(glusterfs *core.GlusterfsVolumeSource, fldPat
}
return allErrs
}
func validateGlusterfsPersistentVolumeSource(glusterfs *core.GlusterfsPersistentVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(glusterfs.EndpointsName) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("endpoints"), ""))
}
if len(glusterfs.Path) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
}
if glusterfs.EndpointsNamespace != nil {
endpointNs := glusterfs.EndpointsNamespace
if *endpointNs == "" {
allErrs = append(allErrs, field.Invalid(fldPath.Child("endpointsNamespace"), *endpointNs, "if the endpointnamespace is set, it must be a valid namespace name"))
} else {
for _, msg := range ValidateNamespaceName(*endpointNs, false) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("endpointsNamespace"), *endpointNs, msg))
}
}
}
return allErrs
}
func validateFlockerVolumeSource(flocker *core.FlockerVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
......@@ -1567,7 +1587,7 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList {
allErrs = append(allErrs, field.Forbidden(specPath.Child("glusterfs"), "may not specify more than 1 volume type"))
} else {
numVolumes++
allErrs = append(allErrs, validateGlusterfsVolumeSource(pv.Spec.Glusterfs, specPath.Child("glusterfs"))...)
allErrs = append(allErrs, validateGlusterfsPersistentVolumeSource(pv.Spec.Glusterfs, specPath.Child("glusterfs"))...)
}
}
if pv.Spec.Flocker != nil {
......
......@@ -1774,6 +1774,60 @@ func TestValidateGlusterfs(t *testing.T) {
}
}
func TestValidateGlusterfsPersistentVolumeSource(t *testing.T) {
var epNs *string
namespace := ""
epNs = &namespace
testCases := []struct {
name string
gfs *core.GlusterfsPersistentVolumeSource
errtype field.ErrorType
errfield string
}{
{
name: "missing endpointname",
gfs: &core.GlusterfsPersistentVolumeSource{EndpointsName: "", Path: "/tmp"},
errtype: field.ErrorTypeRequired,
errfield: "endpoints",
},
{
name: "missing path",
gfs: &core.GlusterfsPersistentVolumeSource{EndpointsName: "my-endpoint", Path: ""},
errtype: field.ErrorTypeRequired,
errfield: "path",
},
{
name: "non null endpointnamespace with empty string",
gfs: &core.GlusterfsPersistentVolumeSource{EndpointsName: "my-endpoint", Path: "/tmp", EndpointsNamespace: epNs},
errtype: field.ErrorTypeInvalid,
errfield: "endpointsNamespace",
},
{
name: "missing endpointname and path",
gfs: &core.GlusterfsPersistentVolumeSource{EndpointsName: "", Path: ""},
errtype: field.ErrorTypeRequired,
errfield: "endpoints",
},
}
for i, tc := range testCases {
errs := validateGlusterfsPersistentVolumeSource(tc.gfs, field.NewPath("field"))
if len(errs) > 0 && tc.errtype == "" {
t.Errorf("[%d: %q] unexpected error(s): %v", i, tc.name, errs)
} else if len(errs) == 0 && tc.errtype != "" {
t.Errorf("[%d: %q] expected error type %v", i, tc.name, tc.errtype)
} else if len(errs) >= 1 {
if errs[0].Type != tc.errtype {
t.Errorf("[%d: %q] expected error type %v, got %v", i, tc.name, tc.errtype, errs[0].Type)
} else if !strings.HasSuffix(errs[0].Field, "."+tc.errfield) {
t.Errorf("[%d: %q] expected error on field %q, got %q", i, tc.name, tc.errfield, errs[0].Field)
}
}
}
}
func TestValidateCSIVolumeSource(t *testing.T) {
testCases := []struct {
name string
......
......@@ -1499,6 +1499,27 @@ func (in *GitRepoVolumeSource) DeepCopy() *GitRepoVolumeSource {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlusterfsPersistentVolumeSource) DeepCopyInto(out *GlusterfsPersistentVolumeSource) {
*out = *in
if in.EndpointsNamespace != nil {
in, out := &in.EndpointsNamespace, &out.EndpointsNamespace
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterfsPersistentVolumeSource.
func (in *GlusterfsPersistentVolumeSource) DeepCopy() *GlusterfsPersistentVolumeSource {
if in == nil {
return nil
}
out := new(GlusterfsPersistentVolumeSource)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlusterfsVolumeSource) DeepCopyInto(out *GlusterfsVolumeSource) {
*out = *in
return
......@@ -2808,8 +2829,8 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) {
}
if in.Glusterfs != nil {
in, out := &in.Glusterfs, &out.Glusterfs
*out = new(GlusterfsVolumeSource)
**out = **in
*out = new(GlusterfsPersistentVolumeSource)
(*in).DeepCopyInto(*out)
}
if in.NFS != nil {
in, out := &in.NFS, &out.NFS
......
......@@ -494,7 +494,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ResourceName(v1.ResourceStorage): resource.MustParse("5G"),
},
PersistentVolumeSource: v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{},
Glusterfs: &v1.GlusterfsPersistentVolumeSource{},
},
AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce,
......@@ -539,7 +539,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ResourceName(v1.ResourceStorage): resource.MustParse("10G"),
},
PersistentVolumeSource: v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{},
Glusterfs: &v1.GlusterfsPersistentVolumeSource{},
},
AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce,
......@@ -582,7 +582,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G"),
},
PersistentVolumeSource: v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{},
Glusterfs: &v1.GlusterfsPersistentVolumeSource{},
},
AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce,
......
......@@ -929,6 +929,15 @@ func printGlusterfsVolumeSource(glusterfs *api.GlusterfsVolumeSource, w PrefixWr
glusterfs.EndpointsName, glusterfs.Path, glusterfs.ReadOnly)
}
func printGlusterfsPersistentVolumeSource(glusterfs *api.GlusterfsPersistentVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tGlusterfs (a Glusterfs mount on the host that shares a pod's lifetime)\n"+
" EndpointsName:\t%v\n"+
" EndpointsNamespace:\t%v\n"+
" Path:\t%v\n"+
" ReadOnly:\t%v\n",
glusterfs.EndpointsName, glusterfs.EndpointsNamespace, glusterfs.Path, glusterfs.ReadOnly)
}
func printPersistentVolumeClaimVolumeSource(claim *api.PersistentVolumeClaimVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tPersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)\n"+
" ClaimName:\t%v\n"+
......@@ -1311,7 +1320,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
case pv.Spec.ISCSI != nil:
printISCSIPersistentVolumeSource(pv.Spec.ISCSI, w)
case pv.Spec.Glusterfs != nil:
printGlusterfsVolumeSource(pv.Spec.Glusterfs, w)
printGlusterfsPersistentVolumeSource(pv.Spec.Glusterfs, w)
case pv.Spec.RBD != nil:
printRBDPersistentVolumeSource(pv.Spec.RBD, w)
case pv.Spec.Quobyte != nil:
......
......@@ -982,7 +982,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
Spec: api.PersistentVolumeSpec{
PersistentVolumeSource: api.PersistentVolumeSource{
Glusterfs: &api.GlusterfsVolumeSource{},
Glusterfs: &api.GlusterfsPersistentVolumeSource{},
},
},
},
......
......@@ -98,15 +98,30 @@ func (plugin *glusterfsPlugin) GetPluginName() string {
}
func (plugin *glusterfsPlugin) GetVolumeName(spec *volume.Spec) (string, error) {
volumeSource, _, err := getVolumeSource(spec)
var endpointName string
var endpointsNsPtr *string
volPath, _, err := getVolumeInfo(spec)
if err != nil {
return "", err
}
return fmt.Sprintf(
"%v:%v",
volumeSource.EndpointsName,
volumeSource.Path), nil
if spec.Volume != nil && spec.Volume.Glusterfs != nil {
endpointName = spec.Volume.Glusterfs.EndpointsName
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.Glusterfs != nil {
endpointName = spec.PersistentVolume.Spec.Glusterfs.EndpointsName
endpointsNsPtr = spec.PersistentVolume.Spec.Glusterfs.EndpointsNamespace
if endpointsNsPtr != nil && *endpointsNsPtr != "" {
return fmt.Sprintf("%v:%v:%v", endpointName, *endpointsNsPtr, volPath), nil
}
return "", fmt.Errorf("invalid endpointsnamespace in provided glusterfs PV spec")
} else {
return "", fmt.Errorf("unable to fetch required parameters from provided glusterfs spec")
}
return fmt.Sprintf("%v:%v", endpointName, volPath), nil
}
func (plugin *glusterfsPlugin) CanSupport(spec *volume.Spec) bool {
......@@ -139,19 +154,17 @@ func (plugin *glusterfsPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode
}
func (plugin *glusterfsPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) {
source, _, err := getVolumeSource(spec)
epName, epNamespace, err := plugin.getEndpointNameAndNamespace(spec, pod.Namespace)
if err != nil {
glog.Errorf("failed to get gluster volumesource: %v", err)
return nil, err
}
epName := source.EndpointsName
// PVC/POD is in same namespace.
podNs := pod.Namespace
kubeClient := plugin.host.GetKubeClient()
if kubeClient == nil {
return nil, fmt.Errorf("failed to get kube client to initialize mounter")
}
ep, err := kubeClient.CoreV1().Endpoints(podNs).Get(epName, metav1.GetOptions{})
ep, err := kubeClient.Core().Endpoints(epNamespace).Get(epName, metav1.GetOptions{})
if err != nil {
glog.Errorf("failed to get endpoint %s: %v", epName, err)
return nil, err
......@@ -160,8 +173,38 @@ func (plugin *glusterfsPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volu
return plugin.newMounterInternal(spec, ep, pod, plugin.host.GetMounter(plugin.GetPluginName()))
}
func (plugin *glusterfsPlugin) getEndpointNameAndNamespace(spec *volume.Spec, defaultNamespace string) (string, string, error) {
if spec.Volume != nil && spec.Volume.Glusterfs != nil {
endpoints := spec.Volume.Glusterfs.EndpointsName
if endpoints == "" {
return "", "", fmt.Errorf("no glusterFS endpoint specified")
}
return endpoints, defaultNamespace, nil
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.Glusterfs != nil {
endpoints := spec.PersistentVolume.Spec.Glusterfs.EndpointsName
endpointsNs := defaultNamespace
overriddenNs := spec.PersistentVolume.Spec.Glusterfs.EndpointsNamespace
if overriddenNs != nil {
if len(*overriddenNs) > 0 {
endpointsNs = *overriddenNs
} else {
return "", "", fmt.Errorf("endpointnamespace field set, but no endpointnamespace specified")
}
}
return endpoints, endpointsNs, nil
}
return "", "", fmt.Errorf("Spec does not reference a GlusterFS volume type")
}
func (plugin *glusterfsPlugin) newMounterInternal(spec *volume.Spec, ep *v1.Endpoints, pod *v1.Pod, mounter mount.Interface) (volume.Mounter, error) {
source, readOnly, _ := getVolumeSource(spec)
volPath, readOnly, err := getVolumeInfo(spec)
if err != nil {
glog.Errorf("failed to get volumesource : %v", err)
return nil, err
}
return &glusterfsMounter{
glusterfs: &glusterfs{
volName: spec.Name(),
......@@ -171,7 +214,7 @@ func (plugin *glusterfsPlugin) newMounterInternal(spec *volume.Spec, ep *v1.Endp
MetricsProvider: volume.NewMetricsStatFS(plugin.host.GetPodVolumeDir(pod.UID, strings.EscapeQualifiedNameForDisk(glusterfsPluginName), spec.Name())),
},
hosts: ep,
path: source.Path,
path: volPath,
readOnly: readOnly,
mountOptions: volutil.MountOptionFromSpec(spec),
}, nil
......@@ -403,15 +446,16 @@ func (b *glusterfsMounter) setUpAtInternal(dir string) error {
}
func getVolumeSource(spec *volume.Spec) (*v1.GlusterfsVolumeSource, bool, error) {
//getVolumeInfo returns 'path' and 'readonly' field values from the provided glusterfs spec.
func getVolumeInfo(spec *volume.Spec) (string, bool, error) {
if spec.Volume != nil && spec.Volume.Glusterfs != nil {
return spec.Volume.Glusterfs, spec.Volume.Glusterfs.ReadOnly, nil
return spec.Volume.Glusterfs.Path, spec.Volume.Glusterfs.ReadOnly, nil
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.Glusterfs != nil {
return spec.PersistentVolume.Spec.Glusterfs, spec.ReadOnly, nil
return spec.PersistentVolume.Spec.Glusterfs.Path, spec.ReadOnly, nil
}
return nil, false, fmt.Errorf("Spec does not reference a Glusterfs volume type")
return "", false, fmt.Errorf("Spec does not reference a Glusterfs volume type")
}
func (plugin *glusterfsPlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) {
......@@ -769,7 +813,7 @@ func (p *glusterfsVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTop
return pv, nil
}
func (p *glusterfsVolumeProvisioner) CreateVolume(gid int) (r *v1.GlusterfsVolumeSource, size int, volID string, err error) {
func (p *glusterfsVolumeProvisioner) CreateVolume(gid int) (r *v1.GlusterfsPersistentVolumeSource, size int, volID string, err error) {
var clusterIDs []string
customVolumeName := ""
capacity := p.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
......@@ -834,10 +878,11 @@ func (p *glusterfsVolumeProvisioner) CreateVolume(gid int) (r *v1.GlusterfsVolum
return nil, 0, "", fmt.Errorf("failed to create endpoint/service %v/%v: %v", epNamespace, epServiceName, err)
}
glog.V(3).Infof("dynamic endpoint %v and service %v ", endpoint, service)
return &v1.GlusterfsVolumeSource{
EndpointsName: endpoint.Name,
Path: volume.Name,
ReadOnly: false,
return &v1.GlusterfsPersistentVolumeSource{
EndpointsName: endpoint.Name,
EndpointsNamespace: &epNamespace,
Path: volume.Name,
ReadOnly: false,
}, sz, volID, nil
}
......
......@@ -66,7 +66,7 @@ func TestCanSupport(t *testing.T) {
if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{}}}}) {
t.Errorf("Expected false")
}
if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{Glusterfs: &v1.GlusterfsVolumeSource{}}}}}) {
if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{Glusterfs: &v1.GlusterfsPersistentVolumeSource{}}}}}) {
t.Errorf("Expected true")
}
}
......@@ -160,7 +160,7 @@ func TestPluginPersistentVolume(t *testing.T) {
},
Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{EndpointsName: "ep", Path: "vol", ReadOnly: false},
Glusterfs: &v1.GlusterfsPersistentVolumeSource{EndpointsName: "ep", Path: "vol", ReadOnly: false},
},
},
}
......@@ -181,7 +181,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
},
Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{EndpointsName: "ep", Path: "vol", ReadOnly: false},
Glusterfs: &v1.GlusterfsPersistentVolumeSource{EndpointsName: "ep", Path: "vol", ReadOnly: false},
},
ClaimRef: &v1.ObjectReference{
Name: "claimA",
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -1375,6 +1375,30 @@ message GitRepoVolumeSource {
// Represents a Glusterfs mount that lasts the lifetime of a pod.
// Glusterfs volumes do not support ownership management or SELinux relabeling.
message GlusterfsPersistentVolumeSource {
// EndpointsName is the endpoint name that details Glusterfs topology.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
optional string endpoints = 1;
// Path is the Glusterfs volume path.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
optional string path = 2;
// ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions.
// Defaults to false.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
optional bool readOnly = 3;
// EndpointsNamespace is the namespace that contains Glusterfs endpoint.
// If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
optional string endpointsNamespace = 4;
}
// Represents a Glusterfs mount that lasts the lifetime of a pod.
// Glusterfs volumes do not support ownership management or SELinux relabeling.
message GlusterfsVolumeSource {
// EndpointsName is the endpoint name that details Glusterfs topology.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
......@@ -2389,7 +2413,7 @@ message PersistentVolumeSource {
// exposed to the pod. Provisioned by an admin.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md
// +optional
optional GlusterfsVolumeSource glusterfs = 4;
optional GlusterfsPersistentVolumeSource glusterfs = 4;
// NFS represents an NFS mount on the host. Provisioned by an admin.
// More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
......
......@@ -191,7 +191,7 @@ type PersistentVolumeSource struct {
// exposed to the pod. Provisioned by an admin.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md
// +optional
Glusterfs *GlusterfsVolumeSource `json:"glusterfs,omitempty" protobuf:"bytes,4,opt,name=glusterfs"`
Glusterfs *GlusterfsPersistentVolumeSource `json:"glusterfs,omitempty" protobuf:"bytes,4,opt,name=glusterfs"`
// NFS represents an NFS mount on the host. Provisioned by an admin.
// More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
// +optional
......@@ -636,6 +636,30 @@ type GlusterfsVolumeSource struct {
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"`
}
// Represents a Glusterfs mount that lasts the lifetime of a pod.
// Glusterfs volumes do not support ownership management or SELinux relabeling.
type GlusterfsPersistentVolumeSource struct {
// EndpointsName is the endpoint name that details Glusterfs topology.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
EndpointsName string `json:"endpoints" protobuf:"bytes,1,opt,name=endpoints"`
// Path is the Glusterfs volume path.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
Path string `json:"path" protobuf:"bytes,2,opt,name=path"`
// ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions.
// Defaults to false.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"`
// EndpointsNamespace is the namespace that contains Glusterfs endpoint.
// If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
EndpointsNamespace *string `json:"endpointsNamespace,omitempty" protobuf:"bytes,4,opt,name=endpointsNamespace"`
}
// Represents a Rados Block Device mount that lasts the lifetime of a pod.
// RBD volumes support ownership management and SELinux relabeling.
type RBDVolumeSource struct {
......
......@@ -695,6 +695,18 @@ func (GitRepoVolumeSource) SwaggerDoc() map[string]string {
return map_GitRepoVolumeSource
}
var map_GlusterfsPersistentVolumeSource = map[string]string{
"": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"endpoints": "EndpointsName is the endpoint name that details Glusterfs topology. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"path": "Path is the Glusterfs volume path. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"readOnly": "ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"endpointsNamespace": "EndpointsNamespace is the namespace that contains Glusterfs endpoint. If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
}
func (GlusterfsPersistentVolumeSource) SwaggerDoc() map[string]string {
return map_GlusterfsPersistentVolumeSource
}
var map_GlusterfsVolumeSource = map[string]string{
"": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"endpoints": "EndpointsName is the endpoint name that details Glusterfs topology. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
......
......@@ -1499,6 +1499,27 @@ func (in *GitRepoVolumeSource) DeepCopy() *GitRepoVolumeSource {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlusterfsPersistentVolumeSource) DeepCopyInto(out *GlusterfsPersistentVolumeSource) {
*out = *in
if in.EndpointsNamespace != nil {
in, out := &in.EndpointsNamespace, &out.EndpointsNamespace
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterfsPersistentVolumeSource.
func (in *GlusterfsPersistentVolumeSource) DeepCopy() *GlusterfsPersistentVolumeSource {
if in == nil {
return nil
}
out := new(GlusterfsPersistentVolumeSource)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlusterfsVolumeSource) DeepCopyInto(out *GlusterfsVolumeSource) {
*out = *in
return
......@@ -2806,8 +2827,8 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) {
}
if in.Glusterfs != nil {
in, out := &in.Glusterfs, &out.Glusterfs
*out = new(GlusterfsVolumeSource)
**out = **in
*out = new(GlusterfsPersistentVolumeSource)
(*in).DeepCopyInto(*out)
}
if in.NFS != nil {
in, out := &in.NFS, &out.NFS
......
......@@ -274,7 +274,7 @@ func (g *glusterFSDriver) GetPersistentVolumeSource(readOnly bool, fsType string
name := gtr.prefix + "-server"
return &v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{
Glusterfs: &v1.GlusterfsPersistentVolumeSource{
EndpointsName: name,
// 'test_vol' comes from test/images/volumes-tester/gluster/run_gluster.sh
Path: "test_vol",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment