Перезапустите Hyper-V VM на потерянном heartbeat

У меня есть Windows Server 2012R2 hyper-v хост. Это выполняет много VMs, включая некоторых Linux VMs.

У меня есть один Linux VM, который был occationally, но несколько регулярно отказывающий где-нибудь в ядре, приводящем к становлению VM абсолютно безразличным.

Я знаю, что hyper-v имеет средство "heartbeat", и он успешно обнаруживает VM, отказывающий как потеря heartbeat.
Однако я в замешательстве относительно того, как настроить hyper-v так, чтобы он на самом деле сделал что-либо с сигналом подтверждения работоспособности. По-видимому, однажды была опция сбросить VM, если heartbeat потерян для> 1 минута, но это было или удалено или помещено куда-нибудь, я не могу найти.

У меня только есть этот сервер, таким образом делание вещей как кластеризация или обработка отказа не действительно жизнеспособно (это - домашний сервер лаборатории).


Прежде чем любой прокомментирует, Да, я пытаюсь разыскать причину катастрофического отказа в VM, но это - неисправность, мешал.

4
задан 22 February 2015 в 09:55
2 ответа

powerhell - это ваше спасение:

$VM = Get-VMIntegrationService -VMName test-vm -Name Heartbeat
if ($VM.PrimaryStatusDescription -ne "OK")
{
    write-host "VM Dead ? restarting ..."
    Stop-VM test-vm -Force -TurnOff
    Start-VM test-vm
}

Просто добавьте это в планировщик задач.

Если ваша ВМ не поддерживает сердцебиение, то измените это на ping ВМ вместо проверки HB.

.
1
ответ дан 3 December 2019 в 04:10

Мне нужно было решение для мониторинга пульса всех виртуальных машин Hyper-V и автоматического выполнения аппаратного сброса при блокировке виртуальной машины. Как вы, наверное, уже знаете. кажется, что вы можете сделать это с помощью Hyper-V, когда у вас настроен кластер, но только с одним хостом Hyper-V, что невозможно без некоторых настраиваемых сценариев.

Я нашел хороший VBS, который отслеживает сердцебиение всех систем и даже имеет настраиваемое количество повторных попыток и льготный период в последней версии . Исходный сценарий и описание можно найти здесь . Было бы неплохо запланировать это для запуска при запуске системы (не помещайте его просто в папку автозагрузки, потому что это потребует от администратора Hyper-V входа в систему до того, как скрипт запустится).

Использование: - Скопируйте сценарий VMHeartBeat.vbs в любое место по вашему выбору. - Либо дважды щелкните сценарий, либо откройте командную строку, перейдите в папку, в которую скопирован сценарий, и затем запустите cscript.exe. VMHeartBeat.vbs

Примечание. Если дважды щелкнуть мышью скрипт wscript.exe или в зависимости от того, какой движок сценариев по умолчанию будет использоваться для запуска сценарий. Когда вы используете cscript.exe,вам нужно сохранить командное окно всегда открыт.

Этот сценарий создаст файл журнала в том же месте, что и сценарий. и продолжайте добавлять к нему события успеха / неудачи. Имя файла журнала VMHeartBeatEvents.log

Вот и все. Все готово для обнаружения потери пульса виртуальной машины, а затем выполнения аппаратного сброса.

Чтобы проверить, работает ли скрипт, вы можете скачать NotMyFault.exe , а затем скопируйте его на виртуальную машину. Теперь просто беги VMHearBeat.vbs на хосте Hyper-V и откройте notmyfault.exe внутри ВМ, выберите ошибку и нажмите «Do Bug». В зависимости от того, какой тип ошибки вы выберите, ВМ может синий экран. На данный момент VMHearBeat.vbs обнаружил бы потерю сердечного ритма и выполнил бы полный сброс виртуальная машина. Вы можете проверить файл журнала, как упоминалось ранее, чтобы узнать, был ли аппаратный сброс успешным или нет.

Чтобы сохранить сценарий, я также вставил последнюю версию кода .VBS (с количеством повторов и льготным периодом) ниже.

ОБНОВЛЕНИЕ: В последней версии сценария действительно были некоторые ошибки, поэтому приведенный ниже сценарий был изменен, и я подтвердил, что он работает на Server 2012R2. \ v2 необходимо добавить в строку №20, а 10 необходимо изменить на 11 в строке №4 функции VMHardReset .

Option Explicit

'Define Event log constants here
Const EVENT_INFO = 4
Const EVENT_ERROR = 1
Const RETRY_COUNT = 3
Const CHECK_EVERY_X_SECS = 6

Dim objSummaryInfo, objWMIService, objVMService, intValArray, objVMitems
Dim InParam, OutParam, objItem, strQuery
Dim Job, objShell
Dim colArgs, strLog, dict, compName

Set colArgs = WScript.Arguments.Named

'Get Command Line arguments in to some variables
strLog = colArgs.Item("log")

Set objShell = Wscript.CreateObject("Wscript.Shell")
Set objWMIService = GetObject("winmgmts:\\" & "." & "\root\virtualization\v2")
Set objVMService = objWMIService.ExecQuery("SELECT * FROM Msvm_VirtualSystemManagementService").ItemIndex(0)
intValArray = Array(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199)

Set dict = CreateObject("Scripting.Dictionary")

While (1)
    Wscript.echo(CStr(Now()) +": Testing Loop ")   
    objVMItems = objVMService.GetSummaryInformation(NULL,intValArray,objSummaryInfo)
    for each objItem in objSummaryInfo
        compName = objItem.ElementName
        if (not dict.Exists(compName)) then
            dict.add compName,0
        end if

        If (objItem.EnabledState=2 AND (objItem.HeartBeat = 6 OR objItem.HeartBeat = 13)) Then
            dict.Item(compName)=dict.Item(compName)+1

            WriteLog("    **"+compName+"** missed heartbeat check; count "+CStr(dict.Item(compName)))

            if (dict.Item(compName) >= RETRY_COUNT ) then       
                dict.Item(compName)= 0
                Wscript.echo(CStr(Now()) +": Now performing a hard reset on "+compName)
                VMHardReset(compName)
            end if
        Else
            dict.Item(compName)= 0
        End If
    Next

    Set objVMItems=Nothing
    Set objItem = Nothing
    Set objSummaryInfo = Nothing

    Wscript.Sleep CHECK_EVERY_X_SECS * 1000
Wend

Set objWMIService = Nothing
Set objVMService = Nothing
Set InValArray = Nothing

Function VMHardReset(vmElementName)
    Dim objvm, strLine
    Set objvm = GetComputerSystem(vmElementName)
    Set InParam = objvm.Methods_("RequestStateChange").InParameters.SpawnInstance_()
    InParam.RequestedState=11
    Set OutParam = objvm.ExecMethod_("RequestStateChange",InParam)
    If (TrackJob(OutParam)) Then
        strLine = "Virtual Machine: " & vmElementName & " has been successfully recovered from a hearbeat failure"
        'Write Success Event to text log
        WriteLog(strLine)
        Set strLine=Nothing
        'Write a Windows Event Log
        objShell.LogEvent EVENT_INFO, strLine
    Else
        strLine = "Virtual Machine: " & vmElementName & " could not be recovered from a hearbeat failure"
        'Write Failure Event to text log
        WriteLog(strLine)
        Set strLine=Nothing
        'Write a Windows Event Log
        objShell.LogEvent EVENT_ERROR, strLine

    End If
    Wscript.echo(CStr(Now()) +": "+strLine)
    Set InParam = nothing
    Set objvm = nothing
    Set vmElementName = Nothing
End Function


Function GetComputerSystem(vmElementName)
    strQuery = "select * from Msvm_ComputerSystem where ElementName = '" & vmElementName & "'"
    set GetComputerSystem = objWMIService.ExecQuery(strQuery).ItemIndex(0)
    'Set GetComputerSystem = Nothing
    Set strQuery = Nothing
End Function


Function TrackJob(OutParam)
    Dim Job
    If (OutParam.ReturnValue = 0) Then
        TrackJob=True
    ElseIf (OutParam.ReturnValue <> 4096) Then
        TrackJob=False
    Else
        Set Job = objWMIService.Get(OutParam.Job)
        While (Job.JobState = 3) or (Job.JobState = 4)
            Set Job = objWMIService.Get(OutParam.Job)
        Wend

        If (Job.JobState <> 7) Then
            TrackJob=False
        Else
            TrackJob = True
        End If
    End If
    Set OutParam = Nothing
    Set Job = Nothing
End Function


Sub WriteLog(line)
    Dim objFileStream, objFileSystem
    Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    Set objFileStream = objFileSystem.OpenTextFile("VMHeartBeatEvents.log", 8, true, -1)
    objfileStream.WriteLine CStr(Now()) +": "+line
    objfileStream.Close
    Set objFileSystem = Nothing
End Sub
0
ответ дан 3 December 2019 в 04:10

Теги

Похожие вопросы