[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/2] Add AutoReboot capability


  • To: <win-pv-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Owen Smith <owen.smith@xxxxxxxxxx>
  • Date: Wed, 9 Dec 2020 13:28:47 +0000
  • Authentication-results: esa1.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none
  • Cc: Owen Smith <owen.smith@xxxxxxxxxx>
  • Delivery-date: Wed, 09 Dec 2020 13:29:18 +0000
  • Ironport-hdrordr: A9a23:Aix1DawfVwScKqZ0iWfaKrPxw+skLtp033Aq2lEZdDV+WKWj+f yGtvIdyBPylXItQ3kmg9+NI+2tRnnb+J5z7+AqTNGfdSPhv3alK5wn0Jv6z1TbalXD38NUyK sISchDIfLqC1wSt6rHySm+V+0t2dyWtJ2v7N2uqktFaSFPR+Ve4xxiCgCde3cGIzVuIZYiDp KT6o5milObCBcqR/+2DHUEQOTPzuej/PmNDCIuPBIp5BKDijml8tfBYnyl9ywTTi9VxvMa+X XF+jaJn5mLie2xyRPXygbojqh+pd2J8LR+Lf3JrsAULzn24zzYBrhccriJijA5sYiTwVwh+e Ojnz4rOcNv53TNOnyvqRz21AX6lDoo4XnuyViX6EGTx/DRTjQ8FsZHmMZFYgLUgnBQxO1U3a pX0wui16Z/AgjHmE3Gi+TgVxYvjUaspGpnjOh7tQ07baIbZKVKpYISuENZea1wfx7S7IAiHK 1wANrH5PBQGGnqCEzxpWVkzNyyUnlbJH7vKSJuhuWP3zdbh3x/xUcDrfZv+kso754hV4JCo/ 3NL6UArsA2cuYNcal/CO0dKPHXNkXRR3v3X166MBDiHKEDN2mlke+U3IkI
  • Ironport-sdr: ldwI4YF/0LygZoX63hxdjeSCloEfPSYjcVe0SBuSOj5pb49ugQHSH1td3Md1NxxkCHEVbULwU1 gjpl4VXH0ynqr9FiKaJVwG/46AHOiwmB6RrR4n2bIOrxh6eUK8F2qiJ4Ixhod5zihFpi7hxyCb IhGZOUH420srx6tr2j77TUzEsl+3MFgT0DoAYhbcCuAiCEbaY0hWjsNpZIdHwNrqXSHMFnWWog 8VAMJN0BpbBa7RhGVE+SnLfgZlI0gl75KHgGBj+cVSfeIYkXrYfu+6fweav6+zhZ7Ls0qC5w3t QGw=
  • List-id: Developer list for the Windows PV Drivers subproject <win-pv-devel.lists.xenproject.org>

Setting HKLM\System\CCS\Services\xenbus_monitor\AutoReboot to non-zero
will allow xenbus_monitor to trigger a reboot when another driver
requests a reboot. AutoReboot is set to the maximum number of reboots
to perform. Auto reboots display a message with a 60 second timeout.

This setting can be used to allow headless/unmonitored VMs to complete
the neccessary number of reboots to return to PV disks/networks. Without
this capability its possible to update the driver on a parent device,
which may prompt for a reboot. After this reboot, its likely that
emulated devices are used whilst drivers are rebound to the device
nodes. This can leave headless/unmonitored VMs in a state where emulated
devices are in use with a pending reboot. If network settings have been
changed for PV devices (e.g. static IP addressing), then the VM may not
be accessible over RDP or similar connections.

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/monitor/monitor.c | 133 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 129 insertions(+), 4 deletions(-)

diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index 07bf8c1..5d58be4 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -301,7 +301,8 @@ WTSStateName(
 
 static VOID
 DoReboot(
-    VOID
+    IN PTCHAR   Message,
+    IN DWORD    Timeout
     )
 {
     Log("waiting for pending install events...");
@@ -312,8 +313,8 @@ DoReboot(
 
 #pragma prefast(suppress:28159)
     (VOID) InitiateSystemShutdownEx(NULL,
-                                    NULL,
-                                    0,
+                                    Message,
+                                    Timeout,
                                     TRUE,
                                     TRUE,
                                     SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
@@ -451,6 +452,125 @@ fail1:
     return NULL;
 }
 
+static BOOL
+TryAutoReboot(
+    IN PTCHAR           DriverName
+    )
+{
+    PMONITOR_CONTEXT    Context = &MonitorContext;
+    HRESULT             Result;
+    DWORD               Type;
+    DWORD               AutoReboot;
+    DWORD               RebootCount;
+    DWORD               Length;
+    PTCHAR              DisplayName;
+    PTCHAR              Description;
+    PTCHAR              Text;
+    DWORD               TextLength;
+    HRESULT             Error;
+
+    Length = sizeof (DWORD);
+
+    Error = RegQueryValueEx(Context->ParametersKey,
+                            "AutoReboot",
+                            NULL,
+                            &Type,
+                            (LPBYTE)&AutoReboot,
+                            &Length);
+    if (Error != ERROR_SUCCESS ||
+        Type != REG_DWORD)
+        AutoReboot = 0;
+
+    if (AutoReboot == 0)
+        goto done;
+
+    Length = sizeof (DWORD);
+
+    Error = RegQueryValueEx(Context->ParametersKey,
+                            "RebootCount",
+                            NULL,
+                            &Type,
+                            (LPBYTE)&RebootCount,
+                            &Length);
+    if (Error != ERROR_SUCCESS ||
+        Type != REG_DWORD)
+        RebootCount = 0;
+
+    if (RebootCount >= AutoReboot)
+        goto done;
+
+    Log("AutoRebooting (reboot %u of %u)\n",
+        RebootCount,
+        AutoReboot);
+
+    ++RebootCount;
+
+    (VOID) RegSetValueEx(Context->ParametersKey,
+                         "RebootCount",
+                         0,
+                         REG_DWORD,
+                         (const BYTE*)&RebootCount,
+                         (DWORD) sizeof(DWORD));
+
+    (VOID) RegFlushKey(Context->ParametersKey);
+
+    Context->RebootPending = TRUE;
+
+    DisplayName = GetDisplayName(DriverName);
+    if (DisplayName == NULL)
+        goto fail1;
+
+    Description = _tcsrchr(DisplayName, ';');
+    if (Description == NULL)
+        Description = DisplayName;
+    else
+        Description++;
+
+    TextLength = (DWORD)((_tcslen(Description) +
+                          1 + // ' '
+                          _tcslen(Context->Text) +
+                          1) * sizeof (TCHAR));
+
+    Text = calloc(1, TextLength);
+    if (Text == NULL)
+        goto fail2;
+
+    Result = StringCbPrintf(Text,
+                            TextLength,
+                            TEXT("%s %s"),
+                            Description,
+                            Context->Text);
+    assert(SUCCEEDED(Result));
+
+    free(DisplayName);
+
+    DoReboot(Text, 60);
+
+    free(Text);
+
+    return TRUE;
+
+done:
+    return FALSE;
+
+fail2:
+    Log("fail2");
+
+    free(DisplayName);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
 static VOID
 PromptForReboot(
     IN PTCHAR           DriverName
@@ -476,6 +596,10 @@ PromptForReboot(
     TitleLength = (DWORD)((_tcslen(Context->Title) +
                            1) * sizeof (TCHAR));
 
+    // AutoReboot is set, DoReboot has been called
+    if (TryAutoReboot(DriverName))
+        goto done;
+
     DisplayName = GetDisplayName(DriverName);
     if (DisplayName == NULL)
         goto fail1;
@@ -547,7 +671,7 @@ PromptForReboot(
         Context->RebootPending = TRUE;
 
         if (Response == IDYES || Response == IDTIMEOUT)
-            DoReboot();
+            DoReboot(NULL, 0);
 
         break;
     }
@@ -556,6 +680,7 @@ PromptForReboot(
 
     free(DisplayName);
 
+done:
     Log("<====");
 
     return;
-- 
2.28.0.windows.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.