mirror of https://github.com/k3s-io/k3s
Add storageClass.mountOptions and use it in all applicable plugins
parent
25da6e64e2
commit
5e772b8e4b
|
@ -54,6 +54,11 @@ type StorageClass struct {
|
|||
// PersistentVolumes of this storage class are created with
|
||||
// +optional
|
||||
ReclaimPolicy *api.PersistentVolumeReclaimPolicy
|
||||
|
||||
// mountOptions are the mount options that dynamically provisioned
|
||||
// PersistentVolumes of this storage class are created with
|
||||
// +optional
|
||||
MountOptions []string
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
|
|
@ -807,12 +807,13 @@ const operationDelete = "Delete"
|
|||
const operationRecycle = "Recycle"
|
||||
|
||||
var (
|
||||
classGold string = "gold"
|
||||
classSilver string = "silver"
|
||||
classEmpty string = ""
|
||||
classNonExisting string = "non-existing"
|
||||
classExternal string = "external"
|
||||
classUnknownInternal string = "unknown-internal"
|
||||
classGold string = "gold"
|
||||
classSilver string = "silver"
|
||||
classEmpty string = ""
|
||||
classNonExisting string = "non-existing"
|
||||
classExternal string = "external"
|
||||
classUnknownInternal string = "unknown-internal"
|
||||
classUnsupportedMountOptions string = "unsupported-mountoptions"
|
||||
)
|
||||
|
||||
// wrapTestWithPluginCalls returns a testCall that:
|
||||
|
|
|
@ -81,6 +81,18 @@ var storageClasses = []*storage.StorageClass{
|
|||
Parameters: class1Parameters,
|
||||
ReclaimPolicy: &deleteReclaimPolicy,
|
||||
},
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "unsupported-mountoptions",
|
||||
},
|
||||
Provisioner: mockPluginName,
|
||||
Parameters: class1Parameters,
|
||||
ReclaimPolicy: &deleteReclaimPolicy,
|
||||
MountOptions: []string{"foo"},
|
||||
},
|
||||
}
|
||||
|
||||
// call to storageClass 1, returning an error
|
||||
|
@ -392,6 +404,17 @@ func TestProvisionSync(t *testing.T) {
|
|||
testSyncClaim,
|
||||
),
|
||||
},
|
||||
{
|
||||
// No provisioning + warning event with unsupported storageClass.mountOptions
|
||||
"11-20 - unsupported storageClass.mountOptions",
|
||||
novolumes,
|
||||
novolumes,
|
||||
newClaimArray("claim11-20", "uid11-20", "1Gi", "", v1.ClaimPending, &classUnsupportedMountOptions),
|
||||
newClaimArray("claim11-20", "uid11-20", "1Gi", "", v1.ClaimPending, &classUnsupportedMountOptions, annStorageProvisioner),
|
||||
// Expect event to be prefixed with "Mount options" because saving PV will fail anyway
|
||||
[]string{"Warning ProvisioningFailed Mount options"},
|
||||
noerrors, wrapTestWithProvisionCalls([]provisionCall{}, testSyncClaim),
|
||||
},
|
||||
}
|
||||
runSyncTests(t, tests, storageClasses)
|
||||
}
|
||||
|
|
|
@ -1320,6 +1320,7 @@ func (ctrl *PersistentVolumeController) provisionClaimOperation(claimObj interfa
|
|||
|
||||
options := vol.VolumeOptions{
|
||||
PersistentVolumeReclaimPolicy: *storageClass.ReclaimPolicy,
|
||||
MountOptions: storageClass.MountOptions,
|
||||
CloudTags: &tags,
|
||||
ClusterName: ctrl.clusterName,
|
||||
PVName: pvName,
|
||||
|
@ -1327,6 +1328,15 @@ func (ctrl *PersistentVolumeController) provisionClaimOperation(claimObj interfa
|
|||
Parameters: storageClass.Parameters,
|
||||
}
|
||||
|
||||
// Refuse to provision if the plugin doesn't support mount options, creation
|
||||
// of PV would be rejected by validation anyway
|
||||
if !plugin.SupportsMountOption() && len(options.MountOptions) > 0 {
|
||||
strerr := fmt.Sprintf("Mount options are not supported by the provisioner but StorageClass %q has mount options %v", storageClass.Name, options.MountOptions)
|
||||
glog.V(2).Infof("Mount options are not supported by the provisioner but claim %q's StorageClass %q has mount options %v", claimToClaimKey(claim), storageClass.Name, options.MountOptions)
|
||||
ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr)
|
||||
return
|
||||
}
|
||||
|
||||
// Provision the volume
|
||||
provisioner, err := plugin.NewProvisioner(options)
|
||||
if err != nil {
|
||||
|
|
|
@ -465,6 +465,7 @@ func (c *awsElasticBlockStoreProvisioner) Provision() (*v1.PersistentVolume, err
|
|||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
MountOptions: c.options.MountOptions,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -198,6 +198,7 @@ func (p *azureDiskProvisioner) Provision() (*v1.PersistentVolume, error) {
|
|||
FSType: &fsType,
|
||||
},
|
||||
},
|
||||
MountOptions: p.options.MountOptions,
|
||||
},
|
||||
}
|
||||
return pv, nil
|
||||
|
|
|
@ -196,6 +196,7 @@ func (a *azureFileProvisioner) Provision() (*v1.PersistentVolume, error) {
|
|||
SecretNamespace: &secretNamespace,
|
||||
},
|
||||
},
|
||||
MountOptions: a.options.MountOptions,
|
||||
},
|
||||
}
|
||||
return pv, nil
|
||||
|
|
|
@ -499,6 +499,7 @@ func (c *cinderVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
|
|||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
MountOptions: c.options.MountOptions,
|
||||
},
|
||||
}
|
||||
if len(c.options.PVC.Spec.AccessModes) == 0 {
|
||||
|
|
|
@ -410,6 +410,7 @@ func (c *gcePersistentDiskProvisioner) Provision() (*v1.PersistentVolume, error)
|
|||
FSType: fstype,
|
||||
},
|
||||
},
|
||||
MountOptions: c.options.MountOptions,
|
||||
},
|
||||
}
|
||||
if len(c.options.PVC.Spec.AccessModes) == 0 {
|
||||
|
|
|
@ -711,6 +711,7 @@ func (p *glusterfsVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
|
|||
if len(pv.Spec.AccessModes) == 0 {
|
||||
pv.Spec.AccessModes = p.plugin.GetAccessModes()
|
||||
}
|
||||
pv.Spec.MountOptions = p.options.MountOptions
|
||||
|
||||
gidStr := strconv.FormatInt(int64(gid), 10)
|
||||
|
||||
|
|
|
@ -375,6 +375,7 @@ func (p *photonPersistentDiskProvisioner) Provision() (*v1.PersistentVolume, err
|
|||
FSType: fstype,
|
||||
},
|
||||
},
|
||||
MountOptions: p.options.MountOptions,
|
||||
},
|
||||
}
|
||||
if len(p.options.PVC.Spec.AccessModes) == 0 {
|
||||
|
|
|
@ -50,6 +50,8 @@ type VolumeOptions struct {
|
|||
|
||||
// Reclamation policy for a persistent volume
|
||||
PersistentVolumeReclaimPolicy v1.PersistentVolumeReclaimPolicy
|
||||
// Mount options for a persistent volume
|
||||
MountOptions []string
|
||||
// Suggested PV.Name of the PersistentVolume to provision.
|
||||
// This is a generated name guaranteed to be unique in Kubernetes cluster.
|
||||
// If you choose not to use it as volume name, ensure uniqueness by either
|
||||
|
|
|
@ -420,6 +420,7 @@ func (provisioner *quobyteVolumeProvisioner) Provision() (*v1.PersistentVolume,
|
|||
pv.Spec.Capacity = v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)),
|
||||
}
|
||||
pv.Spec.MountOptions = provisioner.options.MountOptions
|
||||
return pv, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -383,6 +383,7 @@ func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
|
|||
pv.Spec.Capacity = v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dMi", sizeMB)),
|
||||
}
|
||||
pv.Spec.MountOptions = r.options.MountOptions
|
||||
return pv, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -379,6 +379,7 @@ func (v *vsphereVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
|
|||
StoragePolicyID: volSpec.StoragePolicyID,
|
||||
},
|
||||
},
|
||||
MountOptions: v.options.MountOptions,
|
||||
},
|
||||
}
|
||||
if len(v.options.PVC.Spec.AccessModes) == 0 {
|
||||
|
|
|
@ -49,6 +49,12 @@ type StorageClass struct {
|
|||
// created with this reclaimPolicy. Defaults to Delete.
|
||||
// +optional
|
||||
ReclaimPolicy *v1.PersistentVolumeReclaimPolicy `json:"reclaimPolicy,omitempty" protobuf:"bytes,4,opt,name=reclaimPolicy,casttype=k8s.io/api/core/v1.PersistentVolumeReclaimPolicy"`
|
||||
|
||||
// Dynamically provisioned PersistentVolumes of this storage class are
|
||||
// created with these mountOptions, e.g. ["ro", "soft"]. Not validated -
|
||||
// mount of the PVs will simply fail if one is invalid.
|
||||
// +optional
|
||||
MountOptions []string `json:"mountOptions,omitempty" protobuf:"bytes,5,opt,name=mountOptions"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
|
|
@ -49,6 +49,12 @@ type StorageClass struct {
|
|||
// created with this reclaimPolicy. Defaults to Delete.
|
||||
// +optional
|
||||
ReclaimPolicy *v1.PersistentVolumeReclaimPolicy `json:"reclaimPolicy,omitempty" protobuf:"bytes,4,opt,name=reclaimPolicy,casttype=k8s.io/api/core/v1.PersistentVolumeReclaimPolicy"`
|
||||
|
||||
// Dynamically provisioned PersistentVolumes of this storage class are
|
||||
// created with these mountOptions, e.g. ["ro", "soft"]. Not validated -
|
||||
// mount of the PVs will simply fail if one is invalid.
|
||||
// +optional
|
||||
MountOptions []string `json:"mountOptions,omitempty" protobuf:"bytes,5,opt,name=mountOptions"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
|
Loading…
Reference in New Issue