diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index ed7aca8791..345e208d78 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -1926,14 +1926,19 @@ func (kl *Kubelet) cleanupOrphanedVolumes(pods []*api.Pod, runningPods []*kubeco glog.Warningf("Orphaned volume %q found, tearing down volume", name) // TODO(yifan): Refactor this hacky string manipulation. kl.volumeManager.DeleteVolumes(types.UID(parts[0])) + // Get path reference count + refs, err := mount.GetMountRefs(kl.mounter, cleanerTuple.Cleaner.GetPath()) + if err != nil { + return fmt.Errorf("Could not get mount path references %v", err) + } //TODO (jonesdl) This should not block other kubelet synchronization procedures - err := cleanerTuple.Cleaner.TearDown() + err = cleanerTuple.Cleaner.TearDown() if err != nil { glog.Errorf("Could not tear down volume %q: %v", name, err) } // volume is unmounted. some volumes also require detachment from the node. - if cleanerTuple.Detacher != nil { + if cleanerTuple.Detacher != nil && len(refs) == 1 { detacher := *cleanerTuple.Detacher err = detacher.Detach() if err != nil { diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 5752fd89a5..0431bb9a65 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -59,6 +59,7 @@ import ( "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/bandwidth" + "k8s.io/kubernetes/pkg/util/mount" utilruntime "k8s.io/kubernetes/pkg/util/runtime" "k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/wait" @@ -93,6 +94,7 @@ type TestKubelet struct { fakeKubeClient *fake.Clientset fakeMirrorClient *kubepod.FakeMirrorClient fakeClock *util.FakeClock + mounter mount.Interface } func newTestKubelet(t *testing.T) *TestKubelet { @@ -192,7 +194,7 @@ func newTestKubelet(t *testing.T) *TestKubelet { kubelet.pleg = pleg.NewGenericPLEG(fakeRuntime, 100, time.Hour, nil) kubelet.clock = fakeClock kubelet.setNodeStatusFuncs = kubelet.defaultNodeStatusFuncs() - return &TestKubelet{kubelet, fakeRuntime, mockCadvisor, fakeKubeClient, fakeMirrorClient, fakeClock} + return &TestKubelet{kubelet, fakeRuntime, mockCadvisor, fakeKubeClient, fakeMirrorClient, fakeClock, nil} } func newTestPods(count int) []*api.Pod { @@ -564,6 +566,7 @@ func TestGetPodVolumesFromDisk(t *testing.T) { func TestCleanupOrphanedVolumes(t *testing.T) { testKubelet := newTestKubelet(t) kubelet := testKubelet.kubelet + kubelet.mounter = &mount.FakeMounter{} kubeClient := testKubelet.fakeKubeClient plug := &volume.FakeVolumePlugin{PluginName: "fake", Host: nil} kubelet.volumePluginMgr.InitPlugins([]volume.VolumePlugin{plug}, &volumeHost{kubelet})