When dealing with Hyper-V on Windows Server 2012 R2, the host system implements automatic shutdown sequencing for running VMs during host reboot. The default behavior follows these steps:
- Host OS initiates shutdown sequence
- Hyper-V sends shutdown signal to all running VMs
- VMs attempt graceful shutdown (if guest integration services are installed)
- After timeout period (default 5 minutes), any unresponsive VMs are force-stopped
While automatic shutdown works, I recommend this PowerShell script for more controlled shutdown procedures:
# Hyper-V Controlled Shutdown Script
$VMs = Get-VM | Where-Object {$_.State -eq 'Running'}
foreach ($VM in $VMs) {
Write-Host "Shutting down $($VM.Name)..."
Stop-VM -Name $VM.Name -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 30 # Wait for clean shutdown
}
# Check VM states before host restart
if ((Get-VM | Where-Object {$_.State -ne 'Off'}).Count -gt 0) {
Write-Warning "Some VMs failed to shut down properly"
Exit 1
}
else {
Write-Host "All VMs shut down successfully"
Restart-Computer -Force
}
For Ubuntu VMs (like your 14.10 instance), additional configuration improves shutdown reliability:
# In Ubuntu guest, edit GRUB configuration
sudo nano /etc/default/grub
# Add these parameters:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash acpi=force"
GRUB_CMDLINE_LINUX="acpi=on"
# Then update GRUB and install hv-kvp-daemon-init
sudo update-grub
sudo apt-get install hv-kvp-daemon-init
Windows guests with integration services installed behave differently than Linux guests:
- Windows VMs receive proper shutdown signals
- Application compatibility with shutdown notifications
- File system stability during forced shutdowns
This PowerShell snippet helps track shutdown events in the Hyper-V log:
Get-WinEvent -LogName "Microsoft-Windows-Hyper-V-Worker-Admin" |
Where-Object {$_.Id -in (50,51,52)} |
Format-Table TimeCreated,Id,Message -AutoSize
For mission-critical environments, modify these registry settings on the host:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization]
"GuestShutdownTimeout"=dword:0000012c # 300 seconds
"TurnOffVmOnHostShutdown"=dword:00000001
html
When rebooting a Windows Server 2012 R2 host running Hyper-V, virtual machines (VMs) with guest operating systems (like Windows 7 Pro or Ubuntu 14.10) have three possible states based on your configuration:
# Check current VM shutdown settings in PowerShell
Get-VM | Select Name, AutomaticStopAction
# Typical output:
# Name AutomaticStopAction
# ---- -------------------
# Win7VM Save
# UbuntuVM TurnOff
The host server's shutdown process will not gracefully shut down VMs by default. Instead, it will perform the action specified in each VM's AutomaticStopAction
setting (Save/TurnOff/ShutDown). While technically functional, this isn't ideal for production environments.
Here's the PowerShell script I use for proper VM shutdown sequencing:
# Graceful shutdown script for Hyper-V VMs before host maintenance
$VMs = Get-VM | Where-Object {$_.State -eq 'Running'}
foreach ($VM in $VMs) {
if ($VM.GuestOS -like "*Windows*") {
# Use integration services for Windows guests
Stop-VM -Name $VM.Name -Force -TurnOff -Passthru | Out-Null
}
elseif ($VM.GuestOS -like "*Linux*") {
# For Linux guests with Hyper-V daemon installed
Invoke-Command -VMName $VM.Name -ScriptBlock {
sudo shutdown -h now
}
Start-Sleep -Seconds 30
if ((Get-VM -Name $VM.Name).State -eq 'Running') {
Stop-VM -Name $VM.Name -Force
}
}
else {
# Fallback for other OS types
Save-VM -Name $VM.Name
}
}
For consistent behavior across reboots, modify the default settings:
# Set all VMs to attempt graceful shutdown first
Get-VM | Set-VM -AutomaticStopAction ShutDown
# Verify settings
Get-VM | Select Name, AutomaticStopAction, AutomaticStartAction
Production environments often require more sophisticated handling:
- Cluster-aware updating for Hyper-V clusters
- Maintenance windows coordination
- VM startup priority configuration
For critical systems, consider implementing a shutdown orchestration script that:
# Advanced shutdown sequence with logging
$logPath = "C:\HyperV\ShutdownLogs\$(Get-Date -Format 'yyyyMMdd').log"
$VMs = Get-VM | Sort-Object -Property @{Expression={$_.Uptime.TotalMinutes}; Ascending=$false}
"Beginning VM shutdown sequence at $(Get-Date)" | Out-File $logPath -Append
foreach ($VM in $VMs) {
try {
"$(Get-Date) - Shutting down $($VM.Name)" | Out-File $logPath -Append
Stop-VM -Name $VM.Name -ErrorAction Stop
"$(Get-Date) - Successfully shut down $($VM.Name)" | Out-File $logPath -Append
}
catch {
"$(Get-Date) - ERROR: Failed to shut down $($VM.Name)" | Out-File $logPath -Append
# Additional error handling here
}
}
"All VMs processed at $(Get-Date)" | Out-File $logPath -Append