[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2] Add AutoReboot capability
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. RebootCount is cleared when no pending required reboots are detected. Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> --- src/monitor/monitor.c | 138 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 134 insertions(+), 4 deletions(-) diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c index 07bf8c1..7d8689f 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; @@ -672,6 +797,11 @@ loop: RegCloseKey(SubKey); } + Error = RegDeleteValue(Context->ParametersKey, + "RebootCount"); + if (Error == ERROR_SUCCESS) + (VOID) RegFlushKey(Context->ParametersKey); + goto done; found: -- 2.28.0.windows.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |