Azure Scale Units – Force your luck

Microsoft Azure Scale Units

Azure Scale Units (SU) basically make up the different types of hardware your Azure VMs run on. Azure VMs can only be resized within their Scale Unit. The current Azure Scale Units where you can deploy VMs on:

  • Type 1: A0-A4 (No Azure Load Balancing, no Autoscale)
  • Type 2: A0-A7 (equal to Type1 but adds A5-A7)
  • Type 3: A8-A11 (High Performance VMs, A8/A9 provide RDMA support)
  • Type 4: A0-A7 and D1-D14 (last gen)
  • Type 5: G1-G5
  • Type 6: DS1-DS14
  • Type 7: D1_V2-D14_V2 (not yet available in West EU)(35% CPU increase (Intel Xeon® E5-2673 v3-processors in combination with Intel Turbo Boost Technology 2.0))

Force your Scale Unit

Imagine deploying a SU1 – A2 VM (Basic Tier) in West EU, this results in :

An Azure VM (for instance A2) is assigned dynamically to Scale Unit 1, 2, or 4.

Now it is possible to force your luck and get the newer hardware of SU4 by making a D1 VM initallly, and scale this down to A2 (Basic tier) VM. After this proces we have a A2 Basic with a faster CPU :).

I would advise deploying from a Dx (SU4), to ensure SU4 vertical scaling flexibility and having more recent underlying hardware.

Comparing both CPUs on clearly states the advantages of the newer CPU platform. One disadvantage is the higher power consumption of the Xeon E5-2670v3… Lucky us, Power consumption is not billed!

Veeam Job-VM-Repositories inventory via Powershell

Powershell script below will create three CSV files (one with job inventory, second one with VM objects and which job they belong to, third one is a summary of the repositories ). Following parameters are displayed:

  • Job name
  • Job type
  • Next Run
  • Scheduled
  • VM objects in job
  • Retention Policy restore points
  • Repository target + path
  • Repository size information (Repo resync is executed before collection)

Instead of outputting to CSV it’s also nice to have a quick overview via the Out-Gridview.

The Get-vPCRepoInfo function is used from the Veeam forum

Add-PSSnapin veeampssnapin
function Get-vPCRepoInfo {
 param (
 [Parameter(Position=0, ValueFromPipeline=$true)]
 Begin {
 $dbServer = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication').SqlServerName
 $dbInstance = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication').SqlInstanceName
 $dbName = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication').SqlDatabaseName
 $outputAry = @()
 function Build-Object {param($name, $path, $free, $total)
 $repoObj = New-Object -TypeName PSObject -Property @{
 Target = $name
 storepath = $path
 StorageFree = [Math]::Round([Decimal]$free/1GB,2)
 StorageTotal = [Math]::Round([Decimal]$total/1GB,2)
 FreePercentage = [Math]::Round(($free/$total)*100)
 return $repoObj
 Process {
 foreach ($r in $Repository) {
 if ($r.GetType().Name -eq [String]) {
 $r = Get-VBRBackupRepository -Name $r
 # Force refresh of free space in repo
 [Veeam.Backup.Core.CBackupRepositoryEx]::SyncSpaceInfoToDb($r, $true)
 # Grab free space for repo directly from DB
 $rspace = Invoke-Sqlcmd -Query "SELECT total_space, free_space from [dbo].[BackupRepositories] where id = '$($'" -ServerInstance $($dbServer + "\" + $dbInstance) -Database $dbName
 $outputObj = Build-Object $r.Name $r.Path $rspace.free_space $rspace.total_space
 $outputAry = $outputAry + $outputObj
 End {
$VbrJobs = Get-VBRJob | Sort-Object typetostring, name
[System.Collections.ArrayList]$arrJobInformation = @()
[System.Collections.ArrayList]$arrJobVMsInformation = @()
[System.Collections.ArrayList]$arrRepos = @()
$Repos = Get-VBRBackupRepository
$Repos | Rescan-VBREntity -Wait

foreach($repo in $Repos){
$repo = $repo | Get-vPCRepoInfo

foreach($VbrJob in $VbrJobs){
$RepoTarget = $VbrJob.FindTargetRepository()
$vmCount = $vbrjob.GetObjectsInJob().count
$veeamJobRetention = $vbrjob.GetOptions().backupstorageoptions.retainCycles

$veeamjob = new-object -TypeName PSobject
Add-Member -InputObject $veeamjob -MemberType NoteProperty -Name Name -value $vbrjob.Name
Add-Member -InputObject $veeamjob -MemberType NoteProperty -Name TypeToString -value $vbrjob.TypeToString
Add-Member -InputObject $veeamjob -MemberType NoteProperty -Name ScheduleOptions -value $vbrjob.ScheduleOptions.get_NextRun()
Add-member -InputObject $veeamjob -MemberType NoteProperty -Name RepoTarget -value $RepoTarget.Name
add-member -InputObject $veeamjob -MemberType NoteProperty -name RepoTargetPath -value $Repotarget.Path
add-member -inputobject $veeamjob -MemberType NoteProperty -name IsScheduled -Value $vbrjob.IsScheduleEnabled
add-member -InputObject $veeamjob -MemberType NoteProperty -name vmCount -value $vmCount
add-member -InputObject $veeamjob -membertype NoteProperty -name RestorePointCount -value $veeamJobRetention
$vms = $vbrjob.GetObjectsInJob()
foreach($vm in $vms){
$veeamjobVM = new-object -TypeName PSobject
Add-Member -InputObject $veeamjobVM -MemberType NoteProperty -Name VbrJobName -value $vbrjob.Name
Add-Member -InputObject $veeamjobVM -MemberType NoteProperty -Name VMName -value $

$arrJobInformation | Export-Csv C:\Script\Report\VeeamJobs.csv -NoTypeInformation
$arrJobVMsInformation | export-csv C:\script\Report\VeeamJobsVM.csv -NoTypeInformation
$arrRepos | Export-Csv c:\Script\Report\VeeamRepo.csv -NoTypeInformation

Azure Creating Virtual Machines

Although the Azure web interface is very intuitive, understanding the workflow behind virtual machine creation/handling becomes clear using the Azure Powershell cmdlet.

Script features:

– Add a new virtual machine and define it’s InstanceSize depending on the region/VNet chosen
– Add a new Cloud service for the VM
– Use an existing Cloud service to add the VM to and add it to an existing Subnet
– Use a specific storage account which is bound to the chosen region/VNet

Example: Let’s add a new VM to the Japan West region and add it to an existing Subnet

  • connect to your Azure-Subscription

  • Choose your VM image by filtering within the GridView

  • Enter an appropriate VM Name

  • In this example we’re going for a new cloud service

  • Add a Cloud Service name which fit’s your taste (and that of Azure 😀 – no validation scripted)

  • I choose to add my VM to a custom vNet named vnet_Japan1

  • vnet_Japan1 has multiple subnets, Let’s choose Subnet-2

  • VM InstanceSize: Basic_A0

  • We have 1 storage subscription within the Japan West region

  • VM status

The powershell script (not optimized/no error handling):

#Global Declaration
$ErrorActionPreference = "Stop"
$adminUser = "user"
$password = "pwd"
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null

#Function getRegionVNetFromCloudService: Get the Region/VNet from a CloudService
function getRegionVNetFromCloudService($azCloudService){

 $azVNetSubnet = Get-AzureVNetSite | where-object {$_.Location -eq $azCloudService.Location} | select AddressSpacePrefixes,Location,Name,Subnets
 write-host $azVNetSubnet
if($azVNetSubnet.count -gt 0){
 $title = "VNet available"
 $message = "Do you want to add the Virtual Machine to an existing VNet?"
 $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
 "Use an Existing VNet"
 $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
 "Create Virtual Machine without adding to existing VNet"
 $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
 $result = $host.ui.PromptForChoice($title, $message, $options, 0)
 switch ($result)
 $azVNetSubnettmp = $azVNetSubnet | Out-GridView -title "Choose your subnet" -PassThru
 $azVnetSubnet = $azVNetSubnettmp.Subnets | Out-GridView -title "Choose the appropriate subnet" -PassThru
 $azVMConfig.Subnet = $azVnetSubnet.Name
 $azVMIS = setVMRegionRole($azCloudService)
 $azVMConfig.InstanceSize = $azVMIS
 $azVMConfig.ServiceName = $azCloudService.ServiceName
 $azVMConfig.VNet = $azVNetSubnettmp.Name
 $azVMConfig.Location = $azCloudService.Location
 $azStorageAcc = getStorageAccountFromRegion($azCloudService)
 $azVMConfig.StorageAccount = $azStorageAcc.StorageACcountName
 $azSubscription = Get-AzureSubscription
 Set-AzureSubscription –SubscriptionName $azSubscription.SubscriptionName –CurrentStorageAccountName $azVMConfig.StorageAccount

 $azVMIS = setVMRegionRole($azCloudService)
 $azVMConfig.InstanceSize = $azVMIS
 $azVMConfig.ServiceName = $azCloudService.ServiceName
 $azVMConfig.Location = $azCloudService.Location
 $azStorageAcc = getStorageAccountFromRegion($azCloudService)
 $azVMConfig.StorageAccount = $azStorageAcc.StorageACcountName
 $azSubscription = Get-AzureSubscription
 Set-AzureSubscription –SubscriptionName $azSubscription.SubscriptionName –CurrentStorageAccountName $azVMConfig.StorageAccount
#Function CreateVM (Create VM depending on the VNet/Region)
function CreateVM($azOption){
 if ($azOption -eq 1){
 $azVMconfigObject = New-AzureVMConfig -Name $azVMConfig.Label -InstanceSize $azVMConfig.InstanceSize -ImageName $azVMConfig.ImageName -Label $azVMConfig.label -DiskLabel "OS" `
 | Set-AzureSubnet $azVMconfig.Subnet | Add-AzureProvisioningConfig -Windows -AdminUsername $adminUser -Password $password
 New-AzureVM -ServiceName $azVMConfig.serviceName -Location $azVMConfig.Location -VMs $azVMconfigObject -VNetName $azVMConfig.VNet
 }elseif($azoption -eq 2){
 $azVMconfigObject = New-AzureVMConfig -Name $azVMConfig.Label -InstanceSize $azVMConfig.InstanceSize -ImageName $azVMConfig.ImageName -Label $azVMConfig.label -DiskLabel "OS" `
 | Add-AzureProvisioningConfig -Windows -AdminUsername $adminUser -Password $password
 New-AzureVM -ServiceName $azVMConfig.serviceName -Location $azVMConfig.Location -VMs $azVMconfigObject
#Function CreateStorageAccountName: Create a new StorageAccount (custom Name,Region)
function CreateStorageAccountName($azSANameInput,$azRegion){
 write-host $azSANameInput
 write-host $azRegion.Location
 New-AzureStorageAccount -StorageAccountName $azSANameInput -label $azSANameInput -Location $azRegion.Location
#Function CreateCloudService: Create Cloud Service
function CreateCloudService($azCSName){
 $azVNetRegion = $azVnetsRegions | select Name,Location,LocationType,Subnets | Out-GridView -title "Choose the Region/VNet to host your Cloud Service" -PassThru
 $azVnetSubnet = $azVNetRegion.Subnets | Out-GridView -title "Choose the appropriate subnet" -PassThru
 New-AzureService -ServiceName $azCSName -Location $azVNetRegion.Location
 $azVMIS = setVMRegionRole($azVNetRegion)
 $azVMConfig.InstanceSize = $azVMIS
 $azVMConfig.Subnet = $azVnetSubnet.Name
 $azvmconfig.servicename = $azCSName
 $azVMConfig.Location = $azVNetRegion.Location
 $azStorageAcc = getStorageAccountFromRegion($azVNetRegion)
 $azVMConfig.StorageAccount = $azStorageAcc.StorageACcountName
 $azSubscription = Get-AzureSubscription
 Set-AzureSubscription –SubscriptionName $azSubscription.SubscriptionName –CurrentStorageAccountName $azVMConfig.StorageAccount

if ($azVNetRegion.LocationType -eq "VNet"){
 $azVMConfig.VNet = $azVNetRegion.Name
}elseif ($azVNetRegion.LocationType -eq "Region"){

#Function setVMRegionRole: Get the VMRoleSizes based on Geo-location
function setVMRegionRole($azVMRegionRoleLocation){
 $azDCLocation = Get-AzureLocation | where-object {$_.DisplayName -eq $azVMRegionRoleLocation.Location}
 $azVMSize = $azDClocation.VirtualMachineRoleSizes | Out-GridView -title "Choose your VM size" -PassThru
 return $azVMSize

#Function TestCloudServiceName
function TestCloudServiceName($azCSName){
$azBool = Test-AzureName -Service $azCSName
if ($azBool){
 $azCSNameInput = [Microsoft.VisualBasic.Interaction]::InputBox("The Cloud Service Name is not available!, Enter a unique Cloud Service Name","Create new Cloud Service","")

#Function getRegions: Get Regions
function getRegions{
 $regions = Get-AzureLocation
 return $regions

#Function getStorageAccountFromRegion:
function getStorageAccountFromRegion($azRegion){
 $storageAccount = Get-AzureStorageAccount | where-object {$_.Location -eq $azRegion.location} | select StorageAccountName, Label, Location ` | Out-GridView -title "Choose your storage subscription" -PassThru
 if (!$storageAccount){
 $azSANameInput = [Microsoft.VisualBasic.Interaction]::InputBox("No Storage Account was found within, Enter a new Storage Account Name " ` + $azRegion.Location, "No Storage Account found", "")
 $newSA = CreateStorageAccountName $azSANameInput $azRegion
 $newSAReturn = Get-AzureStorageAccount | where-object {$_.Location -eq $azRegion.location} | select StorageAccountName, Label, Location ` | Out-GridView -title "Choose your storage subscription" -PassThru
 return $newSAReturn
 return $storageAccount
#Function getVNets: Get Azure VNets
function getVNets{
$vnets = Get-AzureVNetSite
return $vnets

#Function setCloudService:
function setCloudService{
 $title = "Cloud Service"
 $message = "Do you want to use an existing Cloud Service"
 $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
 "Use an existing Cloud Service"
 $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
 "Create a new Cloud Service"
 $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
 $result = $host.ui.PromptForChoice($title, $message, $options, 0)
 switch ($result)
 $azCSexisting = Get-AzureService | select label,servicename,location | out-gridview -title "Choose existing Cloud Service" -PassThru
 $azCSRegionVNET = getRegionVNetFromCloudService $azCSexisting
 $azCSNameInput = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the Cloud Service name, leave blank for default (default:VM Name)", "Create new Cloud Service", $azVMName)
 TestCloudServiceName $azCSNameInput

#Collect Regions and VNets
[System.Collections.ArrayList]$azVNReg = @()
$azRegions = getRegions
$azVNets = getVNets
foreach($azRegion in $azRegions){
 Add-Member -InputObject $azRegion -MemberType NoteProperty -Name LocationType -Value "Region"
 Add-Member -InputObject $azRegion -MemberType NoteProperty -Name Location -Value $azregion.Name
foreach($azVnet in $azVNets){
 Add-Member -InputObject $azVnet -MemberType NoteProperty -Name LocationType -Value "VNet"
$azVnetsRegions = $azVNReg

#Create Custom VMConfig PSobject
$azVMConfig = new-object -TypeName PSobject
Add-Member -InputObject $azVMConfig -MemberType NoteProperty -Name InstanceSize -value ""
Add-Member -InputObject $azVMConfig -MemberType NoteProperty -Name ImageName -value ""
Add-Member -InputObject $azVMConfig -MemberType NoteProperty -Name Label -value ""
Add-member -InputObject $azVMConfig -MemberType NoteProperty -Name Subnet -value ""
add-member -InputObject $azVMConfig -MemberType NoteProperty -name ServiceName -value ""
add-member -inputobject $azVMConfig -MemberType NoteProperty -name Location -Value ""
add-member -InputObject $azVMConfig -MemberType NoteProperty -name VNet -value ""
add-member -InputObject $azVMConfig -MemberType NoteProperty -name StorageAccount -value ""

#Prompt for VMImage
$azVMimage = Get-AzureVMImage | select imagename, imagefamily,publisheddate| Out-GridView -Title "Choose your Azure VM Image" -PassThru
$azVMConfig.ImageName = $azVMimage.ImageName

#Input VMname
$azVMName = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the Virtual Machine name", "Config VM name", "")
$azvmconfig.label = $azVMName

#Define The Cloud Service