forked from kubernetes-csi/csi-proxy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsmb.go
153 lines (129 loc) · 4.39 KB
/
smb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package smb
import (
"context"
"fmt"
"strings"
fs "github.com/kubernetes-csi/csi-proxy/pkg/filesystem"
smbapi "github.com/kubernetes-csi/csi-proxy/pkg/smb/hostapi"
"k8s.io/klog/v2"
)
type SMB struct {
hostAPI smbapi.HostAPI
fs fs.Interface
}
type Interface interface {
// NewSMBGlobalMapping creates an SMB mapping on the SMB client to an SMB share.
NewSMBGlobalMapping(context.Context, *NewSMBGlobalMappingRequest) (*NewSMBGlobalMappingResponse, error)
// RemoveSMBGlobalMapping removes the SMB mapping to an SMB share.
RemoveSMBGlobalMapping(context.Context, *RemoveSMBGlobalMappingRequest) (*RemoveSMBGlobalMappingResponse, error)
}
// check that SMB implements the Interface
var _ Interface = &SMB{}
func normalizeWindowsPath(path string) string {
normalizedPath := strings.Replace(path, "/", "\\", -1)
return normalizedPath
}
func getRootMappingPath(path string) (string, error) {
items := strings.Split(path, "\\")
parts := []string{}
for _, s := range items {
if len(s) > 0 {
parts = append(parts, s)
if len(parts) == 2 {
break
}
}
}
if len(parts) != 2 {
klog.Errorf("remote path (%s) is invalid", path)
return "", fmt.Errorf("remote path (%s) is invalid", path)
}
// parts[0] is a SMB host name
// parts[1] is a SMB share name
return strings.ToLower("\\\\" + parts[0] + "\\" + parts[1]), nil
}
func New(hostAPI smbapi.HostAPI, fsClient fs.Interface) (*SMB, error) {
return &SMB{
hostAPI: hostAPI,
fs: fsClient,
}, nil
}
func (s *SMB) NewSMBGlobalMapping(context context.Context, request *NewSMBGlobalMappingRequest) (*NewSMBGlobalMappingResponse, error) {
klog.V(2).Infof("calling NewSMBGlobalMapping with remote path %q", request.RemotePath)
response := &NewSMBGlobalMappingResponse{}
remotePath := normalizeWindowsPath(request.RemotePath)
localPath := request.LocalPath
if remotePath == "" {
klog.Errorf("remote path is empty")
return response, fmt.Errorf("remote path is empty")
}
mappingPath, err := getRootMappingPath(remotePath)
if err != nil {
return response, err
}
isMapped, err := s.hostAPI.IsSMBMapped(mappingPath)
if err != nil {
isMapped = false
}
if isMapped {
klog.V(4).Infof("Remote %s already mapped. Validating...", mappingPath)
validResp, err := s.fs.PathValid(context, &fs.PathValidRequest{Path: mappingPath})
if err != nil {
klog.Warningf("PathValid(%s) failed with %v, ignore error", mappingPath, err)
}
if !validResp.Valid {
klog.V(4).Infof("RemotePath %s is not valid, removing now", mappingPath)
err := s.hostAPI.RemoveSMBGlobalMapping(mappingPath)
if err != nil {
klog.Errorf("RemoveSMBGlobalMapping(%s) failed with %v", mappingPath, err)
return response, err
}
isMapped = false
} else {
klog.V(4).Infof("RemotePath %s is valid", mappingPath)
}
}
if !isMapped {
klog.V(4).Infof("Remote %s not mapped. Mapping now!", mappingPath)
err = s.hostAPI.NewSMBGlobalMapping(mappingPath, request.Username, request.Password)
if err != nil {
klog.Errorf("failed NewSMBGlobalMapping %v", err)
return response, err
}
}
if len(localPath) != 0 {
klog.V(4).Infof("ValidatePathWindows: '%s'", localPath)
err = fs.ValidatePathWindows(localPath)
if err != nil {
klog.Errorf("failed validate plugin path %v", err)
return response, err
}
err = s.hostAPI.NewSMBLink(remotePath, localPath)
if err != nil {
klog.Errorf("failed NewSMBLink %v", err)
return response, fmt.Errorf("creating link %s to %s failed with error: %v", localPath, remotePath, err)
}
}
klog.V(2).Infof("NewSMBGlobalMapping on remote path %q is completed", request.RemotePath)
return response, nil
}
func (s *SMB) RemoveSMBGlobalMapping(context context.Context, request *RemoveSMBGlobalMappingRequest) (*RemoveSMBGlobalMappingResponse, error) {
klog.V(2).Infof("calling RemoveSMBGlobalMapping with remote path %q", request.RemotePath)
response := &RemoveSMBGlobalMappingResponse{}
remotePath := normalizeWindowsPath(request.RemotePath)
if remotePath == "" {
klog.Errorf("remote path is empty")
return response, fmt.Errorf("remote path is empty")
}
mappingPath, err := getRootMappingPath(remotePath)
if err != nil {
return response, err
}
err = s.hostAPI.RemoveSMBGlobalMapping(mappingPath)
if err != nil {
klog.Errorf("failed RemoveSMBGlobalMapping %v", err)
return response, err
}
klog.V(2).Infof("RemoveSMBGlobalMapping on remote path %q is completed", request.RemotePath)
return response, nil
}