diff --git a/pkg/controller/volume/attachdetach/testing/testvolumespec.go b/pkg/controller/volume/attachdetach/testing/testvolumespec.go index 86b66f8f244..183d7dd7e14 100644 --- a/pkg/controller/volume/attachdetach/testing/testvolumespec.go +++ b/pkg/controller/volume/attachdetach/testing/testvolumespec.go @@ -32,6 +32,7 @@ import ( "k8s.io/klog" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/util" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" ) const TestPluginName = "kubernetes.io/testPlugin" @@ -445,6 +446,11 @@ func (attacher *testPluginAttacher) MountDevice(spec *volume.Spec, devicePath st return nil } +func (attacher *testPluginAttacher) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := attacher.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + // Detacher type testPluginDetacher struct { detachedVolumeMap map[string][]string diff --git a/pkg/volume/awsebs/attacher.go b/pkg/volume/awsebs/attacher.go index 35bf55df8fe..aa22034e091 100644 --- a/pkg/volume/awsebs/attacher.go +++ b/pkg/volume/awsebs/attacher.go @@ -34,6 +34,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" "k8s.io/legacy-cloud-providers/aws" ) @@ -250,6 +251,11 @@ func (attacher *awsElasticBlockStoreAttacher) MountDevice(spec *volume.Spec, dev return nil } +func (attacher *awsElasticBlockStoreAttacher) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := attacher.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + type awsElasticBlockStoreDetacher struct { mounter mount.Interface awsVolumes aws.Volumes diff --git a/pkg/volume/azure_dd/attacher.go b/pkg/volume/azure_dd/attacher.go index 42296172f0d..c5c4705ca18 100644 --- a/pkg/volume/azure_dd/attacher.go +++ b/pkg/volume/azure_dd/attacher.go @@ -37,6 +37,7 @@ import ( cloudprovider "k8s.io/cloud-provider" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/util" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" "k8s.io/legacy-cloud-providers/azure" ) @@ -259,6 +260,11 @@ func (attacher *azureDiskAttacher) MountDevice(spec *volume.Spec, devicePath str return nil } +func (d *azureDiskAttacher) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := d.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + // Detach detaches disk from Azure VM. func (d *azureDiskDetacher) Detach(diskURI string, nodeName types.NodeName) error { if diskURI == "" { diff --git a/pkg/volume/cinder/attacher.go b/pkg/volume/cinder/attacher.go index ebf84d31d0f..3340d2d53c2 100644 --- a/pkg/volume/cinder/attacher.go +++ b/pkg/volume/cinder/attacher.go @@ -34,6 +34,7 @@ import ( "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" ) type cinderDiskAttacher struct { @@ -303,6 +304,11 @@ func (attacher *cinderDiskAttacher) MountDevice(spec *volume.Spec, devicePath st return nil } +func (attacher *cinderDiskAttacher) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := attacher.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + type cinderDiskDetacher struct { mounter mount.Interface cinderProvider BlockStorageProvider diff --git a/pkg/volume/csi/csi_attacher.go b/pkg/volume/csi/csi_attacher.go index b25aba98068..bd7b7a3e4f0 100644 --- a/pkg/volume/csi/csi_attacher.go +++ b/pkg/volume/csi/csi_attacher.go @@ -341,6 +341,11 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo return nil } +func (c *csiAttacher) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := c.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + var _ volume.Detacher = &csiAttacher{} var _ volume.DeviceUnmounter = &csiAttacher{} diff --git a/pkg/volume/fc/attacher.go b/pkg/volume/fc/attacher.go index 4a431fd9928..385a916eca1 100644 --- a/pkg/volume/fc/attacher.go +++ b/pkg/volume/fc/attacher.go @@ -32,6 +32,7 @@ import ( "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" ) type fcAttacher struct { @@ -131,6 +132,11 @@ func (attacher *fcAttacher) MountDevice(spec *volume.Spec, devicePath string, de return nil } +func (attacher *fcAttacher) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := attacher.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + type fcDetacher struct { mounter mount.Interface manager diskManager diff --git a/pkg/volume/flexvolume/attacher.go b/pkg/volume/flexvolume/attacher.go index 3b98eefa079..e83da3ff2d3 100644 --- a/pkg/volume/flexvolume/attacher.go +++ b/pkg/volume/flexvolume/attacher.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/klog" "k8s.io/kubernetes/pkg/volume" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" ) type flexVolumeAttacher struct { @@ -97,6 +98,11 @@ func (a *flexVolumeAttacher) MountDevice(spec *volume.Spec, devicePath string, d return err } +func (attacher *flexVolumeAttacher) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := attacher.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + func (a *flexVolumeAttacher) VolumesAreAttached(specs []*volume.Spec, nodeName types.NodeName) (map[*volume.Spec]bool, error) { volumesAttachedCheck := make(map[*volume.Spec]bool) for _, spec := range specs { diff --git a/pkg/volume/gcepd/attacher.go b/pkg/volume/gcepd/attacher.go index 43c03564c59..e9aa83e980d 100644 --- a/pkg/volume/gcepd/attacher.go +++ b/pkg/volume/gcepd/attacher.go @@ -38,6 +38,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" "k8s.io/legacy-cloud-providers/gce" ) @@ -328,6 +329,11 @@ func (attacher *gcePersistentDiskAttacher) MountDevice(spec *volume.Spec, device return nil } +func (attacher *gcePersistentDiskAttacher) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := attacher.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + type gcePersistentDiskDetacher struct { host volume.VolumeHost gceDisks gce.Disks diff --git a/pkg/volume/iscsi/attacher.go b/pkg/volume/iscsi/attacher.go index 7b3d439077e..00d64cf21e4 100644 --- a/pkg/volume/iscsi/attacher.go +++ b/pkg/volume/iscsi/attacher.go @@ -31,6 +31,8 @@ import ( "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" + "k8s.io/utils/keymutex" ) type iscsiAttacher struct { @@ -134,6 +136,11 @@ func (attacher *iscsiAttacher) MountDevice(spec *volume.Spec, devicePath string, return nil } +func (attacher *iscsiAttacher) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := attacher.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + type iscsiDetacher struct { host volume.VolumeHost mounter mount.Interface diff --git a/pkg/volume/local/local.go b/pkg/volume/local/local.go index b79180a6c87..53de686dacf 100644 --- a/pkg/volume/local/local.go +++ b/pkg/volume/local/local.go @@ -33,6 +33,7 @@ import ( "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util/hostutil" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" "k8s.io/kubernetes/pkg/volume/validation" "k8s.io/utils/keymutex" "k8s.io/utils/mount" @@ -370,6 +371,11 @@ func (dm *deviceMounter) MountDevice(spec *volume.Spec, devicePath string, devic } } +func (dm *deviceMounter) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := dm.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + func getVolumeSourceFSType(spec *volume.Spec) (string, error) { if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Local != nil { diff --git a/pkg/volume/rbd/attacher.go b/pkg/volume/rbd/attacher.go index 12c2e77c935..7bfa3fa3a8a 100644 --- a/pkg/volume/rbd/attacher.go +++ b/pkg/volume/rbd/attacher.go @@ -28,6 +28,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/volume" volutil "k8s.io/kubernetes/pkg/volume/util" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" ) // NewAttacher implements AttachableVolumePlugin.NewAttacher. @@ -184,6 +185,11 @@ func (attacher *rbdAttacher) MountDevice(spec *volume.Spec, devicePath string, d return nil } +func (attacher *rbdAttacher) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := attacher.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + // rbdDetacher implements volume.Detacher interface. type rbdDetacher struct { plugin *rbdPlugin diff --git a/pkg/volume/testing/testing.go b/pkg/volume/testing/testing.go index e74750cb067..0810d83c231 100644 --- a/pkg/volume/testing/testing.go +++ b/pkg/volume/testing/testing.go @@ -1054,6 +1054,11 @@ func (fv *FakeVolume) MountDevice(spec *Spec, devicePath string, deviceMountPath return nil } +func (fv *FakeVolume) MountDeviceWithStatusTracking(spec *Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := fv.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + func (fv *FakeVolume) GetMountDeviceCallCount() int { fv.RLock() defer fv.RUnlock() diff --git a/pkg/volume/util/operationexecutor/operation_generator.go b/pkg/volume/util/operationexecutor/operation_generator.go index 2956ada9e66..5d530d4472f 100644 --- a/pkg/volume/util/operationexecutor/operation_generator.go +++ b/pkg/volume/util/operationexecutor/operation_generator.go @@ -575,12 +575,12 @@ func (og *operationGenerator) GenerateMountVolumeFunc( } // Mount device to global mount path - err = volumeDeviceMounter.MountDevice( + operationState, err := volumeDeviceMounter.MountDeviceWithStatusTracking( volumeToMount.VolumeSpec, devicePath, deviceMountPath) if err != nil { - if volumetypes.IsOperationTimeOutError(err) { + if operationState == volumetypes.OperationInProgress { markDeviceUncertainError := actualStateOfWorld.MarkDeviceAsUncertain(volumeToMount.VolumeName, devicePath, deviceMountPath) if markDeviceUncertainError != nil { klog.Infof("MountVolume.MarkDeviceAsUncertain failed with %v", markDeviceUncertainError) diff --git a/pkg/volume/util/types/types.go b/pkg/volume/util/types/types.go index 425e5b47f6d..baaa488137d 100644 --- a/pkg/volume/util/types/types.go +++ b/pkg/volume/util/types/types.go @@ -51,6 +51,23 @@ func (o *GeneratedOperations) Run() (eventErr, detailedErr error) { return o.OperationFunc() } +type OperationStatus string + +const ( + // OperationFinished means volume operation has been finished + OperationFinished OperationStatus = "Finished" + + // OperationInProgress means volume operation has been started and + // is in-progress. This state does not indicate if operation will succeed or fail but + // merely it has been started and in in-progress. + OperationInProgress OperationStatus = "InProgress" + + // OperationStateNoChange indicates it is unchanged from previous state. + // This can be used to indicate transient failures for an operation which + // was in-progress previously. + OperationStateNoChange OperationStatus = "NoChange" +) + // OperationTimedOutError indicates a particular volume operation has timed out. type OperationTimedOutError struct { msg string diff --git a/pkg/volume/volume.go b/pkg/volume/volume.go index 31fa8216e3e..83a79623694 100644 --- a/pkg/volume/volume.go +++ b/pkg/volume/volume.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" ) // Volume represents a directory used by pods or hosts on a node. All method @@ -248,6 +249,9 @@ type DeviceMounter interface { // individual pods can then bind mount // Note that devicePath can be empty if the volume plugin does not implement any of Attach and WaitForAttach methods. MountDevice(spec *Spec, devicePath string, deviceMountPath string) error + + // MountDeviceWithStatusTracking is same as MountDevice except status of mount operation is also returned + MountDeviceWithStatusTracking(spec *Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) } type BulkVolumeVerifier interface { diff --git a/pkg/volume/vsphere_volume/attacher.go b/pkg/volume/vsphere_volume/attacher.go index 8c247167858..947fc57d2cf 100644 --- a/pkg/volume/vsphere_volume/attacher.go +++ b/pkg/volume/vsphere_volume/attacher.go @@ -33,6 +33,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" + volumetypes "k8s.io/kubernetes/pkg/volume/util/types" "k8s.io/legacy-cloud-providers/vsphere" ) @@ -248,6 +249,11 @@ func (attacher *vsphereVMDKAttacher) MountDevice(spec *volume.Spec, devicePath s return nil } +func (attacher *vsphereVMDKAttacher) MountDeviceWithStatusTracking(spec *volume.Spec, devicePath string, deviceMountPath string) (volumetypes.OperationStatus, error) { + err := attacher.MountDevice(spec, devicePath, deviceMountPath) + return volumetypes.OperationFinished, err +} + type vsphereVMDKDetacher struct { mounter mount.Interface vsphereVolumes vsphere.Volumes