/
Get-CIVMData.ps1
235 lines (191 loc) · 10.1 KB
/
Get-CIVMData.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
226
227
228
229
230
231
232
233
234
235
Function Get-CIVMData
{
<#
.SYNOPSIS
Gathers information about a target CIVM
.DESCRIPTION
This function gathers CIVM Name, Parent vApp (obj), Parent vApp Name, All network adapters
(including IP, NIC index, and network), and vCenter VMX path details returning the resulting
ordered list.
.PARAMETER CIVM
The target vCloud VM from which information will be gathered
.NOTES
Author: Brian Marsh
Version: 1.0
#>
[CmdletBinding()]
Param (
[Parameter(
Position=0,
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[VMware.VimAutomation.Cloud.Types.V1.CIVM] $CIVM
)
BEGIN
{
}
PROCESS
{
$NewObj = [Ordered]@{}
$NewObj.GetCIVMData = @{}
$NewObj.GetCIVMData.Successful = $true
# Get the vCenter VM from the vCloud VM object
$vm = $civm | Get-VM -Debug:$False -Verbose:$False
Write-Verbose "Storing CIVM Name: $($CIVM.Name)/ Status: $($CIVM.Status)"
$NewObj.Name = $CIVM.Name
$NewObj.Status = $CIVM.Status
Write-Verbose "Recording Reservations"
$NewObj.Reservations = @{}
$NewObj.Reservations.CPU = @{}
$NewObj.Reservations.Memory = @{}
$NewObj.Reservations.CPU.Reservation = $vm.ExtensionData.ResourceConfig.CpuAllocation.Reservation
$NewObj.Reservations.CPU.Limit = $vm.ExtensionData.ResourceConfig.CpuAllocation.Limit
$NewObj.Reservations.Memory.Reservation = $vm.ExtensionData.ResourceConfig.MemoryAllocation.Reservation
$NewObj.Reservations.Memory.Limit = $vm.ExtensionData.ResourceConfig.MemoryAllocation.Limit
# Get the UUid from the Id, split out the UUID and pass it along
# Sample Id: urn:vcloud:vm:d9ca710d-cdf2-44eb-a274-26e1dcfd01bb
Write-Verbose "Storing CIVM UUID: $(($CIVM.Id).Split(':')[3])"
$NewObj.Uuid = ($CIVM.Id).Split(':')[3]
Write-Verbose "Gathering Network details"
$vAppNetworkAdapters = @()
$NetworkAdapters = Get-CINetworkAdapter -VM $civm -Debug:$False -Verbose:$False
foreach ($networkAdapter in $networkAdapters)
{
# Remove any existing VMNIC variables
Remove-Variable -Name VMNic -ErrorAction SilentlyContinue
$vAppNicInfo = [Ordered]@{}
$vAppNicInfo.NIC = ("NIC" + $networkAdapter.Index)
$vAppNicInfo.Index = $networkAdapter.Index
$vAppNicInfo.Connected = $networkAdapter.Connected
$vAppNicInfo.ExternalIP = $networkAdapter.IpAddress
$vAppNicInfo.InternalIP = $networkAdapter.ExternalIpAddress
$vAppNicInfo.MacAddress = $networkAdapter.MACAddress
$vAppNicInfo.vAppNetwork = [Ordered]@{}
$vAppNicInfo.vAppNetwork.Name = $networkAdapter.VAppNetwork.Name
<#
There is a chance that the vApp Network Name may not match a PortGroup which causes issues upon importing the VM after migration.
To fix this issue, we'll try to find get the PortGroup in this data gathering stage. If it is not found, we'll move on to attempted
remediation:
1) Get the vCenter VM network adapter that corresponds to this vCloud Director VM network adapter (where MAC Addresses match)
2) If the vCenter VM network adapter's network name doesn't match 'none' (indicating the VM is powered off) and the vCenter Network
name does not match the vCloud Director network name, set this target object's vAppNetwork Name to the vCenter PortGroup
3) If the vCenter VM network adapter's network name is 'none' then this VM is probably powered off and the network information is
not defined in vCenter. In this case, we mark the get-data as unsuccessful, set an error message and return.
#>
try
{
$vm | Get-VMHost -Debug:$false -Verbose:$false | Get-VDSwitch -Debug:$false -Verbose:$false -ErrorAction Stop | `
Get-VDPortgroup -name $networkAdapter.vAppNetwork.Name -Debug:$false -Verbose:$false -ErrorAction Stop | Out-Null
}
catch
{
Write-Debug "Portgroup not found by name $($networkAdapter.vAppNetwork.Name), Debug?"
Write-Verbose "Portgroup not found by name $($networkAdapter.vAppNetwork.Name), attempting fall back."
# Get VIVM network adapter where adapter mac matches vappnicinfo MacAddress
$VMNic = $vm | Get-NetworkAdapter -Debug:$false -Verbose:$false | Where-Object { $_.MacAddress -eq $vAppNicInfo.MacAddress }
# If VMNic Network Name doesn't match 'none' and doesn't match the vAppNetworkName, set vAppNetwork name to VMNic Network name
If ( ($VMNic.NetworkName -notlike 'none') -and ($VMNic.NetworkName -ne $vAppNicInfo.vAppNetwork.Name))
{
$vAppNicInfo.vAppNetwork.Name = $VMNic.NetworkName
}
else
{
Write-Debug "Tried to recover from missing network port group. Failed. Debug?"
$ErrorMessage = "VM [ $($CIVM.Name) ] has vAppNetwork connection that doesn't exist in vCenter [ $($vAppNicInfo.vAppNetwork.Name) ]"
$NewObj.GetCIVMData.Successful = $False
$NewObj.GetCIVMData.Error = $ErrorMessage
Write-Error $ErrorMessage
#Return whatever object we have at this point
$NewObj
Return
}
}
$vAppNetworkAdapters += $vAppNicInfo
}
Write-Verbose "Checking for Duplicate name upon Import"
Try
{
$DupeVM = Get-VM -Name $NewObj.NewName -Debug:$false -Verbose:$false -ErrorAction Stop -ErrorVariable DupeVM
If ($DupeVM)
{
$NewObj.GetCIVMData.Successful = $False
$NewObj.GetCIVMData.Error = "VM with name $($NewObj.NewName) already exists in vCenter"
Write-Error "VM with name $($NewObj.NewName) already exists in vCenter"
#Return whatever object we have at this point
$NewObj
return
}
}
Catch
{
Write-Verbose "No Duplicate Name Found!"
}
$NewObj.vAppNetworkAdapters = $vAppNetworkAdapters
Write-Verbose "Setting VIVIM object, parent vApp details, and CIVM object"
try
{
$NewObj.VIVM = $vm
$NewObj.ToolsStatus = $vm.ExtensionData.Guest.ToolsStatus
$NewObj.ToolsRunningStatus = $vm.ExtensionData.Guest.ToolsRunningStatus
$NewObj.HasSnapshots = ($vm | Get-Snapshot -Debug:$false -Verbose:$false -ErrorAction Stop | Select-Object Name, Description,VMId)
$NewObj.NeedsConsolidation = $vm.ExtensionData.Runtime.ConsolidationNeeded
$NewObj.OldMoref = $vm.Id
$NewObj.VmPathName = $vm.ExtensionData.Config.Files.VmPathName
$NewObj.ParentVApp = $CIVM.VApp.Name
$NewObj.StorageReservation = ($vm |Get-DatastoreCluster -Debug:$false -Verbose:$false -ErrorAction Stop | Select-Object -ExpandProperty Name)
$NewObj.CIVMId = $CIVM.Id
}
catch
{
$NewObj.GetCIVMData.Successful = $False
$NewObj.GetCIVMData.Error = "VM [ $($CIVM.Name) ] something went wrong while gathering details: $_"
Write-Debug "VM [ $($CIVM.Name) ] something went wrong while gathering details: $_, Debug"
Write-Error "VM [ $($CIVM.Name) ] something went wrong while gathering details: $_. "
#Return whatever object we have at this point
$NewObj
Return
}
# If ToolsStatus is not 'toolsOk' and status is not "PoweredOn", bomb out. We won't be able to power this VM off later.
If ($NewObj.ToolsRunningStatus -ne 'guestToolsRunning' -and $NewObj.status -eq "PoweredOn")
{
$NewObj.GetCIVMData.Successful = $False
$NewObj.GetCIVMData.Error = "VM [ $($CIVM.Name) ] tools are not running but the VM is powered On. Fix and try again."
Write-Debug "VM [ $($CIVM.Name) ] tools are not running but the VM is powered On, Debug"
Write-Error "VM [ $($CIVM.Name) ] tools are not running but the VM is powered On. "
#Return whatever object we have at this point
$NewObj
Return
}
If ($NewObj.HasSnapshots)
{
$NewObj.GetCIVMData.Successful = $False
$NewObj.GetCIVMData.Error = "VM [ $($CIVM.Name) ] has snapshots. Remove before trying again."
Write-Debug "VM [ $($CIVM.Name) ] has snapshots. Remove before trying again, Debug"
Write-Error "VM [ $($CIVM.Name) ] has snapshots. Remove before trying again."
#Return whatever object we have at this point
$NewObj
Return
}
Write-Verbose "Determining the VMX Path for this VM"
# Get this VM's path on disk
$vmPathName = $vm.ExtensionData.Config.Files.VmPathName
# Determine in which Datacenter this VM resides
$datacenter = $vm | get-Datacenter -Debug:$False -Verbose:$False | Select-Object -expand name
# Split out the datastore from the path name
$datastore = $vmPathName.Split("]")[0].split("[")[1]
# Split out the folder from the path name
$vmFolderPath = $vmPathName.Split("/")[0].split("]")[1].trim()
# Re-combine into a valid folder path
$vmxPath = "vmstore:\$($datacenter)\$($datastore)\$vmFolderPath"
Write-Verbose "VMXPath $vmxPath"
$NewObj.vmxPath = $vmxPath
$NewObj
}
END
{
Write-Debug "About to exit Get-CIVMData, anything else?"
Write-Verbose "Exited Get-CIVMData"
}
}