Automation

Auto Shutdown ASM Virtual Machines in Azure | Azure Automation

I put together a quick script to auto shutdown tagged ARM VMs.

There are many people still running ASM VMs and why wouldn’t you they are still supported (as of 9/2016).

The process is not much different and in fact now Azure Automation enables a RunAs account at set up its much easier to configure.

In the example below I have tacked on changes to the Azure Automation Team’s sample script, one of four created for you when you enable the feature.

<# .DESCRIPTION An example runbook which gets all the Classic VMs in a subscription using the Classic Run As Account (certificate) and then shuts down running VMs .NOTES AUTHOR: Azure Automation Team + Jonathan Wade LASTEDIT: 28-08-2016 #>

$ConnectionAssetName = "AzureClassicRunAsConnection"
$ServiceName = "wadeclassiv01"
	
# Get the connection
$connection = Get-AutomationConnection -Name $connectionAssetName        

# Authenticate to Azure with certificate
Write-Verbose "Get connection asset: $ConnectionAssetName" -Verbose
$Conn = Get-AutomationConnection -Name $ConnectionAssetName
if ($Conn -eq $null)
{
    throw "Could not retrieve connection asset: $ConnectionAssetName. Assure that this asset exists in the Automation account."
}

$CertificateAssetName = $Conn.CertificateAssetName
Write-Verbose "Getting the certificate: $CertificateAssetName" -Verbose
$AzureCert = Get-AutomationCertificate -Name $CertificateAssetName
if ($AzureCert -eq $null)
{
    throw "Could not retrieve certificate asset: $CertificateAssetName. Assure that this asset exists in the Automation account."
}

Write-Verbose "Authenticating to Azure with certificate." -Verbose
Set-AzureSubscription -SubscriptionName $Conn.SubscriptionName -SubscriptionId $Conn.SubscriptionID -Certificate $AzureCert 
Select-AzureSubscription -SubscriptionId $Conn.SubscriptionID

# Get cloud service
    
$VMs = Get-AzureVM -ServiceName $ServiceName

    # Stop each of the started VMs
    foreach ($VM in $VMs)
    {
		if ($VM.PowerState -eq "Stopped")
		{
			# The VM is already stopped, so send notice
			Write-Output ($VM.InstanceName + " is already stopped")
		}
		else
		{
			# The VM needs to be stopped
        	$StopRtn = Stop-AzureVM -Name $VM.Name -ServiceName $VM.ServiceName -Force -ErrorAction Continue

	        if ($StopRtn.OperationStatus -ne 'Succeeded')
	        {
				# The VM failed to stop, so send notice
                Write-Output ($VM.InstanceName + " failed to stop")
	        }
			else
			{
				# The VM stopped, so send notice
				Write-Output ($VM.InstanceName + " has been stopped")
			}
		}
    }


Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Auto Shutdown ARM Virtual Machines in Azure | Azure Automation

With the release of the RunAs feature in Azure Automation.  A service account can now be called in Azure Automation scripts to enable and run Resource Manager functions.

I think one of the most useful features of this is to auto shutdown virtual machines by TAG.

In the example below I have set up the following:

  • A TAG called “Environment” with and ID of “Lab” and applied to each VM I want to control.
  • A RunAs service account as part of my AzureAutomation resource.
  • A PowerShell Workflow script to scan for the TAGs applied to Windows virtual machines and to shut them all down in parallel.
  • An Azure Automation schedule to run Monday-Friday at 17:00 to call the published workflow.

When configuring a schedule through the browser it uses the browser’s local time zone.  This is stored in UTC but is converted for you.   You’ll need to consider this is managing multiple resources across the globe.

This workflow and process has been created via the Azure Portal.

The -Parallel feature is only available in Powershell Workflows.

workflow TestPowershellworkflow
{
$Conn = Get-AutomationConnection -Name AzureRunAsConnection
Add-AzureRMAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint

    $FindVMs = Find-AzureRmResource -TagName "Environment" -TagValue "Lab" | where {$_.ResourceType -like "Microsoft.Compute/virtualMachines"}

   Foreach -Parallel ($vm in $Findvms)

   {
    $vmName = $VM.Name
    $ResourceGroupName = $VM.ResourceGroupName

    Write-Output "Stopping $($vm.Name)";
    Stop-AzureRmVm -Name $vm.Name -ResourceGroupName $ResourceGroupName -Force;
    }
}

I’d be very interested in your feedback.  Happy automating.

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.