1
2
3
4
19
20 package util
21
22 import (
23 "errors"
24 "fmt"
25 "net"
26 "os"
27 "path/filepath"
28 "strconv"
29 "strings"
30
31 "k8s.io/klog/v2"
32 )
33
34
35 func (handler *deviceHandler) FindMultipathDeviceForDevice(device string) string {
36 io := handler.getIo
37 disk, err := findDeviceForPath(device, io)
38 if err != nil {
39 return ""
40 }
41 sysPath := "/sys/block/"
42 if dirs, err := io.ReadDir(sysPath); err == nil {
43 for _, f := range dirs {
44 name := f.Name()
45 if strings.HasPrefix(name, "dm-") {
46 if _, err1 := io.Lstat(sysPath + name + "/slaves/" + disk); err1 == nil {
47 return "/dev/" + name
48 }
49 }
50 }
51 }
52 return ""
53 }
54
55
56
57 func findDeviceForPath(path string, io IoUtil) (string, error) {
58 devicePath, err := io.EvalSymlinks(path)
59 if err != nil {
60 return "", err
61 }
62
63
64 parts := strings.Split(devicePath, "/")
65 if len(parts) == 3 && strings.HasPrefix(parts[1], "dev") {
66 return parts[2], nil
67 }
68 return "", errors.New("Illegal path for device " + devicePath)
69 }
70
71
72
73 func (handler *deviceHandler) FindSlaveDevicesOnMultipath(dm string) []string {
74 var devices []string
75 io := handler.getIo
76
77 parts := strings.Split(dm, "/")
78 if len(parts) != 3 || !strings.HasPrefix(parts[1], "dev") {
79 return devices
80 }
81 disk := parts[2]
82 slavesPath := filepath.Join("/sys/block/", disk, "/slaves/")
83 if files, err := io.ReadDir(slavesPath); err == nil {
84 for _, f := range files {
85 devices = append(devices, filepath.Join("/dev/", f.Name()))
86 }
87 }
88 return devices
89 }
90
91
92
93
94
95
96
97
98 func (handler *deviceHandler) GetISCSIPortalHostMapForTarget(targetIqn string) (map[string]int, error) {
99 portalHostMap := make(map[string]int)
100 io := handler.getIo
101
102
103 sysPath := "/sys/class/iscsi_host"
104 hostDirs, err := io.ReadDir(sysPath)
105 if err != nil {
106 if os.IsNotExist(err) {
107 return portalHostMap, nil
108 }
109 return nil, err
110 }
111 for _, hostDir := range hostDirs {
112
113
114 hostName := hostDir.Name()
115 if !strings.HasPrefix(hostName, "host") {
116 continue
117 }
118 hostNumber, err := strconv.Atoi(strings.TrimPrefix(hostName, "host"))
119 if err != nil {
120 klog.Errorf("Could not get number from iSCSI host: %s", hostName)
121 continue
122 }
123
124
125
126 devicePath := sysPath + "/" + hostName + "/device"
127 deviceDirs, err := io.ReadDir(devicePath)
128 if err != nil {
129 return nil, err
130 }
131 for _, deviceDir := range deviceDirs {
132
133
134
135 sessionName := deviceDir.Name()
136 if !strings.HasPrefix(sessionName, "session") {
137 continue
138 }
139
140 sessionPath := devicePath + "/" + sessionName
141
142
143 targetNamePath := sessionPath + "/iscsi_session/" + sessionName + "/targetname"
144 targetName, err := io.ReadFile(targetNamePath)
145 if err != nil {
146 klog.Infof("Failed to process session %s, assuming this session is unavailable: %s", sessionName, err)
147 continue
148 }
149
150
151 if strings.TrimSpace(string(targetName)) != targetIqn {
152 continue
153 }
154
155
156
157 dirs2, err := io.ReadDir(sessionPath)
158 if err != nil {
159 klog.Infof("Failed to process session %s, assuming this session is unavailable: %s", sessionName, err)
160 continue
161 }
162 for _, dir2 := range dirs2 {
163
164
165
166 dirName := dir2.Name()
167 if !strings.HasPrefix(dirName, "connection") {
168 continue
169 }
170
171 connectionPath := sessionPath + "/" + dirName + "/iscsi_connection/" + dirName
172
173
174 addrPath := connectionPath + "/address"
175 addr, err := io.ReadFile(addrPath)
176 if err != nil {
177 klog.Infof("Failed to process connection %s, assuming this connection is unavailable: %s", dirName, err)
178 continue
179 }
180
181 portPath := connectionPath + "/port"
182 port, err := io.ReadFile(portPath)
183 if err != nil {
184 klog.Infof("Failed to process connection %s, assuming this connection is unavailable: %s", dirName, err)
185 continue
186 }
187
188 persistentAddrPath := connectionPath + "/persistent_address"
189 persistentAddr, err := io.ReadFile(persistentAddrPath)
190 if err != nil {
191 klog.Infof("Failed to process connection %s, assuming this connection is unavailable: %s", dirName, err)
192 continue
193 }
194
195 persistentPortPath := connectionPath + "/persistent_port"
196 persistentPort, err := io.ReadFile(persistentPortPath)
197 if err != nil {
198 klog.Infof("Failed to process connection %s, assuming this connection is unavailable: %s", dirName, err)
199 continue
200 }
201
202
203
204
205 portal := net.JoinHostPort(strings.TrimSpace(string(addr)), strings.TrimSpace(string(port)))
206 portalHostMap[portal] = hostNumber
207
208 persistentPortal := net.JoinHostPort(strings.TrimSpace(string(persistentAddr)), strings.TrimSpace(string(persistentPort)))
209 portalHostMap[persistentPortal] = hostNumber
210 }
211 }
212 }
213
214 return portalHostMap, nil
215 }
216
217
218
219 func (handler *deviceHandler) FindDevicesForISCSILun(targetIqn string, lun int) ([]string, error) {
220 devices := make([]string, 0)
221 io := handler.getIo
222
223
224 sysPath := "/sys/class/iscsi_host"
225 hostDirs, err := io.ReadDir(sysPath)
226 if err != nil {
227 return nil, err
228 }
229 for _, hostDir := range hostDirs {
230
231
232 hostName := hostDir.Name()
233 if !strings.HasPrefix(hostName, "host") {
234 continue
235 }
236 hostNumber, err := strconv.Atoi(strings.TrimPrefix(hostName, "host"))
237 if err != nil {
238 klog.Errorf("Could not get number from iSCSI host: %s", hostName)
239 continue
240 }
241
242
243
244 devicePath := sysPath + "/" + hostName + "/device"
245 deviceDirs, err := io.ReadDir(devicePath)
246 if err != nil {
247 return nil, err
248 }
249 for _, deviceDir := range deviceDirs {
250
251
252
253 sessionName := deviceDir.Name()
254 if !strings.HasPrefix(sessionName, "session") {
255 continue
256 }
257
258
259 targetNamePath := devicePath + "/" + sessionName + "/iscsi_session/" + sessionName + "/targetname"
260 targetName, err := io.ReadFile(targetNamePath)
261 if err != nil {
262 return nil, err
263 }
264
265
266
267 if strings.TrimSpace(string(targetName)) != targetIqn {
268 continue
269 }
270
271
272
273
274
275 targetPath := devicePath + "/" + sessionName + fmt.Sprintf("/target%d:0:0", hostNumber)
276
277
278
279 blockDevicePath := targetPath + fmt.Sprintf("/%d:0:0:%d", hostNumber, lun)
280
281
282 _, err = io.Lstat(blockDevicePath)
283 if err != nil {
284 continue
285 }
286
287
288
289 path := blockDevicePath + "/block"
290 dirs, err := io.ReadDir(path)
291 if err != nil {
292 return nil, err
293 }
294 if 0 < len(dirs) {
295 devices = append(devices, dirs[0].Name())
296 }
297 }
298 }
299
300 return devices, nil
301 }
302
View as plain text