This repository has been archived by the owner on Oct 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 143
/
Migrate-Image-From-Classic.ps1
156 lines (134 loc) · 5.47 KB
/
Migrate-Image-From-Classic.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<#
.SYNOPSIS
Migrate-Image-From-Classic.ps1
.DESCRIPTION
Migrates an image from the classic image store to RM
.PARAMETER ImageName
Original image name
.PARAMETER TargetStorageAccount
Target account to copy to
.PARAMETER TargetResourceGroup
Resource group of the target storage account
.PARAMETER TargetContainer
Target container to put the VHD
.PARAMETER TargetVirtualPath
Virtual path to put the blob in. If not specified, defaults to the virtual path of the source URI
.PARAMETER TargetBlobName
Blob name to copy to. If not specified, defaults to the blob name of the source URI
#>
param (
[Parameter(Mandatory=$true)]
[string]$ImageName,
[Parameter(Mandatory=$true)]
[string]$TargetBlob,
[Parameter(Mandatory=$true)]
$TargetStorageAccount = $null
[Parameter(Mandatory=$true)]
[string]$TargetResourceGroup,
[string]$TargetContainer = 'system',
[Parameter(Mandatory=$true)]
[string]$TargetVirtualPath = 'Microsoft.Compute/Images/custom'
)
# Ensure logged in
$ctx = Get-AzureRmContext
if (!$ctx) {
Exit
}
# First find the VM image and determine what account it is in.
Write-Output "Looking up image $ImageName"
$image = Get-AzureVMImage $ImageName
if (!$image) {
throw "Could not find $ImageName"
}
# Determine the current storage account location.
$vhdURI = $null
if ($image.MediaLink) {
# Contains the media link URL in the image info, rather than the os disk config. Parse this
$vhdURI = $image.MediaLink
}
else {
$vhdURI = $image.OSDiskConfiguration.MediaLink.AbsoluteUri
}
# Parse out the source URI info
$uriInfo = .\Parse-VHD-Uri.ps1 $vhdURI -ErrorAction Stop
$sourceStorageAccountName = $uriInfo.StorageAccount
$sourceStorageContainer = $uriInfo.ContainerName
$sourceStorageBlob = $uriInfo.Blob
$sourceStorageVirtualPath = $uriInfo.VirtualPath
Write-Output "Copy details:"
Write-Output " Storage Account $sourceStorageAccountName -> $TargetStorageAccount"
Write-Output " Container $sourceStorageContainer -> $TargetContainer"
if ($TargetVirtualPath -or $sourceStorageVirtualPath) {
Write-Output " Virtual Path $sourceStorageVirtualPath -> $TargetVirtualPath"
}
Write-Output " Blob $sourceStorageBlob -> $TargetBlob"
# Validate that we got the storage account right
$storageAccount = Get-AzureStorageAccount $sourceStorageAccountName
if (!$storageAccount) {
throw "Could not find storage account $sourceStorageAccountName"
}
# Generate the source and target contexts
$sourceKey = Get-AzureStorageKey -StorageAccountName $sourceStorageAccountName
$sourceContext = New-AzureStorageContext -StorageAccountName $sourceStorageAccountName -StorageAccountKey $sourceKey.Primary
# Grab the source blob
$sourceBlob = $null
if ($sourceStorageVirtualPath) {
$sourceBlob = Get-AzureStorageBlob -Blob "$sourceStorageVirtualPath/$sourceStorageBlob" -Container $sourceStorageContainer -Context $sourceContext -ErrorAction SilentlyContinue
}
else {
$sourceBlob = Get-AzureStorageBlob -Blob $sourceStorageBlob -Container $sourceStorageContainer -Context $sourceContext -ErrorAction SilentlyContinue
}
if (!$sourceBlob) {
Write-Error "Could not locate source blob $sourceStorageBlob"
Exit
}
if ($TargetVirtualPath) {
$targetUri = "https://$TargetStorageAccount.blob.core.windows.net/$TargetContainer/$TargetVirtualPath/$TargetBlob"
}
else {
$targetUri = "https://$TargetStorageAccount.blob.core.windows.net/$TargetContainer/$TargetBlob"
}
# Locate the storage account key for the target
$targetStorageAccountKeys = Get-AzureRmStorageAccountKey $TargetStorageAccount -ResourceGroupName $TargetResourceGroup -ErrorAction SilentlyContinue
if ($targetStorageAccountKeys) {
if ($targetStorageAccountKeys[0]) {
$targetStorageAccountKey = $targetStorageAccountKeys[0].Value
}
else {
$targetStorageAccountKey = $targetStorageAccountKeys.Key1
}
}
if (!$targetStorageAccountKey) {
Write-Error "Could not find target storage account $TargetStorageAccount or locate the storage key, skipping"
Exit
}
# Create a storage context for the target
$targetContext = New-AzureStorageContext -StorageAccountName $TargetStorageAccount -StorageAccountKey $targetStorageAccountKey
# Ensure that the container is created if not existing
$existingContainer = Get-AzureStorageContainer -Context $targetContext -Name $TargetContainer -ErrorAction SilentlyContinue
if (!$existingContainer) {
Write-Output "Target storage container $TargetContainer doesn't exist, creating"
New-AzureStorageContainer -Context $targetContext -Name $TargetContainer
}
$fullTargetBlobName = $TargetBlob
if ($TargetVirtualPath) {
$fullTargetBlobName = "$TargetVirtualPath/$TargetBlob"
}
$blobCopy = Start-AzureStorageBlobCopy -CloudBlob $sourceBlob.ICloudBlob -Context $sourceContext -DestContext $targetContext -DestContainer $TargetContainer -DestBlob $fullTargetBlobName
Write-Output "Started $vhdURI -> $targetUri"
# Waiting till all copies done
$allFinished = $false
while (!$allFinished) {
$allFinished = $true
$blobCopyState = $blobCopy | Get-AzureStorageBlobCopyState
if ($blobCopyState.Status -eq "Pending")
{
$allFinished = $false
$percent = ($blobCopyState.BytesCopied * 100) / $blobCopyState.TotalBytes
$percent = [math]::round($percent,2)
$blobCopyName = $blobCopyState.CopyId
Write-Progress -Id 0 -Activity "Copying from classic... " -PercentComplete $percent -CurrentOperation "Copying $blobCopyName"
}
Start-Sleep -s 30
}
Write-Output "All operations complete"