Update : updated script to support Azure Az powershell module.
Azure Managed disk is Microsoft disk storage solution. With managed disks, all you have to do is provision the disk, and Azure takes care of the rest.
Microsoft provides different Managed disk types for different performance category/IOPS. Refer here for more information.
It is very common to deploy Azure VMs with Premium disk to get better performance. However, it is more expensive than a Standard disk.
If higher IOPS is not an absolute requirement, it is always better to provision VMs with Standard disk. However, sometimes we only realize once the VM is already running. Therefore, a script will be very handy to quickly convert Premium disk to Standard disk, specially, if we have a large number of VMs. Following script will help to quickly convert Premium disk to Standard disk in Azure or vice-a-versa.
Before start using this script, make sure, you have Azure Az Module installed and imported on the system. For more information on how to install and configure Az module refer following article : https://docs.microsoft.com/en-us/powershell/azure/new-azureps-module-az?view=azps-5.5.0
Set parameter values based on your requirements. Hope it helps!
Param(
[Parameter(Mandatory=$true)]
[string]$vmListPath,
[Parameter(Mandatory=$false)]
[string]$diskSku
)
$date = Get-Date -UFormat "%m-%d-%Y_%H%M%S"
$tFile = "$($env:TEMP)\DiskConversion_Transcript_$($date).txt"
$dFormat = "%m-%d-%Y %H:%M:%S"
Start-Transcript -Path $tFile -Append -NoClobber
# Target Disk SKU - options - Standard_LRS and Premium_LRS based on requirements
$diskSku = 'Standard_LRS'
#
foreach($vm in Get-Content $vmListPath){
Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: Script Execution Starts on VM $vm" -ForegroundColor Green
$vmDetails = $vmId = $osDiskName = $dataDisks = $vmName = $updateDisk = ""
$vmName = $vm
# Get VM Resource Details
$vmInfo = Get-AzResource -Name $vmName -ResourceType Microsoft.Compute/virtualMachines
$resourceGroupName = $vmInfo.ResourceGroupName
# Stop and deallocate the VM before changing the size
$vmPowerStatus = (Get-AzVM -Name $vmName -ResourceGroupName $resourceGroupName -Status).Statuses.code
if($vmPowerStatus -contains "PowerState/running"){
$vmRunning = $true
#Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: VM is running, don't do anything on VM $vmName" -ForegroundColor Green
Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: VM is running, Deallocating $vmName" -ForegroundColor Green
$stopVM = Stop-AzVM -Name $vmName -ResourceGroupName $resourceGroupName -Force -Confirm:$false
do
{
Start-Sleep -Seconds 5
$vmPowerStatus = (Get-AzVM -Name $vmName -ResourceGroupName $resourceGroupName -Status).Statuses.code
}while($vmPowerStatus -contains "PowerState/running")
$allDisks = @()
$vmDetails = Get-AzVM -Name $vmName -resourceGroupName $resourceGroupName
$vmId = $vmDetails.Id
$osDiskName = $vmDetails.StorageProfile.OsDisk.Name
$allDisks += $osDiskName
$dataDisks = $vmDetails.StorageProfile.DataDisks
if([string]::IsNullOrEmpty($dataDisks)){
Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: No Data disk attached to VM $vmName" -ForegroundColor Green
}else{
foreach($dataDisk in $dataDisks){
$allDisks += $dataDisk.Name
}
}
foreach($disk in $allDisks){
$sku = $diskManagedBy = ""
$vmDiskDetails = Get-AzDisk -Name $disk -ResourceGroupName $resourceGroupName
if([string]::IsNullOrEmpty($vmDiskDetails)){
Write-Host "[$(Get-Date -UFormat $dFormat)] ERROR: VM Disk not found - $disk" -ForegroundColor Red
}else{
$sku = $vmDiskDetails.Sku.Name
$diskManagedBy = $vmDiskDetails.ManagedBy
if($sku -eq 'Premium_LRS' -or $sku -eq 'StandardSSD_LRS'){
if($diskManagedBy -eq $vmId){
Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: Changing Disk sku for Disk $disk on VM $vmName" -ForegroundColor Green
$diskUpdateConfig = New-AzDiskUpdateConfig -SkuName $diskSku
$updateDisk = Update-AzDisk -DiskUpdate $diskUpdateConfig -ResourceGroupName $resourceGroupName -DiskName $disk
}else{
Write-Host "[$(Get-Date -UFormat $dFormat)] ERROR: Disk $disk not managed by VM $vmName" -ForegroundColor Red
}
}else{
Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: VM Disk $disk is not Premium_LRS or StandardSSD_LRS.No action required." -ForegroundColor Green
}
}
}
}else{
Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: VM is NOT running, Disk sku will be changed if sku is 'Premium_LRS' or 'StandardSSD_LRS' for VM $vmName" -ForegroundColor Green
$allDisks = @()
$vmDetails = Get-AzVM -Name $vmName -resourceGroupName $resourceGroupName
$vmId = $vmDetails.Id
$osDiskName = $vmDetails.StorageProfile.OsDisk.Name
$allDisks += $osDiskName
$dataDisks = $vmDetails.StorageProfile.DataDisks
if([string]::IsNullOrEmpty($dataDisks)){
Write-Host "[$(Get-Date -UFormat $dFormat)] INORMATION: No Data disk attached to VM $vmName" -ForegroundColor Green
}else{
foreach($dataDisk in $dataDisks){
$allDisks += $dataDisk.Name
}
}
foreach($disk in $allDisks){
$sku = $diskManagedBy = ""
$vmDiskDetails = Get-AzDisk -Name $disk -ResourceGroupName $resourceGroupName
if([string]::IsNullOrEmpty($vmDiskDetails)){
Write-Host "[$(Get-Date -UFormat $dFormat)] ERROR: VM Disk not found - $disk" -ForegroundColor Red
}else{
$sku = $vmDiskDetails.Sku.Name
$diskManagedBy = $vmDiskDetails.ManagedBy
if($sku -eq 'Premium_LRS' -or $sku -eq 'StandardSSD_LRS'){
if($diskManagedBy -eq $vmId){
Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: Changing Disk sku for Disk $disk on VM $vmName" -ForegroundColor Green
$diskUpdateConfig = New-AzDiskUpdateConfig -SkuName $diskSku
$updateDisk = Update-AzDisk -DiskUpdate $diskUpdateConfig -ResourceGroupName $resourceGroupName -DiskName $disk
}else{
Write-Host "[$(Get-Date -UFormat $dFormat)] ERROR: Disk $disk not managed by VM $vmName" -ForegroundColor Red
}
}else{
Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: VM Disk $disk is not Premium_LRS or StandardSSD_LRS.No action required." -ForegroundColor Green
}
}
}
}
if($vmRunning){
try{
Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: Powering on Virtual Machine $vmName" -ForegroundColor Green
$startVM = Start-AzVM -Name $vmName -ResourceGroupName $resourceGroupName -Confirm:$false
do
{
Start-Sleep -Seconds 5
$vmPowerStatus = (Get-AzVM -Name $vmName -ResourceGroupName $resourceGroupName -Status).Statuses.code
}while(!($vmPowerStatus -contains "PowerState/running"))
Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: Virtual Machine $vmName is back online now" -ForegroundColor Green
}
catch{
Write-Host "[$(Get-Date -UFormat $dFormat)] ERROR: Failed to bring $vmName online.Please check the $vmName through portal." -ForegroundColor Red
}
}
Write-Host "[$(Get-Date -UFormat $dFormat)] INFORMATION: Script Execution Ends on VM $vmName" -ForegroundColor Green
Write-Host (("=") * 100)
}
Stop-Transcript
Download above script and save it with a .ps1 file extension. Open powershell console and, login to your Azure account using – Login-AzAccount. It will prompt you to enter your Azure credentials.
Once you login to Azure, run the powershell script saved in previous step.
Provide the path to the file containing list of Azure VMs as below and press enter to tun the script.