Azure: Moving VHD to Azure and create VM image using PowerShell Az Module
Credits
Original Article: https://wikiazure.com/compute/move-vhd-to-azure-and-create-virtual-machine-image-using-powershell-az-module/
Introduction
This article intends to help you move your VHD to Azure and create the Virtual Machine image using Powershell Az Module.
In case you are using the ARM module you can check out this article: https://social.technet.microsoft.com/wiki/contents/articles/52418.azure-moving-vhd-to-azure-with-powershell-and-create-vm-image.aspx
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 VHD to Azure using PowerShell and create an image object from the OS Disk
Prerequisites:
- Active Azure subscription – Azure Free Account
- Azure PowerShell Az module: /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
Script Download
Here is the complete script available on Github: https://github.com/daveRendon/Move-VHD-to-Azure-and-Create-VM-Image-using-PowerShell/blob/master/src/moveVhd2Azure-createVmImage.ps1
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