mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-02 00:07:50 +00:00
fix: kubelet event about unattached volumes is incorrect (#112719)
* fix kubelet event * add ut * fix ut
This commit is contained in:
parent
41b442534d
commit
575616cc72
@ -419,18 +419,21 @@ func (vm *volumeManager) WaitForAttachAndMount(pod *v1.Pod) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
unmountedVolumes :=
|
unmountedVolumes :=
|
||||||
vm.getUnmountedVolumes(uniquePodName, expectedVolumes)
|
vm.getUnmountedVolumes(uniquePodName, expectedVolumes)
|
||||||
// Also get unattached volumes for error message
|
// Also get unattached volumes and volumes not in dsw for error message
|
||||||
unattachedVolumes :=
|
unattachedVolumes :=
|
||||||
vm.getUnattachedVolumes(expectedVolumes)
|
vm.getUnattachedVolumes(uniquePodName)
|
||||||
|
volumesNotInDSW :=
|
||||||
|
vm.getVolumesNotInDSW(uniquePodName, expectedVolumes)
|
||||||
|
|
||||||
if len(unmountedVolumes) == 0 {
|
if len(unmountedVolumes) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"unmounted volumes=%v, unattached volumes=%v: %s",
|
"unmounted volumes=%v, unattached volumes=%v, failed to process volumes=%v: %s",
|
||||||
unmountedVolumes,
|
unmountedVolumes,
|
||||||
unattachedVolumes,
|
unattachedVolumes,
|
||||||
|
volumesNotInDSW,
|
||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,15 +477,30 @@ func (vm *volumeManager) WaitForUnmount(pod *v1.Pod) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getUnattachedVolumes returns a list of the volumes that are expected to be attached but
|
func (vm *volumeManager) getVolumesNotInDSW(uniquePodName types.UniquePodName, expectedVolumes []string) []string {
|
||||||
// are not currently attached to the node
|
volumesNotInDSW := sets.NewString(expectedVolumes...)
|
||||||
func (vm *volumeManager) getUnattachedVolumes(expectedVolumes []string) []string {
|
|
||||||
unattachedVolumes := []string{}
|
for _, volumeToMount := range vm.desiredStateOfWorld.GetVolumesToMount() {
|
||||||
for _, volume := range expectedVolumes {
|
if volumeToMount.PodName == uniquePodName {
|
||||||
if !vm.actualStateOfWorld.VolumeExists(v1.UniqueVolumeName(volume)) {
|
volumesNotInDSW.Delete(volumeToMount.OuterVolumeSpecName)
|
||||||
unattachedVolumes = append(unattachedVolumes, volume)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return volumesNotInDSW.List()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(uniquePodName types.UniquePodName) []string {
|
||||||
|
unattachedVolumes := []string{}
|
||||||
|
for _, volumeToMount := range vm.desiredStateOfWorld.GetVolumesToMount() {
|
||||||
|
if volumeToMount.PodName == uniquePodName &&
|
||||||
|
volumeToMount.PluginIsAttachable &&
|
||||||
|
!vm.actualStateOfWorld.VolumeExists(volumeToMount.VolumeName) {
|
||||||
|
unattachedVolumes = append(unattachedVolumes, volumeToMount.OuterVolumeSpecName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return unattachedVolumes
|
return unattachedVolumes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -137,6 +138,82 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWaitForAttachAndMountError(t *testing.T) {
|
||||||
|
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't make a temp dir: %v", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
podManager := kubepod.NewBasicPodManager(podtest.NewFakeMirrorClient())
|
||||||
|
|
||||||
|
pod := &v1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "abc",
|
||||||
|
Namespace: "nsA",
|
||||||
|
UID: "1234",
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{
|
||||||
|
{
|
||||||
|
Name: "container1",
|
||||||
|
VolumeMounts: []v1.VolumeMount{
|
||||||
|
{
|
||||||
|
Name: volumetest.FailMountDeviceVolumeName,
|
||||||
|
MountPath: "/vol1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "vol2",
|
||||||
|
MountPath: "/vol2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "vol3",
|
||||||
|
MountPath: "/vol3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Volumes: []v1.Volume{
|
||||||
|
{
|
||||||
|
Name: volumetest.FailMountDeviceVolumeName,
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
ConfigMap: &v1.ConfigMapVolumeSource{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "vol2",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
RBD: &v1.RBDVolumeSource{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "vol3",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
AzureDisk: &v1.AzureDiskVolumeSource{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
kubeClient := fake.NewSimpleClientset(pod)
|
||||||
|
|
||||||
|
manager := newTestVolumeManager(t, tmpDir, podManager, kubeClient, nil)
|
||||||
|
|
||||||
|
stopCh := runVolumeManager(manager)
|
||||||
|
defer close(stopCh)
|
||||||
|
|
||||||
|
podManager.SetPods([]*v1.Pod{pod})
|
||||||
|
|
||||||
|
err = manager.WaitForAttachAndMount(pod)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expected error, got none")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(),
|
||||||
|
"unattached volumes=[vol2], failed to process volumes=[vol3]") {
|
||||||
|
t.Errorf("Unexpected error info: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestInitialPendingVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
func TestInitialPendingVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
||||||
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
|
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -282,14 +359,29 @@ func (p *fakePodStateProvider) ShouldPodContainersBeTerminating(uid kubetypes.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newTestVolumeManager(t *testing.T, tmpDir string, podManager kubepod.Manager, kubeClient clientset.Interface, node *v1.Node) VolumeManager {
|
func newTestVolumeManager(t *testing.T, tmpDir string, podManager kubepod.Manager, kubeClient clientset.Interface, node *v1.Node) VolumeManager {
|
||||||
plug := &volumetest.FakeVolumePlugin{PluginName: "fake", Host: nil}
|
attachablePlug := &volumetest.FakeVolumePlugin{
|
||||||
|
PluginName: "fake",
|
||||||
|
Host: nil,
|
||||||
|
CanSupportFn: func(spec *volume.Spec) bool {
|
||||||
|
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.RBD != nil) ||
|
||||||
|
(spec.Volume != nil && spec.Volume.RBD != nil)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
unattachablePlug := &volumetest.FakeVolumePlugin{
|
||||||
|
PluginName: "unattachable-fake-plugin",
|
||||||
|
Host: nil,
|
||||||
|
NonAttachable: true,
|
||||||
|
CanSupportFn: func(spec *volume.Spec) bool {
|
||||||
|
return spec.Volume != nil && spec.Volume.ConfigMap != nil
|
||||||
|
},
|
||||||
|
}
|
||||||
fakeRecorder := &record.FakeRecorder{}
|
fakeRecorder := &record.FakeRecorder{}
|
||||||
plugMgr := &volume.VolumePluginMgr{}
|
plugMgr := &volume.VolumePluginMgr{}
|
||||||
// TODO (#51147) inject mock prober
|
// TODO (#51147) inject mock prober
|
||||||
fakeVolumeHost := volumetest.NewFakeKubeletVolumeHost(t, tmpDir, kubeClient, nil)
|
fakeVolumeHost := volumetest.NewFakeKubeletVolumeHost(t, tmpDir, kubeClient, nil)
|
||||||
fakeVolumeHost.WithNode(node)
|
fakeVolumeHost.WithNode(node)
|
||||||
|
|
||||||
plugMgr.InitPlugins([]volume.VolumePlugin{plug}, nil /* prober */, fakeVolumeHost)
|
plugMgr.InitPlugins([]volume.VolumePlugin{attachablePlug, unattachablePlug}, nil /* prober */, fakeVolumeHost)
|
||||||
stateProvider := &fakePodStateProvider{}
|
stateProvider := &fakePodStateProvider{}
|
||||||
fakePathHandler := volumetest.NewBlockVolumePathHandler()
|
fakePathHandler := volumetest.NewBlockVolumePathHandler()
|
||||||
vm := NewVolumeManager(
|
vm := NewVolumeManager(
|
||||||
|
@ -183,6 +183,7 @@ type FakeVolumePlugin struct {
|
|||||||
SupportsRemount bool
|
SupportsRemount bool
|
||||||
SupportsSELinux bool
|
SupportsSELinux bool
|
||||||
DisableNodeExpansion bool
|
DisableNodeExpansion bool
|
||||||
|
CanSupportFn func(*volume.Spec) bool
|
||||||
|
|
||||||
// default to false which means it is attachable by default
|
// default to false which means it is attachable by default
|
||||||
NonAttachable bool
|
NonAttachable bool
|
||||||
@ -269,7 +270,10 @@ func (plugin *FakeVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *FakeVolumePlugin) CanSupport(spec *volume.Spec) bool {
|
func (plugin *FakeVolumePlugin) CanSupport(spec *volume.Spec) bool {
|
||||||
// TODO: maybe pattern-match on spec.Name() to decide?
|
if plugin.CanSupportFn != nil {
|
||||||
|
return plugin.CanSupportFn(spec)
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user