This article intends to help you move your VHD to Azure and create the Virtual Machine image using Powershell Az Module.
Issue
This article is provided as an alternative solution for migrating a KEMP LoadMaster virtual machine on an Azure subscription, however it applies to any vhd that need to be migrated to Azure.
In case you want to use the AzureRM module you can check this article: https://wikiazure.com/compute/mover-vhd-hacia-azure-usando-powershell/
Solution
Move your VHD to Azure and create the virtual machine image object from the OS Disk
Prerequisites:
- Active Azure subscription – Azure Free Account
- Azure PowerShell Az module: https://docs.microsoft.com/en-us/powershell/azure/new-azureps-module-az?view=azps-4.3.0
- VHD of your Virtual Machine – Download VHD
- A resource group previously provisioned in the Azure subscription – see Creating Resource Groups using PowerShell
- Validate that the VHD is fixed size, that means it cannot be 10.1GB or 10.01GB in that case expand the size of the disk to 11GB using hyper-v manager
Steps to move VHD to Azure and create Virtual Machine image using PowerShell Az Module
- Open Powershell on your local computer and access to the Azure subscription through the command:
Connect-AzAccount
- Get your subscription Id with the cmd below:
Get-AzSubscription
- To simplify the process let’s use the variables below:
$subscriptionName = "AzureCloud"
$subscriptionId = "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
$tenantId ="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
$resourceGroupName = 'Your-Resource-Group-Name'
$location = 'EastUS'
$vhdName = 'Your-VHD-Name.vhd'
$imageName = 'Your-Image-Name'
$containerName = "Your-Container-Name"
$storageAccountName = "Your-Storage-Account-Name"
- Now set the subscription to use in the current session with the following command:
Set-AzContext -SubscriptionId $subscriptionId
- Proceed to create a Storage Account and set the context through the following command:
$storageAccount = New-AzStorageAccount -ResourceGroupName $resourceGroupName -AccountName $storageAccountName -SkuName Standard_LRS -Location $location
$ctx = $storageAccount.Context
- Now let’s create the storage container:
New-AzStorageContainer -Name $containerName -Context $ctx -Permission blob
- Set the local path from the vhd
$localPath = 'Path-to-Your-VHD-File.vhd'
- Assign a variable to name the VHD:
$vhdName = 'your-vhd-file.vhd'
Set the url of the image and move the vhd, also use the -overwrite option since process might fail sporadically. “overwrite” solves the error “The pipeline was not run because a pipeline is already running.”
$urlOfUploadedImageVhd = ('https://' + $storageAccountName + '.blob.core.windows.net/' + $containerName + '/' + $vhdName)
Add-AzVhd -ResourceGroupName $resourceGroupName -Destination $urlOfUploadedImageVhd `
-LocalFilePath $localPath -OverWrite
Add-AzureRmVhd cmdlet uploads on-premises virtual hard disks, in .vhd file format, to a blob storage account as fixed virtual hard disks
There are other optional parameters that can be utilized:
- AsJob: Run cmdlet in the background and return a Job to track progress.
- BaseImageUriToPatch: Specifies the URI to a base image blob in Azure Blob Storage
- DefaultProfile: The credentials, account, tenant, and subscription used for communication with Azure.
- NumberOfUploaderThreads: Specifies the number of uploader threads to be used when uploading the .vhd file.
- OverWrite: Indicates that this cmdlet overwrites an existing blob in the specified destination URI, if one exists.
The VHD migration process will start right away and depending on the size it could take a couple of minutes:
- Create a managed image from the uploaded VHD
$imageConfig = New-AzImageConfig -Location $location
- Set the managed disk from the image
$imageConfig = Set-AzImageOsDisk -Image $imageConfig -OsType Windows -OsState Generalized `
-BlobUri $urlOfUploadedImageVhd
- Now proceed to generate the image:
$image = New-AzImage -ImageName $imageName -ResourceGroupName $resourceGroupName -Image $imageConfig
Complete script to move VHD to Azure and create virtual machine image using Powershell Az Module
Connect-AzAccount
$subscriptionName = "AzureCloud"
$subscriptionId = "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
$tenantId ="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
$resourceGroupName = 'Your-Resource-Group-Name'
$location = 'EastUS'
$vhdName = 'Your-VHD-Name.vhd'
$imageName = 'Your-Image-Name'
$containerName = "Your-Container-Name"
#Be sure to provide a valid storage account name. Storage account name must be between 3 and 24 characters in length and use numbers and lower-case letters only.
$storageAccountName = "Your-Storage-Account-Name"
#Set the Subscription to use in the current session
Set-AzContext -SubscriptionId $subscriptionId
#create new storage account
$storageAccount = New-AzStorageAccount -ResourceGroupName $resourceGroupName -AccountName $storageAccountName -SkuName Standard_LRS -Location $location
$ctx = $storageAccount.Context
#create storage container
New-AzStorageContainer -Name $containerName -Context $ctx -Permission blob
#set the local path from the vhd
$localPath = 'Path-to-Your-VHD-File.vhd'
# set the url of the image and move the vhd, also use the -overwrite option since process might fail sporadically
# -overwrite solves the error "The pipeline was not run because a pipeline is already running."
$urlOfUploadedImageVhd = ('https://' + $storageAccountName + '.blob.core.windows.net/' + $containerName + '/' + $vhdName)
Add-AzVhd -ResourceGroupName $resourceGroupName -Destination $urlOfUploadedImageVhd `
-LocalFilePath $localPath -OverWrite
# Create a managed image from the uploaded VHD
$imageConfig = New-AzImageConfig -Location $location
#set the managed disk from the image, ensure to select the correct OS Type (Windows or Linux)
$imageConfig = Set-AzImageOsDisk -Image $imageConfig -OsType Windows -OsState Generalized `
-BlobUri $urlOfUploadedImageVhd
#Create image
$image = New-AzImage -ImageName $imageName -ResourceGroupName $resourceGroupName -Image $imageConfig
Github Repository
Feel free to contribute – https://github.com/daveRendon/Move-VHD-to-Azure-and-Create-VM-Image-using-PowerShell
Troubleshooting
Discover questions
- Was the VHD uploaded to Azure Cloud or the OS on the VHD is from Azure Marketplace?
- What Operation System/version is installed on the VHD?
- Did you install Azure Guest Agent on the OS?
- Was the VHD OS generalized before shutdown?
You should be able to identify what Linux OS type/version is running on your local machine, install Guest Agent, generalize the OS before importing it to Azure Cloud.
Steps you may apply in order to fix the issue
- Identify OS type/version, and install on it Guest Agent. Please review an article: Linux distributions endorsed on Azure
- Generalize the OS: How to create an image of a virtual machine or VHD
- Review the Azure documentation in order to prepare the OS. Following article contains steps how to prepare the OS and install required applications: Understanding and using the Azure Linux Agent
- Fix the size of the vhd, that is, the VHD size integer, i.e. 200GB, it cannot be 200.5GB or 200.05GB.
- Ensure that blob is formatted as VHD
See Also
- Prepare a Windows VHD or VHDX to upload to Azure
- How to use Packer to create Windows virtual machine images in Azure
- List of supported images for Azure – The list says for stack but it is applicable for all of Azure.