// getPodVolumePathListFromDisk returns a list of the volume paths by reading the // volume directories for the given pod from the disk. func (kl *Kubelet) getPodVolumePathListFromDisk(podUID types.UID) ([]string, error) { volumes := []string{} podVolDir := kl.getPodVolumesDir(podUID) if pathExists, pathErr := volumeutil.PathExists(podVolDir); pathErr != nil { return volumes, fmt.Errorf("Error checking if path %q exists: %v", podVolDir, pathErr) } else if !pathExists { glog.Warningf("Warning: path %q does not exist: %q", podVolDir) return volumes, nil } volumePluginDirs, err := ioutil.ReadDir(podVolDir) if err != nil { glog.Errorf("Could not read directory %s: %v", podVolDir, err) return volumes, err } for _, volumePluginDir := range volumePluginDirs { volumePluginName := volumePluginDir.Name() volumePluginPath := path.Join(podVolDir, volumePluginName) volumeDirs, err := util.ReadDirNoStat(volumePluginPath) if err != nil { return volumes, fmt.Errorf("Could not read directory %s: %v", volumePluginPath, err) } for _, volumeDir := range volumeDirs { volumes = append(volumes, path.Join(volumePluginPath, volumeDir)) } } return volumes, nil }
func verifyDevicePath(path string) (string, error) { if pathExists, err := volumeutil.PathExists(path); err != nil { return "", fmt.Errorf("Error checking if path exists: %v", err) } else if pathExists { return path, nil } return "", nil }
func (c *rbdUnmounter) TearDownAt(dir string) error { if pathExists, pathErr := volutil.PathExists(dir); pathErr != nil { return fmt.Errorf("Error checking if path exists: %v", pathErr) } else if !pathExists { glog.Warningf("Warning: Unmount skipped because path does not exist: %v", dir) return nil } return diskTearDown(c.manager, *c, dir, c.mounter) }
// TearDownAt simply deletes everything in the directory. func (f *flexVolumeUnmounter) TearDownAt(dir string) error { if pathExists, pathErr := util.PathExists(dir); pathErr != nil { return fmt.Errorf("Error checking if path exists: %v", pathErr) } else if !pathExists { glog.Warningf("Warning: Unmount skipped because path does not exist: %v", dir) return nil } notmnt, err := f.mounter.IsLikelyNotMountPoint(dir) if err != nil { glog.Errorf("Error checking mount point %s, error: %v", dir, err) return err } if notmnt { return os.Remove(dir) } device, refCount, err := mount.GetDeviceNameFromMount(f.mounter, dir) if err != nil { glog.Errorf("Failed to get reference count for volume: %s", dir) return err } if err := f.manager.unmount(f, dir); err != nil { if !isCmdNotSupportedErr(err) { glog.Errorf("Failed to unmount volume %s", f.volName) return err } // Unmount not supported by the driver. Use core unmount logic. if err := f.mounter.Unmount(dir); err != nil { glog.Errorf("Failed to unmount volume: %s, error: %v", dir, err) return err } } if refCount == 1 { if err := f.manager.detach(f, device); err != nil { if !isCmdNotSupportedErr(err) { glog.Errorf("Failed to teardown volume: %s, error: %v", dir, err) return err } // Teardown not supported by driver. Unmount is good enough. } } notmnt, err = f.mounter.IsLikelyNotMountPoint(dir) if err != nil { glog.Errorf("Error checking mount point %s, error: %v", dir, err) return err } if notmnt { return os.Remove(dir) } return nil }
func verifyDevicePath(path string) (string, error) { if pathExists, err := volumeutil.PathExists(path); err != nil { return "", fmt.Errorf("Error checking if path exists: %v", err) } else if pathExists { return path, nil } glog.V(4).Infof("verifyDevicePath: path not exists yet") return "", nil }
// WaitForDetach detects if the disk is detached on the node func (detacher *azureDiskDetacher) WaitForDetach(devicePath string, timeout time.Duration) error { return wait.Poll(checkSleepDuration, timeout, func() (bool, error) { glog.V(4).Infof("Checking device %q is detached.", devicePath) if pathExists, err := util.PathExists(devicePath); err != nil { return false, fmt.Errorf("Error checking if device path exists: %v", err) } else if !pathExists { return true, nil } else { return false, nil } }) }
// Returns the first path that exists, or empty string if none exist. func verifyAllPathsRemoved(devicePaths []string) (bool, error) { allPathsRemoved := true for _, path := range devicePaths { if exists, err := volumeutil.PathExists(path); err != nil { return false, fmt.Errorf("Error checking if path exists: %v", err) } else { allPathsRemoved = allPathsRemoved && !exists } } return allPathsRemoved, nil }
// Unmounts the bind mount, and detaches the disk only if the PD // resource was the last reference to that disk on the kubelet. func (c *azureDiskUnmounter) TearDownAt(dir string) error { if pathExists, pathErr := util.PathExists(dir); pathErr != nil { return fmt.Errorf("Error checking if path exists: %v", pathErr) } else if !pathExists { glog.Warningf("Warning: Unmount skipped because path does not exist: %v", dir) return nil } notMnt, err := c.mounter.IsLikelyNotMountPoint(dir) if err != nil { glog.Errorf("Error checking if mountpoint %s: %v", dir, err) return err } if notMnt { glog.V(2).Info("Not mountpoint, deleting") return os.Remove(dir) } // lock the volume (and thus wait for any concurrrent SetUpAt to finish) c.plugin.volumeLocks.LockKey(c.diskName) defer c.plugin.volumeLocks.UnlockKey(c.diskName) refs, err := mount.GetMountRefs(c.mounter, dir) if err != nil { glog.Errorf("Error getting mountrefs for %s: %v", dir, err) return err } if len(refs) == 0 { glog.Errorf("Did not find pod-mount for %s during tear down", dir) return fmt.Errorf("%s is not mounted", dir) } c.diskName = path.Base(refs[0]) glog.V(4).Infof("Found volume %s mounted to %s", c.diskName, dir) // Unmount the bind-mount inside this pod if err := c.mounter.Unmount(dir); err != nil { glog.Errorf("Error unmounting dir %s %v", dir, err) return err } notMnt, mntErr := c.mounter.IsLikelyNotMountPoint(dir) if mntErr != nil { glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr) return err } if notMnt { if err := os.Remove(dir); err != nil { glog.Errorf("Error removing mountpoint %s %v", dir, err) return err } } return nil }
// Returns the first path that exists, or empty string if none exist. func verifyAllPathsRemoved(devicePaths []string) (bool, error) { allPathsRemoved := true for _, path := range devicePaths { if err := udevadmChangeToDrive(path); err != nil { // udevadm errors should not block disk detachment, log and continue glog.Errorf("%v", err) } if exists, err := volumeutil.PathExists(path); err != nil { return false, fmt.Errorf("Error checking if path exists: %v", err) } else { allPathsRemoved = allPathsRemoved && !exists } } return allPathsRemoved, nil }
// Returns the first path that exists, or empty string if none exist. func verifyDevicePath(devicePaths []string, sdBeforeSet sets.String) (string, error) { if err := udevadmChangeToNewDrives(sdBeforeSet); err != nil { // udevadm errors should not block disk detachment, log and continue glog.Errorf("udevadmChangeToNewDrives failed with: %v", err) } for _, path := range devicePaths { if pathExists, err := volumeutil.PathExists(path); err != nil { return "", fmt.Errorf("Error checking if path exists: %v", err) } else if pathExists { return path, nil } } return "", nil }
// UnmountViaEmptyDir delegates the tear down operation for secret, configmap, git_repo and downwardapi // to empty_dir func UnmountViaEmptyDir(dir string, host VolumeHost, volName string, volSpec Spec, podUID types.UID) error { glog.V(3).Infof("Tearing down volume %v for pod %v at %v", volName, podUID, dir) if pathExists, pathErr := volutil.PathExists(dir); pathErr != nil { return fmt.Errorf("Error checking if path exists: %v", pathErr) } else if !pathExists { glog.Warningf("Warning: Unmount skipped because path does not exist: %v", dir) return nil } // Wrap EmptyDir, let it do the teardown. wrapped, err := host.NewWrapperUnmounter(volName, volSpec, podUID) if err != nil { return err } return wrapped.TearDownAt(dir) }
func (detacher *gcePersistentDiskDetacher) WaitForDetach(devicePath string, timeout time.Duration) error { ticker := time.NewTicker(checkSleepDuration) defer ticker.Stop() timer := time.NewTimer(timeout) defer timer.Stop() for { select { case <-ticker.C: glog.V(5).Infof("Checking device %q is detached.", devicePath) if pathExists, err := volumeutil.PathExists(devicePath); err != nil { return fmt.Errorf("Error checking if device path exists: %v", err) } else if !pathExists { return nil } case <-timer.C: return fmt.Errorf("Timeout reached; PD Device %v is still attached", devicePath) } } }
// TearDownAt simply discards everything in the directory. func (ed *emptyDir) TearDownAt(dir string) error { if pathExists, pathErr := volumeutil.PathExists(dir); pathErr != nil { return fmt.Errorf("Error checking if path exists: %v", pathErr) } else if !pathExists { glog.Warningf("Warning: Unmount skipped because path does not exist: %v", dir) return nil } // Figure out the medium. medium, isMnt, err := ed.mountDetector.GetMountMedium(dir) if err != nil { return err } if isMnt && medium == mediumMemory { ed.medium = v1.StorageMediumMemory return ed.teardownTmpfs(dir) } // assume StorageMediumDefault return ed.teardownDefault(dir) }
func (attacher *cinderDiskAttacher) WaitForAttach(spec *volume.Spec, devicePath string, timeout time.Duration) (string, error) { // NOTE: devicePath is is path as reported by Cinder, which may be incorrect and should not be used. See Issue #33128 volumeSource, _, err := getVolumeSource(spec) if err != nil { return "", err } volumeID := volumeSource.VolumeID if devicePath == "" { return "", fmt.Errorf("WaitForAttach failed for Cinder disk %q: devicePath is empty.", volumeID) } ticker := time.NewTicker(checkSleepDuration) defer ticker.Stop() timer := time.NewTimer(timeout) defer timer.Stop() for { probeAttachedVolume() select { case <-ticker.C: glog.V(5).Infof("Checking Cinder disk %q is attached.", volumeID) probeAttachedVolume() if !attacher.cinderProvider.ShouldTrustDevicePath() { // Using the Cinder volume ID, find the real device path (See Issue #33128) devicePath = attacher.cinderProvider.GetDevicePath(volumeID) } exists, err := volumeutil.PathExists(devicePath) if exists && err == nil { glog.Infof("Successfully found attached Cinder disk %q at %v.", volumeID, devicePath) return devicePath, nil } else { // Log an error, and continue checking periodically glog.Errorf("Error: could not find attached Cinder disk %q: %v", volumeID, err) } case <-timer.C: return "", fmt.Errorf("Could not find attached Cinder disk %q. Timeout waiting for mount paths to be created.", volumeID) } } }
func (attacher *cinderDiskAttacher) WaitForAttach(spec *volume.Spec, devicePath string, timeout time.Duration) (string, error) { volumeSource, _, err := getVolumeSource(spec) if err != nil { return "", err } volumeID := volumeSource.VolumeID if devicePath == "" { return "", fmt.Errorf("WaitForAttach failed for Cinder disk %q: devicePath is empty.", volumeID) } ticker := time.NewTicker(checkSleepDuration) defer ticker.Stop() timer := time.NewTimer(timeout) defer timer.Stop() for { probeAttachedVolume() select { case <-ticker.C: glog.V(5).Infof("Checking Cinder disk %q is attached.", volumeID) probeAttachedVolume() exists, err := volumeutil.PathExists(devicePath) if exists && err == nil { glog.Infof("Successfully found attached Cinder disk %q.", volumeID) return devicePath, nil } else { //Log error, if any, and continue checking periodically glog.Errorf("Error Stat Cinder disk (%q) is attached: %v", volumeID, err) } case <-timer.C: return "", fmt.Errorf("Could not find attached Cinder disk %q. Timeout waiting for mount paths to be created.", volumeID) } } }
// Unmounts the bind mount, and detaches the disk only if the PD // resource was the last reference to that disk on the kubelet. func (c *cinderVolumeUnmounter) TearDownAt(dir string) error { if pathExists, pathErr := util.PathExists(dir); pathErr != nil { return fmt.Errorf("Error checking if path exists: %v", pathErr) } else if !pathExists { glog.Warningf("Warning: Unmount skipped because path does not exist: %v", dir) return nil } glog.V(5).Infof("Cinder TearDown of %s", dir) notmnt, err := c.mounter.IsLikelyNotMountPoint(dir) if err != nil { glog.V(4).Infof("IsLikelyNotMountPoint check failed: %v", err) return err } if notmnt { glog.V(4).Infof("Nothing is mounted to %s, ignoring", dir) return os.Remove(dir) } // Find Cinder volumeID to lock the right volume // TODO: refactor VolumePlugin.NewUnmounter to get full volume.Spec just like // NewMounter. We could then find volumeID there without probing MountRefs. refs, err := mount.GetMountRefs(c.mounter, dir) if err != nil { glog.V(4).Infof("GetMountRefs failed: %v", err) return err } if len(refs) == 0 { glog.V(4).Infof("Directory %s is not mounted", dir) return fmt.Errorf("directory %s is not mounted", dir) } c.pdName = path.Base(refs[0]) glog.V(4).Infof("Found volume %s mounted to %s", c.pdName, dir) // lock the volume (and thus wait for any concurrrent SetUpAt to finish) c.plugin.volumeLocks.LockKey(c.pdName) defer c.plugin.volumeLocks.UnlockKey(c.pdName) // Reload list of references, there might be SetUpAt finished in the meantime refs, err = mount.GetMountRefs(c.mounter, dir) if err != nil { glog.V(4).Infof("GetMountRefs failed: %v", err) return err } if err := c.mounter.Unmount(dir); err != nil { glog.V(4).Infof("Unmount failed: %v", err) return err } glog.V(3).Infof("Successfully unmounted: %s\n", dir) notmnt, mntErr := c.mounter.IsLikelyNotMountPoint(dir) if mntErr != nil { glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr) return err } if notmnt { if err := os.Remove(dir); err != nil { glog.V(4).Infof("Failed to remove directory after unmount: %v", err) return err } } return nil }