Skip to content

Instantly share code, notes, and snippets.

@markcowl
Created May 19, 2017 16:46
Show Gist options
  • Save markcowl/cf294e4524115a68c034a6604e2fed1d to your computer and use it in GitHub Desktop.
Save markcowl/cf294e4524115a68c034a6604e2fed1d to your computer and use it in GitHub Desktop.
Updated migration script for AzureRM version 4.0
<#
.Synopsis
This script will copy a virtual machine with one or many datadisks from Azure Service Manager to Azure Resource Manager
.DESCRIPTION
This script will copy a virtual machine with one or many datadisks from Azure Service Manager to Azure Resource Manager
.EXAMPLE
Example of how to use this script with no parameters
.\Copy-VM-to-Arm.ps1
.EXAMPLE
Example of how to use this script with a private IPAddress
.\Copy-VM-to-Arm.ps1 -PrivateIPAddress 10.1.4.5
.PARAMETER PrivateIPAddress
This parameter set the private address for the virtual machine at config. This IP address must be vaid for the selected Virtual Machine
#>
#############################################################################
# #
# This Sample Code is provided for the purpose of illustration only #
# and is not intended to be used in a production environment. THIS #
# SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT #
# WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT #
# LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS #
# FOR A PARTICULAR PURPOSE. We grant You a nonexclusive, royalty-free #
# right to use and modify the Sample Code and to reproduce and distribute #
# the object code form of the Sample Code, provided that You agree: #
# (i) to not use Our name, logo, or trademarks to market Your software #
# product in which the Sample Code is embedded; (ii) to include a valid #
# copyright notice on Your software product in which the Sample Code is #
# embedded; and (iii) to indemnify, hold harmless, and defend Us and #
# Our suppliers from and against any claims or lawsuits, including #
# attorneys' fees, that arise or result from the use or distribution #
# of the Sample Code. #
# #
#############################################################################
#requires -modules @{ModuleName="AzureRM.Resources"; ModuleVersion="4.0.0"}, @{ModuleName="Azure"; ModuleVersion="4.0.0"}
#requires -Version 5
Param([String]$PrivateIPAddress="Dynamic")
$ErrorActionPreference = 'SilentlyContinue'
Login-AzureRmAccount
$UserInput = @{
VMName = ""
Location = ""
StorageAcount = ""
DataStorageAcount = ""
VirtualNetwork = ""
Subnet = ""
OSDisk = ""
ResourceGroup = ""
SubscriptionName = ""
OSType = ""
}
Function Select-Option
{
Param([Parameter(Mandatory=$true)]$Message,$Data,[ValidateSet("VMName", "Location", "StorageAcount", "VirtualNetwork", "Subnet", "OSDisk", "ResourceGroup","SubscriptionName","DataStorageAcount")]$Selection)
[void][reflection.assembly]::Load('System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][reflection.assembly]::Load('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
$Form = New-Object System.Windows.Forms.Form
$CmbSelection = New-Object System.Windows.Forms.ComboBox
$lblMessage = New-Object System.Windows.Forms.Label
$btnOK = New-Object System.Windows.Forms.Button
$btnCancel = New-Object System.Windows.Forms.Button
$Form.Width = 400
$Form.Height = 200
$lblMessage.Text = $Message
$lblMessage.Location = '20, 10'
$lblMessage.Width = '370'
$lblMessage.Height = '40'
$CmbSelection.Location = '20, 60'
$CmbSelection.Width = '240'
$data | %{$CmbSelection.Items.Add($_)}
If ($data.count -gt 0)
{
$CmbSelection.SelectedIndex = 0
}
$btnOK.Location = '20, 100'
$btnOK.Text = 'OK'
$btnCancel.Location = '100, 100'
$btnCancel.Text = 'Cancel'
$btnOK.add_click(
{
$UserInput[$Selection] = $CmbSelection.SelectedItem
$Form.Close()
})
$btnCancel.add_Click({$form.Close()})
$CmbSelection,$lblMessage,$btnOK,$btnCancel | %{$Form.Controls.Add($_)}
$Form.ShowDialog()
}
Select-Option -Message 'Select Azure Subscription to use.' -Data @(Get-AzurermSubscription -ErrorAction SilentlyContinue| select Name -ExpandProperty Name) -Selection SubscriptionName | Out-Null
Write-Host "Selecting Azure subscription..." -ForegroundColor Cyan
Select-AzureRmSubscription -SubscriptionName $UserInput.Name ;
Select-AzureSubscription -SubscriptionName $UserInput.Name -ErrorVariable SelectError -ErrorAction SilentlyContinue
IF ($SelectError -ne $null)
{
Write-Host "Azure Service Manager Account not visible" -ForegroundColor Yellow
Add-AzureAccount
Select-AzureSubscription -SubscriptionName $UserInput.Name -ErrorVariable 2dnError -ErrorAction SilentlyContinue
}
IF ($2dnError -ne $null)
{
Write-Host "Azure Service Manager Account not visible, make sure you can run add-azureaccount. This script will exit." -ForegroundColor red; start-sleep 30
}
Select-Option -Message 'Select Azure Service Manager Virtual Machine to Migrate, Virtual Machines in a running state will not be displayed.' -Data @(Get-azurevm -ErrorAction SilentlyContinue| ?{$_.status -eq 'StoppedDeallocated' -or $_.status -eq 'StoppedVM' } | select Name -ExpandProperty Name) -Selection VMName | Out-Null
Select-Option -Message "Select Detination Resource Group for Virtual Machine $($UserInput.VMName)" -Data @(Get-AzureRmResourceGroup -ErrorAction SilentlyContinue| select ResourceGroupName -ExpandProperty ResourceGroupName) -Selection ResourceGroup | Out-Null
Select-Option -Message 'Select Azure Resource Manager Destination StorageAccount' -Data @(Get-AzureRmStorageAccount -ErrorAction SilentlyContinue| select StorageaccountName -ExpandProperty StorageaccountName) -Selection StorageAcount | Out-Null
Select-Option -Message 'Select Azure Service Manager Virtual Network for the Migrated Virtual Machine' -Data @(Get-AzureRmVirtualNetwork -ErrorAction SilentlyContinue| select Name -ExpandProperty name) -Selection VirtualNetwork | Out-Null
Select-Option -Message "Select the Subnet to use from Virtual Network $($UserInput.VirtualNetwork)" -Data @((Get-AzureRmVirtualNetwork -ErrorAction SilentlyContinue| ?{$_.Name -eq "$($UserInput.VirtualNetwork)"}).Subnets | select Name -ExpandProperty Name) -Selection Subnet | Out-Null
$SourceVM = Get-AzureVm | ?{$_.Name -eq $UserInput.VMName}
$storageInfo = @(Get-AzureDisk | ?{$_.AttachedTo.RoleName -eq $UserInput.VMName})
If ($storageInfo.Count -gt 1)
{
Select-Option -Message "VM $($UserInput.VMName) contains multiple Hard drives, please select the Disk containing the Operating System for Boot" -Data @(($storageInfo.medialink.segments |Select-String -Pattern ".vhd")) -Selection OSDisk | Out-Null
Select-Option -Message "Select the Storage Account where the Data Disks should be copied to" -Data @(Get-AzureRmStorageAccount -ErrorAction SilentlyContinue| select StorageaccountName -ExpandProperty StorageaccountName) -Selection DataStorageAcount | Out-Null
}
Else
{
$UserInput.OSDisk = @(($storageInfo.medialink.segments |Select-String -Pattern ".vhd"))[0]
$UserInput.DataStorageAcount = $UserInput.StorageAcount
}
$vmName = $UserInput.VMName ; Write-Host "VM Name is $VMName" -ForegroundColor Green
$VMSize = $SourceVM.InstanceSize ; Write-Host "VM Size is $VMSize" -ForegroundColor Green
$UserInput.Location = $storageInfo[0].Location
Write-Host "Getting OS Type Information..." -ForegroundColor Yellow -NoNewline
$UserInput.OSType = (Get-AzureDisk |?{$_.AttachedTo.RoleName -eq $UserInput.VMName -and $_.MediaLink.OriginalString -like "*$($UserInput.OSDisk)"}).OS
Write-Host $UserInput.OSType -ForegroundColor Cyan
IF ($UserInput.Values -contains ""){Write-Host "Not all required infromation was collected, the script will exit" -ForegroundColor 'Red';Start-Sleep 5 ; Exit}
$CopyStatus = @()
Foreach ($Disk in $storageInfo)
{
$SourceData = Get-AzureStorageKey -StorageAccountName ($Disk.MediaLink.Authority -split ".blob")[0]
$SourceStorageAccount = $SourceData.StorageAccountName
$SourceStorageKey = $SourceData.Primary
$VHDName = ($Disk.MediaLink.AbsolutePath -split "/")[-1]
IF ($Disk.medialink.OriginalString -like "*$($UserInput.OSDisk)")
{
$Dest_StorageAccount = Get-AzureRmStorageAccount | ?{$_.StorageAccountName -eq $UserInput.StorageAcount}
}
Else
{
$Dest_StorageAccount = Get-AzureRmStorageAccount | ?{$_.StorageAccountName -eq $UserInput.DataStorageAcount}
}
Write-Host "Getting Destination storage key..." -ForegroundColor Green
$Dest_StorageKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $Dest_StorageAccount.ResourceGroupName -Name $Dest_StorageAccount.StorageAccountName).Key1
if ($Dest_StorageKey -eq $null)
{
$Dest_StorageKey = ((Get-AzureRmStorageAccountKey -ResourceGroupName $Dest_StorageAccount.ResourceGroupName -Name $Dest_StorageAccount.StorageAccountName).value)[0]
}
if ($Dest_StorageKey -eq $null)
{
Write-Host "All attemtps to retrieve key failed...Script will exit" -ForegroundColor red ; Start-Sleep 5
Exit
}
$SRC_Context = New-AzureStorageContext –StorageAccountName $SourceStorageAccount –StorageAccountKey $SourceStorageKey
$Dst_Context = New-AzureStorageContext –StorageAccountName $Dest_StorageAccount.StorageAccountName –StorageAccountKey $Dest_StorageKey
New-AzureStorageContainer -Context $Dst_Context -Name 'vhds' -Permission Off -ErrorAction SilentlyContinue
$CopyStatus += Start-AzureStorageBlobCopy -Context $SRC_Context –AbsoluteUri $Disk.MediaLink.AbsoluteUri –DestContainer "vhds" –DestBlob $VHDName –DestContext $Dst_Context
}
Do {
$CopyStatus | Get-AzureStorageBlobCopyState |?{$_.Status -ne 'Success'} | %{Write-host "CopyID = $($_.CopyID) `t BytesCopied: $($_.BytesCopied) of TotalBytes: $($_.TotalBytes) `t Status = $($_.Status)" -ForegroundColor Yellow }
Start-Sleep 60;
}
until( @(($CopyStatus | Get-AzureStorageBlobCopyState ).status) -notcontains 'Pending' )
If (@(($CopyStatus | Get-AzureStorageBlobCopyState ).status) -contains 'Failed')
{
Write-Host "One or more Virtual Disk copies failed, the script will exit" -ForegroundColor red ;Exit
}
Else
{
Write-Host "Virtual Disk copies completed" -ForegroundColor green
}
Write-Host "Retrieving Storage account" -ForegroundColor green
$Cfg_StorageAccount = Get-AzureRmStorageAccount | ?{$_.StorageAccountName -eq $UserInput.StorageAcount}
Write-Host "Retrieving Virtual Network" -ForegroundColor green
$Cfg_vnet = Get-AzureRmVirtualNetwork |?{$_.Name -eq $UserInput.VirtualNetwork}
$CFG_NicName= "$($UserInput.VMName)-nic1"
Write-Host "Network Adapater Name $CFG_NicName" -ForegroundColor green
$CFG_OSDiskName= $UserInput.OSDisk
IF ($PrivateIPAddress -eq "Dynamic")
{
$CFG_Nic = New-AzureRmNetworkInterface -Name $CFG_NicName –ResourceGroupName $UserInput.ResourceGroup -Location $UserInput.Location –SubnetId ($Cfg_vnet.Subnets | ?{$_.Name -eq $UserInput.Subnet}).id
}
Else
{
Write-host "Creating Network interface with Private Address $PrivateIPAddress" -ForegroundColor Yellow
$CFG_Nic = New-AzureRmNetworkInterface -Name $CFG_NicName –ResourceGroupName $UserInput.ResourceGroup -Location $UserInput.Location –SubnetId ($Cfg_vnet.Subnets | ?{$_.Name -eq $UserInput.Subnet}).id -PrivateIpAddress $PrivateIPAddress
}
$VMConfig = New-AzureRmVMConfig –vmName $vmName –vmSize $VMSize
$VMConfig = Add-AzureRmVMNetworkInterface -VM $VMConfig -Id $CFG_Nic.Id
$destOSDiskUri = "https://$($UserInput.StorageAcount).blob.core.windows.net/vhds/$($UserInput.OSDisk)"
if ($UserInput.OSType="Linux")
{
$VMConfig = Set-AzureRmVMOSDisk -VM $VMConfig -Name $UserInput.OSDisk –VhdUri $destOSDiskUri -Linux –CreateOption attach
}
Else
{
$VMConfig = Set-AzureRmVMOSDisk -VM $VMConfig -Name $UserInput.OSDisk –VhdUri $destOSDiskUri -Windows –CreateOption attach
}
IF ($storageInfo.Count -gt 1)
{
$Datadisks = @($storageInfo | ?{$_.Medialink.segments -notcontains $UserInput.OSDisk})
Foreach ($DataDisk in $Datadisks)
{
$DatadiskURI = $DataDisk.Medialink.originalstring -replace "$($DataDisk.Medialink.Authority)","$($UserInput.DataStorageAcount).blob.core.windows.net"
Write-Host "Attaching Data Disk $DatadiskURI" -ForegroundColor Yellow
$VMConfig = Add-AzureRmVMDataDisk -VM $VMConfig -Name ($DatadiskURI -split '/')[-1] -Caching None -DiskSizeInGB $Datadisks.DiskSizeInGB -VhdUri $DatadiskURI -CreateOption attach
}
}
Write-Host "Deploying Virtual Machine $($UserInput.VMName) in ResourceGroup $($UserInput.ResourceGroup)" -ForegroundColor Yellow
New-AzureRmVM -ResourceGroupName $UserInput.ResourceGroup -Location $UserInput.Location -VM $VMConfig -ErrorVariable Er
if ($er -ne $null)
{
Write-Host "Virtual Machine Migration Failed" -ForegroundColor red
$Error | Out-File .\MigrationLog.log
}
Else
{
Write-Host "Virtual Machine Migrated successfull" -ForegroundColor green
}
@markcowl
Copy link
Author

Note that this is a copy of the script provided here:https://gallery.technet.microsoft.com/scriptcenter/ASM-to-ARM-VM-Migration-504edee2

With modifications to support the latest version of Azure PowerShell

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment