]> xenbits.xensource.com Git - people/pauldu/xeniface.git/commitdiff
Set VM's time based on host's time exposed by Xen
authorOwen Smith <owen.smith@citrix.com>
Wed, 29 Jun 2016 15:24:40 +0000 (16:24 +0100)
committerPaul Durrant <paul.durrant@citrix.com>
Thu, 7 Jul 2016 10:37:53 +0000 (11:37 +0100)
Sets the VM's time when XenIface starts and on resume from suspend.
Uses the underlying host's time, accessed via Xen. Provide an option
for the guest to treat Xen's time as UTC or the current timezone.
This option adds 2 new brandable variables that specify a partial
registry path and value in the VM that determines how the time offset
is modified. These values are REG_TOOLS_PATH and REG_UTC_NAME which
should be specified in the build environment if the values need to
be different.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
Changed REG_TOOLS_PATH to REG_KEY_NAME, which now defaults to 'Windows
PV Drivers' (that being the official XenProject sub-project name), and
use hard coded 'HostTime' key name instead of brandable REG_UTC_NAME.
If we have a brandable parent registry key, then we don't really need
to brand the value names under it.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
build.py
src/xenagent/service.cpp
src/xenagent/service.h

index f49374cdf3b5bc9557c1212c676c883ea80b1a5b..1d587fad6137be4b78a821626e1c316664eee114 100755 (executable)
--- a/build.py
+++ b/build.py
@@ -70,6 +70,9 @@ def make_header():
     file.write('#define DAY_STR\t\t\t"' + str(now.day) + '"\n')
     file.write('\n')
 
+    file.write('#define REG_KEY_NAME\t\t\t"' + os.environ['REG_KEY_NAME'] + '"\n')
+    file.write('\n')
+
     file.close()
 
 
@@ -426,6 +429,9 @@ if __name__ == '__main__':
     if 'OBJECT_PREFIX' not in os.environ.keys():
         os.environ['OBJECT_PREFIX'] = 'XenProject'
 
+    if 'REG_KEY_NAME' not in os.environ.keys():
+        os.environ['REG_KEY_NAME'] = 'Windows PV Drivers'
+
     os.environ['MAJOR_VERSION'] = '8'
     os.environ['MINOR_VERSION'] = '2'
     os.environ['MICRO_VERSION'] = '0'
index 2520c2cac0cdbaddde66fb7deb18e62301a539a2..2633809a27b097bd4e5823886eaca7cc73b4bb9d 100644 (file)
@@ -218,6 +218,8 @@ CXenAgent::~CXenAgent()
 
         // suspend
         m_device->SuspendRegister(m_evt_suspend, &m_ctxt_suspend);
+
+        SetXenTime();
     }
 }
 
@@ -317,6 +319,121 @@ void CXenAgent::EventLog(DWORD evt)
     }
 }
 
+bool CXenAgent::IsHostTimeUTC()
+{
+#ifdef _WIN64
+    // Check SOFTWARE\Wow6432Node\$(VENDOR_NAME_STR)\$(REG_KEY_NAME) $(REG_UTC_NAME) == UTC
+    if (RegCheckIsUTC("SOFTWARE\\Wow6432Node"))
+        return true;
+#endif
+    // Check SOFTWARE\$(VENDOR_NAME_STR)\$(REG_KEY_NAME) $(REG_UTC_NAME) == UTC
+    if (RegCheckIsUTC("SOFTWARE"))
+        return true;
+
+    return false;
+}
+
+void CXenAgent::AdjustXenTimeToUTC(FILETIME* now)
+{
+    std::string vm;
+    if (!m_device->StoreRead("vm", vm))
+        return;
+
+    std::string offs;
+    if (!m_device->StoreRead(vm + "/rtc/timeoffset", offs))
+        return;
+
+    long offset = (long)atoi(offs.c_str());
+
+    ULARGE_INTEGER lnow;
+    lnow.LowPart  = now->dwLowDateTime;
+    lnow.HighPart = now->dwHighDateTime;
+
+    lnow.QuadPart -= ((LONGLONG)offset * 1000000);
+
+    now->dwLowDateTime  = lnow.LowPart;
+    now->dwHighDateTime = lnow.HighPart;
+}
+
+bool CXenAgent::RegCheckIsUTC(const char* rootpath)
+{
+    HKEY    key;
+    LRESULT lr;
+    std::string path;
+    bool    match = false;
+
+    path = rootpath;
+    path += "\\";
+    path += VENDOR_NAME_STR;
+    path += "\\";
+    path += REG_KEY_NAME;
+
+    lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_READ, &key);
+    if (lr != ERROR_SUCCESS)
+        goto fail1;
+
+    long size = 32;
+    DWORD length;
+    char* buffer = NULL;
+
+    do {
+        length = size;
+        if (buffer)
+            delete [] buffer;
+
+        buffer = new char[size];
+        if (buffer == NULL)
+            goto fail2;
+
+        lr = RegQueryValueEx(key, "HostTime", NULL, NULL, (LPBYTE)buffer, &length);
+        size *= 2;
+    } while (lr == ERROR_MORE_DATA);
+    if (lr != ERROR_SUCCESS)
+        goto fail3;
+
+    if (!_strnicoll("UTC", buffer, length))
+        match = true;
+
+fail3:
+    delete [] buffer;
+fail2:
+    RegCloseKey(key);
+fail1:
+
+    return match;
+}
+
+void CXenAgent::SetXenTime()
+{
+    // Set VM's time to Xen's time (adjust for UTC settings of VM and guest)
+    FILETIME now = { 0 };
+    if (!m_device->SharedInfoGetTime(&now))
+        return;
+
+    bool IsUTC = IsHostTimeUTC();
+    if (IsUTC)
+        AdjustXenTimeToUTC(&now);
+
+    SYSTEMTIME sys = { 0 };
+    if (!FileTimeToSystemTime(&now, &sys))
+        return;
+
+    SYSTEMTIME cur = { 0 };
+    GetLocalTime(&cur);
+
+    CXenAgent::Log("Time Now = %d/%d/%d %d:%02d:%02d.%d\n",
+                   cur.wYear, cur.wMonth, cur.wDay,
+                   cur.wHour, cur.wMinute, cur.wSecond, cur.wMilliseconds);
+    CXenAgent::Log("New Time = %d/%d/%d %d:%02d:%02d.%d\n",
+                   sys.wYear, sys.wMonth, sys.wDay,
+                   sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds);
+
+    if (IsUTC)
+        SetSystemTime(&sys);
+    else
+        SetLocalTime(&sys);
+}
+
 void CXenAgent::OnShutdown()
 {
     CCritSec crit(&m_crit);
@@ -379,6 +496,8 @@ void CXenAgent::OnSuspend()
     EventLog(EVENT_XENUSER_UNSUSPENDED);
 
     m_device->StoreWrite("control/feature-shutdown", "1");
+
+    SetXenTime();
 }
 
 void CXenAgent::SetServiceStatus(DWORD state, DWORD exit /*= 0*/, DWORD hint /*= 0*/)
index 97bd158bd9e588b7b59f5efe8907330fe6bd4d22..978e51b5c9a2a66a2aabba6f271516ec28604d3a 100644 (file)
@@ -71,6 +71,10 @@ private: // service events
 private: // helpers
     void AcquireShutdownPrivilege();
     void EventLog(DWORD evt);
+    bool IsHostTimeUTC();
+    void AdjustXenTimeToUTC(FILETIME* time);
+    bool RegCheckIsUTC(const char* path);
+    void SetXenTime();
     void OnShutdown();
     void OnSuspend();