in mount_windows.go [79:161]
func (mounter *Mounter) MountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
target = NormalizeWindowsPath(target)
sanitizedOptionsForLogging := sanitizedOptionsForLogging(options, sensitiveOptions)
if source == "tmpfs" {
klog.V(3).Infof("mounting source (%q), target (%q), with options (%q)", source, target, sanitizedOptionsForLogging)
return os.MkdirAll(target, 0755)
}
parentDir := filepath.Dir(target)
if err := os.MkdirAll(parentDir, 0755); err != nil {
return err
}
klog.V(4).Infof("mount options(%q) source:%q, target:%q, fstype:%q, begin to mount",
sanitizedOptionsForLogging, source, target, fstype)
bindSource := source
if bind, _, _, _ := MakeBindOptsSensitive(options, sensitiveOptions); bind {
bindSource = NormalizeWindowsPath(source)
} else {
allOptions := []string{}
allOptions = append(allOptions, options...)
allOptions = append(allOptions, sensitiveOptions...)
if len(allOptions) < 2 {
return fmt.Errorf("mount options(%q) should have at least 2 options, current number:%d, source:%q, target:%q",
sanitizedOptionsForLogging, len(allOptions), source, target)
}
// currently only cifs mount is supported
if strings.ToLower(fstype) != "cifs" {
return fmt.Errorf("only cifs mount is supported now, fstype: %q, mounting source (%q), target (%q), with options (%q)", fstype, source, target, sanitizedOptionsForLogging)
}
// lock smb mount for the same source
getSMBMountMutex.LockKey(source)
defer getSMBMountMutex.UnlockKey(source)
username := allOptions[0]
password := allOptions[1]
if output, err := newSMBMapping(username, password, source); err != nil {
klog.Warningf("SMB Mapping(%s) returned with error(%v), output(%s)", source, err, string(output))
if isSMBMappingExist(source) {
valid, err := isValidPath(source)
if !valid {
if err == nil || isAccessDeniedError(err) {
klog.V(2).Infof("SMB Mapping(%s) already exists while it's not valid, return error: %v, now begin to remove and remount", source, err)
if output, err = removeSMBMapping(source); err != nil {
return fmt.Errorf("Remove-SmbGlobalMapping failed: %v, output: %q", err, output)
}
if output, err := newSMBMapping(username, password, source); err != nil {
return fmt.Errorf("New-SmbGlobalMapping(%s) failed: %v, output: %q", source, err, output)
}
}
} else {
klog.V(2).Infof("SMB Mapping(%s) already exists and is still valid, skip error(%v)", source, err)
}
} else {
return fmt.Errorf("New-SmbGlobalMapping(%s) failed: %v, output: %q", source, err, output)
}
}
}
// There is an issue in golang where EvalSymlinks fails on Windows when passed a
// UNC share root path without a trailing backslash.
// Ex: \\SERVER\share will fail to resolve but \\SERVER\share\ will resolve
// containerD on Windows calls EvalSymlinks so we'll add the backslash when making the symlink if it is missing.
// https://github.com/golang/go/pull/42096 fixes this issue in golang but a fix will not be available until
// golang v1.16
mklinkSource := bindSource
if !strings.HasSuffix(mklinkSource, "\\") {
mklinkSource = mklinkSource + "\\"
}
output, err := exec.Command("cmd", "/c", "mklink", "/D", target, mklinkSource).CombinedOutput()
if err != nil {
klog.Errorf("mklink failed: %v, source(%q) target(%q) output: %q", err, mklinkSource, target, string(output))
return err
}
klog.V(2).Infof("mklink source(%q) on target(%q) successfully, output: %q", mklinkSource, target, string(output))
return nil
}