Azure Autmation Account — Powershell Start Stop VM

Michal Molka
3 min readAug 16, 2024

--

Today, we create a simple PowerShell script which checks a VM state and either start or deallocate the machine. In order to orchestrate the script, we use an Azure automation account. I would like to emphasize that there is a lot of ready-made more robust scripts on the Internet which do the same. This example is simpler. And a goal of the post is how to use Azure Automate, not writing advanced PowerShell scripts.

First things first. In order to authenticate to the VM we use a System Assigned Identity belonging to the automation account and…

…assigned to the VM. For the sake of brevity, a Contributor role has been used. But I recommend creating a custom role containing following actions:

"Microsoft.Compute/*/read",
"Microsoft.Compute/virtualMachines/start/action",
"Microsoft.Compute/virtualMachines/deallocate/action"

Now, it’s time to create a runbook.

Before we go to the runbook. Let’s define two variables.

Here is a code:

Param
(
[Parameter (Mandatory= $true)]
[String] $resourceGroupName,

[Parameter (Mandatory= $true)]
[String] $vmName
)


$tenantId = Get-AutomationVariable -Name 'TenantId'
$subscriptionId = Get-AutomationVariable -Name 'SubscriptionId'
$runStates = "VM running", "VM stopped"

Connect-AzAccount -Identity -TenantId $tenantId -Subscription $subscriptionId | Out-Null

$currentContext = Get-AzContext
$outputTenantSubscription = [string]::Join(' ',"Tenant:",$currentContext.Tenant.Id, "Subscription:", $currentContext.Subscription.Name)
Write-Output $outputTenantSubscription


$vmStatusInitial = (Get-AzVM -ResourceGroupName $resourceGroupName -Name $vmName -Status).Statuses[1].DisplayStatus

$outputInitial = [string]::Join(' ',"A first status: The VM is in a",$vmStatusInitial, "state.")
Write-Output $outputInitial
if($runStates -contains $vmStatusInitial) {
Stop-AzVM -ResourceGroupName $resourceGroupName -Name $vmName -Force
Write-Output "The VM has been deallocated."
} elseif($vmStatusInitial -eq "VM deallocated") {
Start-AzVM -ResourceGroupName $resourceGroupName -Name $vmName
Write-Output "The VM has been started."
} else {
Write-Output "The VM is not in a supported state."
}
$vmStatusAfter = (Get-AzVM -ResourceGroupName $resourceGroupName -Name $vmName -Status).Statuses[1].DisplayStatus
$outputAfter = [string]::Join(' ',"A second status: The VM is in a",$vmStatusAfter, "state.")
Write-Output $outputAfter

What is happening here.

$resourceGroupName and $vmName parameters are provided right before a script run.

$tenantId and $subscriptionId variables are values we declared at the Variables section in the previous step.

Connect-AzAccount -Identity… connects to Azure through the system assigned managed identity.

Rest of the code is self-explanatory. If the VM is deallocated, then it’s started. If it’s in a running or stopped state, then is deallocated. This script operates on these three states, but there are more. You can check them out here.

And there is a tested function down there.

--

--

Michal Molka

Architect | Azure | Power BI | Fabric | Power Platform | Infrastructure | Security | M365