Vinzenz Feenstra has uploaded a new change for review.

Change subject: win32: Read serial info directly when not available through WMI
......................................................................

win32: Read serial info directly when not available through WMI

The SerialNumber field in the WMI table 'Win32_DiskDrive' is only
available from Windows Vista and Windows 2008 Server.

This patch works around this issue by querying the device directly,
but only if the SerialNumber field is not available.

Change-Id: Id39914464377c388b8ef3e2551a47a295de4a750
Bug-Url: https://bugzilla.redhat.com/1158907
Signed-off-by: Vinzenz Feenstra <vfeen...@redhat.com>
---
M ovirt-guest-agent/GuestAgentWin32.py
1 file changed, 64 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-guest-agent 
refs/changes/35/35035/1

diff --git a/ovirt-guest-agent/GuestAgentWin32.py 
b/ovirt-guest-agent/GuestAgentWin32.py
index 8678b05..469a9a2 100644
--- a/ovirt-guest-agent/GuestAgentWin32.py
+++ b/ovirt-guest-agent/GuestAgentWin32.py
@@ -7,6 +7,7 @@
 import win32net
 import win32ts
 import win32api
+import win32file
 import win32pipe
 import win32security
 import win32process
@@ -21,12 +22,39 @@
 from ctypes.util import find_library
 from ctypes.wintypes import DWORD
 import _winreg
-
+import ctypes
+import ctypes.wintypes
 
 # Constants according to
 # http://msdn.microsoft.com/en-us/library/windows/desktop/ms724878.aspx
 KEY_WOW64_32KEY = 0x0100
 KEY_WOW64_64KEY = 0x0200
+
+
+class StoragePropertyQuery(ctypes.Structure):
+    _fields_ = (
+        ("a", ctypes.wintypes.ULONG),
+        ("b", ctypes.wintypes.ULONG),
+        ("c", ctypes.wintypes.BYTE),
+    )
+
+
+class StorageDeviceDescriptor(ctypes.Structure):
+    _fields_ = (
+        ("Version", ctypes.wintypes.ULONG),
+        ("Size", ctypes.wintypes.ULONG),
+        ("DeviceType", ctypes.wintypes.BYTE),
+        ("DeviceTypeModifier", ctypes.wintypes.BYTE),
+        ("RemovableMedia", ctypes.wintypes.BOOLEAN),
+        ("CommandQueueing", ctypes.wintypes.BOOLEAN),
+        ("VendorIdOffset", ctypes.wintypes.ULONG),
+        ("ProductIdOffset", ctypes.wintypes.ULONG),
+        ("ProductRevisionOffset", ctypes.wintypes.ULONG),
+        ("SerialNumberOffset", ctypes.wintypes.ULONG),
+        ("BusType", ctypes.wintypes.DWORD),
+        ("RawPropertiesLength", ctypes.wintypes.ULONG),
+        ("DATA", ctypes.wintypes.BYTE * 1024),
+    )
 
 
 # _winreg.QueryValueEx and win32api.RegQueryValueEx don't support reading
@@ -488,6 +516,35 @@
             logging.exception("Error retrieving disks usages.")
         return usages
 
+    def _readSMART(self, name):
+        serial = 'NO SERIAL NUMBER'
+        handle = ctypes.windll.kernel32.CreateFileW(
+            name,
+            win32file.GENERIC_READ | win32file.GENERIC_WRITE,
+            win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE,
+            None, win32file.OPEN_EXISTING, 0, 0)
+        if handle == -1:
+            logging.warning("Failed to open device '%s' for querying the "
+                            "serial number. Error code: %d", name,
+                            win32api.GetLastError())
+            return serial
+        q = StoragePropertyQuery()
+        r = StorageDeviceDescriptor()
+        read_count = ctypes.wintypes.ULONG()
+        ret = ctypes.windll.kernel32.DeviceIoControl(
+            handle, 0x002D1400, ctypes.addressof(q), ctypes.sizeof(q),
+            ctypes.addressof(r), ctypes.sizeof(r),
+            ctypes.addressof(read_count), 0)
+
+        if ret:
+            serial = buffer(r)[r.SerialNumberOffset:r.SerialNumberOffset + 20]
+        else:
+            logging.warning("DeviceIoControl for device %s failed with"
+                            "eror code: %d. Could not look up serial number",
+                            name, win32api.GetLastError())
+        ctypes.windll.kernel32.CloseHandle(handle)
+        return serial
+
     def getDiskMapping(self):
         result = {}
         try:
@@ -500,7 +557,11 @@
                 objSWbemServices.ExecQuery(
                     "SELECT * FROM Win32_DiskDrive")
             for objItem in colItems:
-                result[objItem.SerialNumber] = {'name': objItem.DeviceID}
+                try:
+                    serial = objItem.SerialNumber
+                except AttributeError:
+                    serial = self._readSMART(objItem.DeviceID)
+                result[serial] = {'name': objItem.DeviceID}
         except Exception:
             logging.exception("Failed to retrieve disk mapping")
         return result
@@ -600,6 +661,7 @@
     print "Active User:", dr.getActiveUser()
     print "Disks Usage:", dr.getDisksUsage()
     print "Memory Stats:", dr.getMemoryStats()
+    print "DiskMapping:", dr.getDiskMapping()
 
 if __name__ == '__main__':
     test()


-- 
To view, visit http://gerrit.ovirt.org/35035
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id39914464377c388b8ef3e2551a47a295de4a750
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-guest-agent
Gerrit-Branch: master
Gerrit-Owner: Vinzenz Feenstra <vfeen...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to