diff --git a/pkg/kubelet/kubelet_volumes.go b/pkg/kubelet/kubelet_volumes.go index 9396a5c62c4..5942da47afa 100644 --- a/pkg/kubelet/kubelet_volumes.go +++ b/pkg/kubelet/kubelet_volumes.go @@ -74,7 +74,7 @@ func (kl *Kubelet) ListBlockVolumesForPod(podUID types.UID) (map[string]volume.B // pods for the specified volume are mounted. func (kl *Kubelet) podVolumesExist(podUID types.UID) bool { if mountedVolumes := - kl.volumeManager.GetMountedVolumesForPod( + kl.volumeManager.GetPossiblyMountedVolumesForPod( volumetypes.UniquePodName(podUID)); len(mountedVolumes) > 0 { return true } diff --git a/pkg/kubelet/kubelet_volumes_test.go b/pkg/kubelet/kubelet_volumes_test.go index 0f4117c3a58..6b7128b4f4a 100644 --- a/pkg/kubelet/kubelet_volumes_test.go +++ b/pkg/kubelet/kubelet_volumes_test.go @@ -397,6 +397,9 @@ func TestVolumeAttachAndMountControllerEnabled(t *testing.T) { podVolumes := kubelet.volumeManager.GetMountedVolumesForPod( util.GetUniquePodName(pod)) + allPodVolumes := kubelet.volumeManager.GetPossiblyMountedVolumesForPod( + util.GetUniquePodName(pod)) + assert.Equal(t, podVolumes, allPodVolumes, "GetMountedVolumesForPod and GetPossiblyMountedVolumesForPod should return the same volumes") expectedPodVolumes := []string{"vol1"} assert.Len(t, podVolumes, len(expectedPodVolumes), "Volumes for pod %+v", pod) @@ -476,6 +479,9 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) { podVolumes := kubelet.volumeManager.GetMountedVolumesForPod( util.GetUniquePodName(pod)) + allPodVolumes := kubelet.volumeManager.GetPossiblyMountedVolumesForPod( + util.GetUniquePodName(pod)) + assert.Equal(t, podVolumes, allPodVolumes, "GetMountedVolumesForPod and GetPossiblyMountedVolumesForPod should return the same volumes") expectedPodVolumes := []string{"vol1"} assert.Len(t, podVolumes, len(expectedPodVolumes), "Volumes for pod %+v", pod) @@ -500,6 +506,9 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) { // Verify volumes unmounted podVolumes = kubelet.volumeManager.GetMountedVolumesForPod( util.GetUniquePodName(pod)) + allPodVolumes = kubelet.volumeManager.GetPossiblyMountedVolumesForPod( + util.GetUniquePodName(pod)) + assert.Equal(t, podVolumes, allPodVolumes, "GetMountedVolumesForPod and GetPossiblyMountedVolumesForPod should return the same volumes") assert.Len(t, podVolumes, 0, "Expected volumes to be unmounted and detached. But some volumes are still mounted: %#v", podVolumes) diff --git a/pkg/kubelet/volumemanager/cache/actual_state_of_world.go b/pkg/kubelet/volumemanager/cache/actual_state_of_world.go index 70a4c3d3409..62025e7114a 100644 --- a/pkg/kubelet/volumemanager/cache/actual_state_of_world.go +++ b/pkg/kubelet/volumemanager/cache/actual_state_of_world.go @@ -136,6 +136,11 @@ type ActualStateOfWorld interface { // current actual state of the world. GetMountedVolumesForPod(podName volumetypes.UniquePodName) []MountedVolume + // GetPossiblyMountedVolumesForPod generates and returns a list of volumes for + // the specified pod that either are attached and mounted or are "uncertain", + // i.e. a volume plugin may be mounting the volume right now. + GetPossiblyMountedVolumesForPod(podName volumetypes.UniquePodName) []MountedVolume + // GetGloballyMountedVolumes generates and returns a list of all attached // volumes that are globally mounted. This list can be used to determine // which volumes should be reported as "in use" in the node's VolumesInUse @@ -757,6 +762,26 @@ func (asw *actualStateOfWorld) GetMountedVolumesForPod( return mountedVolume } +func (asw *actualStateOfWorld) GetPossiblyMountedVolumesForPod( + podName volumetypes.UniquePodName) []MountedVolume { + asw.RLock() + defer asw.RUnlock() + mountedVolume := make([]MountedVolume, 0 /* len */, len(asw.attachedVolumes) /* cap */) + for _, volumeObj := range asw.attachedVolumes { + for mountedPodName, podObj := range volumeObj.mountedPods { + if mountedPodName == podName && + (podObj.volumeMountStateForPod == operationexecutor.VolumeMounted || + podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain) { + mountedVolume = append( + mountedVolume, + getMountedVolume(&podObj, &volumeObj)) + } + } + } + + return mountedVolume +} + func (asw *actualStateOfWorld) GetGloballyMountedVolumes() []AttachedVolume { asw.RLock() defer asw.RUnlock() diff --git a/pkg/kubelet/volumemanager/cache/actual_state_of_world_test.go b/pkg/kubelet/volumemanager/cache/actual_state_of_world_test.go index 224a1e954dd..b019c2040b9 100644 --- a/pkg/kubelet/volumemanager/cache/actual_state_of_world_test.go +++ b/pkg/kubelet/volumemanager/cache/actual_state_of_world_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/stretchr/testify/require" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/volume" volumetesting "k8s.io/kubernetes/pkg/volume/testing" @@ -653,7 +653,18 @@ func TestUncertainVolumeMounts(t *testing.T) { } } if volumeFound { - t.Fatalf("expected volume %s to be not found in asw", volumeSpec1.Name()) + t.Fatalf("expected volume %s to be not found in asw.GetMountedVolumesForPod", volumeSpec1.Name()) + } + + possiblyMountedVolumes := asw.GetPossiblyMountedVolumesForPod(podName1) + volumeFound = false + for _, volume := range possiblyMountedVolumes { + if volume.InnerVolumeSpecName == volumeSpec1.Name() { + volumeFound = true + } + } + if !volumeFound { + t.Fatalf("expected volume %s to be found in aws.GetPossiblyMountedVolumesForPod", volumeSpec1.Name()) } volExists, _, _ := asw.PodExistsInVolume(podName1, generatedVolumeName1) diff --git a/pkg/kubelet/volumemanager/volume_manager.go b/pkg/kubelet/volumemanager/volume_manager.go index 72e5f494b3d..1245f46679e 100644 --- a/pkg/kubelet/volumemanager/volume_manager.go +++ b/pkg/kubelet/volumemanager/volume_manager.go @@ -113,6 +113,14 @@ type VolumeManager interface { // volumes. GetMountedVolumesForPod(podName types.UniquePodName) container.VolumeMap + // GetPossiblyMountedVolumesForPod returns a VolumeMap containing the volumes + // referenced by the specified pod that are either successfully attached + // and mounted or are "uncertain", i.e. a volume plugin may be mounting + // them right now. The key in the map is the OuterVolumeSpecName (i.e. + // pod.Spec.Volumes[x].Name). It returns an empty VolumeMap if pod has no + // volumes. + GetPossiblyMountedVolumesForPod(podName types.UniquePodName) container.VolumeMap + // GetExtraSupplementalGroupsForPod returns a list of the extra // supplemental groups for the Pod. These extra supplemental groups come // from annotations on persistent volumes that the pod depends on. @@ -290,6 +298,19 @@ func (vm *volumeManager) GetMountedVolumesForPod(podName types.UniquePodName) co return podVolumes } +func (vm *volumeManager) GetPossiblyMountedVolumesForPod(podName types.UniquePodName) container.VolumeMap { + podVolumes := make(container.VolumeMap) + for _, mountedVolume := range vm.actualStateOfWorld.GetPossiblyMountedVolumesForPod(podName) { + podVolumes[mountedVolume.OuterVolumeSpecName] = container.VolumeInfo{ + Mounter: mountedVolume.Mounter, + BlockVolumeMapper: mountedVolume.BlockVolumeMapper, + ReadOnly: mountedVolume.VolumeSpec.ReadOnly, + InnerVolumeSpecName: mountedVolume.InnerVolumeSpecName, + } + } + return podVolumes +} + func (vm *volumeManager) GetExtraSupplementalGroupsForPod(pod *v1.Pod) []int64 { podName := util.GetUniquePodName(pod) supplementalGroups := sets.NewString() diff --git a/pkg/kubelet/volumemanager/volume_manager_fake.go b/pkg/kubelet/volumemanager/volume_manager_fake.go index b21d34a14ce..ad4e87e7ad8 100644 --- a/pkg/kubelet/volumemanager/volume_manager_fake.go +++ b/pkg/kubelet/volumemanager/volume_manager_fake.go @@ -17,7 +17,7 @@ limitations under the License. package volumemanager import ( - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/kubernetes/pkg/kubelet/config" "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/volume/util/types" @@ -55,6 +55,11 @@ func (f *FakeVolumeManager) GetMountedVolumesForPod(podName types.UniquePodName) return nil } +// GetPossiblyMountedVolumesForPod is not implemented +func (f *FakeVolumeManager) GetPossiblyMountedVolumesForPod(podName types.UniquePodName) container.VolumeMap { + return nil +} + // GetExtraSupplementalGroupsForPod is not implemented func (f *FakeVolumeManager) GetExtraSupplementalGroupsForPod(pod *v1.Pod) []int64 { return nil