@@ -111,6 +111,15 @@ func (m *mounter) GetDevicePath(ctx context.Context, volumeID string) (string, e
111111}
112112
113113func (m * mounter ) getDevicePathBySerialID (volumeID string ) (string , error ) {
114+ // Try VMware device paths
115+ vmwareDevicePath , err := m .getDevicePathForVMware (volumeID )
116+ if err != nil {
117+ fmt .Printf ("Failed to get VMware device path: %v\n " , err )
118+ }
119+ if vmwareDevicePath != "" {
120+ return vmwareDevicePath , nil
121+ }
122+ // Fall back to standard device paths (for KVM)
114123 sourcePathPrefixes := []string {"virtio-" , "scsi-" , "scsi-0QEMU_QEMU_HARDDISK_" }
115124 serial := diskUUIDToSerial (volumeID )
116125 for _ , prefix := range sourcePathPrefixes {
@@ -127,6 +136,96 @@ func (m *mounter) getDevicePathBySerialID(volumeID string) (string, error) {
127136 return "" , nil
128137}
129138
139+ func (m * mounter ) getDevicePathForVMware (volumeID string ) (string , error ) {
140+ // Loop through /dev/sdb to /dev/sdz (/dev/sda -> the root disk)
141+ for i := 'b' ; i <= 'z' ; i ++ {
142+ devicePath := fmt .Sprintf ("/dev/sd%c" , i )
143+ fmt .Printf ("Checking VMware device path: %s\n " , devicePath )
144+
145+ if _ , err := os .Stat (devicePath ); err == nil {
146+ isBlock , err := m .IsBlockDevice (devicePath )
147+ if err == nil && isBlock {
148+ // Use the same verification as for XenServer
149+ if m .verifyVMwareDevice (devicePath , volumeID ) {
150+ fmt .Printf ("Found and verified VMware device: %s\n " , devicePath )
151+ return devicePath , nil
152+ }
153+ }
154+ }
155+ }
156+ return "" , fmt .Errorf ("device not found for volume %s" , volumeID )
157+ }
158+
159+ func (m * mounter ) verifyVMwareDevice (devicePath string , volumeID string ) bool {
160+ size , err := m .GetBlockSizeBytes (devicePath )
161+ if err != nil {
162+ fmt .Printf ("Failed to get device size: %v\n " , err )
163+ return false
164+ }
165+ fmt .Printf ("Device size: %d bytes\n " , size )
166+
167+ mounted , err := m .isDeviceMounted (devicePath )
168+ if err != nil {
169+ fmt .Printf ("Failed to check if device is mounted: %v\n " , err )
170+ return false
171+ }
172+ if mounted {
173+ fmt .Printf ("Device is already mounted: %s\n " , devicePath )
174+ return false
175+ }
176+
177+ props , err := m .getDeviceProperties (devicePath )
178+ if err != nil {
179+ fmt .Printf ("Failed to get device properties: %v\n " , err )
180+ return false
181+ }
182+ fmt .Printf ("Device properties: %v\n " , props )
183+
184+ return true
185+ }
186+
187+ func (m * mounter ) isDeviceMounted (devicePath string ) (bool , error ) {
188+ output , err := m .Exec .Command ("grep" , devicePath , "/proc/mounts" ).Output ()
189+ if err != nil {
190+ if strings .Contains (err .Error (), "exit status 1" ) {
191+ return false , nil
192+ }
193+ return false , err
194+ }
195+ return len (output ) > 0 , nil
196+ }
197+
198+ func (m * mounter ) isDeviceInUse (devicePath string ) (bool , error ) {
199+ output , err := m .Exec .Command ("lsof" , devicePath ).Output ()
200+ if err != nil {
201+ if strings .Contains (err .Error (), "exit status 1" ) {
202+ return false , nil
203+ }
204+ return false , err
205+ }
206+ return len (output ) > 0 , nil
207+ }
208+
209+ func (m * mounter ) getDeviceProperties (devicePath string ) (map [string ]string , error ) {
210+ output , err := m .Exec .Command ("udevadm" , "info" , "--query=property" , devicePath ).Output ()
211+ if err != nil {
212+ return nil , err
213+ }
214+
215+ props := make (map [string ]string )
216+ for _ , line := range strings .Split (string (output ), "\n " ) {
217+ if line == "" {
218+ continue
219+ }
220+ parts := strings .Split (line , "=" )
221+ if len (parts ) == 2 {
222+ props [parts [0 ]] = parts [1 ]
223+ }
224+ }
225+
226+ return props , nil
227+ }
228+
130229func (m * mounter ) probeVolume (ctx context.Context ) {
131230 logger := klog .FromContext (ctx )
132231 logger .V (2 ).Info ("Scanning SCSI host" )
0 commit comments