Created
May 19, 2017 16:46
-
-
Save markcowl/cf294e4524115a68c034a6604e2fed1d to your computer and use it in GitHub Desktop.
Updated migration script for AzureRM version 4.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.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 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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