Auto Start-Stop Azure VM using Azure Automation
Problem Statement
We a have requirement, where we want to start Azure VM every morning 8.30am and stop VM at 6.30pm excluding Saturday and Sunday.
Pre-Requisite
- Azure subscription
- Virtual Machine
- Azure Automation
Installation
Activate Azure Automation
- Activate Azure automation from preview portal. Navigate to following URL to activate Automation. https://account.windowsazure.com/PreviewFeatures
- Add Automation account
- Select automation and click on Create
- Provide proper account name and region
Connect to VM using automation
- Using Certificate
- Using Organization ID
Part 1: Using Certificate
Certificate Installation
- Open Windows run and type following command (inetmgr)
- Double click on Server certificate
- Create self-sign certificate (Top-Right corner)
Provide useful name on select type personal.
Now we required .cer and .pfx file for azure automation.
Save .pfx file:
Select path and type password. Password is required for uploading certificate on Azure.
Save .cer file:
Right click on AzureAutomation and click on view.
Click on copy to file button.
Upload certificate on Azure
- Upload .cer file
Select .cer certificate from local machine.
- Upload .pfx file
Navigate to Automation :- AutomationDemo(Account name) :- Assets
Click on Add setting
Click on Credential and provide credential name. This name we will used in Automation workflow as certificate name.
Define connection for Automation Workflow
Parameter: Automation certificate name will be same as Certificate name. Refer below image.
For Subscription ID refer below image.
Now we have completed with installation. Next part is to create wokflow.
Add workflow for automation
- Create runbook under AutomationDemo account.
We are creating runbook for auto start/stop VM. I have created runbook as StartVM under AutomationDemo account.
- After runbook is created, navigate to StartVM runbook.
Kindly find sample code below
workflow StartVM { param() #connection $MyConnection = "automationconnection" $MyCert = "automationcredential" # Get the Azure Automation Connection $Con = Get-AutomationConnection -Name $MyConnection if ($Con -eq $null) { Write-Output "Connection entered: $MyConnection does not exist in the automation service. Please create one `n" } else { $SubscriptionID = $Con.SubscriptionID $ManagementCertificate = $Con.AutomationCertificateName } # Get Certificate & print out its properties $Cert = Get-AutomationCertificate -Name $MyCert if ($Cert -eq $null) { Write-Output "Certificate entered: $MyCert does not exist in the automation service. Please create one `n" } else { $Thumbprint = $Cert.Thumbprint } #Set and Select the Azure Subscription Set-AzureSubscription ` -SubscriptionName "My Azure Subscription" ` -Certificate $Cert ` -SubscriptionId $SubscriptionID ` #Select Azure Subscription Select-AzureSubscription ` -SubscriptionName "My Azure Subscription" Write-Output "-------------------------------------------------------------------------" Write-Output "Starting the VM.." # Please type the name of your Domain Controllers inlinescript{ # function to get local time (example Convert UTC tome to Indian Time Zone) Function Get-LocalTime($UTCTime) { $strCurrentTimeZone = 'India Standard Time' $TZ = [System.TimeZoneInfo]::FindSystemTimeZoneById($strCurrentTimeZone) $LocalTime = [System.TimeZoneInfo]::ConvertTimeFromUtc($UTCTime, $TZ) Return $LocalTime } #convert date time to UTC time Zone $date = (Get-Date).ToUniversalTime() # call function to get local time $locatTime= Get-LocalTime($date) #get day of week eg. Friday $locatTimeDayOfWeek= ($locatTime).DayOfWeek #get current day of the date eg. if current date is 21 November 2014 09:55:18 then day will be 21 $localTimeDay= ($locatTime).Day #$locatTimeDayOfWeek #$localTimeDay #do not start VM on saturday and Sunday if($locatTimeDayOfWeek -ne "Saturday" -and $locatTimeDayOfWeek -ne "Sunday") { #$sample = Get-AzureWinRMUri -ServiceName $Using:CloudServiceName -Name $Using:VMName $StartOutPut = Start-AzureVM -ServiceName "democf" -Name "democf" Write-Output $"Virtual Machine democf started." Write-Output $StartOutPut } elseif($localTimeDay -le 7 -and $locatTimeDayOfWeek -eq "Saturday") { $StartOutPut = Start-AzureVM -ServiceName "democf" -Name "democf" Write-Output $"Virtual Machine democf started." Write-Output $StartOutPut } else{ Write-Output "Virtual Machine is not started, because today is not a working day." } } }
Changes in above code
Replace VM name with your VM name.
Example :
Start-AzureVM -ServiceName “democf” -Name “democf”
- ServiceName : Cloud Service name where vm is located
- -Name : is actual VM name
In our case cloud service name and vm name is same, it can be deferent for other cases.
After above changes is completed click on save and test. Check whether code is running perfectly or not. VM will not be start if it is Saturday or Sunday (Requirement).
Now we will automate this workflow using schedule
Now this workflow will be run every day at 8.30am to auto start VM.
Same code auto stop vm using workflow, with small changes.
workflow StopVM { param() #connection $MyConnection = "automationconnection" $MyCert = "automationcredential" # Get the Azure Automation Connection $Con = Get-AutomationConnection -Name $MyConnection if ($Con -eq $null) { Write-Output "Connection entered: $MyConnection does not exist in the automation service. Please create one `n" } else { $SubscriptionID = $Con.SubscriptionID $ManagementCertificate = $Con.AutomationCertificateName } # Get Certificate & print out its properties $Cert = Get-AutomationCertificate -Name $MyCert if ($Cert -eq $null) { Write-Output "Certificate entered: $MyCert does not exist in the automation service. Please create one `n" } else { $Thumbprint = $Cert.Thumbprint } #Set and Select the Azure Subscription Set-AzureSubscription ` -SubscriptionName "My Azure Subscription" ` -Certificate $Cert ` -SubscriptionId $SubscriptionID ` #Select Azure Subscription Select-AzureSubscription ` -SubscriptionName "My Azure Subscription" Write-Output "-------------------------------------------------------------------------" Write-Output "Stoping the VM.." # Please type the name of your Domain Controllers inlinescript{ # function to get local time (example Convert UTC tome to Indian Time Zone) Function Get-LocalTime($UTCTime) { $strCurrentTimeZone = 'India Standard Time' $TZ = [System.TimeZoneInfo]::FindSystemTimeZoneById($strCurrentTimeZone) $LocalTime = [System.TimeZoneInfo]::ConvertTimeFromUtc($UTCTime, $TZ) Return $LocalTime } #convert date time to UTC time Zone $date = (Get-Date).ToUniversalTime() # call function to get local time $locatTime= Get-LocalTime($date) #get day of week eg. Friday $locatTimeDayOfWeek= ($locatTime).DayOfWeek #get current day of the date eg. if current date is 21 November 2014 09:55:18 then day will be 21 $localTimeDay= ($locatTime).Day #$locatTimeDayOfWeek #$localTimeDay #do not start VM on saturday and Sunday if($locatTimeDayOfWeek -ne "Saturday" -and $locatTimeDayOfWeek -ne "Sunday") { #$StopOutPut = Start-AzureVM -ServiceName "mkadamvm" -Name $Using:test #$sample = Get-AzureWinRMUri -ServiceName $Using:CloudServiceName -Name $Using:VMName $StopOutPut = Stop-AzureVM -ServiceName "democf" -Name "democf" -Force Write-Output $"Virtual Machine democf Stopped." Write-Output $StopOutPut } elseif($localTimeDay -le 7 -and $locatTimeDayOfWeek -eq "Saturday") { $StopOutPut = Stop-AzureVM -ServiceName "democf" -Name "democf" -Force Write-Output $"Virtual Machine democf Stopped." Write-Output $StartOutPut } else{ Write-Output "Virtual Machine is not started, because today is not a working day." } } }
References
1. http://clemmblog.azurewebsites.net/using-azure-automation-start-und-stop-virtual-machines-schedule/
2. http://blogs.technet.com/b/keithmayer/archive/2014/04/04/step-by-step-getting-started-with-windows-azure-automation.aspx