[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 2/2] 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. 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |