Added CIVM Data gathering function for vCD export/Migration
This commit is contained in:
245
Scripts/Get-CIVMData.ps1
Normal file
245
Scripts/Get-CIVMData.ps1
Normal file
@@ -0,0 +1,245 @@
|
||||
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
|
||||
|
||||
# Do some logic here, if the VM name matches "tmpl" or "tpl", it's a template. Grab the vApp name and set "New Name"
|
||||
If ($CIVM.Name -match "tmpl" -or $CIVM.Name -match "tpl")
|
||||
{
|
||||
$NewObj.NewName = $CIVM.VApp.Name
|
||||
}
|
||||
Else
|
||||
{
|
||||
$NewObj.NewName = $CIVM.Name
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user