Restart-VM

From the W2012 Host computer I want to schedule a restart of one of the VM. I have it working via this command however the 'force' syntax is not a graceful restart...

Powershell.exe Restart-VM BNRVM1 -Force

I would rather do a graceful restart and remove the -Force syntax and instead enter a Y when the prompt is trying to confirm that I want to restart.

Can someone please advise on what the syntax is to have a Y entered instead of the -Force

January 29th, 2015 5:19am

The Restart-VM cmdlet will never provide a graceful restart. Here's the description from the cmdlet's help file: "The Restart-VM cmdlet restarts a virtual machine. Running this cmdlet results in a hard restart, like powering the machine down, then back up again. This can result in data loss in the virtual machine."

My first thought was to use a scheduled task inside the guest computer to do a restart, however, that may not provide everything you need depending on your individual situation. After a little more reading in the help files, you might be better served to do a Stop-VM and then a Start-VM, after the server has been down for a reasonable time. Between the time you send issue the Stop-VM command and the start command, you may want to utilize Start-Sleep to pause your script, and Test-Connection to ensure it's not replying to ICMP requests (pings).

Edit: Back to the part where I mentioned doing things from inside a guest computer: If you have PSRemoting set up properly, you can use the Invoke-Command cmdlet to run something on that server, from that server. Invoke-Command -Computer VMGuestComputer -ScriptBlock {Restart-Computer}.

And speaking of the Restart-Computer cmdlet, it has a -ComputerName parameter: Restart-Computer -Computer VMGuestComputer

It seems like one of these options might work.

Free Windows Admin Tool Kit Click here and download it now
January 29th, 2015 6:41am

Hi Bnrtech,

In addition, I found this function, which can help us to Gracefully Restart Virtual Machines on Hyper-V, please note I haven't tested:

function Restart-VM {
	<#
	.SYNOPSIS
		Restarts one or more virtual machines by performing an orderly shutdown and startup sequence.
	.DESCRIPTION
		Restarts one or more virtual machines by performing an orderly shutdown and startup sequence.
		Shadows the built-in Restart-VM, which does not contain the same functionality.
	.PARAMETER Name
		A string array containing the name(s) of the virtual machine to restart.
	.PARAMETER ComputerName
		The name(s) of the computer(s) that host(s) the target virtual machine(s). If not specified, the local host will be used.
	.PARAMETER AsJob
		Places the restart operation in a job and returns immediately.
		Cannot be included with Passthru.
	.PARAMETER Force
		If the virtual machine is not running integration services, or if the integration services do not respond promptly, performs a Turn Off operation.
		If not specified, only virtual machines with responding integration services will be restarted.
	.PARAMETER VM
		The virtual machine object to be restarted.
	.PARAMETER Timeout
		Maximum number of seconds to wait for the target system to shut down gracefully before performing a Turn Off operation. Default is eternity.
		If multiple virtual machines are specified, each has its own separate timer.
	.PARAMETER ForceTimeout
		Number of seconds to wait for a forced turn off to work before assuming the worker process is hung. Default and minimum is 5 seconds.
		If multiple virtual machines are specified, each has its own separate timer.
		Has no effect if Force is not also specified.
	.PARAMETER Passthru
		Causes the script to emit a virtual machine object that represents the VM that was restarted.
		Cannot be included with AsJob.
	.OUTPUTS
		None by default.
		If -Passthru is specified, Microsoft.HyperV.PowerShell.VirtualMachine.
		If -AsJob is specified, System.Management.Automation.PSRemotingJob.
	.NOTES
	    Author: Eric Siron
	    Copyright: (C) 2014 Altaro Software
	    Version 1.0.1
	    Authored Date: November 15, 2014
 
		 1.0.1 revision: November 26, 2014: Minor fix to timeout logic.
	.LINK
	    http://www.altaro.com/hyper-v/free-script-restart-vm/
	.EXAMPLE
		C:\PS> Restart-VM svtest
		Description
		-----------
		Restarts the virtual machine named test on the local host.
	.EXAMPLE
		C:\PS> Restart-VM svhungsystem -Force
		Description
		-----------
		Restarts the virtual machine named svhungsystem on the local host even if it is not responding.
	.EXAMPLE
		C:\PS> Get-VM -Name svtrouble | Restart-VM -Force -ForceTimeout 30
		Description
		-----------
		Forces the virtual machine named svtrouble to shut down, but extends the maximum wait time from 5 seconds to 30 seconds.
	.EXAMPLE
		C:\PS> Restart-VM svserver1, svserver2 -ComputerName svhv1 -Timeout 60
		Description
		-----------
		Restarts VMs named svserver1 and svserver2 on Hyper-V host svhv1. If either does not shut down within 60 seconds, it is forcefully turned off.
	.EXAMPLE
		C:\PS> Get-ClusterVM | Restart-VM
		Description
		-----------
		Using the output of Get-ClusterVM (another free script from Altaro), restarts all cluster VMs.
	#>
	[CmdletBinding(DefaultParameterSetName='ByName', SupportsShouldProcess=$true)]
	param(
		[Alias("VMName")]
		[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName='ByName', Mandatory=$true, Position=1)]
		[String[]]$Name,
		[Alias("VMHost")]
		[Parameter(ValueFromPipelineByPropertyName=$true, Position=2, ParameterSetName='ByName')]
		[String[]]$ComputerName = @(, $env:COMPUTERNAME),
		[Parameter(ValueFromPipelineByPropertyName=$true)]
		[Switch]$AsJob,
		[Parameter(ValueFromPipelineByPropertyName=$true)]
		[Switch]$Force,
		[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName='ByVM')]
		[Microsoft.HyperV.PowerShell.VirtualMachine[]]$VM,
		[Parameter(ValueFromPipelineByPropertyName=$true)]
		[UInt32]$Timeout = 0,
		[Parameter(ValueFromPipelineByPropertyName=$true)]
		[UInt32]$ForceTimeout = 5,
		[Parameter(ValueFromPipelineByPropertyName=$true)]
		[Switch]$Passthru
	)
	BEGIN {
		### Globals ###
		$JobList = @()
		### Script blocks ###
		$RestartScript = {
			param(
				[Parameter(Position=1)][Object]$VMObject,	# deserialized and cannot be used as a VM object
				[Parameter(Position=2)][UInt32]$Timeout,
				[Parameter(Position=3)][UInt32]$ForceTimeout,
				[Parameter(Position=4)][Switch]$Force,
				[Parameter(Position=5)][Switch]$Passthru
			)
			### Constants ###
			New-Variable -Name VMStateRunning -Value 2 -Option Constant
			New-Variable -Name VMStateTurnedOff -Value 3 -Option Constant
			New-Variable -Name MinimumForceTimeout -Value 5 -Option Constant
			### Functions ###
			function TurnOff {
				param(
					[Parameter()][Object]$VMObject,	# deserialized and cannot be used as a VM object
					[Parameter()][UInt32]$Timeout,
					[Parameter()][ValidateSet("Shutdown", "TurnOff")][String]$Mode
				)
				switch($Mode)
				{
					"Shutdown" {
						Stop-VM -ComputerName $VMObject.ComputerName -Name $VMObject.Name -Force
					}
					"TurnOff" {
						Stop-VM -ComputerName $VMObject.ComputerName -Name $VMObject.Name -Force -TurnOff
					}
				}
				$TimeoutCounter = 0
				$Continue = $true
				while($Continue)
				{
					Start-Sleep -Seconds 1
					$Continue = ((Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_ComputerSystem -ComputerName $VMObject.ComputerName -Filter "Name = '$($VMObject.VMId.Guid.ToString().ToUpper())'").EnabledState -ne $VMStateTurnedOff)
					if($Timeout -and $Continue)
					{
						$TimeoutCounter++
						if($TimeoutCounter -ge $Timeout)
						{
							$false
							return
						}
					}
				}
				$true
			}
			if($ForceTimeout -lt $MinimumForceTimeout) { $ForceTimeout = $MinimumForceTimeout }
			$ForceRequired = $true	# this will be set off if a graceful shutdown is successful
			$StopAttempted = $false
			# output from get-vm isn't always reliable, ask WMI if the VM is on
			if((Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_ComputerSystem -ComputerName $VMObject.ComputerName -Filter "Name = '$($VMObject.VMId.Guid.ToString().ToUpper())'").EnabledState -eq $VMStateRunning)
			{
				# The VM is on. Check for the shutdown integration service.
				$ShutdownIntegrationStatus = Get-VMIntegrationService -Name "Shutdown" -ComputerName $VMObject.ComputerName -VMName $VMObject.VMName
				if($ShutdownIntegrationStatus.Enabled)
				{
					if($ShutdownIntegrationStatus.PrimaryOperationalStatus -eq "Ok")
					{
						$StopAttempted = $true
						if(TurnOff -VMObject $VMObject -Timeout $Timeout -Mode "Shutdown")
						{
							$ForceRequired = $false
						}
						else
						{
							Write-Warning "Graceful shutdown for $($VMObject.Name) was unsuccessful."
						}
					}
				}
				if($Force -and $ForceRequired)
				{
					$StopAttempted = $true
					Write-Verbose -Message "Attempting to turn off (hard shut down) $($VMObject.VMName) on $($VMObject.ComputerName)"
					if(-not(TurnOff -VMObject $VMObject -Timeout $ForceTimeout -Mode "TurnOff"))
					{
						Write-Warning -Message "Unable to turn off $($VMObject.VMName)"
					}
				}
				if($ForceRequired -and -not $Force)
				{
					Write-Warning -Message "VM $($VMObject.VMName) can only be restarted with the -Force switch"
				}
				# start the VM if the script tried to turn it off and its status is off
				if((Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_ComputerSystem -ComputerName $VMObject.ComputerName -Filter "Name = '$($VMObject.VMId.Guid.ToString().ToUpper())'").EnabledState -eq $VMStateTurnedOff)
				{
					Start-VM -ComputerName $VMObject.ComputerName -Name $VMObject.Name
					if($Passthru)
					{
						# just passing the object back will return a deserialized object. allow the calling thread to retrieve the object
						[String]::Join(",", ($VMObject.Computername, $VMObject.Name))
					}
				}
				elseif($StopAttempted)
				{
					Write-Error "VM $($VMObject.Name) cannot be started because it was not successfully turned off"
				}
			}
		}
	}
	PROCESS {
			if($Name -eq $null -and $VM -eq $null)
			{
				throw("Must select at least one virtual machine to restart.")
			}
			if($AsJob -and $Passthru)
			{
				throw("AsJob and Passthru cannot be specified together")
			}
			# if submitted by VM object, use as-is. otherwise retrieve VM objects
			if(-not $VM.Count)
			{
				$VM = @()
			}
			foreach($VMHost in $ComputerName)
			{
				foreach($VMName in $Name) # $Name is the input parameter for virtual machine name(s)
				{
					try
					{
						Write-Verbose -Message "Checking for $VMName on $VMHost"
						$VM += Get-VM -ComputerName $VMHost -Name $VMName -ErrorAction Stop
					}
					catch
					{
						Write-Verbose -Message "No VM with the name $VMName is present on host $VMHost"
					}
				}
			}
			foreach($VMObject in $VM)
			{
				Write-Verbose -Message "Performing restart of $($VMObject.Name) on $($VMObject.ComputerName)"
				if($PSCmdlet.ShouldProcess("$($VMObject.Name) on $($VMObject.ComputerName)", "Restart"))
				{
					$JobList += Start-Job -ScriptBlock $RestartScript -Name "Restart-VM-$($VMObject.ComputerName)-$($VMObject.Name)-$($VMObject.VMId)" -ArgumentList $VMObject, $Timeout, $ForceTimeout, $Force, $Passthru
				}
			}
	}
	END {
		if($JobList)
		{
			if($AsJob)
			{
				$JobList
			}
			else
			{
				$ResultsArray = @()
				Wait-Job -Job $JobList | Out-Null
				foreach($Job in $JobList)
				{
					$ResultsArray += Receive-Job -Job $Job
				}
				$JobList | Remove-Job
				if($Passthru)
				{
					foreach($Result in $ResultsArray)
					{
						try
						{
							$VMItem = $Result.Split(",")
							Get-VM -ComputerName $VMItem[0] -Name $VMItem[1] -ErrorAction Stop
						}
						catch
						{
							; # really nothing to do about it
						}
					}
				}
				else
				{
					$ResultsArray
				}
			}
		}
	}
}

Refer to:

http://www.altaro.com/hyper-v/free-script-restart-virtual-machines-hyper-v/

If there is anything else regarding this issue, please feel free to post back.

Best Regards,

Anna Wang

January 29th, 2015 11:18am

Anna,

Thank you for this post, but I must be missing something as I cannot get the syntax of Restat-VM to work. I can get it to work if I add the FORCE option but that is not what I am looking for in the long run.

Free Windows Admin Tool Kit Click here and download it now
February 3rd, 2015 8:25am

Hi Bnrtech,

In order to distinguish it from Restart-VM, I change the function name to "Restart-VMNew", I tested on my hyper-v host, and it can restart vm without prompt and force:

If there is anything else regarding this issue, please feel free to post back.

Best Regards,

Anna Wang

February 4th, 2015 2:52am

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics