@@ -80,9 +80,9 @@ func (m *mounter) GetBlockSizeBytes(devicePath string) (int64, error) {
80
80
81
81
func (m * mounter ) GetDevicePath (ctx context.Context , volumeID string ) (string , error ) {
82
82
backoff := wait.Backoff {
83
- Duration : 1 * time .Second ,
84
- Factor : 1.1 ,
85
- Steps : 15 ,
83
+ Duration : 2 * time .Second ,
84
+ Factor : 1.5 ,
85
+ Steps : 20 ,
86
86
}
87
87
88
88
var devicePath string
@@ -111,6 +111,24 @@ func (m *mounter) GetDevicePath(ctx context.Context, volumeID string) (string, e
111
111
}
112
112
113
113
func (m * mounter ) getDevicePathBySerialID (volumeID string ) (string , error ) {
114
+ // First try XenServer device paths
115
+ xenDevicePath , err := m .getDevicePathForXenServer (volumeID )
116
+ if err != nil {
117
+ fmt .Printf ("Failed to get XenServer device path: %v\n " , err )
118
+ }
119
+ if xenDevicePath != "" {
120
+ return xenDevicePath , nil
121
+ }
122
+
123
+ // Try VMware device paths
124
+ vmwareDevicePath , err := m .getDevicePathForVMware (volumeID )
125
+ if err != nil {
126
+ fmt .Printf ("Failed to get VMware device path: %v\n " , err )
127
+ }
128
+ if vmwareDevicePath != "" {
129
+ return vmwareDevicePath , nil
130
+ }
131
+ // Fall back to standard device paths (for KVM)
114
132
sourcePathPrefixes := []string {"virtio-" , "scsi-" , "scsi-0QEMU_QEMU_HARDDISK_" }
115
133
serial := diskUUIDToSerial (volumeID )
116
134
for _ , prefix := range sourcePathPrefixes {
@@ -120,13 +138,150 @@ func (m *mounter) getDevicePathBySerialID(volumeID string) (string, error) {
120
138
return source , nil
121
139
}
122
140
if ! os .IsNotExist (err ) {
141
+ fmt .Printf ("Not found: %s\n " , err .Error ())
123
142
return "" , err
124
143
}
125
144
}
126
145
127
146
return "" , nil
128
147
}
129
148
149
+ func (m * mounter ) getDevicePathForXenServer (volumeID string ) (string , error ) {
150
+ for i := 'b' ; i <= 'z' ; i ++ {
151
+ devicePath := fmt .Sprintf ("/dev/xvd%c" , i )
152
+ fmt .Printf ("Checking XenServer device path: %s\n " , devicePath )
153
+
154
+ if _ , err := os .Stat (devicePath ); err == nil {
155
+ isBlock , err := m .IsBlockDevice (devicePath )
156
+ if err == nil && isBlock {
157
+ if m .verifyXenServerDevice (devicePath , volumeID ) {
158
+ fmt .Printf ("Found and verified XenServer device: %s\n " , devicePath )
159
+ return devicePath , nil
160
+ }
161
+ }
162
+ }
163
+ }
164
+ return "" , fmt .Errorf ("device not found for volume %s" , volumeID )
165
+ }
166
+
167
+ func (m * mounter ) verifyXenServerDevice (devicePath string , volumeID string ) bool {
168
+ size , err := m .GetBlockSizeBytes (devicePath )
169
+ if err != nil {
170
+ fmt .Printf ("Failed to get device size: %v\n " , err )
171
+ return false
172
+ }
173
+ fmt .Printf ("Device size: %d bytes\n " , size )
174
+
175
+ mounted , err := m .isDeviceMounted (devicePath )
176
+ if err != nil {
177
+ fmt .Printf ("Failed to check if device is mounted: %v\n " , err )
178
+ return false
179
+ }
180
+ if mounted {
181
+ fmt .Printf ("Device is already mounted: %s\n " , devicePath )
182
+ return false
183
+ }
184
+
185
+ props , err := m .getDeviceProperties (devicePath )
186
+ if err != nil {
187
+ fmt .Printf ("Failed to get device properties: %v\n " , err )
188
+ return false
189
+ }
190
+ fmt .Printf ("Device properties: %v\n " , props )
191
+
192
+ return true
193
+ }
194
+
195
+ func (m * mounter ) getDevicePathForVMware (volumeID string ) (string , error ) {
196
+ // Loop through /dev/sdb to /dev/sdz (/dev/sda -> the root disk)
197
+ for i := 'b' ; i <= 'z' ; i ++ {
198
+ devicePath := fmt .Sprintf ("/dev/sd%c" , i )
199
+ fmt .Printf ("Checking VMware device path: %s\n " , devicePath )
200
+
201
+ if _ , err := os .Stat (devicePath ); err == nil {
202
+ isBlock , err := m .IsBlockDevice (devicePath )
203
+ if err == nil && isBlock {
204
+ // Use the same verification as for XenServer
205
+ if m .verifyVMwareDevice (devicePath , volumeID ) {
206
+ fmt .Printf ("Found and verified VMware device: %s\n " , devicePath )
207
+ return devicePath , nil
208
+ }
209
+ }
210
+ }
211
+ }
212
+ return "" , fmt .Errorf ("device not found for volume %s" , volumeID )
213
+ }
214
+
215
+ func (m * mounter ) verifyVMwareDevice (devicePath string , volumeID string ) bool {
216
+ size , err := m .GetBlockSizeBytes (devicePath )
217
+ if err != nil {
218
+ fmt .Printf ("Failed to get device size: %v\n " , err )
219
+ return false
220
+ }
221
+ fmt .Printf ("Device size: %d bytes\n " , size )
222
+
223
+ mounted , err := m .isDeviceMounted (devicePath )
224
+ if err != nil {
225
+ fmt .Printf ("Failed to check if device is mounted: %v\n " , err )
226
+ return false
227
+ }
228
+ if mounted {
229
+ fmt .Printf ("Device is already mounted: %s\n " , devicePath )
230
+ return false
231
+ }
232
+
233
+ props , err := m .getDeviceProperties (devicePath )
234
+ if err != nil {
235
+ fmt .Printf ("Failed to get device properties: %v\n " , err )
236
+ return false
237
+ }
238
+ fmt .Printf ("Device properties: %v\n " , props )
239
+
240
+ return true
241
+ }
242
+
243
+ func (m * mounter ) isDeviceMounted (devicePath string ) (bool , error ) {
244
+ output , err := m .Exec .Command ("grep" , devicePath , "/proc/mounts" ).Output ()
245
+ if err != nil {
246
+ if strings .Contains (err .Error (), "exit status 1" ) {
247
+ return false , nil
248
+ }
249
+ return false , err
250
+ }
251
+ return len (output ) > 0 , nil
252
+ }
253
+
254
+ func (m * mounter ) isDeviceInUse (devicePath string ) (bool , error ) {
255
+ output , err := m .Exec .Command ("lsof" , devicePath ).Output ()
256
+ if err != nil {
257
+ if strings .Contains (err .Error (), "exit status 1" ) {
258
+ return false , nil
259
+ }
260
+ return false , err
261
+ }
262
+ return len (output ) > 0 , nil
263
+ }
264
+
265
+ func (m * mounter ) getDeviceProperties (devicePath string ) (map [string ]string , error ) {
266
+ output , err := m .Exec .Command ("udevadm" , "info" , "--query=property" , devicePath ).Output ()
267
+ if err != nil {
268
+ return nil , err
269
+ }
270
+
271
+ props := make (map [string ]string )
272
+ for _ , line := range strings .Split (string (output ), "\n " ) {
273
+ if line == "" {
274
+ continue
275
+ }
276
+ parts := strings .Split (line , "=" )
277
+ if len (parts ) == 2 {
278
+ props [parts [0 ]] = parts [1 ]
279
+ }
280
+ }
281
+
282
+ return props , nil
283
+ }
284
+
130
285
func (m * mounter ) probeVolume (ctx context.Context ) {
131
286
logger := klog .FromContext (ctx )
132
287
logger .V (2 ).Info ("Scanning SCSI host" )
0 commit comments