Azure PowerShell – ARM – Properly delete (clean-up) a Single or Multiple ARM Virtual Machine(s) including deleting disks and NIC

We all know the perils of working with the new Azure Portal. Although, it is a very well designed portal, it still lacks some basic functionality. Specifically, if we need to work with multiple resources at once.

I will address three of the most common shortcomings in the Azure Portal with this script:

  1. The ability to delete attached disks when deleting a virtual machine. This feature was available in the the old Azure management portal, but was somehow left out of the new portal (maybe intentionally to make the portal idiot proof!). The following script will give you an option to delete disks when deleting virtual machine(s).
  2. The ability to delete multiple virtual machines at once (this problem is common with performing any operation on multiple resources at once, but this script with address it for the delete operation). The following script will allow you to select a single or multiple virtual machines for deletion.
  3. This Script will also delete the Network Interface Cards attached to the virtual machine(s).

#Login to your Azure account
Add-AzureRmAccount

#Select Subscription
$subId = (Get-AzureSubscription | Out-GridView -Title "Select a Subscription" -PassThru).SubscriptionId
Select-AzureRmSubscription -SubscriptionId $subId

$vms = Get-AzureRmVM | Out-GridView -Title "Select VMs to delete. Use Crtl/Shift for multi selection." -PassThru

$deleteDisks = "No","Yes" | Out-GridView -Title "Do you wish to delete disks attached to the VM(s)?" -PassThru

$disksToDelete = @()
$nicToDelete = @()

foreach($vm in $vms)
{
$disksToDelete = Get-VMDisks($vm)
$nicToDelete = Get-VMNIC($vm)
Write-Host "Deleting VM:" $vm.Name -ForegroundColor Yellow
Remove-AzureRmVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Force
Write-Host "Deleting NIC:" $nicToDelete -ForegroundColor Yellow
Remove-AzureRmNetworkInterface -Name $nicToDelete -ResourceGroupName $vm.ResourceGroupName -Force
if($deleteDisks -eq "Yes")
{
foreach ($disk in $disksToDelete)
{
Write-Host "Deleting Disk:" $disk -ForegroundColor Yellow
Delete-Disk($disk)
}
}
}

function Get-VMDisks($vm)
{
#Function to get all disks attached to a VM
$disks = @()
$disks += ,$vm.StorageProfile.OsDisk.Vhd.Uri
foreach ($disk in $vm.StorageProfile.DataDisks)
{
$disks += ,$disk.Vhd.Uri
}
return $disks
}

function Delete-Disk($uri)
{
#Function to get delete disk and delete the container if it is empty
$uriSplit = $uri.Split("/").Split(".")
$saName = $uriSplit[2]
$container = $uriSplit[$uriSplit.Length-3]
$blob = $uriSplit[$uriSplit.Length-2] + ".vhd"
$sa = Get-AzureRmStorageAccount | where {$_.StorageAccountName -eq $saName}
$saKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $sa.ResourceGroupName -Name $sa.StorageAccountName).Value[0]
$saContext = New-AzureStorageContext -StorageAccountName $sa.StorageAccountName -StorageAccountKey $saKey
Remove-AzureStorageBlob -Blob $blob -Container $container -Context $saContext

$remainingBlobs = Get-AzureStorageContainer -Name $container -Context $saContext | Get-AzureStorageBlob

if ($remainingBlobs -eq $null)
{
Remove-AzureStorageContainer -Name $container -Context $saContext -Force
}
}

function Get-VMNIC($vm)
{
$nic = $vm.NetworkInterfaceIDs.split("/") | Select-Object -Last 1
return $nic
}

 

Azure PowerShell – ARM – Enable Azure Disk encryption for Linux VM

Azure Disk Encryption is a new capability that lets you encrypt your Windows and Linux IaaS virtual machine disks. Azure Disk Encryption leverages the industry standard BitLocker feature of Windows…

Source: Azure PowerShell – ARM – Enable Azure Disk encryption for Linux VM

Azure PowerShell – Automate storage migration of Virtual Machines to Azure Premium or Standard Storage

This Azure PowerShell script completely automates storage migration for a classic Azure VM. The script does the following: Completely automates storage migration. Deletes Original VM and re-creates…

Source: Azure PowerShell – Automate storage migration of Virtual Machines to Azure Premium or Standard Storage

Azure PowerShell (ARM) – Add multiple data disks to an Azure Resource Manager (ARM) based Virtual Machine

The following Azure PowerShell (ARM) script allows you to add multiple data disks to an Azure Resource Manager (ARM) based Azure Virtual Machine.

  1. The script allows you to select the target VM from a list of all VMs
  2. Checks the size of the selected VM and determines the maximum number of data disks allowed for the VM
  3. Presents a list to choose the number of data data disks to attach
  4. Asks user input for the size of each data disk in GB (Max: 1023)
  5. Attaches specified number of empty data disks each of the specified size and updates the VM

# Login to Azure ARM

Login-AzureRmAccount

# Select Subscription

$subId = (Get-AzureRmSubscription | Out-GridView -Title "Select a Subscription" -PassThru).SubscriptionId
Select-AzureRmSubscription -SubscriptionId $subId

# Select VM

$vm = Get-AzureRmVM | Out-GridView -Title "Select the Virtual Machine to add Data Disks to" -PassThru

# Select Number of data disk

$azureSize = Get-AzureRmVMSize -Location $vm.Location | Where-Object -Property Name -EQ -Value $vm.HardwareProfile.VmSize
$maxDataDisks = $azureSize.MaxDataDiskCount
$noOfDataDisks = 1..$maxDataDisks
$noOfDisksToAdd = $noOfDataDisks | Out-GridView -Title "Number of Data Disks to add" -PassThru

#Get size for each Data Disk

$diskSizeinGB = Read-Host "Enter Size for each Data Disk in GB (Max: 1023)"

# Get VHD Storage account

$vhdSA = ($vm.StorageProfile.OSDisk.Vhd.Uri).Split('/')[2]

# Add Data Disks

for($i = 1; $i -le $noOfDisksToAdd; $i++)
{
$diskName = $vm.Name + "-DataDisk-" + $i.ToString()
$vhdUri = "https://" + $vhdSA + "/vhds/" + $diskName +".vhd"
$lun = $i - 1
Add-AzureRmVMDataDisk -VM $vm -Name $diskName -VhdUri $vhdUri -Lun $lun -Caching None -DiskSizeInGB $diskSizeinGB -CreateOption empty
}

#Update VM

$vm | Update-AzureRmVM

Azure PowerShell Classic – Bulk add or update Azure Endpoint and Access Control Lists (ACLs) for multiple Virtual Machines

The following Azure PowerShell script completely automates the process of apply Azure endpoints and Access Control Lists (ACLs) to Multiple Azure virtual machines.

This script can be used to bulk add or updated endpoints and ACLs on multiple virtual machines at once.

The script creates and Azure Endpoint and ACL configuration and applies it to all selected VMs:

  1. If this is a new endpoint (the script checks if the local port specified in the endpoint configuration is already used on the virtual machine or not),  The endpoint is applied to the virtual machine.
  2. If This is an endpoint update (the script checks if the local port specified in the endpoint configuration is already used on the virtual machine or not), the existing endpoint is deleted and the new one is applied.

The script starts with a random public port number of 50371 (you can change this), and increments the port number by 1 each time to ensure uniqueness (cloud services require all VMs to have unique public ports for VM endpoints)

#Define remote subnets to permit
$remoteSubnetsToPermit = "192.168.1.10/32", "192.168.1.14/32" , "192.168.1.20/32", "192.168.1.25/32", "10.20.172.0/24"

#endpoint configuration
$localPort = 3389
$publicPort = 50371
$endpointName = "RDP"

#Login to your Azure account
Add-AzureAccount

#Select Subscription
$subId = (Get-AzureSubscription | Out-GridView -Title "Select a Subscription" -PassThru).SubscriptionId
Select-AzureSubscription -SubscriptionId $subId

#Select VMs
$vms = Get-AzureVM | Out-GridView -Title "Select the Virtual Machines to apply ACL Config" -PassThru

#Build ACL by adding permit rule for each subnet
$acl1 = New-AzureAclConfig
$order = 0
foreach ($remoteSubnet in $remoteSubnetsToPermit)
{
$order += 100
Set-AzureAclConfig –AddRule –ACL $acl1 –Order $order –Action permit –RemoteSubnet $remoteSubnet –Description ("Permit " + $remoteSubnet)
}

#Apply config to all selected VMs
foreach ($vm in $vms)
{
$existingEndpoints = $vm | Get-AzureEndpoint
foreach ($endpoint in $existingEndpoints)
{
if ($endpoint.LocalPort -eq $localPort)
{
#remove existing endpoint if Local port is already used
Remove-AzureEndpoint -Name $endpoint.Name -VM $vm
}
}
$vm | Add-AzureEndpoint –Name $endpointName –Protocol tcp –Localport $localPort -PublicPort $publicPort –ACL $acl1 | Update-AzureVM
$publicPort += 1
}

Azure PowerShell ARM – Add multiple DNS Servers to Azure RM vNet via PowerShell

As per the Azure online documentation, you can add up to a maximum of 12 DNS servers to a Virtual Network (vNet).

This was easy to do for the classic (v1) vNets via the old Azure management portal. But what if you have an Azure Resource Manager (ARM) based vNet? There is no easy way as you cannot see an ARM based vNet in the classic portal.

The new Azure portal allows you to modify the list of DNS servers for a vNet, but you can add only two DNS entries.

So how do we add more than 2 DNS servers? The answer as usual is, via Azure PowerShell. The following script does exactly that and can be used to add multiple DNS servers to an Azure RM vNet

$subName = "<Subscription Name>"
$rgName = "<Resource Group Name>"
$vNetName = "<vNet Name>"
$DNSIPs = "192.168.1.10", "192.168.1.11", "192.168.1.12" #Modify as necessary. Maximum 12 DNS servers per vNet

Login-AzureRmAccount
Select-AzureRmSubscription -SubscriptionName $subName

$vnet = Get-AzureRmVirtualNetwork -ResourceGroupName $rgName -name $vNetName

foreach ($IP in $DNSIPs)
{
$vnet.DhcpOptions.DnsServers += $IP
}

Set-AzureRmVirtualNetwork -VirtualNetwork $vnet

In case you wish to modify the existing DNS server values and replace them with new values, use the script below which sets the DNS server to NULL before applying the new list of DNS servers:


$subName = "<Subscription Name>"
$rgName = "<Resource Group Name>"
$vNetName = "<vNet Name>"
$DNSIPs = "192.168.1.10", "192.168.1.11", "192.168.1.12" #Modify as necessary. Maximum 12 DNS servers per vNet

Login-AzureRmAccount
Select-AzureRmSubscription -SubscriptionName $subName

$vnet = Get-AzureRmVirtualNetwork -ResourceGroupName $rgName -name $vNetName

$vnet.DhcpOptions.DnsServers = $null

foreach ($IP in $DNSIPs)
{
$vnet.DhcpOptions.DnsServers += $IP
}

Set-AzureRmVirtualNetwork -VirtualNetwork $vnet

Azure PowerShell – Automate storage migration of Virtual Machines to Azure Premium or Standard Storage

This Azure PowerShell script completely automates storage migration for a classic Azure VM. The script does the following:

  1. Completely automates storage migration.
  2. Deletes Original VM and re-creates VM with same configuration
  3. Option to change size of VM during Migration
  4. Can be used to Migrate VM to Premium size and storage from standard or vice-versa
  5. Saves Virtual Network, Subnet and endpoint configuration and applies to migrated VM
  6. Saves VM config in xml file in case the original VM needs to be restored
Add-AzureAccount
$subId = (Get-AzureSubscription | Out-GridView -Title "Select a Subscription" -PassThru).SubscriptionId
Select-AzureSubscription -SubscriptionId $subId
$vm = Get-AzureVM | Out-GridView -Title "Select VM to Migrate" -PassThru
$vmName = $vm.Name
$csName = $vm.ServiceName
$destSAName = (Get-AzureStorageAccount | select StorageAccountName, AccountType | Out-GridView -Title "Select Destination Storage Account" -PassThru).StorageAccountName
$locationName = (Get-AzureService -ServiceName $csName).Location
$location = Get-AzureLocation | where {$_.Name -eq $locationName}
$targetVMSize = $location.VirtualMachineRoleSizes | Out-GridView -Title "Select Target VM Size" -PassThru
$migrateOSDisk = "Yes","No" | Out-GridView -Title "Do you wish to Migrate the OS Disk?" -PassThru

$vNet = $vm.VirtualNetworkName
$subnet = Get-AzureSubnet -VM $vm
$endpoints = Get-AzureEndpoint -VM $vm


# check if VM is in a stopped state
if ( $vm.Status -ne "StoppedDeallocated" )
{
$vm | Stop-AzureVM
# wait until the VM has stopped
$vmStatus = (Get-AzureVM –ServiceName $csName –Name $vmName).Status
while ($vmStatus -ne "StoppedDeallocated")
{
Write-Host "`n Stopping The VM" -ForegroundColor Yellow
Sleep -Seconds 5
$vmStatus = (Get-AzureVM –ServiceName $csName –Name $vmName).Status
}
Write-Host "`n Stopped the VM" -ForegroundColor Green
}
# export VM config file
$workingDir = (Get-Location).Path
$vmConfigurationPath = $workingDir + "\VM-" + $vmName + ".xml"
Write-Host "`n Exporting VM configuration to $vmConfigurationPath" -ForegroundColor Yellow
$exportRe = $vm | Export-AzureVM -Path $vmConfigurationPath

# Copy VHDs to Destination SA
$sourceOSDisk = $vm.VM.OSVirtualHardDisk
$sourceDataDisks = $vm.VM.DataVirtualHardDisks
$sourceSAName = $sourceOSDisk.MediaLink.Host -split "\." | select -First 1
$sourceSAKey = (Get-AzureStorageKey -StorageAccountName $sourceSAName).Primary
$sourceSAContext = New-AzureStorageContext –StorageAccountName $sourceSAName -StorageAccountKey $sourceSAKey
$destSAKey = (Get-AzureStorageKey -StorageAccountName $destSAName).Primary
$destSAContext = New-AzureStorageContext –StorageAccountName $destSAName -StorageAccountKey $destSAKey
if ((Get-AzureStorageContainer -Context $destSAContext -Name vhds -ErrorAction SilentlyContinue) -eq $null)
{
New-AzureStorageContainer -Context $destSAContext -Name vhds
}
$sourceOSVHD = $sourceOSDisk.MediaLink.Segments[2]
$destOSVHD = Get-AzureStorageBlob -Blob $sourceOSVHD -Container vhds -Context $sourceSAContext
Write-Host "`n Deleting the Original VM and waiting for OS Disk to be released." -ForegroundColor Yellow
Remove-AzureVM -Name $vmName -ServiceName $csName
$diskAttachedTo = (Get-AzureDisk -DiskName $sourceOSDisk.DiskName).AttachedTo
while ($diskAttachedTo -ne $null)
{
Start-Sleep -Seconds 10
$diskAttachedTo = (Get-AzureDisk -DiskName $sourceOSDisk.DiskName).AttachedTo
}
Write-Host "`n OS Disk released." -ForegroundColor Green

if ($migrateOSDisk -eq "Yes")
{
$allDisksToCopy = $sourceDataDisks + $sourceOSDisk
Write-Host "`n Starting copy of OS disk." -ForegroundColor Yellow
$targetBlob = Start-AzureStorageBlobCopy -SrcContainer vhds -SrcBlob $sourceOSVHD -DestContainer vhds -DestBlob $sourceOSVHD -Context $sourceSAContext -DestContext $destSAContext -Force
$destOSVHD = $targetBlob
}
else
{
$allDisksToCopy = $sourceDataDisks
}
foreach($disk in $sourceDataDisks)
{
$blobName = $disk.MediaLink.Segments[2]
Write-Host "`n Starting copy of data disk $($disk.DiskName)" -ForegroundColor Yellow
$targetBlob = Start-AzureStorageBlobCopy -SrcContainer vhds -SrcBlob $blobName -DestContainer vhds -DestBlob $blobName -Context $sourceSAContext -DestContext $destSAContext -Force
$disk.MediaLink = $targetBlob.ICloudBlob.Uri.AbsoluteUri
}
# Wait until all vhd files are copied.
$diskComplete = @()
Write-Host "`n Waiting for all disk copy to complete. Checking status every 30 seconds." -ForegroundColor Yellow
do
{

Sleep -Seconds 30
foreach ( $disk in $allDisksToCopy)
{
if ($diskComplete -contains $disk)
{
Continue
}
$blobName = $disk.MediaLink.Segments[2]
$copyState = Get-AzureStorageBlobCopyState -Blob $blobName -Container vhds -Context $destSAContext
if ($copyState.Status -eq "Success")
{
Write-Host "`n Copy complete for $($disk.DiskName) at $($copyState.CompletionTime)" -ForegroundColor Green
$diskComplete += $disk
}
else
{
if ($copyState.TotalBytes -gt 0)
{
$percent = ($copyState.BytesCopied / $copyState.TotalBytes) * 100
Write-Host "`n $('{0:N2}' -f $percent)% of disk $($disk.DiskName) copied." -ForegroundColor Yellow
}
}
}
}
while($diskComplete.Count -lt $allDisksToCopy.Count)

# Create a new vm
Set-AzureSubscription -SubscriptionId $subId -CurrentStorageAccountName $destSAName
if ($migrateOSDisk -eq "Yes")
{
$newOSDisk = Add-AzureDisk -OS $sourceOSDisk.OS -DiskName ($sourceOSDisk.DiskName + "-migr") -MediaLocation $destOSVHD.ICloudBlob.Uri.AbsoluteUri
$newVM = New-AzureVMConfig -Name $vmName -InstanceSize $targetVMSize -DiskName $newOSDisk.DiskName
}
else
{
$newVM = New-AzureVMConfig -Name $vmName -InstanceSize $targetVMSize -DiskName $sourceOSDisk.DiskName
}
foreach ($dataDisk in $sourceDataDisks)
{
$diskLabel = $vmName + "Disk" + $dataDisk.Lun
$newVM | Add-AzureDataDisk -ImportFrom -DiskLabel $diskLabel -LUN $dataDisk.Lun -MediaLocation $dataDisk.MediaLink
}
foreach ($endpoint in $endpoints)
{
$newVM | Add-AzureEndpoint -Protocol $endpoint.Protocol -LocalPort $endpoint.LocalPort -PublicPort $endpoint.Port -Name $endpoint.Name
}
$newVM | Set-AzureSubnet -SubnetNames $subnet
Write-Host "`n Creating new VM from copied disk(s)" -ForegroundColor Yellow
New-AzureVM -ServiceName $csName -VMs $newVM -Location $locationName -VNetName $vNet
Write-Host "`n Script Execution complete" -ForegroundColor Green

Azure PowerShell – ARM – Enable Azure Disk encryption for Linux VM

Azure Disk Encryption is a new capability that lets you encrypt your Windows and Linux IaaS virtual machine disks. Azure Disk Encryption leverages the industry standard BitLocker feature of Windows and the DM-Crypt feature of Linux to provide volume encryption for the OS and the data disks. The solution is integrated with Azure Key Vault to help you control and manage the disk encryption keys and secrets in your key vault subscription, while ensuring that all data in the virtual machine disks are encrypted at rest in your Azure storage.

This article describes how to enable data disk encryption for a Linux VM running in Azure via Azure ARM PowerShell.

Note: Azure Disk Encryption is supported on the following Linux server SKUs – Ubuntu, CentOS, SUSE and SUSE Linux Enterprise Server (SLES) and Red Hat Enterprise Linux.

Azure disk excryption for Linux is only supported for data volumes. All sensitive information you wish to encrypt must be stored on the Data volumes and not the OS volume. OS Disk encryption for Linux VMs is only supported for a pre-encrypted VHD uploaded to Azure.

$subName = "<Subscription Name>"
$rgName = "<Resource Group Name>"
$location = "<Azure Location>"
$keyVaultName = "<Azure Key Vault Name"
$aadClientSecret = “<Azure AD Client Secret>”
$vmName = "<Linux VM Name to enable encyption on>"

#Start an Azure PowerShell session and sign in to your Azure account
Login-AzureRmAccount

#Select the correct Azure subscription
Select-AzureSubscription -SubscriptionName $subName

#Create a key vault
New-AzureRmKeyVault -VaultName $keyVaultName -ResourceGroupName $rgName -Location $location

#Add a key to the key vault
$key = Add-AzureKeyVaultKey -VaultName $keyVaultName -Name 'FirstKey' -Destination 'Software'

#Create a new Azure AD app. The values for parameters -HomePage and -IdentifierUris do not have to be real. You can make up anything.
$azureAdApplication = New-AzureRmADApplication -DisplayName "ADELinuxApp" -HomePage "https://YourApplicationHomePage.com" -IdentifierUris "https://YouApplicationUri.com" -Password $aadClientSecret
$servicePrincipal = New-AzureRmADServicePrincipal –ApplicationId $azureAdApplication.ApplicationId

#Set Key Vault Access policy for the Azure AD Application
$aadClientID = $azureAdApplication.ApplicationId
Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -ServicePrincipalName $aadClientID -PermissionsToKeys all -PermissionsToSecrets all -ResourceGroupName $rgName
Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -ResourceGroupName $rgName –EnabledForDiskEncryption

#Enable encryption on VM
$KeyVault = Get-AzureRmKeyVault -VaultName $keyVaultName -ResourceGroupName $rgName
$diskEncryptionKeyVaultUrl = $KeyVault.VaultUri
$KeyVaultResourceId = $KeyVault.ResourceId
Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $rgName -VMName $vmName -AadClientID $aadClientID -AadClientSecret $aadClientSecret -DiskEncryptionKeyVaultUrl $diskEncryptionKeyVaultUrl -DiskEncryptionKeyVaultId $KeyVaultResourceId -VolumeType Data

To Enable Encryption for additional Linux VMs. Just run the last section of the script again replacing the variable $vmName

$vmName = "<Linux VM Name to enable encyption on>"
$KeyVault = Get-AzureRmKeyVault -VaultName $keyVaultName -ResourceGroupName $rgName
$diskEncryptionKeyVaultUrl = $KeyVault.VaultUri
$KeyVaultResourceId = $KeyVault.ResourceId
Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $rgName -VMName $vmName -AadClientID $aadClientID -AadClientSecret $aadClientSecret -DiskEncryptionKeyVaultUrl $diskEncryptionKeyVaultUrl -DiskEncryptionKeyVaultId $KeyVaultResourceId -VolumeType Data

Azure PowerShell – ARM -VPN Gateway Diagnostics

An Azure Resource Manager (ARM) PowerShell script to automate the process of generating and downloading VPN gateway diagnostic logs.

This script does not require you to modify values for any variables. All variables are auto populated by using the PowerShell Out-GridView function.

When running the script, you will be prompted to enter your credentials twice as this script requires you to authenticate to both ARM and classic Azure PowerShell API

# Login to Azure ARM

Login-AzureRmAccount

# Select Subscription

$subId = (Get-AzureRmSubscription | Out-GridView -Title "Select a Subscription" -PassThru).SubscriptionId
Select-AzureRmSubscription -SubscriptionId $subId

# Select Resource Group

$rg = (Get-AzureRmResourceGroup | Out-GridView -Title "Select the Resource Group VPN Gateway belongs to" -PassThru).ResourceGroupName

# Select vNet Gateway

$gateway = (Get-AzureRmVirtualNetworkGateway -ResourceGroupName $rg | Out-GridView -Title "Select vNet Gateway" -PassThru).Name

# Select Storage Account place the logs in

$sa = Get-AzureRmStorageAccount | Out-GridView -Title "Select Storage Account in the same region" -PassThru
$saName = $sa.StorageAccountName
$saRG = $sa.ResourceGroupName
$saKey = (Get-AzureRmStorageAccountKey -Name $saName -ResourceGroupName $saRG).Value[0]

# Login to Azure Classic

Add-AzureAccount

# Select same subscription in classic mode

Select-AzureSubscription -SubscriptionId $subId

# Set SA Context

$saContext = New-AzureStorageContext -StorageAccountName $saName -StorageAccountKey $saKey

# Get Gateway ID

$gateways = Get-AzureVirtualNetworkGateway
$gatewayId = (($gateways | ? GatewayName -eq $gateway).GatewayId)[-1]

# Start Diagnostics capture

$duration = 60

$saContainer = "vpndiag"

Start-AzureVirtualNetworkGatewayDiagnostics -GatewayId $gatewayId -CaptureDurationInSeconds $duration -StorageContext $saContext -ContainerName $saContainer

# Wait for Diagnostics capture to finish

Sleep -Seconds $duration

# Download Diagnostics log

$diagUrl = (Get-AzureVirtualNetworkGatewayDiagnostics -GatewayId $gatewayId).DiagnosticsUrl
$content = (Invoke-WebRequest -Uri $diagUrl).RawContent
$content | Out-File -FilePath vpnlogs.txt

The logs will be placed in the file vpnlogs.txt under the current folder.

Azure Automation -Automatically resize Virtual Machines – Scale Up and Scale Down – Save Money!!!

Microsoft Azure offers some cheap low spec virtual machines. But as we all know, the prices can go up pretty quickly as the specs go up. But we need large VMs to support today’s modern day workloads. The downside is that most of these workloads are only present during business hours but you end up running and paying for these large VMs even during non-business hours and on weekends.

One option is to have an Azure automation script to shut down the VMs during non-business hours and have another script automation script to power these back up just before start of business.

Although, this solution might work for some dev/test kind of VMs, it won’t be feasible for most of your VMs as you still need the critical services to be up during non-business hours, just not on large monstrous VMs.

The solution here is to have an azure automation script that resizes the VMs to the lowest possible size during non-business hours and have another automation script to resize the VMs to their original size just before start of business.

We will use two resource tags to help us achieve this:

Reducesize=”Yes”
Originalsize=<Original size of VM> (Eg: Originalsize=Standard_D4)

The tricky part here is that the lowest possible size differs based on the number of data disks attached to the VM. The script below looks at the number of data disks attached and chooses the lowest possible size for the VM based on it.

Script: ScaleDownVMs


$CredentialAssetName = '<Your Automation Credentials>'

$Cred = Get-AutomationPSCredential -Name $CredentialAssetName
if(!$Cred) {
Throw 'Could not find an Automation Credential Asset named '${CredentialAssetName}'. Make sure you have created one in this Automation Account.'
}

Add-AzureRmAccount -Credential $Cred | Out-Null
Select-AzureRmSubscription -SubscriptionName "<Subscription Name>"
$vmList = Find-AzureRmResource | Where-Object {$_.Tags.Name -eq 'Reducesize' -and $_.Tags.Value -eq 'Yes'}

foreach($vmEntry in $vmList)
{
$vm = Get-AzureRmVM -Name $vmEntry.Name -ResourceGroupName $vmEntry.ResourceGroupName
$DataDisksCount = $vm.StorageProfile.DataDisks.Count

if($DataDisksCount -le 1 )
{
$targetSize = "Standard_A0"
}
elseif($DataDisksCount -le 2 )
{
$targetSize = "Standard_A1"
}
elseif($DataDisksCount -le 4 )
{
$targetSize = "Standard_A2"
}
elseif($DataDisksCount -le 8 )
{
$targetSize = "Standard_A3"
}
else
{
$targetSize = "Standard_A4"
}
$vm.HardwareProfile.vmSize = $targetSize
Update-AzureRmVM -ResourceGroupName $vmEntry.ResourceGroupName -VM $vm
}

Script: ScaleUpVMs


$CredentialAssetName = '<Your Automation Credentials>'

$Cred = Get-AutomationPSCredential -Name $CredentialAssetName
if(!$Cred) {
Throw 'Could not find an Automation Credential Asset named '${CredentialAssetName}'. Make sure you have created one in this Automation Account.'}

Login-AzureRmAccount -Credential $Cred
Select-AzureRmSubscription -SubscriptionName "<Subscription Name>"

$vmList = Find-AzureRmResource | Where-Object {$_.Tags.Name-eq 'Reducesize' -and $_.Tags.Value -eq 'Yes'}

foreach($vmEntry in $vmList)
{
$vm = Get-AzureRmVM -Name $vmEntry.Name -ResourceGroupName $vmEntry.ResourceGroupName
$OriginalSize = $vm.Tags.Originalsize.ToString()
$vm.HardwareProfile.vmSize = $OriginalSize
Update-AzureRmVM -ResourceGroupName $vmEntry.ResourceGroupName -VM $vm
}

 

Design a site like this with WordPress.com
Get started