Skip to content

Commit 38935b7

Browse files
committed
Do not fail volume attach operation at kubelet if staging target path already exists on windows worker node.
1 parent 67733c6 commit 38935b7

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

pkg/util/filesystem/defaultfs.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ limitations under the License.
1717
package filesystem
1818

1919
import (
20+
"fmt"
2021
"os"
2122
"path/filepath"
23+
"runtime"
2224
"strings"
2325
"time"
2426
)
@@ -75,6 +77,32 @@ func (fs *DefaultFs) MkdirAll(path string, perm os.FileMode) error {
7577
return os.MkdirAll(fs.prefix(path), perm)
7678
}
7779

80+
// MkdirAllWithPathCheck checks if path exists already. If not, it creates a directory
81+
// named path, along with any necessary parents, and returns nil, or else returns an error.
82+
// Permission bits perm (before umask) are used for all directories that
83+
// MkdirAllWithPathCheck creates.
84+
// If path is already a directory, MkdirAllWithPathCheck does nothing and returns nil.
85+
// NOTE: In case of Windows NTFS, mount points are implemented as reparse-point
86+
// (similar to symlink) and do not represent actual directory. Hence Directory existence
87+
// check for windows NTFS will NOT check for dir, but for symlink presence.
88+
func MkdirAllWithPathCheck(path string, perm os.FileMode) error {
89+
if dir, err := os.Lstat(path); err == nil {
90+
// If the path exists already,
91+
// 1. for Unix/Linux OS, check if the path is directory.
92+
// 2. for windows NTFS, check if the path is symlink instead of directory.
93+
if dir.IsDir() ||
94+
(runtime.GOOS == "windows" && (dir.Mode()&os.ModeSymlink != 0)) {
95+
return nil
96+
}
97+
return fmt.Errorf("path %v exists but is not a directory", path)
98+
}
99+
// If existence of path not known, attempt to create it.
100+
if err := os.MkdirAll(path, perm); err != nil {
101+
return err
102+
}
103+
return nil
104+
}
105+
78106
// Chtimes via os.Chtimes
79107
func (fs *DefaultFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
80108
return os.Chtimes(fs.prefix(name), atime, mtime)

pkg/volume/csi/csi_attacher.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"k8s.io/client-go/kubernetes"
3838
"k8s.io/klog/v2"
3939
"k8s.io/kubernetes/pkg/features"
40+
"k8s.io/kubernetes/pkg/util/filesystem"
4041
"k8s.io/kubernetes/pkg/volume"
4142
"k8s.io/kubernetes/pkg/volume/util"
4243
volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
@@ -341,9 +342,10 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo
341342

342343
// Store volume metadata for UnmountDevice. Keep it around even if the
343344
// driver does not support NodeStage, UnmountDevice still needs it.
344-
if err = os.MkdirAll(deviceMountPath, 0750); err != nil {
345+
if err = filesystem.MkdirAllWithPathCheck(deviceMountPath, 0750); err != nil {
345346
return errors.New(log("attacher.MountDevice failed to create dir %#v: %v", deviceMountPath, err))
346347
}
348+
347349
klog.V(4).Info(log("created target path successfully [%s]", deviceMountPath))
348350
dataDir := filepath.Dir(deviceMountPath)
349351
data := map[string]string{

0 commit comments

Comments
 (0)