Merge pull request #88673 from jsafrane/block-feature-ga

Promote block volumes to GA
This commit is contained in:
Kubernetes Prow Robot 2020-03-03 12:17:12 -08:00 committed by GitHub
commit 9d0cbb7503
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 125 additions and 878 deletions

View File

@ -5632,7 +5632,7 @@
"type": "boolean" "type": "boolean"
}, },
"volumeDevices": { "volumeDevices": {
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature.", "description": "volumeDevices is the list of block devices to be used by the container.",
"items": { "items": {
"$ref": "#/definitions/io.k8s.api.core.v1.VolumeDevice" "$ref": "#/definitions/io.k8s.api.core.v1.VolumeDevice"
}, },
@ -6234,7 +6234,7 @@
"type": "boolean" "type": "boolean"
}, },
"volumeDevices": { "volumeDevices": {
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature.", "description": "volumeDevices is the list of block devices to be used by the container.",
"items": { "items": {
"$ref": "#/definitions/io.k8s.api.core.v1.VolumeDevice" "$ref": "#/definitions/io.k8s.api.core.v1.VolumeDevice"
}, },
@ -7847,7 +7847,7 @@
"type": "string" "type": "string"
}, },
"volumeMode": { "volumeMode": {
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature.", "description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.",
"type": "string" "type": "string"
}, },
"volumeName": { "volumeName": {
@ -8067,7 +8067,7 @@
"description": "StorageOS represents a StorageOS volume that is attached to the kubelet's host machine and mounted into the pod More info: https://examples.k8s.io/volumes/storageos/README.md" "description": "StorageOS represents a StorageOS volume that is attached to the kubelet's host machine and mounted into the pod More info: https://examples.k8s.io/volumes/storageos/README.md"
}, },
"volumeMode": { "volumeMode": {
"description": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is a beta feature.", "description": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec.",
"type": "string" "type": "string"
}, },
"vsphereVolume": { "vsphereVolume": {

View File

@ -25,10 +25,6 @@ import (
// DropDisabledFields removes disabled fields from the pv spec. // DropDisabledFields removes disabled fields from the pv spec.
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pv spec. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pv spec.
func DropDisabledFields(pvSpec *api.PersistentVolumeSpec, oldPVSpec *api.PersistentVolumeSpec) { func DropDisabledFields(pvSpec *api.PersistentVolumeSpec, oldPVSpec *api.PersistentVolumeSpec) {
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeModeInUse(oldPVSpec) {
pvSpec.VolumeMode = nil
}
if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandCSIVolumes) && !hasExpansionSecrets(oldPVSpec) { if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandCSIVolumes) && !hasExpansionSecrets(oldPVSpec) {
if pvSpec.CSI != nil { if pvSpec.CSI != nil {
pvSpec.CSI.ControllerExpandSecretRef = nil pvSpec.CSI.ControllerExpandSecretRef = nil
@ -46,13 +42,3 @@ func hasExpansionSecrets(oldPVSpec *api.PersistentVolumeSpec) bool {
} }
return false return false
} }
func volumeModeInUse(oldPVSpec *api.PersistentVolumeSpec) bool {
if oldPVSpec == nil {
return false
}
if oldPVSpec.VolumeMode != nil {
return true
}
return false
}

View File

@ -28,68 +28,18 @@ import (
) )
func TestDropDisabledFields(t *testing.T) { func TestDropDisabledFields(t *testing.T) {
specWithMode := func(mode *api.PersistentVolumeMode) *api.PersistentVolumeSpec {
return &api.PersistentVolumeSpec{VolumeMode: mode}
}
secretRef := &api.SecretReference{ secretRef := &api.SecretReference{
Name: "expansion-secret", Name: "expansion-secret",
Namespace: "default", Namespace: "default",
} }
modeBlock := api.PersistentVolumeBlock
tests := map[string]struct { tests := map[string]struct {
oldSpec *api.PersistentVolumeSpec oldSpec *api.PersistentVolumeSpec
newSpec *api.PersistentVolumeSpec newSpec *api.PersistentVolumeSpec
expectOldSpec *api.PersistentVolumeSpec expectOldSpec *api.PersistentVolumeSpec
expectNewSpec *api.PersistentVolumeSpec expectNewSpec *api.PersistentVolumeSpec
blockEnabled bool
csiExpansionEnabled bool csiExpansionEnabled bool
}{ }{
"disabled block clears new": {
blockEnabled: false,
newSpec: specWithMode(&modeBlock),
expectNewSpec: specWithMode(nil),
oldSpec: nil,
expectOldSpec: nil,
},
"disabled block clears update when old pv did not use block": {
blockEnabled: false,
newSpec: specWithMode(&modeBlock),
expectNewSpec: specWithMode(nil),
oldSpec: specWithMode(nil),
expectOldSpec: specWithMode(nil),
},
"disabled block does not clear new on update when old pv did use block": {
blockEnabled: false,
newSpec: specWithMode(&modeBlock),
expectNewSpec: specWithMode(&modeBlock),
oldSpec: specWithMode(&modeBlock),
expectOldSpec: specWithMode(&modeBlock),
},
"enabled block preserves new": {
blockEnabled: true,
newSpec: specWithMode(&modeBlock),
expectNewSpec: specWithMode(&modeBlock),
oldSpec: nil,
expectOldSpec: nil,
},
"enabled block preserves update when old pv did not use block": {
blockEnabled: true,
newSpec: specWithMode(&modeBlock),
expectNewSpec: specWithMode(&modeBlock),
oldSpec: specWithMode(nil),
expectOldSpec: specWithMode(nil),
},
"enabled block preserves update when old pv did use block": {
blockEnabled: true,
newSpec: specWithMode(&modeBlock),
expectNewSpec: specWithMode(&modeBlock),
oldSpec: specWithMode(&modeBlock),
expectOldSpec: specWithMode(&modeBlock),
},
"disabled csi expansion clears secrets": { "disabled csi expansion clears secrets": {
csiExpansionEnabled: false, csiExpansionEnabled: false,
newSpec: specWithCSISecrets(secretRef), newSpec: specWithCSISecrets(secretRef),
@ -129,7 +79,6 @@ func TestDropDisabledFields(t *testing.T) {
for name, tc := range tests { for name, tc := range tests {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, tc.blockEnabled)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandCSIVolumes, tc.csiExpansionEnabled)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandCSIVolumes, tc.csiExpansionEnabled)()
DropDisabledFields(tc.newSpec, tc.oldSpec) DropDisabledFields(tc.newSpec, tc.oldSpec)

View File

@ -30,24 +30,11 @@ const (
// DropDisabledFields removes disabled fields from the pvc spec. // DropDisabledFields removes disabled fields from the pvc spec.
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pvc spec. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pvc spec.
func DropDisabledFields(pvcSpec, oldPVCSpec *core.PersistentVolumeClaimSpec) { func DropDisabledFields(pvcSpec, oldPVCSpec *core.PersistentVolumeClaimSpec) {
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeModeInUse(oldPVCSpec) {
pvcSpec.VolumeMode = nil
}
if !dataSourceIsEnabled(pvcSpec) && !dataSourceInUse(oldPVCSpec) { if !dataSourceIsEnabled(pvcSpec) && !dataSourceInUse(oldPVCSpec) {
pvcSpec.DataSource = nil pvcSpec.DataSource = nil
} }
} }
func volumeModeInUse(oldPVCSpec *core.PersistentVolumeClaimSpec) bool {
if oldPVCSpec == nil {
return false
}
if oldPVCSpec.VolumeMode != nil {
return true
}
return false
}
func dataSourceInUse(oldPVCSpec *core.PersistentVolumeClaimSpec) bool { func dataSourceInUse(oldPVCSpec *core.PersistentVolumeClaimSpec) bool {
if oldPVCSpec == nil { if oldPVCSpec == nil {
return false return false

View File

@ -28,96 +28,6 @@ import (
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
) )
func TestDropAlphaPVCVolumeMode(t *testing.T) {
vmode := core.PersistentVolumeFilesystem
pvcWithoutVolumeMode := func() *core.PersistentVolumeClaim {
return &core.PersistentVolumeClaim{
Spec: core.PersistentVolumeClaimSpec{
VolumeMode: nil,
},
}
}
pvcWithVolumeMode := func() *core.PersistentVolumeClaim {
return &core.PersistentVolumeClaim{
Spec: core.PersistentVolumeClaimSpec{
VolumeMode: &vmode,
},
}
}
pvcInfo := []struct {
description string
hasVolumeMode bool
pvc func() *core.PersistentVolumeClaim
}{
{
description: "pvc without VolumeMode",
hasVolumeMode: false,
pvc: pvcWithoutVolumeMode,
},
{
description: "pvc with Filesystem VolumeMode",
hasVolumeMode: true,
pvc: pvcWithVolumeMode,
},
{
description: "is nil",
hasVolumeMode: false,
pvc: func() *core.PersistentVolumeClaim { return nil },
},
}
for _, enabled := range []bool{true, false} {
for _, oldpvcInfo := range pvcInfo {
for _, newpvcInfo := range pvcInfo {
oldpvcHasVolumeMode, oldpvc := oldpvcInfo.hasVolumeMode, oldpvcInfo.pvc()
newpvcHasVolumeMode, newpvc := newpvcInfo.hasVolumeMode, newpvcInfo.pvc()
if newpvc == nil {
continue
}
t.Run(fmt.Sprintf("feature enabled=%v, old pvc %v, new pvc %v", enabled, oldpvcInfo.description, newpvcInfo.description), func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, enabled)()
var oldpvcSpec *core.PersistentVolumeClaimSpec
if oldpvc != nil {
oldpvcSpec = &oldpvc.Spec
}
DropDisabledFields(&newpvc.Spec, oldpvcSpec)
// old pvc should never be changed
if !reflect.DeepEqual(oldpvc, oldpvcInfo.pvc()) {
t.Errorf("old pvc changed: %v", diff.ObjectReflectDiff(oldpvc, oldpvcInfo.pvc()))
}
switch {
case enabled || oldpvcHasVolumeMode:
// new pvc should not be changed if the feature is enabled, or if the old pvc had BlockVolume
if !reflect.DeepEqual(newpvc, newpvcInfo.pvc()) {
t.Errorf("new pvc changed: %v", diff.ObjectReflectDiff(newpvc, newpvcInfo.pvc()))
}
case newpvcHasVolumeMode:
// new pvc should be changed
if reflect.DeepEqual(newpvc, newpvcInfo.pvc()) {
t.Errorf("new pvc was not changed")
}
// new pvc should not have BlockVolume
if !reflect.DeepEqual(newpvc, pvcWithoutVolumeMode()) {
t.Errorf("new pvc had pvcBlockVolume: %v", diff.ObjectReflectDiff(newpvc, pvcWithoutVolumeMode()))
}
default:
// new pvc should not need to be changed
if !reflect.DeepEqual(newpvc, newpvcInfo.pvc()) {
t.Errorf("new pvc changed: %v", diff.ObjectReflectDiff(newpvc, newpvcInfo.pvc()))
}
}
})
}
}
}
}
func TestDropDisabledSnapshotDataSource(t *testing.T) { func TestDropDisabledSnapshotDataSource(t *testing.T) {
pvcWithoutDataSource := func() *core.PersistentVolumeClaim { pvcWithoutDataSource := func() *core.PersistentVolumeClaim {
return &core.PersistentVolumeClaim{ return &core.PersistentVolumeClaim{

View File

@ -385,8 +385,6 @@ func dropDisabledFields(
}) })
} }
dropDisabledVolumeDevicesFields(podSpec, oldPodSpec)
dropDisabledRunAsGroupField(podSpec, oldPodSpec) dropDisabledRunAsGroupField(podSpec, oldPodSpec)
dropDisabledGMSAFields(podSpec, oldPodSpec) dropDisabledGMSAFields(podSpec, oldPodSpec)
@ -484,17 +482,6 @@ func dropDisabledProcMountField(podSpec, oldPodSpec *api.PodSpec) {
} }
} }
// dropDisabledVolumeDevicesFields removes disabled fields from []VolumeDevice if it has not been already populated.
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a VolumeDevice
func dropDisabledVolumeDevicesFields(podSpec, oldPodSpec *api.PodSpec) {
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeDevicesInUse(oldPodSpec) {
VisitContainers(podSpec, func(c *api.Container) bool {
c.VolumeDevices = nil
return true
})
}
}
// dropDisabledCSIVolumeSourceAlphaFields removes disabled alpha fields from []CSIVolumeSource. // dropDisabledCSIVolumeSourceAlphaFields removes disabled alpha fields from []CSIVolumeSource.
// This should be called from PrepareForCreate/PrepareForUpdate for all pod specs resources containing a CSIVolumeSource // This should be called from PrepareForCreate/PrepareForUpdate for all pod specs resources containing a CSIVolumeSource
func dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec *api.PodSpec) { func dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec *api.PodSpec) {
@ -646,24 +633,6 @@ func emptyDirSizeLimitInUse(podSpec *api.PodSpec) bool {
return false return false
} }
// volumeDevicesInUse returns true if the pod spec is non-nil and has VolumeDevices set.
func volumeDevicesInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false
}
var inUse bool
VisitContainers(podSpec, func(c *api.Container) bool {
if c.VolumeDevices != nil {
inUse = true
return false
}
return true
})
return inUse
}
// runAsGroupInUse returns true if the pod spec is non-nil and has a SecurityContext's RunAsGroup field set // runAsGroupInUse returns true if the pod spec is non-nil and has a SecurityContext's RunAsGroup field set
func runAsGroupInUse(podSpec *api.PodSpec) bool { func runAsGroupInUse(podSpec *api.PodSpec) bool {
if podSpec == nil { if podSpec == nil {

View File

@ -435,150 +435,6 @@ func TestPodConfigmaps(t *testing.T) {
} }
} }
func TestDropAlphaVolumeDevices(t *testing.T) {
podWithVolumeDevices := func() *api.Pod {
return &api.Pod{
Spec: api.PodSpec{
RestartPolicy: api.RestartPolicyNever,
Containers: []api.Container{
{
Name: "container1",
Image: "testimage",
VolumeDevices: []api.VolumeDevice{
{
Name: "myvolume",
DevicePath: "/usr/test",
},
},
},
},
InitContainers: []api.Container{
{
Name: "container1",
Image: "testimage",
VolumeDevices: []api.VolumeDevice{
{
Name: "myvolume",
DevicePath: "/usr/test",
},
},
},
},
Volumes: []api.Volume{
{
Name: "myvolume",
VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{
Path: "/dev/xvdc",
},
},
},
},
},
}
}
podWithoutVolumeDevices := func() *api.Pod {
return &api.Pod{
Spec: api.PodSpec{
RestartPolicy: api.RestartPolicyNever,
Containers: []api.Container{
{
Name: "container1",
Image: "testimage",
},
},
InitContainers: []api.Container{
{
Name: "container1",
Image: "testimage",
},
},
Volumes: []api.Volume{
{
Name: "myvolume",
VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{
Path: "/dev/xvdc",
},
},
},
},
},
}
}
podInfo := []struct {
description string
hasVolumeDevices bool
pod func() *api.Pod
}{
{
description: "has VolumeDevices",
hasVolumeDevices: true,
pod: podWithVolumeDevices,
},
{
description: "does not have VolumeDevices",
hasVolumeDevices: false,
pod: podWithoutVolumeDevices,
},
{
description: "is nil",
hasVolumeDevices: false,
pod: func() *api.Pod { return nil },
},
}
for _, enabled := range []bool{true, false} {
for _, oldPodInfo := range podInfo {
for _, newPodInfo := range podInfo {
oldPodHasVolumeDevices, oldPod := oldPodInfo.hasVolumeDevices, oldPodInfo.pod()
newPodHasVolumeDevices, newPod := newPodInfo.hasVolumeDevices, newPodInfo.pod()
if newPod == nil {
continue
}
t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, enabled)()
var oldPodSpec *api.PodSpec
if oldPod != nil {
oldPodSpec = &oldPod.Spec
}
dropDisabledFields(&newPod.Spec, nil, oldPodSpec, nil)
// old pod should never be changed
if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) {
t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod()))
}
switch {
case enabled || oldPodHasVolumeDevices:
// new pod should not be changed if the feature is enabled, or if the old pod had VolumeDevices
if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
}
case newPodHasVolumeDevices:
// new pod should be changed
if reflect.DeepEqual(newPod, newPodInfo.pod()) {
t.Errorf("new pod was not changed")
}
// new pod should not have VolumeDevices
if !reflect.DeepEqual(newPod, podWithoutVolumeDevices()) {
t.Errorf("new pod had VolumeDevices: %v", diff.ObjectReflectDiff(newPod, podWithoutVolumeDevices()))
}
default:
// new pod should not need to be changed
if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
}
}
})
}
}
}
}
func TestDropSubPath(t *testing.T) { func TestDropSubPath(t *testing.T) {
podWithSubpaths := func() *api.Pod { podWithSubpaths := func() *api.Pod {
return &api.Pod{ return &api.Pod{

View File

@ -302,7 +302,6 @@ type PersistentVolumeSpec struct {
MountOptions []string MountOptions []string
// volumeMode defines if a volume is intended to be used with a formatted filesystem // volumeMode defines if a volume is intended to be used with a formatted filesystem
// or to remain in raw block state. Value of Filesystem is implied when not included in spec. // or to remain in raw block state. Value of Filesystem is implied when not included in spec.
// This is a beta feature.
// +optional // +optional
VolumeMode *PersistentVolumeMode VolumeMode *PersistentVolumeMode
// NodeAffinity defines constraints that limit what nodes this volume can be accessed from. // NodeAffinity defines constraints that limit what nodes this volume can be accessed from.
@ -416,7 +415,6 @@ type PersistentVolumeClaimSpec struct {
StorageClassName *string StorageClassName *string
// volumeMode defines what type of volume is required by the claim. // volumeMode defines what type of volume is required by the claim.
// Value of Filesystem is implied when not included in claim spec. // Value of Filesystem is implied when not included in claim spec.
// This is a beta feature.
// +optional // +optional
VolumeMode *PersistentVolumeMode VolumeMode *PersistentVolumeMode
// This field can be used to specify either: // This field can be used to specify either:
@ -2057,7 +2055,6 @@ type Container struct {
// +optional // +optional
VolumeMounts []VolumeMount VolumeMounts []VolumeMount
// volumeDevices is the list of block devices to be used by the container. // volumeDevices is the list of block devices to be used by the container.
// This is a beta feature.
// +optional // +optional
VolumeDevices []VolumeDevice VolumeDevices []VolumeDevice
// +optional // +optional
@ -2969,7 +2966,6 @@ type EphemeralContainerCommon struct {
// +optional // +optional
VolumeMounts []VolumeMount VolumeMounts []VolumeMount
// volumeDevices is the list of block devices to be used by the container. // volumeDevices is the list of block devices to be used by the container.
// This is a beta feature.
// +optional // +optional
VolumeDevices []VolumeDevice VolumeDevices []VolumeDevice
// Probes are not allowed for ephemeral containers. // Probes are not allowed for ephemeral containers.

View File

@ -1475,204 +1475,168 @@ func TestValidatePersistentVolumeClaimUpdate(t *testing.T) {
oldClaim *core.PersistentVolumeClaim oldClaim *core.PersistentVolumeClaim
newClaim *core.PersistentVolumeClaim newClaim *core.PersistentVolumeClaim
enableResize bool enableResize bool
enableBlock bool
}{ }{
"valid-update-volumeName-only": { "valid-update-volumeName-only": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validUpdateClaim, newClaim: validUpdateClaim,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"valid-no-op-update": { "valid-no-op-update": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validUpdateClaim, oldClaim: validUpdateClaim,
newClaim: validUpdateClaim, newClaim: validUpdateClaim,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"invalid-update-change-resources-on-bound-claim": { "invalid-update-change-resources-on-bound-claim": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validUpdateClaim, oldClaim: validUpdateClaim,
newClaim: invalidUpdateClaimResources, newClaim: invalidUpdateClaimResources,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"invalid-update-change-access-modes-on-bound-claim": { "invalid-update-change-access-modes-on-bound-claim": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validUpdateClaim, oldClaim: validUpdateClaim,
newClaim: invalidUpdateClaimAccessModes, newClaim: invalidUpdateClaimAccessModes,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"valid-update-volume-mode-block-to-block": { "valid-update-volume-mode-block-to-block": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaimVolumeModeBlock, oldClaim: validClaimVolumeModeBlock,
newClaim: validClaimVolumeModeBlock, newClaim: validClaimVolumeModeBlock,
enableResize: false, enableResize: false,
enableBlock: true,
}, },
"valid-update-volume-mode-file-to-file": { "valid-update-volume-mode-file-to-file": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaimVolumeModeFile, oldClaim: validClaimVolumeModeFile,
newClaim: validClaimVolumeModeFile, newClaim: validClaimVolumeModeFile,
enableResize: false, enableResize: false,
enableBlock: true,
}, },
"invalid-update-volume-mode-to-block": { "invalid-update-volume-mode-to-block": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaimVolumeModeFile, oldClaim: validClaimVolumeModeFile,
newClaim: validClaimVolumeModeBlock, newClaim: validClaimVolumeModeBlock,
enableResize: false, enableResize: false,
enableBlock: true,
}, },
"invalid-update-volume-mode-to-file": { "invalid-update-volume-mode-to-file": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaimVolumeModeBlock, oldClaim: validClaimVolumeModeBlock,
newClaim: validClaimVolumeModeFile, newClaim: validClaimVolumeModeFile,
enableResize: false, enableResize: false,
enableBlock: true,
}, },
"invalid-update-volume-mode-nil-to-file": { "invalid-update-volume-mode-nil-to-file": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: invalidClaimVolumeModeNil, oldClaim: invalidClaimVolumeModeNil,
newClaim: validClaimVolumeModeFile, newClaim: validClaimVolumeModeFile,
enableResize: false, enableResize: false,
enableBlock: true,
}, },
"invalid-update-volume-mode-nil-to-block": { "invalid-update-volume-mode-nil-to-block": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: invalidClaimVolumeModeNil, oldClaim: invalidClaimVolumeModeNil,
newClaim: validClaimVolumeModeBlock, newClaim: validClaimVolumeModeBlock,
enableResize: false, enableResize: false,
enableBlock: true,
}, },
"invalid-update-volume-mode-block-to-nil": { "invalid-update-volume-mode-block-to-nil": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaimVolumeModeBlock, oldClaim: validClaimVolumeModeBlock,
newClaim: invalidClaimVolumeModeNil, newClaim: invalidClaimVolumeModeNil,
enableResize: false, enableResize: false,
enableBlock: true,
}, },
"invalid-update-volume-mode-file-to-nil": { "invalid-update-volume-mode-file-to-nil": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaimVolumeModeFile, oldClaim: validClaimVolumeModeFile,
newClaim: invalidClaimVolumeModeNil, newClaim: invalidClaimVolumeModeNil,
enableResize: false, enableResize: false,
enableBlock: true,
}, },
"invalid-update-volume-mode-empty-to-mode": { "invalid-update-volume-mode-empty-to-mode": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validClaimVolumeModeBlock, newClaim: validClaimVolumeModeBlock,
enableResize: false, enableResize: false,
enableBlock: true,
}, },
"invalid-update-volume-mode-mode-to-empty": { "invalid-update-volume-mode-mode-to-empty": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaimVolumeModeBlock, oldClaim: validClaimVolumeModeBlock,
newClaim: validClaim, newClaim: validClaim,
enableResize: false, enableResize: false,
enableBlock: true,
},
// with the new validation changes this test should not fail
"noop-update-volumemode-allowed": {
isExpectedFailure: false,
oldClaim: validClaimVolumeModeFile,
newClaim: validClaimVolumeModeFile,
enableResize: false,
enableBlock: false,
}, },
"invalid-update-change-storage-class-annotation-after-creation": { "invalid-update-change-storage-class-annotation-after-creation": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaimStorageClass, oldClaim: validClaimStorageClass,
newClaim: invalidUpdateClaimStorageClass, newClaim: invalidUpdateClaimStorageClass,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"valid-update-mutable-annotation": { "valid-update-mutable-annotation": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaimAnnotation, oldClaim: validClaimAnnotation,
newClaim: validUpdateClaimMutableAnnotation, newClaim: validUpdateClaimMutableAnnotation,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"valid-update-add-annotation": { "valid-update-add-annotation": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validAddClaimAnnotation, newClaim: validAddClaimAnnotation,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"valid-size-update-resize-disabled": { "valid-size-update-resize-disabled": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validSizeUpdate, newClaim: validSizeUpdate,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"valid-size-update-resize-enabled": { "valid-size-update-resize-enabled": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validSizeUpdate, newClaim: validSizeUpdate,
enableResize: true, enableResize: true,
enableBlock: false,
}, },
"invalid-size-update-resize-enabled": { "invalid-size-update-resize-enabled": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: invalidSizeUpdate, newClaim: invalidSizeUpdate,
enableResize: true, enableResize: true,
enableBlock: false,
}, },
"unbound-size-update-resize-enabled": { "unbound-size-update-resize-enabled": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: unboundSizeUpdate, newClaim: unboundSizeUpdate,
enableResize: true, enableResize: true,
enableBlock: false,
}, },
"valid-upgrade-storage-class-annotation-to-spec": { "valid-upgrade-storage-class-annotation-to-spec": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaimStorageClass, oldClaim: validClaimStorageClass,
newClaim: validClaimStorageClassInSpec, newClaim: validClaimStorageClassInSpec,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"invalid-upgrade-storage-class-annotation-to-spec": { "invalid-upgrade-storage-class-annotation-to-spec": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaimStorageClass, oldClaim: validClaimStorageClass,
newClaim: invalidClaimStorageClassInSpec, newClaim: invalidClaimStorageClassInSpec,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"valid-upgrade-storage-class-annotation-to-annotation-and-spec": { "valid-upgrade-storage-class-annotation-to-annotation-and-spec": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaimStorageClass, oldClaim: validClaimStorageClass,
newClaim: validClaimStorageClassInAnnotationAndSpec, newClaim: validClaimStorageClassInAnnotationAndSpec,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"invalid-upgrade-storage-class-annotation-to-annotation-and-spec": { "invalid-upgrade-storage-class-annotation-to-annotation-and-spec": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaimStorageClass, oldClaim: validClaimStorageClass,
newClaim: invalidClaimStorageClassInAnnotationAndSpec, newClaim: invalidClaimStorageClassInAnnotationAndSpec,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"invalid-upgrade-storage-class-in-spec": { "invalid-upgrade-storage-class-in-spec": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaimStorageClassInSpec, oldClaim: validClaimStorageClassInSpec,
newClaim: invalidClaimStorageClassInSpec, newClaim: invalidClaimStorageClassInSpec,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
"invalid-downgrade-storage-class-spec-to-annotation": { "invalid-downgrade-storage-class-spec-to-annotation": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaimStorageClassInSpec, oldClaim: validClaimStorageClassInSpec,
newClaim: validClaimStorageClass, newClaim: validClaimStorageClass,
enableResize: false, enableResize: false,
enableBlock: false,
}, },
} }
@ -1680,7 +1644,6 @@ func TestValidatePersistentVolumeClaimUpdate(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
// ensure we have a resource version specified for updates // ensure we have a resource version specified for updates
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandPersistentVolumes, scenario.enableResize)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandPersistentVolumes, scenario.enableResize)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)()
scenario.oldClaim.ResourceVersion = "1" scenario.oldClaim.ResourceVersion = "1"
scenario.newClaim.ResourceVersion = "1" scenario.newClaim.ResourceVersion = "1"
errs := ValidatePersistentVolumeClaimUpdate(scenario.newClaim, scenario.oldClaim) errs := ValidatePersistentVolumeClaimUpdate(scenario.newClaim, scenario.oldClaim)
@ -4092,9 +4055,6 @@ func TestHugePagesIsolation(t *testing.T) {
} }
func TestPVCVolumeMode(t *testing.T) { func TestPVCVolumeMode(t *testing.T) {
// Enable feature BlockVolume for PVC
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
block := core.PersistentVolumeBlock block := core.PersistentVolumeBlock
file := core.PersistentVolumeFilesystem file := core.PersistentVolumeFilesystem
fake := core.PersistentVolumeMode("fake") fake := core.PersistentVolumeMode("fake")
@ -4125,9 +4085,6 @@ func TestPVCVolumeMode(t *testing.T) {
} }
func TestPVVolumeMode(t *testing.T) { func TestPVVolumeMode(t *testing.T) {
// Enable feature BlockVolume for PVC
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
block := core.PersistentVolumeBlock block := core.PersistentVolumeBlock
file := core.PersistentVolumeFilesystem file := core.PersistentVolumeFilesystem
fake := core.PersistentVolumeMode("fake") fake := core.PersistentVolumeMode("fake")

View File

@ -22,10 +22,7 @@ import (
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
storage "k8s.io/api/storage/v1" storage "k8s.io/api/storage/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilfeature "k8s.io/apiserver/pkg/util/feature"
featuregatetesting "k8s.io/component-base/featuregate/testing"
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util" pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
"k8s.io/kubernetes/pkg/features"
) )
// Test single call to syncClaim and syncVolume methods. // Test single call to syncClaim and syncVolume methods.
@ -611,68 +608,6 @@ func TestSync(t *testing.T) {
}, []*v1.Pod{}) }, []*v1.Pod{})
} }
func TestSyncBlockVolumeDisabled(t *testing.T) {
modeBlock := v1.PersistentVolumeBlock
modeFile := v1.PersistentVolumeFilesystem
// All of these should bind as feature set is not enabled for BlockVolume
// meaning volumeMode will be ignored and dropped
tests := []controllerTest{
{
// syncVolume binds a requested block claim to a block volume
"14-1 - binding to volumeMode block",
withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
withClaimVolumeMode(&modeBlock, newClaimArray("claim14-1", "uid14-1", "10Gi", "", v1.ClaimPending, nil)),
withClaimVolumeMode(&modeBlock, newClaimArray("claim14-1", "uid14-1", "10Gi", "", v1.ClaimPending, nil)),
noevents, noerrors, testSyncClaim,
},
{
// syncVolume binds a requested filesystem claim to a filesystem volume
"14-2 - binding to volumeMode filesystem",
withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-2", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-2", "10Gi", "uid14-2", "claim14-2", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, pvutil.AnnBoundByController)),
withClaimVolumeMode(&modeFile, newClaimArray("claim14-2", "uid14-2", "10Gi", "", v1.ClaimPending, nil)),
withClaimVolumeMode(&modeFile, newClaimArray("claim14-2", "uid14-2", "10Gi", "volume14-2", v1.ClaimBound, nil, pvutil.AnnBoundByController, pvutil.AnnBindCompleted)),
noevents, noerrors, testSyncClaim,
},
{
// syncVolume binds an unspecified volumemode for claim to a specified filesystem volume
"14-3 - binding to volumeMode filesystem using default for claim",
withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-3", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-3", "10Gi", "uid14-3", "claim14-3", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, pvutil.AnnBoundByController)),
withClaimVolumeMode(nil, newClaimArray("claim14-3", "uid14-3", "10Gi", "", v1.ClaimPending, nil)),
withClaimVolumeMode(nil, newClaimArray("claim14-3", "uid14-3", "10Gi", "volume14-3", v1.ClaimBound, nil, pvutil.AnnBoundByController, pvutil.AnnBindCompleted)),
noevents, noerrors, testSyncClaim,
},
{
// syncVolume binds a requested filesystem claim to an unspecified volumeMode for volume
"14-4 - binding to unspecified volumeMode using requested filesystem for claim",
withVolumeVolumeMode(nil, newVolumeArray("volume14-4", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
withVolumeVolumeMode(nil, newVolumeArray("volume14-4", "10Gi", "uid14-4", "claim14-4", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, pvutil.AnnBoundByController)),
withClaimVolumeMode(&modeFile, newClaimArray("claim14-4", "uid14-4", "10Gi", "", v1.ClaimPending, nil)),
withClaimVolumeMode(&modeFile, newClaimArray("claim14-4", "uid14-4", "10Gi", "volume14-4", v1.ClaimBound, nil, pvutil.AnnBoundByController, pvutil.AnnBindCompleted)),
noevents, noerrors, testSyncClaim,
},
{
// syncVolume binds a requested filesystem claim to an unspecified volumeMode for volume
"14-5 - binding different volumeModes should be ignored",
withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-5", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-5", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
withClaimVolumeMode(&modeFile, newClaimArray("claim14-5", "uid14-5", "10Gi", "", v1.ClaimPending, nil)),
withClaimVolumeMode(&modeFile, newClaimArray("claim14-5", "uid14-5", "10Gi", "", v1.ClaimPending, nil)),
noevents, noerrors, testSyncClaim,
},
}
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
runSyncTests(t, tests, []*storage.StorageClass{
{
ObjectMeta: metav1.ObjectMeta{Name: classWait},
VolumeBindingMode: &modeWait,
},
}, []*v1.Pod{})
}
func TestSyncBlockVolume(t *testing.T) { func TestSyncBlockVolume(t *testing.T) {
modeBlock := v1.PersistentVolumeBlock modeBlock := v1.PersistentVolumeBlock
modeFile := v1.PersistentVolumeFilesystem modeFile := v1.PersistentVolumeFilesystem
@ -853,8 +788,6 @@ func TestSyncBlockVolume(t *testing.T) {
}, },
} }
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
runSyncTests(t, tests, []*storage.StorageClass{}, []*v1.Pod{}) runSyncTests(t, tests, []*storage.StorageClass{}, []*v1.Pod{})
} }

View File

@ -1060,91 +1060,56 @@ func TestVolumeModeCheck(t *testing.T) {
isExpectedMismatch bool isExpectedMismatch bool
vol *v1.PersistentVolume vol *v1.PersistentVolume
pvc *v1.PersistentVolumeClaim pvc *v1.PersistentVolumeClaim
enableBlock bool
}{ }{
"feature enabled - pvc block and pv filesystem": { "pvc block and pv filesystem": {
isExpectedMismatch: true, isExpectedMismatch: true,
vol: createVolumeModeFilesystemTestVolume(), vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil), pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: true,
}, },
"feature enabled - pvc filesystem and pv block": { "pvc filesystem and pv block": {
isExpectedMismatch: true, isExpectedMismatch: true,
vol: createVolumeModeBlockTestVolume(), vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil), pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: true,
}, },
"feature enabled - pvc block and pv block": { "pvc block and pv block": {
isExpectedMismatch: false, isExpectedMismatch: false,
vol: createVolumeModeBlockTestVolume(), vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil), pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: true,
}, },
"feature enabled - pvc filesystem and pv filesystem": { "pvc filesystem and pv filesystem": {
isExpectedMismatch: false, isExpectedMismatch: false,
vol: createVolumeModeFilesystemTestVolume(), vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil), pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: true,
}, },
"feature enabled - pvc filesystem and pv nil": { "pvc filesystem and pv nil": {
isExpectedMismatch: false, isExpectedMismatch: false,
vol: createVolumeModeNilTestVolume(), vol: createVolumeModeNilTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil), pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: true,
}, },
"feature enabled - pvc nil and pv filesystem": { "pvc nil and pv filesystem": {
isExpectedMismatch: false, isExpectedMismatch: false,
vol: createVolumeModeFilesystemTestVolume(), vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", nil, nil), pvc: makeVolumeModePVC("8G", nil, nil),
enableBlock: true,
}, },
"feature enabled - pvc nil and pv nil": { "pvc nil and pv nil": {
isExpectedMismatch: false, isExpectedMismatch: false,
vol: createVolumeModeNilTestVolume(), vol: createVolumeModeNilTestVolume(),
pvc: makeVolumeModePVC("8G", nil, nil), pvc: makeVolumeModePVC("8G", nil, nil),
enableBlock: true,
}, },
"feature enabled - pvc nil and pv block": { "pvc nil and pv block": {
isExpectedMismatch: true, isExpectedMismatch: true,
vol: createVolumeModeBlockTestVolume(), vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", nil, nil), pvc: makeVolumeModePVC("8G", nil, nil),
enableBlock: true,
}, },
"feature enabled - pvc block and pv nil": { "pvc block and pv nil": {
isExpectedMismatch: true, isExpectedMismatch: true,
vol: createVolumeModeNilTestVolume(), vol: createVolumeModeNilTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil), pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: true,
},
"feature disabled - pvc block and pv filesystem": {
isExpectedMismatch: true,
vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: false,
},
"feature disabled - pvc filesystem and pv block": {
isExpectedMismatch: true,
vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: false,
},
"feature disabled - pvc block and pv block": {
isExpectedMismatch: true,
vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: false,
},
"feature disabled - pvc filesystem and pv filesystem": {
isExpectedMismatch: false,
vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: false,
}, },
} }
for name, scenario := range scenarios { for name, scenario := range scenarios {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)()
expectedMismatch := pvutil.CheckVolumeModeMismatches(&scenario.pvc.Spec, &scenario.vol.Spec) expectedMismatch := pvutil.CheckVolumeModeMismatches(&scenario.pvc.Spec, &scenario.vol.Spec)
// expected to match but either got an error or no returned pvmatch // expected to match but either got an error or no returned pvmatch
if expectedMismatch && !scenario.isExpectedMismatch { if expectedMismatch && !scenario.isExpectedMismatch {
@ -1167,73 +1132,46 @@ func TestFilteringVolumeModes(t *testing.T) {
isExpectedMatch bool isExpectedMatch bool
vol persistentVolumeOrderedIndex vol persistentVolumeOrderedIndex
pvc *v1.PersistentVolumeClaim pvc *v1.PersistentVolumeClaim
enableBlock bool
}{ }{
"1-1 feature enabled - pvc block and pv filesystem": { "pvc block and pv filesystem": {
isExpectedMatch: false, isExpectedMatch: false,
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()), vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
pvc: makeVolumeModePVC("8G", &blockMode, nil), pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: true,
}, },
"1-2 feature enabled - pvc filesystem and pv block": { "pvc filesystem and pv block": {
isExpectedMatch: false, isExpectedMatch: false,
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()), vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil), pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: true,
}, },
"1-3 feature enabled - pvc block and pv no mode with default filesystem": { "pvc block and pv no mode with default filesystem": {
isExpectedMatch: false, isExpectedMatch: false,
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()), vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
pvc: makeVolumeModePVC("8G", &blockMode, nil), pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: true,
}, },
"1-4 feature enabled - pvc no mode defaulted to filesystem and pv block": { "pvc no mode defaulted to filesystem and pv block": {
isExpectedMatch: false, isExpectedMatch: false,
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()), vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil), pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: true,
}, },
"1-5 feature enabled - pvc block and pv block": { "pvc block and pv block": {
isExpectedMatch: true, isExpectedMatch: true,
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()), vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
pvc: makeVolumeModePVC("8G", &blockMode, nil), pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: true,
}, },
"1-6 feature enabled - pvc filesystem and pv filesystem": { "pvc filesystem and pv filesystem": {
isExpectedMatch: true, isExpectedMatch: true,
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()), vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil), pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: true,
}, },
"1-7 feature enabled - pvc mode is nil and defaulted and pv mode is nil and defaulted": { "pvc mode is nil and defaulted and pv mode is nil and defaulted": {
isExpectedMatch: true, isExpectedMatch: true,
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()), vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil), pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: true,
},
"2-1 feature disabled - pvc mode is nil and pv mode is nil": {
isExpectedMatch: true,
vol: createTestVolOrderedIndex(testVolume("nomode-1", "8G")),
pvc: makeVolumeModePVC("8G", nil, nil),
enableBlock: false,
},
"2-2 feature disabled - pvc mode is block and pv mode is block - fields should be dropped by api and not analyzed with gate disabled": {
isExpectedMatch: false,
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: false,
},
"2-3 feature disabled - pvc mode is filesystem and pv mode is filesystem - fields should be dropped by api and not analyzed with gate disabled": {
isExpectedMatch: true,
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: false,
}, },
} }
for name, scenario := range scenarios { for name, scenario := range scenarios {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)()
pvmatch, err := scenario.vol.findBestMatchForClaim(scenario.pvc, false) pvmatch, err := scenario.vol.findBestMatchForClaim(scenario.pvc, false)
// expected to match but either got an error or no returned pvmatch // expected to match but either got an error or no returned pvmatch
if pvmatch == nil && scenario.isExpectedMatch { if pvmatch == nil && scenario.isExpectedMatch {

View File

@ -6,7 +6,6 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/testing", importpath = "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/testing",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//pkg/features:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
@ -14,7 +13,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",

View File

@ -30,11 +30,9 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
core "k8s.io/client-go/testing" core "k8s.io/client-go/testing"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/kubernetes/pkg/features"
) )
// ErrVersionConflict is the error returned when resource version of requested // ErrVersionConflict is the error returned when resource version of requested
@ -114,7 +112,7 @@ func (r *VolumeReactor) React(action core.Action) (handled bool, ret runtime.Obj
} }
// mimic apiserver defaulting // mimic apiserver defaulting
if volume.Spec.VolumeMode == nil && utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { if volume.Spec.VolumeMode == nil {
volume.Spec.VolumeMode = new(v1.PersistentVolumeMode) volume.Spec.VolumeMode = new(v1.PersistentVolumeMode)
*volume.Spec.VolumeMode = v1.PersistentVolumeFilesystem *volume.Spec.VolumeMode = v1.PersistentVolumeFilesystem
} }

View File

@ -307,23 +307,6 @@ func FindMatchingVolume(
// CheckVolumeModeMismatches is a convenience method that checks volumeMode for PersistentVolume // CheckVolumeModeMismatches is a convenience method that checks volumeMode for PersistentVolume
// and PersistentVolumeClaims // and PersistentVolumeClaims
func CheckVolumeModeMismatches(pvcSpec *v1.PersistentVolumeClaimSpec, pvSpec *v1.PersistentVolumeSpec) bool { func CheckVolumeModeMismatches(pvcSpec *v1.PersistentVolumeClaimSpec, pvSpec *v1.PersistentVolumeSpec) bool {
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
if pvcSpec.VolumeMode != nil && *pvcSpec.VolumeMode == v1.PersistentVolumeBlock {
// Block PVC does not match anything when the feature is off. We explicitly want
// to prevent binding block PVC to filesystem PV.
// The PVC should be ignored by PV controller.
return true
}
if pvSpec.VolumeMode != nil && *pvSpec.VolumeMode == v1.PersistentVolumeBlock {
// Block PV does not match anything when the feature is off. We explicitly want
// to prevent binding block PV to filesystem PVC.
// The PV should be ignored by PV controller.
return true
}
// Both PV + PVC are not block.
return false
}
// In HA upgrades, we cannot guarantee that the apiserver is on a version >= controller-manager. // In HA upgrades, we cannot guarantee that the apiserver is on a version >= controller-manager.
// So we default a nil volumeMode to filesystem // So we default a nil volumeMode to filesystem
requestedVolumeMode := v1.PersistentVolumeFilesystem requestedVolumeMode := v1.PersistentVolumeFilesystem

View File

@ -183,7 +183,8 @@ const (
// owner: @screeley44 // owner: @screeley44
// alpha: v1.9 // alpha: v1.9
// beta: v1.13 // beta: v1.13
// ga: v1.18
// //
// Enable Block volume support in containers. // Enable Block volume support in containers.
BlockVolume featuregate.Feature = "BlockVolume" BlockVolume featuregate.Feature = "BlockVolume"
@ -295,7 +296,8 @@ const (
// owner: @vladimirvivien // owner: @vladimirvivien
// alpha: v1.11 // alpha: v1.11
// beta: v1.14 // beta: v1.14
// ga: v1.18
// //
// Enables CSI to use raw block storage volumes // Enables CSI to use raw block storage volumes
CSIBlockVolume featuregate.Feature = "CSIBlockVolume" CSIBlockVolume featuregate.Feature = "CSIBlockVolume"
@ -594,7 +596,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
NodeDisruptionExclusion: {Default: false, PreRelease: featuregate.Alpha}, NodeDisruptionExclusion: {Default: false, PreRelease: featuregate.Alpha},
CSIDriverRegistry: {Default: true, PreRelease: featuregate.Beta}, CSIDriverRegistry: {Default: true, PreRelease: featuregate.Beta},
CSINodeInfo: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.19 CSINodeInfo: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.19
BlockVolume: {Default: true, PreRelease: featuregate.Beta}, BlockVolume: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.20
StorageObjectInUseProtection: {Default: true, PreRelease: featuregate.GA}, StorageObjectInUseProtection: {Default: true, PreRelease: featuregate.GA},
ResourceLimitsPriorityFunction: {Default: false, PreRelease: featuregate.Alpha}, ResourceLimitsPriorityFunction: {Default: false, PreRelease: featuregate.Alpha},
SupportIPVSProxyMode: {Default: true, PreRelease: featuregate.GA}, SupportIPVSProxyMode: {Default: true, PreRelease: featuregate.GA},
@ -621,7 +623,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
VolumeSubpath: {Default: true, PreRelease: featuregate.GA}, VolumeSubpath: {Default: true, PreRelease: featuregate.GA},
BalanceAttachedNodeVolumes: {Default: false, PreRelease: featuregate.Alpha}, BalanceAttachedNodeVolumes: {Default: false, PreRelease: featuregate.Alpha},
VolumeSubpathEnvExpansion: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.19, VolumeSubpathEnvExpansion: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.19,
CSIBlockVolume: {Default: true, PreRelease: featuregate.Beta}, CSIBlockVolume: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.20
CSIInlineVolume: {Default: true, PreRelease: featuregate.Beta}, CSIInlineVolume: {Default: true, PreRelease: featuregate.Beta},
RuntimeClass: {Default: true, PreRelease: featuregate.Beta}, RuntimeClass: {Default: true, PreRelease: featuregate.Beta},
NodeLease: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, NodeLease: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},

View File

@ -457,15 +457,12 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *v1.Pod, container *v1.Contai
opts.PortMappings = kubecontainer.MakePortMappings(container) opts.PortMappings = kubecontainer.MakePortMappings(container)
// TODO: remove feature gate check after no longer needed blkutil := volumepathhandler.NewBlockVolumePathHandler()
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { blkVolumes, err := kl.makeBlockVolumes(pod, container, volumes, blkutil)
blkutil := volumepathhandler.NewBlockVolumePathHandler() if err != nil {
blkVolumes, err := kl.makeBlockVolumes(pod, container, volumes, blkutil) return nil, nil, err
if err != nil {
return nil, nil, err
}
opts.Devices = append(opts.Devices, blkVolumes...)
} }
opts.Devices = append(opts.Devices, blkVolumes...)
envs, err := kl.makeEnvironmentVariables(pod, container, podIP, podIPs) envs, err := kl.makeEnvironmentVariables(pod, container, podIP, podIPs)
if err != nil { if err != nil {

View File

@ -48,7 +48,6 @@ go_test(
srcs = ["volume_manager_test.go"], srcs = ["volume_manager_test.go"],
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//pkg/features:go_default_library",
"//pkg/kubelet/config:go_default_library", "//pkg/kubelet/config:go_default_library",
"//pkg/kubelet/configmap:go_default_library", "//pkg/kubelet/configmap:go_default_library",
"//pkg/kubelet/container/testing:go_default_library", "//pkg/kubelet/container/testing:go_default_library",
@ -66,12 +65,10 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library",
"//staging/src/k8s.io/client-go/util/testing:go_default_library", "//staging/src/k8s.io/client-go/util/testing:go_default_library",
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
"//vendor/k8s.io/utils/mount:go_default_library", "//vendor/k8s.io/utils/mount:go_default_library",
], ],
) )

View File

@ -541,14 +541,12 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec(
podVolume.Name, podVolume.Name,
volumeMode) volumeMode)
} }
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { // Error if a container has volumeDevices but the volumeMode of PVC isn't Block
// Error if a container has volumeDevices but the volumeMode of PVC isn't Block if devices.Has(podVolume.Name) && volumeMode != v1.PersistentVolumeBlock {
if devices.Has(podVolume.Name) && volumeMode != v1.PersistentVolumeBlock { return nil, nil, "", fmt.Errorf(
return nil, nil, "", fmt.Errorf( "volume %s has volumeMode %s, but is specified in volumeDevices",
"volume %s has volumeMode %s, but is specified in volumeDevices", podVolume.Name,
podVolume.Name, volumeMode)
volumeMode)
}
} }
return pvc, volumeSpec, volumeGidValue, nil return pvc, volumeSpec, volumeGidValue, nil
} }

View File

@ -269,9 +269,6 @@ func TestFindAndRemoveDeletedPodsWithActualState(t *testing.T) {
} }
func TestFindAndAddNewPods_FindAndRemoveDeletedPods_Valid_Block_VolumeDevices(t *testing.T) { func TestFindAndAddNewPods_FindAndRemoveDeletedPods_Valid_Block_VolumeDevices(t *testing.T) {
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
// create dswp // create dswp
mode := v1.PersistentVolumeBlock mode := v1.PersistentVolumeBlock
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
@ -471,9 +468,6 @@ func TestCreateVolumeSpec_Valid_Nil_VolumeMounts(t *testing.T) {
} }
func TestCreateVolumeSpec_Valid_Block_VolumeDevices(t *testing.T) { func TestCreateVolumeSpec_Valid_Block_VolumeDevices(t *testing.T) {
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
// create dswp // create dswp
mode := v1.PersistentVolumeBlock mode := v1.PersistentVolumeBlock
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
@ -520,9 +514,6 @@ func TestCreateVolumeSpec_Valid_Block_VolumeDevices(t *testing.T) {
} }
func TestCreateVolumeSpec_Invalid_File_VolumeDevices(t *testing.T) { func TestCreateVolumeSpec_Invalid_File_VolumeDevices(t *testing.T) {
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
// create dswp // create dswp
mode := v1.PersistentVolumeFilesystem mode := v1.PersistentVolumeFilesystem
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
@ -569,9 +560,6 @@ func TestCreateVolumeSpec_Invalid_File_VolumeDevices(t *testing.T) {
} }
func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) { func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) {
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
// create dswp // create dswp
mode := v1.PersistentVolumeBlock mode := v1.PersistentVolumeBlock
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
@ -617,56 +605,6 @@ func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) {
} }
} }
func TestCreateVolumeSpec_Invalid_Block_VolumeMounts_Disabled(t *testing.T) {
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
// create dswp
mode := v1.PersistentVolumeBlock
pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{
Name: "dswp-test-volume-name",
},
Spec: v1.PersistentVolumeSpec{
ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "block-bound"},
VolumeMode: &mode,
},
}
pvc := &v1.PersistentVolumeClaim{
Spec: v1.PersistentVolumeClaimSpec{
VolumeName: "dswp-test-volume-name",
VolumeMode: &mode,
},
Status: v1.PersistentVolumeClaimStatus{
Phase: v1.ClaimBound,
},
}
dswp, fakePodManager, _ := createDswpWithVolume(t, pv, pvc)
// create pod
containers := []v1.Container{
{
VolumeMounts: []v1.VolumeMount{
{
Name: "dswp-test-volume-name",
MountPath: "/mnt",
},
},
},
}
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "block-bound", containers)
fakePodManager.AddPod(pod)
mountsMap, devicesMap := util.GetPodVolumeNames(pod)
_, volumeSpec, _, err :=
dswp.createVolumeSpec(pod.Spec.Volumes[0], pod.Name, pod.Namespace, mountsMap, devicesMap)
// Assert
if volumeSpec != nil || err == nil {
t.Fatalf("Unexpected volumeMode and volumeMounts/volumeDevices combination is accepted")
}
}
func TestCheckVolumeFSResize(t *testing.T) { func TestCheckVolumeFSResize(t *testing.T) {
setCapacity := func(pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim, capacity int) { setCapacity := func(pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim, capacity int) {
pv.Spec.Capacity = volumeCapacity(capacity) pv.Spec.Capacity = volumeCapacity(capacity)

View File

@ -487,8 +487,7 @@ func (rc *reconciler) reconstructVolume(volume podVolume) (*reconstructedVolume,
if err != nil { if err != nil {
return nil, err return nil, err
} }
// TODO: remove feature gate check after no longer needed if volume.volumeMode == v1.PersistentVolumeBlock && mapperPlugin == nil {
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && volume.volumeMode == v1.PersistentVolumeBlock && mapperPlugin == nil {
return nil, fmt.Errorf("could not find block volume plugin %q (spec.Name: %q) pod %q (UID: %q)", volume.pluginName, volume.volumeSpecName, volume.podName, pod.UID) return nil, fmt.Errorf("could not find block volume plugin %q (spec.Name: %q) pod %q (UID: %q)", volume.pluginName, volume.volumeSpecName, volume.podName, pod.UID)
} }
@ -521,8 +520,7 @@ func (rc *reconciler) reconstructVolume(volume podVolume) (*reconstructedVolume,
// Path to the mount or block device to check // Path to the mount or block device to check
var checkPath string var checkPath string
// TODO: remove feature gate check after no longer needed if volume.volumeMode == v1.PersistentVolumeBlock {
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && volume.volumeMode == v1.PersistentVolumeBlock {
var newMapperErr error var newMapperErr error
volumeMapper, newMapperErr = mapperPlugin.NewBlockVolumeMapper( volumeMapper, newMapperErr = mapperPlugin.NewBlockVolumeMapper(
volumeSpec, volumeSpec,
@ -697,12 +695,10 @@ func getVolumesFromPodDir(podDir string) ([]podVolume, error) {
volumesDirs := map[v1.PersistentVolumeMode]string{ volumesDirs := map[v1.PersistentVolumeMode]string{
v1.PersistentVolumeFilesystem: path.Join(podDir, config.DefaultKubeletVolumesDirName), v1.PersistentVolumeFilesystem: path.Join(podDir, config.DefaultKubeletVolumesDirName),
} }
// TODO: remove feature gate check after no longer needed // Find block volume information
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { // ex. block volume: /pods/{podUid}/volumeDevices/{escapeQualifiedPluginName}/{volumeName}
// Find block volume information volumesDirs[v1.PersistentVolumeBlock] = path.Join(podDir, config.DefaultKubeletVolumeDevicesDirName)
// ex. block volume: /pods/{podUid}/volumeDevices/{escapeQualifiedPluginName}/{volumeName}
volumesDirs[v1.PersistentVolumeBlock] = path.Join(podDir, config.DefaultKubeletVolumeDevicesDirName)
}
for volumeMode, volumesDir := range volumesDirs { for volumeMode, volumesDir := range volumesDirs {
var volumesDirInfo []os.FileInfo var volumesDirInfo []os.FileInfo
if volumesDirInfo, err = ioutil.ReadDir(volumesDir); err != nil { if volumesDirInfo, err = ioutil.ReadDir(volumesDir); err != nil {

View File

@ -443,9 +443,6 @@ func Test_Run_Positive_VolumeUnmountControllerAttachEnabled(t *testing.T) {
// Verifies there are attach/get map paths/setupDevice calls and // Verifies there are attach/get map paths/setupDevice calls and
// no detach/teardownDevice calls. // no detach/teardownDevice calls.
func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) { func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) {
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
pod := &v1.Pod{ pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "pod1", Name: "pod1",
@ -543,9 +540,6 @@ func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) {
// and no teardownDevice call. // and no teardownDevice call.
// Verifies there are no attach/detach calls. // Verifies there are no attach/detach calls.
func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) { func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) {
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
pod := &v1.Pod{ pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "pod1", Name: "pod1",
@ -647,9 +641,6 @@ func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) {
// Deletes volume/pod from desired state of world. // Deletes volume/pod from desired state of world.
// Verifies one detach/teardownDevice calls are issued. // Verifies one detach/teardownDevice calls are issued.
func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) { func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) {
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
pod := &v1.Pod{ pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "pod1", Name: "pod1",
@ -758,9 +749,6 @@ func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) {
// Verifies one teardownDevice call is made. // Verifies one teardownDevice call is made.
// Verifies there are no attach/detach calls made. // Verifies there are no attach/detach calls made.
func Test_Run_Positive_VolumeUnmapControllerAttachEnabled(t *testing.T) { func Test_Run_Positive_VolumeUnmapControllerAttachEnabled(t *testing.T) {
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
pod := &v1.Pod{ pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "pod1", Name: "pod1",
@ -883,9 +871,6 @@ func Test_GenerateMapVolumeFunc_Plugin_Not_Found(t *testing.T) {
}, },
} }
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
for name, tc := range testCases { for name, tc := range testCases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
volumePluginMgr := &volume.VolumePluginMgr{} volumePluginMgr := &volume.VolumePluginMgr{}
@ -937,9 +922,6 @@ func Test_GenerateUnmapVolumeFunc_Plugin_Not_Found(t *testing.T) {
}, },
} }
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
for name, tc := range testCases { for name, tc := range testCases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
volumePluginMgr := &volume.VolumePluginMgr{} volumePluginMgr := &volume.VolumePluginMgr{}
@ -983,9 +965,6 @@ func Test_GenerateUnmapDeviceFunc_Plugin_Not_Found(t *testing.T) {
}, },
} }
// Enable BlockVolume feature gate
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
for name, tc := range testCases { for name, tc := range testCases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
volumePluginMgr := &volume.VolumePluginMgr{} volumePluginMgr := &volume.VolumePluginMgr{}

View File

@ -30,13 +30,10 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
utilfeature "k8s.io/apiserver/pkg/util/feature"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
utiltesting "k8s.io/client-go/util/testing" utiltesting "k8s.io/client-go/util/testing"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/kubelet/config" "k8s.io/kubernetes/pkg/kubelet/config"
"k8s.io/kubernetes/pkg/kubelet/configmap" "k8s.io/kubernetes/pkg/kubelet/configmap"
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
@ -58,11 +55,10 @@ const (
func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) { func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
pvMode, podMode v1.PersistentVolumeMode pvMode, podMode v1.PersistentVolumeMode
disableBlockFeature bool expectMount bool
expectMount bool expectError bool
expectError bool
}{ }{
{ {
name: "filesystem volume", name: "filesystem volume",
@ -78,14 +74,6 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
expectMount: true, expectMount: true,
expectError: false, expectError: false,
}, },
{
name: "block volume with block feature off",
pvMode: v1.PersistentVolumeBlock,
podMode: v1.PersistentVolumeBlock,
disableBlockFeature: true,
expectMount: false,
expectError: false,
},
{ {
name: "mismatched volume", name: "mismatched volume",
pvMode: v1.PersistentVolumeBlock, pvMode: v1.PersistentVolumeBlock,
@ -97,10 +85,6 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
if test.disableBlockFeature {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
}
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest") tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
if err != nil { if err != nil {
t.Fatalf("can't make a temp dir: %v", err) t.Fatalf("can't make a temp dir: %v", err)

View File

@ -20,7 +20,6 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/volume/awsebs", importpath = "k8s.io/kubernetes/pkg/volume/awsebs",
deps = [ deps = [
"//pkg/features:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//pkg/volume/util/volumepathhandler:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library",
@ -29,7 +28,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library", "//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
"//staging/src/k8s.io/legacy-cloud-providers/aws:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/aws:go_default_library",

View File

@ -35,8 +35,6 @@ import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
"k8s.io/legacy-cloud-providers/aws" "k8s.io/legacy-cloud-providers/aws"
@ -501,13 +499,10 @@ func (c *awsElasticBlockStoreProvisioner) Provision(selectedNode *v1.Node, allow
fstype = "ext4" fstype = "ext4"
} }
var volumeMode *v1.PersistentVolumeMode volumeMode := c.options.PVC.Spec.VolumeMode
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
volumeMode = c.options.PVC.Spec.VolumeMode // Block volumes should not have any FSType
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock { fstype = ""
// Block volumes should not have any FSType
fstype = ""
}
} }
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{

View File

@ -24,7 +24,6 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/volume/azure_dd", importpath = "k8s.io/kubernetes/pkg/volume/azure_dd",
deps = [ deps = [
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/features:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//pkg/volume/util/volumepathhandler:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library",
@ -34,7 +33,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library", "//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
"//staging/src/k8s.io/legacy-cloud-providers/azure:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure:go_default_library",

View File

@ -29,9 +29,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
utilfeature "k8s.io/apiserver/pkg/util/feature"
volumehelpers "k8s.io/cloud-provider/volume/helpers" volumehelpers "k8s.io/cloud-provider/volume/helpers"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
"k8s.io/legacy-cloud-providers/azure" "k8s.io/legacy-cloud-providers/azure"
@ -286,13 +284,10 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
} }
} }
var volumeMode *v1.PersistentVolumeMode volumeMode := p.options.PVC.Spec.VolumeMode
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
volumeMode = p.options.PVC.Spec.VolumeMode // Block volumes should not have any FSType
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock { fsType = ""
// Block volumes should not have any FSType
fsType = ""
}
} }
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{

View File

@ -17,7 +17,6 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/volume/cinder", importpath = "k8s.io/kubernetes/pkg/volume/cinder",
deps = [ deps = [
"//pkg/features:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//pkg/volume/util/volumepathhandler:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library",
@ -27,7 +26,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library", "//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",

View File

@ -34,9 +34,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
"k8s.io/legacy-cloud-providers/openstack" "k8s.io/legacy-cloud-providers/openstack"
@ -572,13 +570,10 @@ func (c *cinderVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopolo
return nil, err return nil, err
} }
var volumeMode *v1.PersistentVolumeMode volumeMode := c.options.PVC.Spec.VolumeMode
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
volumeMode = c.options.PVC.Spec.VolumeMode // Block volumes should not have any FSType
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock { fstype = ""
// Block volumes should not have any FSType
fstype = ""
}
} }
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{

View File

@ -17,14 +17,12 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/volume/fc", importpath = "k8s.io/kubernetes/pkg/volume/fc",
deps = [ deps = [
"//pkg/features:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//pkg/volume/util/volumepathhandler:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/k8s.io/utils/mount:go_default_library", "//vendor/k8s.io/utils/mount:go_default_library",

View File

@ -28,8 +28,6 @@ import (
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
volumeutil "k8s.io/kubernetes/pkg/volume/util" volumeutil "k8s.io/kubernetes/pkg/volume/util"
) )
@ -209,26 +207,17 @@ func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost) (*fcDiskMoun
wwids: wwids, wwids: wwids,
io: &osIOHandler{}, io: &osIOHandler{},
} }
// TODO: remove feature gate check after no longer needed
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { volumeMode, err := volumeutil.GetVolumeMode(spec)
volumeMode, err := volumeutil.GetVolumeMode(spec) if err != nil {
if err != nil { return nil, err
return nil, err
}
klog.V(5).Infof("fc: volumeSpecToMounter volumeMode %s", volumeMode)
return &fcDiskMounter{
fcDisk: fcDisk,
fsType: fc.FSType,
volumeMode: volumeMode,
readOnly: readOnly,
mounter: volumeutil.NewSafeFormatAndMountFromHost(fcPluginName, host),
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
mountOptions: volumeutil.MountOptionFromSpec(spec),
}, nil
} }
klog.V(5).Infof("fc: volumeSpecToMounter volumeMode %s", volumeMode)
return &fcDiskMounter{ return &fcDiskMounter{
fcDisk: fcDisk, fcDisk: fcDisk,
fsType: fc.FSType, fsType: fc.FSType,
volumeMode: volumeMode,
readOnly: readOnly, readOnly: readOnly,
mounter: volumeutil.NewSafeFormatAndMountFromHost(fcPluginName, host), mounter: volumeutil.NewSafeFormatAndMountFromHost(fcPluginName, host),
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()), deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),

View File

@ -31,8 +31,6 @@ import (
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler" "k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
@ -134,32 +132,22 @@ func (plugin *fcPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID,
io: &osIOHandler{}, io: &osIOHandler{},
plugin: plugin, plugin: plugin,
} }
// TODO: remove feature gate check after no longer needed
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { volumeMode, err := util.GetVolumeMode(spec)
volumeMode, err := util.GetVolumeMode(spec) if err != nil {
if err != nil { return nil, err
return nil, err
}
klog.V(5).Infof("fc: newMounterInternal volumeMode %s", volumeMode)
return &fcDiskMounter{
fcDisk: fcDisk,
fsType: fc.FSType,
volumeMode: volumeMode,
readOnly: readOnly,
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
mountOptions: util.MountOptionFromSpec(spec),
}, nil
} }
klog.V(5).Infof("fc: newMounterInternal volumeMode %s", volumeMode)
return &fcDiskMounter{ return &fcDiskMounter{
fcDisk: fcDisk, fcDisk: fcDisk,
fsType: fc.FSType, fsType: fc.FSType,
volumeMode: volumeMode,
readOnly: readOnly, readOnly: readOnly,
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec}, mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()), deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
mountOptions: util.MountOptionFromSpec(spec), mountOptions: util.MountOptionFromSpec(spec),
}, nil }, nil
} }
func (plugin *fcPlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.BlockVolumeMapper, error) { func (plugin *fcPlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.BlockVolumeMapper, error) {

View File

@ -28,8 +28,6 @@ import (
"k8s.io/utils/mount" "k8s.io/utils/mount"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
volumeutil "k8s.io/kubernetes/pkg/volume/util" volumeutil "k8s.io/kubernetes/pkg/volume/util"
) )
@ -243,14 +241,12 @@ func (util *fcUtil) AttachDisk(b fcDiskMounter) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
// TODO: remove feature gate check after no longer needed
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { // If the volumeMode is 'Block', plugin don't have to format the volume.
// If the volumeMode is 'Block', plugin don't have to format the volume. // The globalPDPath will be created by operationexecutor. Just return devicePath here.
// The globalPDPath will be created by operationexecutor. Just return devicePath here. klog.V(5).Infof("fc: AttachDisk volumeMode: %s, devicePath: %s", b.volumeMode, devicePath)
klog.V(5).Infof("fc: AttachDisk volumeMode: %s, devicePath: %s", b.volumeMode, devicePath) if b.volumeMode == v1.PersistentVolumeBlock {
if b.volumeMode == v1.PersistentVolumeBlock { return devicePath, nil
return devicePath, nil
}
} }
// mount it // mount it

View File

@ -17,7 +17,6 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/volume/gcepd", importpath = "k8s.io/kubernetes/pkg/volume/gcepd",
deps = [ deps = [
"//pkg/features:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//pkg/volume/util/volumepathhandler:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library",
@ -26,7 +25,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/cloud-provider/volume:go_default_library", "//staging/src/k8s.io/cloud-provider/volume:go_default_library",
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library", "//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",

View File

@ -34,9 +34,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
volumehelpers "k8s.io/cloud-provider/volume/helpers" volumehelpers "k8s.io/cloud-provider/volume/helpers"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
gcecloud "k8s.io/legacy-cloud-providers/gce" gcecloud "k8s.io/legacy-cloud-providers/gce"
@ -500,13 +498,10 @@ func (c *gcePersistentDiskProvisioner) Provision(selectedNode *v1.Node, allowedT
fstype = "ext4" fstype = "ext4"
} }
var volumeMode *v1.PersistentVolumeMode volumeMode := c.options.PVC.Spec.VolumeMode
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
volumeMode = c.options.PVC.Spec.VolumeMode // Block volumes should not have any FSType
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock { fstype = ""
// Block volumes should not have any FSType
fstype = ""
}
} }
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{

View File

@ -17,7 +17,6 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/volume/iscsi", importpath = "k8s.io/kubernetes/pkg/volume/iscsi",
deps = [ deps = [
"//pkg/features:go_default_library",
"//pkg/kubelet/config:go_default_library", "//pkg/kubelet/config:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
@ -25,7 +24,6 @@ go_library(
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/k8s.io/utils/keymutex:go_default_library", "//vendor/k8s.io/utils/keymutex:go_default_library",

View File

@ -27,8 +27,6 @@ import (
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
volumeutil "k8s.io/kubernetes/pkg/volume/util" volumeutil "k8s.io/kubernetes/pkg/volume/util"
) )
@ -209,26 +207,17 @@ func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost, targetLocks
return nil, err return nil, err
} }
exec := host.GetExec(iscsiPluginName) exec := host.GetExec(iscsiPluginName)
// TODO: remove feature gate check after no longer needed
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { volumeMode, err := volumeutil.GetVolumeMode(spec)
volumeMode, err := volumeutil.GetVolumeMode(spec) if err != nil {
if err != nil { return nil, err
return nil, err
}
klog.V(5).Infof("iscsi: VolumeSpecToMounter volumeMode %s", volumeMode)
return &iscsiDiskMounter{
iscsiDisk: iscsiDisk,
fsType: fsType,
volumeMode: volumeMode,
readOnly: readOnly,
mounter: &mount.SafeFormatAndMount{Interface: host.GetMounter(iscsiPluginName), Exec: exec},
exec: exec,
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
}, nil
} }
klog.V(5).Infof("iscsi: VolumeSpecToMounter volumeMode %s", volumeMode)
return &iscsiDiskMounter{ return &iscsiDiskMounter{
iscsiDisk: iscsiDisk, iscsiDisk: iscsiDisk,
fsType: fsType, fsType: fsType,
volumeMode: volumeMode,
readOnly: readOnly, readOnly: readOnly,
mounter: &mount.SafeFormatAndMount{Interface: host.GetMounter(iscsiPluginName), Exec: exec}, mounter: &mount.SafeFormatAndMount{Interface: host.GetMounter(iscsiPluginName), Exec: exec},
exec: exec, exec: exec,

View File

@ -34,8 +34,6 @@ import (
"k8s.io/utils/mount" "k8s.io/utils/mount"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/kubelet/config" "k8s.io/kubernetes/pkg/kubelet/config"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
volumeutil "k8s.io/kubernetes/pkg/volume/util" volumeutil "k8s.io/kubernetes/pkg/volume/util"
@ -469,25 +467,23 @@ func (util *ISCSIUtil) AttachDisk(b iscsiDiskMounter) (string, error) {
// If the volumeMode is 'Block', plugin creates a dir and persists iscsi configurations. // If the volumeMode is 'Block', plugin creates a dir and persists iscsi configurations.
// Since volume type is block, plugin doesn't need to format/mount the volume. // Since volume type is block, plugin doesn't need to format/mount the volume.
func globalPDPathOperation(b iscsiDiskMounter) func(iscsiDiskMounter, string, *ISCSIUtil) (string, error) { func globalPDPathOperation(b iscsiDiskMounter) func(iscsiDiskMounter, string, *ISCSIUtil) (string, error) {
// TODO: remove feature gate check after no longer needed klog.V(5).Infof("iscsi: AttachDisk volumeMode: %s", b.volumeMode)
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { if b.volumeMode == v1.PersistentVolumeBlock {
klog.V(5).Infof("iscsi: AttachDisk volumeMode: %s", b.volumeMode) // If the volumeMode is 'Block', plugin don't need to format the volume.
if b.volumeMode == v1.PersistentVolumeBlock { return func(b iscsiDiskMounter, devicePath string, util *ISCSIUtil) (string, error) {
// If the volumeMode is 'Block', plugin don't need to format the volume. globalPDPath := b.manager.MakeGlobalVDPDName(*b.iscsiDisk)
return func(b iscsiDiskMounter, devicePath string, util *ISCSIUtil) (string, error) { // Create dir like /var/lib/kubelet/plugins/kubernetes.io/iscsi/volumeDevices/{ifaceName}/{portal-some_iqn-lun-lun_id}
globalPDPath := b.manager.MakeGlobalVDPDName(*b.iscsiDisk) if err := os.MkdirAll(globalPDPath, 0750); err != nil {
// Create dir like /var/lib/kubelet/plugins/kubernetes.io/iscsi/volumeDevices/{ifaceName}/{portal-some_iqn-lun-lun_id} klog.Errorf("iscsi: failed to mkdir %s, error", globalPDPath)
if err := os.MkdirAll(globalPDPath, 0750); err != nil { return "", err
klog.Errorf("iscsi: failed to mkdir %s, error", globalPDPath)
return "", err
}
// Persist iscsi disk config to json file for DetachDisk path
util.persistISCSI(*(b.iscsiDisk), globalPDPath)
return devicePath, nil
} }
// Persist iscsi disk config to json file for DetachDisk path
util.persistISCSI(*(b.iscsiDisk), globalPDPath)
return devicePath, nil
} }
} }
// If the volumeMode is 'Filesystem', plugin needs to format the volume // If the volumeMode is 'Filesystem', plugin needs to format the volume
// and mount it to globalPDPath. // and mount it to globalPDPath.
return func(b iscsiDiskMounter, devicePath string, util *ISCSIUtil) (string, error) { return func(b iscsiDiskMounter, devicePath string, util *ISCSIUtil) (string, error) {

View File

@ -17,7 +17,6 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/volume/rbd", importpath = "k8s.io/kubernetes/pkg/volume/rbd",
deps = [ deps = [
"//pkg/features:go_default_library",
"//pkg/util/node:go_default_library", "//pkg/util/node:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
@ -30,7 +29,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library", "//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",

View File

@ -35,9 +35,7 @@ import (
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/uuid"
utilfeature "k8s.io/apiserver/pkg/util/feature"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
volutil "k8s.io/kubernetes/pkg/volume/util" volutil "k8s.io/kubernetes/pkg/volume/util"
@ -717,13 +715,10 @@ func (r *rbdVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
rbd.Keyring = keyring rbd.Keyring = keyring
} }
var volumeMode *v1.PersistentVolumeMode volumeMode := r.options.PVC.Spec.VolumeMode
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
volumeMode = r.options.PVC.Spec.VolumeMode // Block volumes should not have any FSType
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock { fstype = ""
// Block volumes should not have any FSType
fstype = ""
}
} }
rbd.RadosUser = r.ID rbd.RadosUser = r.ID

View File

@ -22,7 +22,6 @@ go_library(
"//pkg/api/legacyscheme:go_default_library", "//pkg/api/legacyscheme:go_default_library",
"//pkg/api/v1/pod:go_default_library", "//pkg/api/v1/pod:go_default_library",
"//pkg/apis/core/v1/helper:go_default_library", "//pkg/apis/core/v1/helper:go_default_library",
"//pkg/features:go_default_library",
"//pkg/util/resizefs:go_default_library", "//pkg/util/resizefs:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util/types:go_default_library", "//pkg/volume/util/types:go_default_library",
@ -38,7 +37,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/component-base/metrics:go_default_library", "//staging/src/k8s.io/component-base/metrics:go_default_library",
"//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library", "//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",

View File

@ -39,12 +39,10 @@ import (
apiruntime "k8s.io/apimachinery/pkg/runtime" apiruntime "k8s.io/apimachinery/pkg/runtime"
utypes "k8s.io/apimachinery/pkg/types" utypes "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
utilfeature "k8s.io/apiserver/pkg/util/feature"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
podutil "k8s.io/kubernetes/pkg/api/v1/pod" podutil "k8s.io/kubernetes/pkg/api/v1/pod"
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util/types" "k8s.io/kubernetes/pkg/volume/util/types"
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler" "k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
@ -436,14 +434,12 @@ func GetPersistentVolumeClaimQualifiedName(claim *v1.PersistentVolumeClaim) stri
// CheckVolumeModeFilesystem checks VolumeMode. // CheckVolumeModeFilesystem checks VolumeMode.
// If the mode is Filesystem, return true otherwise return false. // If the mode is Filesystem, return true otherwise return false.
func CheckVolumeModeFilesystem(volumeSpec *volume.Spec) (bool, error) { func CheckVolumeModeFilesystem(volumeSpec *volume.Spec) (bool, error) {
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { volumeMode, err := GetVolumeMode(volumeSpec)
volumeMode, err := GetVolumeMode(volumeSpec) if err != nil {
if err != nil { return true, err
return true, err }
} if volumeMode == v1.PersistentVolumeBlock {
if volumeMode == v1.PersistentVolumeBlock { return false, nil
return false, nil
}
} }
return true, nil return true, nil
} }
@ -451,7 +447,7 @@ func CheckVolumeModeFilesystem(volumeSpec *volume.Spec) (bool, error) {
// CheckPersistentVolumeClaimModeBlock checks VolumeMode. // CheckPersistentVolumeClaimModeBlock checks VolumeMode.
// If the mode is Block, return true otherwise return false. // If the mode is Block, return true otherwise return false.
func CheckPersistentVolumeClaimModeBlock(pvc *v1.PersistentVolumeClaim) bool { func CheckPersistentVolumeClaimModeBlock(pvc *v1.PersistentVolumeClaim) bool {
return utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == v1.PersistentVolumeBlock return pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == v1.PersistentVolumeBlock
} }
// IsWindowsUNCPath checks if path is prefixed with \\ // IsWindowsUNCPath checks if path is prefixed with \\
@ -602,9 +598,7 @@ func GetPodVolumeNames(pod *v1.Pod) (mounts sets.String, devices sets.String) {
mounts.Insert(mount.Name) mounts.Insert(mount.Name)
} }
} }
// TODO: remove feature gate check after no longer needed if container.VolumeDevices != nil {
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) &&
container.VolumeDevices != nil {
for _, device := range container.VolumeDevices { for _, device := range container.VolumeDevices {
devices.Insert(device.Name) devices.Insert(device.Name)
} }

View File

@ -20,7 +20,6 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/volume/vsphere_volume", importpath = "k8s.io/kubernetes/pkg/volume/vsphere_volume",
deps = [ deps = [
"//pkg/features:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//pkg/volume/util/volumepathhandler:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library",
@ -28,7 +27,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library", "//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
"//staging/src/k8s.io/legacy-cloud-providers/vsphere:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/vsphere:go_default_library",

View File

@ -33,9 +33,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
volumehelpers "k8s.io/cloud-provider/volume/helpers" volumehelpers "k8s.io/cloud-provider/volume/helpers"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
) )
@ -382,13 +380,10 @@ func (v *vsphereVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopol
volSpec.Fstype = "ext4" volSpec.Fstype = "ext4"
} }
var volumeMode *v1.PersistentVolumeMode volumeMode := v.options.PVC.Spec.VolumeMode
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
volumeMode = v.options.PVC.Spec.VolumeMode klog.V(5).Infof("vSphere block volume should not have any FSType")
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock { volSpec.Fstype = ""
klog.V(5).Infof("vSphere block volume should not have any FSType")
volSpec.Fstype = ""
}
} }
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{

View File

@ -689,7 +689,6 @@ message Container {
repeated VolumeMount volumeMounts = 9; repeated VolumeMount volumeMounts = 9;
// volumeDevices is the list of block devices to be used by the container. // volumeDevices is the list of block devices to be used by the container.
// This is a beta feature.
// +patchMergeKey=devicePath // +patchMergeKey=devicePath
// +patchStrategy=merge // +patchStrategy=merge
// +optional // +optional
@ -1276,7 +1275,6 @@ message EphemeralContainerCommon {
repeated VolumeMount volumeMounts = 9; repeated VolumeMount volumeMounts = 9;
// volumeDevices is the list of block devices to be used by the container. // volumeDevices is the list of block devices to be used by the container.
// This is a beta feature.
// +patchMergeKey=devicePath // +patchMergeKey=devicePath
// +patchStrategy=merge // +patchStrategy=merge
// +optional // +optional
@ -2636,7 +2634,6 @@ message PersistentVolumeClaimSpec {
// volumeMode defines what type of volume is required by the claim. // volumeMode defines what type of volume is required by the claim.
// Value of Filesystem is implied when not included in claim spec. // Value of Filesystem is implied when not included in claim spec.
// This is a beta feature.
// +optional // +optional
optional string volumeMode = 6; optional string volumeMode = 6;
@ -2852,7 +2849,6 @@ message PersistentVolumeSpec {
// volumeMode defines if a volume is intended to be used with a formatted filesystem // volumeMode defines if a volume is intended to be used with a formatted filesystem
// or to remain in raw block state. Value of Filesystem is implied when not included in spec. // or to remain in raw block state. Value of Filesystem is implied when not included in spec.
// This is a beta feature.
// +optional // +optional
optional string volumeMode = 8; optional string volumeMode = 8;

View File

@ -331,7 +331,6 @@ type PersistentVolumeSpec struct {
MountOptions []string `json:"mountOptions,omitempty" protobuf:"bytes,7,opt,name=mountOptions"` MountOptions []string `json:"mountOptions,omitempty" protobuf:"bytes,7,opt,name=mountOptions"`
// volumeMode defines if a volume is intended to be used with a formatted filesystem // volumeMode defines if a volume is intended to be used with a formatted filesystem
// or to remain in raw block state. Value of Filesystem is implied when not included in spec. // or to remain in raw block state. Value of Filesystem is implied when not included in spec.
// This is a beta feature.
// +optional // +optional
VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,8,opt,name=volumeMode,casttype=PersistentVolumeMode"` VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,8,opt,name=volumeMode,casttype=PersistentVolumeMode"`
// NodeAffinity defines constraints that limit what nodes this volume can be accessed from. // NodeAffinity defines constraints that limit what nodes this volume can be accessed from.
@ -460,7 +459,6 @@ type PersistentVolumeClaimSpec struct {
StorageClassName *string `json:"storageClassName,omitempty" protobuf:"bytes,5,opt,name=storageClassName"` StorageClassName *string `json:"storageClassName,omitempty" protobuf:"bytes,5,opt,name=storageClassName"`
// volumeMode defines what type of volume is required by the claim. // volumeMode defines what type of volume is required by the claim.
// Value of Filesystem is implied when not included in claim spec. // Value of Filesystem is implied when not included in claim spec.
// This is a beta feature.
// +optional // +optional
VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,6,opt,name=volumeMode,casttype=PersistentVolumeMode"` VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,6,opt,name=volumeMode,casttype=PersistentVolumeMode"`
// This field requires the VolumeSnapshotDataSource alpha feature gate to be // This field requires the VolumeSnapshotDataSource alpha feature gate to be
@ -2181,7 +2179,6 @@ type Container struct {
// +patchStrategy=merge // +patchStrategy=merge
VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath" protobuf:"bytes,9,rep,name=volumeMounts"` VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath" protobuf:"bytes,9,rep,name=volumeMounts"`
// volumeDevices is the list of block devices to be used by the container. // volumeDevices is the list of block devices to be used by the container.
// This is a beta feature.
// +patchMergeKey=devicePath // +patchMergeKey=devicePath
// +patchStrategy=merge // +patchStrategy=merge
// +optional // +optional
@ -3298,7 +3295,6 @@ type EphemeralContainerCommon struct {
// +patchStrategy=merge // +patchStrategy=merge
VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath" protobuf:"bytes,9,rep,name=volumeMounts"` VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath" protobuf:"bytes,9,rep,name=volumeMounts"`
// volumeDevices is the list of block devices to be used by the container. // volumeDevices is the list of block devices to be used by the container.
// This is a beta feature.
// +patchMergeKey=devicePath // +patchMergeKey=devicePath
// +patchStrategy=merge // +patchStrategy=merge
// +optional // +optional

View File

@ -336,7 +336,7 @@ var map_Container = map[string]string{
"env": "List of environment variables to set in the container. Cannot be updated.", "env": "List of environment variables to set in the container. Cannot be updated.",
"resources": "Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", "resources": "Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/",
"volumeMounts": "Pod volumes to mount into the container's filesystem. Cannot be updated.", "volumeMounts": "Pod volumes to mount into the container's filesystem. Cannot be updated.",
"volumeDevices": "volumeDevices is the list of block devices to be used by the container. This is a beta feature.", "volumeDevices": "volumeDevices is the list of block devices to be used by the container.",
"livenessProbe": "Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", "livenessProbe": "Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
"readinessProbe": "Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", "readinessProbe": "Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
"startupProbe": "StartupProbe indicates that the Pod has successfully initialized. If specified, no other probes are executed until this completes successfully. If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, when it might take a long time to load data or warm a cache, than during steady-state operation. This cannot be updated. This is a beta feature enabled by the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", "startupProbe": "StartupProbe indicates that the Pod has successfully initialized. If specified, no other probes are executed until this completes successfully. If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, when it might take a long time to load data or warm a cache, than during steady-state operation. This cannot be updated. This is a beta feature enabled by the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
@ -599,7 +599,7 @@ var map_EphemeralContainerCommon = map[string]string{
"env": "List of environment variables to set in the container. Cannot be updated.", "env": "List of environment variables to set in the container. Cannot be updated.",
"resources": "Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources already allocated to the pod.", "resources": "Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources already allocated to the pod.",
"volumeMounts": "Pod volumes to mount into the container's filesystem. Cannot be updated.", "volumeMounts": "Pod volumes to mount into the container's filesystem. Cannot be updated.",
"volumeDevices": "volumeDevices is the list of block devices to be used by the container. This is a beta feature.", "volumeDevices": "volumeDevices is the list of block devices to be used by the container.",
"livenessProbe": "Probes are not allowed for ephemeral containers.", "livenessProbe": "Probes are not allowed for ephemeral containers.",
"readinessProbe": "Probes are not allowed for ephemeral containers.", "readinessProbe": "Probes are not allowed for ephemeral containers.",
"startupProbe": "Probes are not allowed for ephemeral containers.", "startupProbe": "Probes are not allowed for ephemeral containers.",
@ -1300,7 +1300,7 @@ var map_PersistentVolumeClaimSpec = map[string]string{
"resources": "Resources represents the minimum resources the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources", "resources": "Resources represents the minimum resources the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources",
"volumeName": "VolumeName is the binding reference to the PersistentVolume backing this claim.", "volumeName": "VolumeName is the binding reference to the PersistentVolume backing this claim.",
"storageClassName": "Name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1", "storageClassName": "Name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1",
"volumeMode": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature.", "volumeMode": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.",
"dataSource": "This field requires the VolumeSnapshotDataSource alpha feature gate to be enabled and currently VolumeSnapshot is the only supported data source. If the provisioner can support VolumeSnapshot data source, it will create a new volume and data will be restored to the volume at the same time. If the provisioner does not support VolumeSnapshot data source, volume will not be created and the failure will be reported as an event. In the future, we plan to support more data source types and the behavior of the provisioner may change.", "dataSource": "This field requires the VolumeSnapshotDataSource alpha feature gate to be enabled and currently VolumeSnapshot is the only supported data source. If the provisioner can support VolumeSnapshot data source, it will create a new volume and data will be restored to the volume at the same time. If the provisioner does not support VolumeSnapshot data source, volume will not be created and the failure will be reported as an event. In the future, we plan to support more data source types and the behavior of the provisioner may change.",
} }
@ -1378,7 +1378,7 @@ var map_PersistentVolumeSpec = map[string]string{
"persistentVolumeReclaimPolicy": "What happens to a persistent volume when released from its claim. Valid options are Retain (default for manually created PersistentVolumes), Delete (default for dynamically provisioned PersistentVolumes), and Recycle (deprecated). Recycle must be supported by the volume plugin underlying this PersistentVolume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming", "persistentVolumeReclaimPolicy": "What happens to a persistent volume when released from its claim. Valid options are Retain (default for manually created PersistentVolumes), Delete (default for dynamically provisioned PersistentVolumes), and Recycle (deprecated). Recycle must be supported by the volume plugin underlying this PersistentVolume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming",
"storageClassName": "Name of StorageClass to which this persistent volume belongs. Empty value means that this volume does not belong to any StorageClass.", "storageClassName": "Name of StorageClass to which this persistent volume belongs. Empty value means that this volume does not belong to any StorageClass.",
"mountOptions": "A list of mount options, e.g. [\"ro\", \"soft\"]. Not validated - mount will simply fail if one is invalid. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options", "mountOptions": "A list of mount options, e.g. [\"ro\", \"soft\"]. Not validated - mount will simply fail if one is invalid. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options",
"volumeMode": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is a beta feature.", "volumeMode": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec.",
"nodeAffinity": "NodeAffinity defines constraints that limit what nodes this volume can be accessed from. This field influences the scheduling of pods that use this volume.", "nodeAffinity": "NodeAffinity defines constraints that limit what nodes this volume can be accessed from. This field influences the scheduling of pods that use this volume.",
} }