Windows Virtual Desktop - Stop VM on Command
We have recently announced the preview of a new feature in Windows Virtual Desktop allowing users to start their deallocated personal VM, more info is available in this blog post, and the announcment is here
This allows users to power on the VM at just the time they need it. It also enables IT to reduce costs as much as possible as it is only powered on at the time the end user needs it.
But how do you get the VM into a deallocated state in like manner, i.e. how can a user power off their VM?
We do have an existing autoscaling tool, but that only supports pooled host pools today. We do have an "autoscaling service" under development which will bring support for personal host pools.
There are other options available in Azure, such as each VM's Auto-Shutdown feature in VM section of the portal:
So now that we have the user powering on their VM, we want something that also enables the user to power off their VM, and most importantly - at just the time they need to.
What if you could ask Alexa to deallocate your VM?
That's where Alexa and IFTTT, PowerShell and Azure Function Apps come in, in a combined process I'm calling: "Stop VM on Command".
This article will take you through the steps to create a new Azure Function App and integrate it with both IFTTT and Amazon Alexa to deallocate your personal desktop. However, you could actually use this to take any PowerShell action so you could use this to power off all powered on VM's or power on all deallocated vms in your subscription or just those in a Resource group or a specific region. Essentially this will show that you can run any PowerShell command you want from Alexa, it is not limited to just deallocating a single WVD session host. That is just the use case here.
The process is that we instruct Alexa to shut down our VM. Alexa will call IFTTT which itself will call our Function App, which is configured with a PowerShell script to deallocate our VM. This is secured using a new Managed Identity.
This will result in issuing a voice command to Alexa which will then deallocate the VM as per (sound on):
ConfigurationSo, this assumes that you have an Alexa. I am just going to use the Alexa app to show this working.
Azure Function App
So, step 1 is to create a new Azure Function App. As you would expect there are multiple ways to create a Function app, via the portal, PowerShell or directly from VS Code. For simplicity we will do it via the portal.
In the Azure portal click on + Create a resource and in the Marketplace search for Function App:
Click on Create.
Select your resource group and provide a globally unique Function App Name.
In Publish, select Code.
In Runtime stack, select PowerShell Core with a version of 7.0.
Finally select your region.
Click on Next : Hosting >
On the Hosting tab, either create a new Storage account or accept the default new one.
The Operating System will default to Windows
In the Plan type decide which plan you want. Consumption (Serverless) will be the cheapest, but you can use other plans, such as Functions Premium or an App Service plan, where you can also re-use existing ones.
Click on Next : Monitoring >
If you would like to configure Application Insights for this Function App you can do so here:
Click on : Tags > Where you can add your tags as required.
Click on Review + Create and then Create.
So, we now have a new Function App, we now need to a specific function to take the action.
In your new Function App, in the Functions section select Functions,
From within the HTTPTrigger1 (or whatever you named yours) in the Developer section click on Code + Test.
Now it is in here that you would add any PowerShell that does anything, that you want actioned when this Function is called. So, you could develop a script that powered off all VM's in a region etc. etc.
To get started and keep it simple we are going to add a single line to power off our own personal session host.
Replace everything down from and including the line:
For example if you did want to stop all running VM's you would enter something like:
We now need to set up a Managed Identity for this Function App that also has the RBAC permissions required at the correct scope to perform the PowerShell action. This enables the Function App to perform the actions on the Virtual Machine(s).
Back in the Azure Portal go to your Function App and in Settings go to Identity.
In the System assigned tab in the Status section click On and click Save at the top, and Yes. This will go off and register this Function App as a Managed Identity within Azure Active Directory
You can confirm this has been created by going to Azure Active Directory > Enterprise applications. Then in the Application type drop down select Managed Identities and click on Apply to the right. In the resulting list will be a Managed Identity with the same name as your Function App.
Now we need to provide the Managed Identity with the RBAC permissions to power off this VM. The minimum permission that is required is the Virtual Machine Contributor role.
You can assign this at either the Management group, Subscription, the Resource Group that contains your VM or the VM itself, depending on how much access you want this Managed Identity to have across other VMs. Best practices dictate to provide the least privilege as possible.
So, select your scope, I am going to assign this to the Resource Group that contains my personal desktop VMs.
Now to integrate with Alexa.
This trigger will listen to you say "Alexa," and the phrase you want, such as "Shutdown my desktop"
In the next screen enter your phrase you would like to say for this trigger.
Text must all be in lowercase, and it seems some words are confusing for Alexa such as "VM" and "session" at least in my testing. But Alexa will let you know if it does not understand what you have asked.
Click on Create Trigger
So now we have added our phrase we now need IFTTT to take the "That" action, which is call our Azure Function.
Click on the Add in the Than That box
We are looking for webhooks which is at the bottom so enter it in the search field:
Click on Webhooks.
Then click on the Make a web request box:
So now we need our Azure Function URL.
Go back to the Azure portal, go to the Function App, go to your HTTP Trigger, and on the Overview or Code + Test tabs is an icon called Get Function Url:
Click on this and it will display the Function URL, click on the Copy button, then go back to IFTTT.
Paste in the URL.
Leave Method as Get.
Change Content Type to application/json.
Click on Create action at the bottom.
Click on Continue, then review the details and click on Finish.
So now we have IFTTT configured to call our Function App which stops the VM.
So the final step is to configure Alexa to call this IFTTT applet. I am showing this on the Alexa iOS app so screens may differ.
In the Alexa app press More, and then Routines
Press the + to create a new routine.
Give the routine a name.
In the When this happens section click on + and select Voice, and then enter the exact text you want Alexa to listen out for:
In the Add Action section click on the +, scroll down to IFTTT, this will then show you the available IFTTT applets you have created. Select your shut down my desktop applet that you created in the earlier step. Click on Next.
You should now have this:
Click on Save at the top right. You may need to wait for approx. one minute for this to update.
Now to test Alexa.
You can either click on the Play icon to the right on your, but that won't test Alexa actioning this based upon your voice command.
So, go back to Home in the app and press Tap to talk to Alexa
And say your voice command such as "Alexa, trigger shutdown my desktop."
This will now action the whole chain and your VM will now be deallocated.
You can check the activity logs of this applet by click on in the View activity button in IFTTT.