I am excited to announce a significant update to the Auto Start and Stop script for WVD. This update adds a new option that works with the peak time settings to change the load balancing type from Depth-First to Breadth-First. When used, it also starts all available session hosts during peak time to accommodate the user load.
At the end of peak time, the host pool goes back to Depth-First load balancing, and session hosts shut down as users log off. Providing a cost savings auto scale solution during times of low demand.
The new feature is optional. If not enabled, the script will work just as it did before, starting and stopping session hosts based on the user load and the server start threshold. The new Use Breadth-First During Peak option provides capacity for the greatest number of users while leveraging Dept-First during the off-peak time to consolidate user connections and shut down unused Session Hosts.
For full details on the script’s functionality and deployment overview, see the previous video on the Auto Start and Stop script located here: https://www.ciraltos.com/auto-start-and-stop-session-hosts-in-windows-virtual-desktop-spring-update-arm-edition-with-an-azure-function/
The Script can be found at my GitHub page here: https://github.com/tsrob50/WVD-Public/blob/master/WVDARM_ScaleHostPoolVMs.ps1
The $usePeak variable must be set to true to enable the new functionality. The new $useBreadthFirstDuringPeak must also be set to true to enable Breadth-First load balancing during peak time.
To use peak time without changing to Breadth-First load balancing, simply set $usePeak to True and $useBreadthFirstDuringPeak set to $false
13 thoughts on “Update with Breadth-First! Auto Scale Session Hosts in Windows Virtual Desktop Spring Update (ARM) with Azure Function”
getting an error when this is deployed…
2021-01-18T22:35:02.295 [Error] ERROR: No hosts available to shut downException :Type : Microsoft.PowerShell.Commands.WriteErrorExceptionMessage : No hosts available to shut downHResult : -2146233087CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorExceptionFullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Stop-SessionHostInvocationInfo :MyCommand : Stop-SessionHostScriptLineNumber : 242OffsetInLine : 9HistoryId : 1ScriptName : D:\home\site\wwwroot\TimerTrigger1\run.ps1Line : Stop-SessionHost -SessionHosts $sessionHosts -hostsToStop $hostsToStopPositionMessage : At D:\home\site\wwwroot\TimerTrigger1\run.ps1:242 char:9+ Stop-SessionHost -SessionHosts $sessionHosts -hostsToStop $ho …+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PSScriptRoot : D:\home\site\wwwroot\TimerTrigger1PSCommandPath : D:\home\site\wwwroot\TimerTrigger1\run.ps1InvocationName : Stop-SessionHostCommandOrigin : InternalScriptStackTrace : at Stop-SessionHost, D:\home\site\wwwroot\TimerTrigger1\run.ps1: line 91at , D:\home\site\wwwroot\TimerTrigger1\run.ps1: line 242Microsoft.Azure.WebJobs.Script.Workers.Rpc.RpcException : Result: ERROR: No hosts available to shut downException :Type : Microsoft.PowerShell.Commands.WriteErrorExceptionMessage : No hosts available to shut downHResult : -2146233087CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorExceptionFullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Stop-SessionHostInvocationInfo :MyCommand : Stop-SessionHostScriptLineNumber : 242OffsetInLine : 9HistoryId : 1ScriptName : D:\home\site\wwwroot\TimerTrigger1\run.ps1Line : Stop-SessionHost -SessionHosts $sessionHosts -hostsToStop $hostsToStopPositionMessage : At D:\home\site\wwwroot\TimerTrigger1\run.ps1:242 char:9+ Stop-SessionHost -SessionHosts $sessionHosts -hostsToStop $ho …+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PSScriptRoot : D:\home\site\wwwroot\TimerTrigger1PSCommandPath : D:\home\site\wwwroot\TimerTrigger1\run.ps1InvocationName : Stop-SessionHostCommandOrigin : InternalScriptStackTrace : at Stop-SessionHost, D:\home\site\wwwroot\TimerTrigger1\run.ps1: line 91at , D:\home\site\wwwroot\TimerTrigger1\run.ps1: line 242Exception: No hosts available to shut downStack:
this is in a host pool with 2 running VM – both currently with 0 users… so obviously one should be shut down with the script.
Can you verify the session hosts are showing as available? If they are not available, in drain mode for example, they won’t be factored into the shutdown logic.
Getting lot of error in powershell 7, need help
Pingback: Comparing WVD Auto-scaling solutions - Cloud Collaboration
I have to say this script is excellent piece of work. Setup for really easy and quick. Few settings to configure and it’s good to go.
Thank you!
We have a pool of 2 WVD machines. Is there any way to specify a particular machine to be on 24×7 and have the other machine scale as required?
As long as the server start threshold is 1 or more, at lease one Session Hosts will run 24×7. There is no way in this script to specify a particular VM to say running.
Hey Travis!
I am repurposing some of your code to allow for a maintenance window to patch via SCCM – I will be using useBreadthFirstDuringPeak feature to turn all session hosts on at a scheduled time window.
Question I have is our SCCM maintenance is Thursday nights from 10:00pm to 5am Friday. Would setting the days as ‘Thursday’, ‘Friday’, and the start time ’22:00:00′ with stop time as ’05:00:00′ work in your code? I am just reading through it and I believe it would.
Hello,
Is there any way to integrate the “Start VM on Connect” feature with this scaling method ?
The idea would be to have potentially zero VMs turned on, and the 1st one would be started via Start on Connect.
In this way, if nobody uses the service, no VM is started.
Thanks.
Check this out. https://www.ciraltos.com/shut-down-unused-session-hosts-in-a-windows-virtual-desktop-personal-host-pool/
Exactly what i needed, thanks a lot !
Hi, does not seem to work anymore.
The Function app may be missing a module containing the ‘Disable-AzContextAutosave’ command definition. If this command belongs to a module available on the PowerShell Gallery, add a reference to this module to requirements.psd1. Make sure this module is compatible with PowerShell 7. For more details, see https://aka.ms/functions-powershell-managed-dependency. If the module is installed but you are still getting this error, try to import the module explicitly by invoking Import-Module just before the command that produces the error: this will not fix the issue but will expose the root cause.
RROR: The term ‘Disable-AzContextAutosave’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. Exception : Type : System.Management.Automation.CommandNotFoundException ErrorRecord : Exception : Type : System.Management.Automation.ParentContainsErrorRecordException Message : The term ‘Disable-AzContextAutosave’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. HResult : -2146233087 TargetObject : Disable-AzContextAutosave CategoryInfo : ObjectNotFound: (Disable-AzContextAutosave:String) [], ParentContainsErrorRecordException FullyQualifiedErrorId : CommandNotFoundException InvocationInfo : ScriptLineNumber : 15 OffsetInLine : 5 HistoryId : 1 ScriptName : C:\home\site\wwwroot\profile.ps1 Line : Disable-AzContextAutosave -Scope Process | Out-Null PositionMessage : At C:\home\site\wwwroot\profile.ps1:15 char:5 + Disable-AzContextAutosave -Scope Process | Out-Null + ~~~~~~~~~~~~~~~~~~~~~~~~~ PSScriptRoot : C:\home\site\wwwroot PSCommandPath : C:\home\site\wwwroot\profile.ps1 InvocationName : Disable-AzContextAutosave CommandOrigin : Internal ScriptStackTrace : at , C:\home\site\wwwroot\profile.ps1: line 15 CommandName : Disable-AzContextAutosave TargetSite : Name : LookupCommandInfo DeclaringType : System.Management.Automation.CommandDiscovery, System.Management.Automation, Version=7.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 MemberType : Method Module : System.Management.Automation.dll StackTrace : at System.Management.Automation.CommandDiscovery.LookupCommandInfo(String commandName, CommandTypes commandTypes, SearchResolutionOptions searchResolutionOptions, CommandOrigin commandOrigin, ExecutionContext context) at System.Management.Automation.CommandDiscovery.LookupCommandInfo(String commandName, CommandOrigin commandOrigin, ExecutionContext context) at System.Management.Automation.CommandDiscovery.LookupCommandInfo(String commandName, CommandOrigin commandOrigin) at System.Management.Automation.CommandDiscovery.LookupCommandProcessor(String commandName, CommandOrigin commandOrigin, Nullable`1 useLocalScope) at System.Management.Automation.ExecutionContext.CreateCommand(String command, Boolean dotSource) at System.Management.Automation.PipelineOps.AddCommand(PipelineProcessor pipe, CommandParameterInternal[] commandElements, CommandBaseAst commandBaseAst, CommandRedirection[] redirections, ExecutionContext context) at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext) at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) Message : The term ‘Disable-AzContextAutosave’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. Data : System.Collections.ListDictionaryInternal Source : System.Management.Automation HResult : -2146233087 TargetObject : Disable-AzContextAutosave CategoryInfo : ObjectNotFound: (Disable-AzContextAutosave:String) [], CommandNotFoundException FullyQualifiedErrorId : CommandNotFoundException InvocationInfo : ScriptLineNumber : 15 OffsetInLine : 5 HistoryId : 1 ScriptName : C:\home\site\wwwroot\profile.ps1 Line : Disable-AzContextAutosave -Scope Process | Out-Null PositionMessage : At C:\home\site\wwwroot\profile.ps1:15 char:5 + Disable-AzContextAutosave -Scope Process | Out-Null + ~~~~~~~~~~~~~~~~~~~~~~~~~ PSScriptRoot : C:\home\site\wwwroot PSCommandPath : C:\home\site\wwwroot\profile.ps1 InvocationName : Disable-AzContextAutosave CommandOrigin : Internal ScriptStackTrace : at , C:\home\site\wwwroot\profile.ps1: line 15