/
xMove-VM.ps1
225 lines (195 loc) · 8.78 KB
/
xMove-VM.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
<#
.SYNOPSIS
This script demonstrates an xVC-vMotion where a running Virtual Machine
is live migrated between two vCenter Servers which are NOT part of the
same SSO Domain which is only available using the vSphere 6.0 API.
This script also supports live migrating a running Virtual Machine between
two vCenter Servers that ARE part of the same SSO Domain (aka Enhanced Linked Mode)
This script also supports migrating VMs connected to both a VSS/VDS as well as having multiple vNICs
This script also supports migrating to/from VMware Cloud on AWS (VMC)
.NOTES
File Name : xMove-VM.ps1
Author : William Lam - @lamw
Version : 1.0
Updated by : Askar Kopbayev - @akopbayev
Version : 1.1
Description : The script allows to run compute-only xVC-vMotion when the source VM has multiple disks on differnet datastores.
Updated by : William Lam - @lamw
Version : 1.2
Description : Added additional parameters to be able to perform cold migration to/from VMware Cloud on AWS (VMC)
-ResourcePool
-uppercaseuuid
.LINK
http://www.williamlam.com/2016/05/automating-cross-vcenter-vmotion-xvc-vmotion-between-the-same-different-sso-domain.html
.LINK
https://github.com/lamw
.INPUTS
sourceVCConnection, destVCConnection, vm, switchtype, switch,
cluster, resourcepool, datastore, vmhost, vmnetworks, $xvctype, $uppercaseuuid
.OUTPUTS
Console output
#>
Function xMove-VM {
param(
[Parameter(
Position=0,
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[VMware.VimAutomation.ViCore.Util10.VersionedObjectImpl]$sourcevc,
[VMware.VimAutomation.ViCore.Util10.VersionedObjectImpl]$destvc,
[String]$vm,
[String]$switchtype,
[String]$switch,
[String]$cluster,
[String]$resourcepool,
[String]$datastore,
[String]$vmhost,
[String]$vmnetworks,
[Int]$xvctype,
[Boolean]$uppercaseuuid
)
# Retrieve Source VC SSL Thumbprint
$vcurl = "https://" + $destVC
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class IDontCarePolicy : ICertificatePolicy {
public IDontCarePolicy() {}
public bool CheckValidationResult(
ServicePoint sPoint, X509Certificate cert,
WebRequest wRequest, int certProb) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = new-object IDontCarePolicy
# Need to do simple GET connection for this method to work
Invoke-RestMethod -Uri $VCURL -Method Get | Out-Null
$endpoint_request = [System.Net.Webrequest]::Create("$vcurl")
# Get Thumbprint + add colons for a valid Thumbprint
$destVCThumbprint = ($endpoint_request.ServicePoint.Certificate.GetCertHashString()) -replace '(..(?!$))','$1:'
# Source VM to migrate
$vm_view = Get-View (Get-VM -Server $sourcevc -Name $vm) -Property Config.Hardware.Device
# Dest Datastore to migrate VM to
$datastore_view = (Get-Datastore -Server $destVCConn -Name $datastore)
# Dest Cluster/ResourcePool to migrate VM to
if($cluster) {
$cluster_view = (Get-Cluster -Server $destVCConn -Name $cluster)
$resource = $cluster_view.ExtensionData.resourcePool
} else {
$rp_view = (Get-ResourcePool -Server $destVCConn -Name $resourcepool)
$resource = $rp_view.ExtensionData.MoRef
}
# Dest ESXi host to migrate VM to
$vmhost_view = (Get-VMHost -Server $destVCConn -Name $vmhost)
# Find all Etherenet Devices for given VM which
# we will need to change its network at the destination
$vmNetworkAdapters = @()
$devices = $vm_view.Config.Hardware.Device
foreach ($device in $devices) {
if($device -is [VMware.Vim.VirtualEthernetCard]) {
$vmNetworkAdapters += $device
}
}
# Relocate Spec for Migration
$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec
$spec.datastore = $datastore_view.Id
$spec.host = $vmhost_view.Id
$spec.pool = $resource
# Relocate Spec Disk Locator
if($xvctype -eq 1){
$HDs = Get-VM -Server $sourcevc -Name $vm | Get-HardDisk
$HDs | %{
$disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$disk.diskId = $_.Extensiondata.Key
$SourceDS = $_.FileName.Split("]")[0].TrimStart("[")
$DestDS = Get-Datastore -Server $destvc -name $sourceDS
$disk.Datastore = $DestDS.ID
$spec.disk += $disk
}
}
# Service Locator for the destination vCenter Server
# regardless if its within same SSO Domain or not
$service = New-Object VMware.Vim.ServiceLocator
$credential = New-Object VMware.Vim.ServiceLocatorNamePassword
$credential.username = $destVCusername
$credential.password = $destVCpassword
$service.credential = $credential
# For some xVC-vMotion, VC's InstanceUUID must be in all caps
# Haven't figured out why, but this flag would allow user to toggle (default=false)
if($uppercaseuuid) {
$service.instanceUuid = $destVCConn.InstanceUuid
} else {
$service.instanceUuid = ($destVCConn.InstanceUuid).ToUpper()
}
$service.sslThumbprint = $destVCThumbprint
$service.url = "https://$destVC"
$spec.service = $service
# Create VM spec depending if destination networking
# is using Distributed Virtual Switch (VDS) or
# is using Virtual Standard Switch (VSS)
$count = 0
if($switchtype -eq "vds") {
foreach ($vmNetworkAdapter in $vmNetworkAdapters) {
# New VM Network to assign vNIC
$vmnetworkname = ($vmnetworks -split ",")[$count]
# Extract Distributed Portgroup required info
$dvpg = Get-VDPortgroup -Server $destvc -Name $vmnetworkname
$vds_uuid = (Get-View $dvpg.ExtensionData.Config.DistributedVirtualSwitch).Uuid
$dvpg_key = $dvpg.ExtensionData.Config.key
# Device Change spec for VSS portgroup
$dev = New-Object VMware.Vim.VirtualDeviceConfigSpec
$dev.Operation = "edit"
$dev.Device = $vmNetworkAdapter
$dev.device.Backing = New-Object VMware.Vim.VirtualEthernetCardDistributedVirtualPortBackingInfo
$dev.device.backing.port = New-Object VMware.Vim.DistributedVirtualSwitchPortConnection
$dev.device.backing.port.switchUuid = $vds_uuid
$dev.device.backing.port.portgroupKey = $dvpg_key
$spec.DeviceChange += $dev
$count++
}
} else {
foreach ($vmNetworkAdapter in $vmNetworkAdapters) {
# New VM Network to assign vNIC
$vmnetworkname = ($vmnetworks -split ",")[$count]
# Device Change spec for VSS portgroup
$dev = New-Object VMware.Vim.VirtualDeviceConfigSpec
$dev.Operation = "edit"
$dev.Device = $vmNetworkAdapter
$dev.device.backing = New-Object VMware.Vim.VirtualEthernetCardNetworkBackingInfo
$dev.device.backing.deviceName = $vmnetworkname
$spec.DeviceChange += $dev
$count++
}
}
Write-Host "`nMigrating $vmname from $sourceVC to $destVC ...`n"
# Issue Cross VC-vMotion
$task = $vm_view.RelocateVM_Task($spec,"defaultPriority")
$task1 = Get-Task -Id ("Task-$($task.value)")
$task1 | Wait-Task
}
# Variables that must be defined
$vmname = "TinyVM-2"
$sourceVC = "vcenter60-1.primp-industries.com"
$sourceVCUsername = "administrator@vghetto.local"
$sourceVCPassword = "VMware1!"
$destVC = "vcenter60-3.primp-industries.com"
$destVCUsername = "administrator@vghetto.local"
$destVCpassword = "VMware1!"
$datastorename = "la-datastore1"
$resourcepool = "WorkloadRP"
$vmhostname = "vesxi60-5.primp-industries.com"
$vmnetworkname = "LA-VM-Network1,LA-VM-Network2"
$switchname = "LA-VDS"
$switchtype = "vds"
$ComputeXVC = 1
$UppercaseUUID = $false
# Connect to Source/Destination vCenter Server
$sourceVCConn = Connect-VIServer -Server $sourceVC -user $sourceVCUsername -password $sourceVCPassword
$destVCConn = Connect-VIServer -Server $destVC -user $destVCUsername -password $destVCpassword
xMove-VM -sourcevc $sourceVCConn -destvc $destVCConn -VM $vmname -switchtype $switchtype -switch $switchname -resourcepool $resourcepool -vmhost $vmhostname -datastore $datastorename -vmnetwork $vmnetworkname -xvcType $computeXVC -uppercaseuuid $UppercaseUUID
# Disconnect from Source/Destination VC
Disconnect-VIServer -Server $sourceVCConn -Confirm:$false
Disconnect-VIServer -Server $destVCConn -Confirm:$false