This post will show you how to automate the conversion of Azure Stack virtual machines from unmanaged to managed disks and remove the extra layer of administrative overhead.
Table of Contents
Introduction
In June 2017, Microsoft introduced a new type of storage account called “Managed Disks.” Managed Disks are an exciting feature of Azure, which is designed to help with the availability, manageability, scalability, and performance of virtual machine disk storage within Azure.
Starting with Azure Stack Hub build 1808, Microsoft also announced support for managed disks on Azure Stack. This update simplifies disk management for Azure Stack VMs by managing the disk associated with the VM. You only have to specify the type (Premium or Standard) and the size of the disk you need, and Azure Stack creates and manages the disk for you. This work will offer Azure Stack users more options and simplicity when working with VMs. Beginning with the 1811 update, Azure Stack-managed disks are enabled by default when creating VMs using the Azure Stack portal. Furthermore, Microsoft strongly recommends converting your standard disks in Azure Stack to managed disks.
Azure Stack managed disks are NOT featured parity with Azure; there are some key differences that you should be aware of. Please make sure to continue reading Microsoft documentation here to see the differences.
The question is, what if you have an existing Azure Stack VMs with unmanaged standard disks, can I convert them to managed disks? The short answer is YES!
If you still have Azure VMs with unmanaged disks lying around, please check my previous article on converting them to Azure-managed disks.
Convert Azure Stack VMs To Managed Disks
If you had some virtual machines deployed on Azure Stack before you used managed disks, or you decided to simplify and go from an unmanaged disk configuration to a managed disk configuration, Either way, it’s a long process, and it’s completely different than converting Azure VM managed disks.
The Azure PowerShell cmdlets ConvertTo-AzureRmVMManagedDisk and ConvertTo-AzVMManagedDisk can’t be used to convert an unmanaged disk to a managed disk in Azure Stack. Azure Stack doesn’t currently support those cmdlets at the time of this writing. Additionally, the Azure Stack portal cannot be used to convert an unmanaged disk to a managed disk. The only way to convert an Azure Stack VM with unmanaged to managed disk is to delete the VM, detach the disks and then recreate the virtual machine with managed disk as described by Microsoft documentation here.
To convert Azure Stack VM to a managed disk, you must remove the VM configuration before creating the new VM with a managed disk. So you’ve to consider that in terms of things like downtime and availability of your applications. But if this is a non-critical VM then it’s not a big deal, you can go ahead and convert it anytime.
In this example, we’ve got a VM called “vm-azs-sql0“, which uses unmanaged disks. As you can see in the screenshot below, it’s got an operating system OS disk and 2 Data disks.

If I click on the OS disk or any data disks, you can see it’s actually using a storage account. So, this is an unmanaged disk.

The VM is also a member of an Availability Set. It has a public IP address, NIC interface, and Network Security Group configured.

The process of converting an Azure Stack VM from unmanaged to managed disk is as follows:
- Specify the VM you want to convert and which Azure Stack subscription is hosted.
- Specify the Resource Group Name.
- Specify the location where the VHDs that will be used to create the managed disks are located. The VHD file(s) can be deleted once the managed disks are created (Step 10).
- Get the network configuration (vNET, vNIC, NSG, Public IP address).
- Get the storage account for the Boot Diagnostics settings.
- If the VM is a member of an availability set, you need to convert the Availability Set from classic to managed.
- Delete the VM only without its disks.
- Create the OS-managed disk configuration (Linux / Windows).
- Create the Data-managed disk configuration.
- Delete the old VHD file(s).
- Create the network configuration back.
- Add the VM to the availability set.
- Attach the Boot Diagnostics storage account.
- Finally, recreate the virtual machine with its managed disks.
As you can see, there are a lot of steps that you want to go through, and it’s not a simple task, especially if you have a lot of VMs to convert.
To facilitate this process, I have created a PowerShell tool to automate the entire process.
You can run the script as follows:
.EXAMPLE
.\Convert-AzSManagedDisk.ps1 -rgFQDN [region.FQDN] -AADTenantName [domain.com] -AzSCred [user@domain.com] -VMName [VMName] -Storageacc [StorageAccountName] -Verbose
This example will convert a specified Azure Stack VM from an unmanaged to a managed disk; this could be running on Azure Stack Integrated System or Azure Stack Development Kit. You need to specify the region, the external FQDN of the Azure Stack, the username, and the storage account where the VHDs are located. If the VM has multiple data disks attached to it, the tool will convert them all to managed disks.
Here is an example of the output once you run this tool:

Once the VM is recreated, you will see that all disks are created as managed disks now. The whole network configuration will be preserved.

PowerShell Code
The complete script is detailed below to automate the entire process:
<#
.SYNOPSIS
Convert Azure Stack VMs to managed disks.
.DESCRIPTION
Convert Azure Stack VMs from Standard (unmanaged) disks to managed disks.
.NOTES
File Name : Convert-AzSManagedDisk.ps1
Author : Charbel Nemnom
Version : 1.0
Date : 08-August-2019
Update : 13-August-2019
Requires : PowerShell Version 5.1 or above
Module : Azure Stack Version 1.7.1 and above
Version : Azure Stack version 1808 and above
Support : Azure Stack Development Kit and Azure Stack Integrated System
OS : Convert Windows or Linux VMs
.LINK
To provide feedback or for further assistance please visit: https://charbelnemnom.com
.EXAMPLE
.\Convert-AzsManagedDisk.ps1 -rgFqdn -AADTenantName -AzsCred <azs@domain.com> -VMName -storageacc -Verbose
This example will convert a specified Azure Stack VM from unmanaged to managed disk, this could be running on Azure Stack Integrated System or Azure Stack Development Kit, you need to specify the region and the external FQDN of the Azure Stack, as well as the username and the storage account where the VHDs are located.
#>
[CmdletBinding()]
Param (
[Parameter(Position=0, Mandatory=$true, HelpMessage = 'Provide the region and external FQDN of the Azure Stack')]
[Alias('fqdn')]
[String]$rgFqdn,
[Parameter(Position=1, Mandatory=$true, HelpMessage = 'Provide the Azure AD (AAD) Tenant Name')]
[Alias('AAD')]
[String]$AADTenantName,
[Parameter(Position=2, Mandatory=$True, HelpMessage ='Provide Azure Stack Credentials')]
[Alias('Cred')]
[PSCredential]$AzsCred,
[Parameter(Position=3, Mandatory=$True, HelpMessage ='Provide the Azure Stack VM Name that you want to convert')]
[Alias('VM')]
[String]$VMName,
[Parameter(Position=4, Mandatory=$true, HelpMessage ='Provide the Azure Stack Storage Account where the VHDs exist')]
[Alias('StorageAccount')]
[String]$storageacc
)
# Azure Stack 1904 or later (only)
Function Install-AzureRM {
Set-PSRepository -Name PSGallery -Installation Trusted -Verbose:$false
Install-Module -Name AzureRM.BootStrapper -Confirm:$false -Verbose:$false
}
# Azure Stack 1904 or later (only)
Function Install-AzureStack {
Set-PSRepository -Name PSGallery -Installation Trusted -Verbose:$false
Use-AzureRmProfile -Profile 2019-03-01-hybrid -Force -Confirm:$false -Verbose:$false
Install-Module -Name AzureStack -RequiredVersion 1.7.2 -Confirm:$false -Verbose:$false
}
# Install Azure RM AvailabilitySet
Function Install-AzureRmAvailabilitySet {
Try {
Import-Module -Name AzureRm.AvailabilitySetManagement -ErrorAction Stop -Verbose:$false | Out-Null
Write-Verbose "Importing Azure RM AvailabilitySet PowerShell Module..."
}
Catch {
Write-Warning "Azure RM AvailabilitySet PowerShell Module is not installed..."
Write-Verbose "Installing Azure RM AvailabilitySet Module..."
Set-PSRepository -Name PSGallery -Installation Trusted -Verbose:$false
Install-Module -Name AzureRm.AvailabilitySetManagement -Confirm:$false -Verbose:$false
}
}
#! Check Azure Stack Connection
Try {
Write-Verbose "Connecting to Azure Stack..."
Add-AzureRmEnvironment –Name ‘AzureStackUser’ -ArmEndpoint "https://management.$rgfqdn" | Out-Null
# Set your AAD tenant name
$AuthEndpoint = (Get-AzureRmEnvironment -Name "AzureStackUser").ActiveDirectoryAuthority.TrimEnd('/')
$TenantId = (invoke-restmethod "$($AuthEndpoint)/$($AADTenantName)/.well-known/openid-configuration").issuer.TrimEnd('/').Split('/')[-1]
# Signing into Azure Stack
Add-AzureRmAccount -EnvironmentName "AzureStackUser" -Credential $AzsCred -TenantId $TenantId -ErrorAction Stop | Out-Null
}
Catch {
Write-Warning "Cannot connect to Azure Stack environment. Please check your credentials. Exiting!"
Break
}
#! Check AzureRM BootStrapper PowerShell Module
Try {
Import-Module -Name AzureRM.BootStrapper -ErrorAction Stop -Verbose:$false | Out-Null
Write-Verbose "Importing Azure RM BootStrapper PowerShell Module..."
}
Catch {
Write-Verbose "Installing the Azure RM BootStrapper Module..."
Install-AzureRM
}
#! Check Azure Stack PowerShell Module
Try {
Import-Module -Name AzureStack -RequiredVersion 1.7.2 -ErrorAction Stop -Verbose:$false | Out-Null
Write-Verbose "Importing Azure Stack PowerShell Module..."
}
Catch {
Write-Warning "Azure Stack PowerShell Module requires update..."
Write-Verbose "Installing Azure Stack PowerShell Module version 1.7.2"
Install-AzureStack
}
# Get all Azure Stack Tenant Subscriptions and look for the VM that you want to convert
# The source and target VM will be created
Write-Verbose "Get all Azure Stack Tenant Subscriptions..."
$azsSubs = Get-AzureRmSubscription
Write-Verbose "Locate Azure Stack VM ($VMName)..."
$azsVM = $azsSubs | ForEach-Object {Select-AzureRMSubscription $_ | Out-Null; Get-AzureRMVM | Where-Object {$_.Name -eq $VMName} }
If (!$azsVM ) {
Write-Warning "Azure Stack virtual machine ($VMName) cannot be found. Please check your virtual machine name. Exiting!"
Break
}
# Set the context to the subscription ID in which the managed disk will be created.
Write-Verbose "Set the context to the Azure Stack subscription ID: $($azsVM.Id.Split('/')[2])"
Select-AzureRmSubscription -SubscriptionId $azsVM.Id.Split('/')[2] | Out-Null
# Get the virtual NIC interface name and details
$NicName = $azsVM.NetworkProfile.NetworkInterfaces.Id.Split('/')[-1]
$vNic = Get-AzureRmNetworkInterface -Name $NicName -ResourceGroupName $azsVM.ResourceGroupName
# Get the public ip address name where the virtual machine will be hosted.
If ($VNic.IpConfigurations.publicIPAddress.Id -ne $null) {
Write-Verbose "Get the public ip address of the virtual machine..."
$PIpName = $VNic.IpConfigurations.publicIPAddress.Id.Split('/')[-1]
}
# Get the virtual network name where the virtual machine will be hosted.
Write-Verbose "Get the virtual network name where the virtual machine will be hosted..."
$vnetName = Get-AzureRmVirtualNetwork -ResourceGroupName $azsVM.ResourceGroupName `
| % {if($_.Subnets.IpConfigurations.Id.StartsWith($azsVM.NetworkProfile.NetworkInterfaces.Id)){return $_.Name}}
# Get the Boot Diagnostics storage account
If ($azsVM.DiagnosticsProfile.BootDiagnostics.Enabled -eq $true) {
$azsVMstoragediag = $azsVM.DiagnosticsProfile.BootDiagnostics.StorageUri.Split("//")[2]
$azsVMstoragediag = $azsVMstoragediag.Split('.')[0]
}
# Check if the VM that you want to convert to managed disks is in an availability set
If ($azsVM.AvailabilitySetReference.Id -ne $null) {
Install-AzureRmAvailabilitySet
Write-Verbose "Check if the VM that you want to convert is a member of an AvailabilitySet..."
$avSetName = $azsVM.AvailabilitySetReference.Id.Split('/')[-1]
Write-Verbose "Convert the availability set ($avSetName) to a managed availability set..."
$avSet = Get-AzureRmAvailabilitySet -ResourceGroupName $azsVM.ResourceGroupName -Name $avSetName
Update-AzureRmAvailabilitySet -AvailabilitySet $avSet -Sku Aligned | Out-Null
}
#! Get storage account and Blob VHDs Uri URL.
Write-Verbose "Get the storage account and Blob VHDs Uri..."
$azsStorage = Get-AzureRmStorageAccount -ResourceGroupName $azsVM.ResourceGroupName -Name $storageacc
Set-AzureRmCurrentStorageAccount -Name $storageacc -ResourceGroupName $azsVM.ResourceGroupName | Out-Null
$storageContainerName = (Get-AzureStorageContainer).Name
$azsdisks = @($azsvm.StorageProfile.OsDisk)
if ($azsvm.StorageProfile.DataDisks.Vhd.Uri) {
$azsdisks += $azsvm.StorageProfile.DataDisks
}
# Delete old VM, but keep the OS and data disks.
Write-Verbose "Remove Azure Stack VM $($azsVM.Name) configuration, the VM is going offline..."
Remove-AzureRmVm -Name $azsVM.Name -ResourceGroupName $azsVM.ResourceGroupName -Force -Confirm:$false | Out-Null
foreach ($azsdisk in $azsdisks) {
# The size of the new disk in GB. It should be greater than the existing VHD file size.
$NewDiskSize = ($azsdisk.DiskSizeGB)+1
# Create the managed disk configuration.
$DiskConfig = New-AzureRmDiskConfig -AccountType $azsStorage.Sku.Name -Location $azsVM.Location -DiskSizeGB $NewDiskSize `
-SourceUri $azsdisk.Vhd.Uri -CreateOption Import
if ($azsdisk.Name -eq "osdisk") {
# Create virtual machine configuration
Write-Verbose "Create virtual machine configuration..."
If ($avSetName) {
Write-Verbose "Add the VMName $($azsVM.Name) to a managed availability set ($avSetName)"
$VirtualMachine = New-AzureRmVMConfig -VMName $azsVM.Name -VMSize $azsVM.HardwareProfile.VmSize -AvailabilitySetId $avSet.Id
}
Else {
$VirtualMachine = New-AzureRmVMConfig -VMName $azsVM.Name -VMSize $azsVM.HardwareProfile.VmSize
}
# Create OS managed disk.
Write-Verbose "Create the OS managed disk: $($azsVM.Name)-$($azsdisk.Name)"
$OsDisk = New-AzureRmDisk -DiskName "$($azsVM.Name)-$($azsdisk.Name)" -Disk $DiskConfig -ResourceGroupName $azsVM.ResourceGroupName
# Use the managed disk resource ID to attach it to the virtual machine.
# The OS type will be set according to the exisitng VM (Windows/Linux).
If ($azsdisk.ostype -eq "Windows") {
$VirtualMachine = Set-AzureRmVMOSDisk -VM $VirtualMachine -ManagedDiskId $OsDisk.Id -CreateOption Attach -Windows -Caching $azsdisk.Caching
}
Else {
$VirtualMachine = Set-AzureRmVMOSDisk -VM $VirtualMachine -ManagedDiskId $OsDisk.Id -CreateOption Attach -Linux -Caching $azsdisk.Caching
}
# Delete the OS disk VHD file
Remove-AzureStorageBlob -Container $storageContainerName -Blob "$($azsdisk.Vhd.Uri.Split('/')[-1])" -Force -Confirm:$false
}
Else {
# Create Data managed disks.
Write-Verbose "Create the Data managed disk: $($azsdisk.Name)"
$DataDisk = New-AzureRmDisk -DiskName $azsdisk.Name -Disk $DiskConfig -ResourceGroupName $azsVM.ResourceGroupName
# Create the Data managed disk configuration.
$VirtualMachine = Add-AzureRmVMDataDisk -VM $VirtualMachine -ManagedDiskId $DataDisk.Id -CreateOption Attach -Lun $azsdisk.Lun `
-Caching $azsdisk.Caching
# Delete the Data disk VHD file
Remove-AzureStorageBlob -Container $storageContainerName -Blob "$($azsdisk.Vhd.Uri.Split('/')[-1])" -Force -Confirm:$false
}
}
# Create a public IP for the VM.
If ($PIpName) {
$PublicIp = Get-AzureRmPublicIpAddress -Name $PIpName -ResourceGroupName $azsVM.ResourceGroupName
}
# Get the virtual network where the virtual machine will be hosted.
$VNet = Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $azsVM.ResourceGroupName
# Create NIC in the first subnet of the virtual network.
$Nic = Get-AzureRmNetworkInterface -Name $NicName -ResourceGroupName $azsVM.ResourceGroupName
$VirtualMachine = Add-AzureRmVMNetworkInterface -VM $VirtualMachine -Id $Nic.Id
# Enable Boot Diagnostics with the appropriate storage account.
if ($azsVMstoragediag) {
$VirtualMachine = Set-AzureRmVMBootDiagnostics -VM $VirtualMachine -Enable -StorageAccountName $azsVMstoragediag -ResourceGroupName $azsVM.ResourceGroupName
}
# Create the new virtual machine with managed disks.
Write-Verbose "Create the new virtual machine ($($azsVM.Name)) with managed disks..."
New-AzureRmVM -VM $VirtualMachine -ResourceGroupName $azsVM.ResourceGroupName -Location $azsVM.Location
Summary
Azure Stack VMs deployed with managed disk simplifies disk management by managing the disk associated with the VM. You only have to specify the type (Premium or Standard) and the size of the disk you need, and Azure Stack creates and manages the disk for you. This work will offer Azure Stack users more options and simplicity when working with VMs. This tool makes converting any VM (test or production, Linux or Windows) from unmanaged to managed disk even faster.
Roadmap
I am planning to improve this tool in the future. This is still version 1.0. If you have any feedback or changes that everyone should receive, please feel free to leave a comment below.
That’s it, there you have it. Happy Azure Stacking!
__
Thank you for reading my blog.
If you have any questions or feedback, please leave a comment.
-Charbel Nemnom-