diff --git a/pkg/kubelet/events/event.go b/pkg/kubelet/events/event.go index 12740573811..6ec06a2ee99 100644 --- a/pkg/kubelet/events/event.go +++ b/pkg/kubelet/events/event.go @@ -59,6 +59,7 @@ const ( FailedUnmapDevice = "FailedUnmapDevice" WarnAlreadyMountedVolume = "AlreadyMountedVolume" SuccessfulDetachVolume = "SuccessfulDetachVolume" + SuccessfulAttachVolume = "SuccessfulAttachVolume" SuccessfulMountVolume = "SuccessfulMountVolume" SuccessfulUnMountVolume = "SuccessfulUnMountVolume" HostPortConflict = "HostPortConflict" diff --git a/pkg/kubelet/volumemanager/volume_manager.go b/pkg/kubelet/volumemanager/volume_manager.go index d3e7711407b..88027ce5fb3 100644 --- a/pkg/kubelet/volumemanager/volume_manager.go +++ b/pkg/kubelet/volumemanager/volume_manager.go @@ -357,21 +357,38 @@ func (vm *volumeManager) WaitForAttachAndMount(pod *v1.Pod) error { // Timeout expired unmountedVolumes := vm.getUnmountedVolumes(uniquePodName, expectedVolumes) + // Also get unattached volumes for error message + unattachedVolumes := + vm.getUnattachedVolumes(expectedVolumes) + if len(unmountedVolumes) == 0 { return nil } return fmt.Errorf( - "timeout expired waiting for volumes to attach/mount for pod %q/%q. list of unattached/unmounted volumes=%v", + "timeout expired waiting for volumes to attach or mount for pod %q/%q. list of unmounted volumes=%v. list of unattached volumes=%v", pod.Namespace, pod.Name, - unmountedVolumes) + unmountedVolumes, + unattachedVolumes) } glog.V(3).Infof("All volumes are attached and mounted for pod %q", format.Pod(pod)) return nil } +// getUnattachedVolumes returns a list of the volumes that are expected to be attached but +// are not currently attached to the node +func (vm *volumeManager) getUnattachedVolumes(expectedVolumes []string) []string { + unattachedVolumes := []string{} + for _, volume := range expectedVolumes { + if !vm.actualStateOfWorld.VolumeExists(v1.UniqueVolumeName(volume)) { + unattachedVolumes = append(unattachedVolumes, volume) + } + } + return unattachedVolumes +} + // verifyVolumesMountedFunc returns a method that returns true when all expected // volumes are mounted. func (vm *volumeManager) verifyVolumesMountedFunc(podName types.UniquePodName, expectedVolumes []string) wait.ConditionFunc { diff --git a/pkg/volume/util/operationexecutor/operation_generator.go b/pkg/volume/util/operationexecutor/operation_generator.go index a322ed4ca3d..2353e12615f 100644 --- a/pkg/volume/util/operationexecutor/operation_generator.go +++ b/pkg/volume/util/operationexecutor/operation_generator.go @@ -325,6 +325,11 @@ func (og *operationGenerator) GenerateAttachVolumeFunc( return volumeToAttach.GenerateError("AttachVolume.Attach failed", attachErr) } + // Successful attach event is useful for user debugging + simpleMsg, _ := volumeToAttach.GenerateMsg("AttachVolume.Attach succeeded", "") + for _, pod := range volumeToAttach.ScheduledPods { + og.recorder.Eventf(pod, v1.EventTypeNormal, kevents.SuccessfulAttachVolume, simpleMsg) + } glog.Infof(volumeToAttach.GenerateMsgDetailed("AttachVolume.Attach succeeded", "")) // Update actual state of world