Home > Azure > Automated start & stop of Azure vm

Automated start & stop of Azure vm

2017/01/09


An Azure vm is useful but can be expensive, so a typical request of the customer is to reduce the expense by stopping the vm by the night and holidays.
In the new Azure portal there is a different automation system than the one in the old classic Azure portal.
The first thing is to create an Azure Automation account,

in Automation Accounts click Add.

Verify that Yes is selectd for “Create Azure Run As account”.
When the Automation account is successfully created, several resources are automatically created for you: example runbooks, Azure certificates, Azure connections.
With my previous operation i created these items:

Note that the Runbooks are only templates, by default are not linked to a scheduler (that causes a billing, but anyway you have for the basic scheduling 500 minutes free every month).
These tutorial scripts can be used as templates for your activities, and in every case clicking on “Runbooks Gallery” you can find a big collection of examples.

In this case I was managing a classic Azure vm, and the request was to stop the vm not only every night but also Saturday, Sunday and Italian Holidays.
The problem was the Monday after Easter: Easter is also a Sunday, but Easter is not at the same date every year, so the Monday after was to be calculated.
For the first thing, the easy stop task.
I clicked on Add a runbook

and created a stop runbook

As

$ConnectionAssetName = "AzureClassicRunAsConnection"

# 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

Stop-AzureVM -ServiceName "mytestvm" -Name "mytestvm" -Force

In practice until the “Select-AzureSubscription” is all code for environment preparation, after you can write your logic.
In this case there is only a basic Stop-AzureVM: copy, paste, Save and Publish.

Then I can link this runbook to a schedule ,

for example every evening at 20:00

If your customers asks “I would to work by the Saturday, sometimes…” then we can create a Webhook

that gives a URL that MUST be copied now, otherwise you can review it after

So you can create an little utility that make a HTTP POST and your customer is able to stop the vm (in this sample) without the need to access the Azure portal.
But the interesting code is the one of the start runbook:

$ConnectionAssetName = "AzureClassicRunAsConnection"

# 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

function Get-DateOfMondayEaster {
    param(
        [Parameter(ValueFromPipeline)]
        $Year=(Get-Date).Year
    )

    Process {
        [pscustomobject]@{} |
            Add-Member -PassThru -MemberType NoteProperty   C3 $Year |
            Add-Member -PassThru -MemberType ScriptProperty C7  { $this.c3%19 } |
            Add-Member -PassThru -MemberType ScriptProperty C8  { [System.Math]::Truncate($this.c3/100) } |
            Add-Member -PassThru -MemberType ScriptProperty C9  { $this.c3%100 } |
            Add-Member -PassThru -MemberType ScriptProperty C10 { [System.Math]::Truncate($this.c8/4) } |
            Add-Member -PassThru -MemberType ScriptProperty C11 { $this.c8%4 } |
            Add-Member -PassThru -MemberType ScriptProperty C12 { [System.Math]::Truncate(($this.c8+8)/25) } |
            Add-Member -PassThru -MemberType ScriptProperty C13 { [System.Math]::Truncate(($this.c8-$this.c12+1)/3) } |
            Add-Member -PassThru -MemberType ScriptProperty C14 { ((19*$this.c7)+$this.c8-$this.c10-$this.c13+15)%30 } |
            Add-Member -PassThru -MemberType ScriptProperty C15 { [System.Math]::Truncate($this.c9/4)} |
            Add-Member -PassThru -MemberType ScriptProperty C16 { $this.c9%4 } |
            Add-Member -PassThru -MemberType ScriptProperty C17 { (32+2*($this.c11+$this.c15)-$this.c14-$this.c16)%7 } |
            Add-Member -PassThru -MemberType ScriptProperty C18 { [System.Math]::Truncate(($this.c7+(11*$this.c14)+(22*$this.c17))/451) } |
            Add-Member -PassThru -MemberType ScriptProperty C19 { [System.Math]::Truncate(($this.c14+$this.c17-(7*$this.c18)+114)/31) } |
            Add-Member -PassThru -MemberType ScriptProperty C20 { ($this.c14+$this.c17-(7*$this.c18)+114)%31 } |
            Add-Member -PassThru -MemberType ScriptProperty C21 { $this.c20+1 } | # day
            Add-Member -PassThru -MemberType ScriptProperty C22 { $this.c19 }   | # month
            Add-Member -PassThru -MemberType ScriptProperty Easter {
                (Get-Date ("{0}/{1}/{2}" -f $this.c22, $this.c21, $this.c3)).AddDays(1)
            }
    }
}

$boolStart = $true

$year = (Get-Date).Year
$stringyear = [string]$year
$dayall = (Get-Date).ToShortDateString()
$day = (Get-Date).DayOfWeek

$newyeareve = "1/1/" + $stringyear
$befana  = "1/6/" + $stringyear
$liberation = "4/25/" + $stringyear
$laborday = "5/1/" + $stringyear
$republic = "6/2/" + $stringyear
$assunta = "8/15/" + $stringyear
$santi = "11/1/" + $stringyear
$immacolata = "12/8/" + $stringyear
$christmas = "12/25/" + $stringyear
$boxing = "12/26/" + $stringyear

if($dayall -eq $newyeareve){
    $boolStart = $false
}
if($dayall -eq $befana){
    $boolStart = $false
}
if($dayall -eq $liberation){
    $boolStart = $false
}
if($dayall -eq $laborday){
    $boolStart = $false
}
if($dayall -eq $republic){
    $boolStart = $false
}
if($dayall -eq $assunta){
    $boolStart = $false
}
if($dayall -eq $santi){
    $boolStart = $false
}
if($dayall -eq $immacolata){
    $boolStart = $false
}
if($dayall -eq $christmas){
    $boolStart = $false
}
if($dayall -eq $boxing){
    $boolStart = $false
}
if ($day -eq 'Saturday' -or $day -eq 'Sunday'){
    $boolStart = $false
}
# calculate Monday after Easter
$MondayEaster = Get-DateOfMondayEaster
$dayMondayEaster = $MondayEaster.Easter.ToShortDateString()
if($dayall -eq $dayMondayEaster){
    $boolStart = $false
}

if($boolStart -eq $true){
   Start-AzureVM -ServiceName "mytestvm" -Name "mytestvm"
   Write-Output "started"
} else {
   Write-Output "Not started"
}

After the common start code we can see an Powershell function Get-DateOfMondayEaster that calculate the Easter day, and then adding 1 day the Monday after.
Obviously if we need an WebBook for absolute starting we must create an “absstart” RunBook with only an Start-AzureVM, without the holiday logic, and create a WebHook for it.

Advertisements
Categories: Azure
%d bloggers like this: