VMware Cloud Community
winsolo
Enthusiast
Enthusiast
Jump to solution

Need help with SRM API InventoryMapping.GetResourcePoolMappings().SecondaryObject[]

I've modified a script according to my needs, which was originally created by @vishu_dear05 . The script does work and produce the intended output.

$credential = Get-Credential
$vCenters = $Global:DefaultVIServers
$report = @()
$row=''

ForEach ($vCenter in $vCenters) {
    $report=@()
    $vCName = $vCenter.Name
    $srmConnection = Connect-SrmServer -Credential $credential -RemoteCredential $credential -Port 443
    $srmApi = $srmConnection.ExtensionData
    $recoveryplans = $srmApi.Recovery.ListPlans()

    ForEach ($recoveryplan in $recoveryplans) {
        $protectionGroups = $recoveryplan.GetInfo().ProtectionGroups

        ForEach ($protectionGroup in $protectionGroups) {
            $protectionGroupInfo = $protectionGroup.GetInfo()
            $recoveryplanInfo =$recoveryplan.GetInfo()
            $vms = $protectionGroup.ListAssociatedVms()
            $vmp = $protectionGroup.ListProtectedVms()

            ForEach ($vm in $vmp) {
                $row = "" | Select-Object VMName, PowerState, VMProtectionState, VMPeerState, VMNeedsConfiguration, ProtectionGroupName, ProtectionGroupState, ProtectionGroupConfigured, RecoveryStatus, RecoveryPriority, SkipGuestShutDown, PowerOnTimeoutSeconds, PowerOnDelaySeconds, PowerOffTimeoutSeconds, FinalPowerState, RecoveryPlanName, DestinationHost, DestinationPort, QuiesceGuestEnabled, Paused, OppUpdatesEnabled, NetCompressionEnabled, NetEncryptionEnabled, ConfiguredDisks, ClusterName, ResourcePoolName, Datastore, RPO, IPAddress, VMtoolStatus, vCenterName
                $vm.Vm.UpdateViewData()
                if(($vm.vm.Config.RepConfig)) {
                    $row.VmName = $vm.vm.Name
                    $row.PowerState = $vm.Vm.Runtime.PowerState
                    $row.VMProtectionState = ($vmp | Where-Object {$_.VmName -eq $vm.vm.Name}).State
                    $row.VMPeerState = ($vmp | Where-Object {$_.VmName -eq $vm.vm.Name}).PeerState
                    $row.VMNeedsConfiguration = ($vmp | Where-Object {$_.VmName -eq $vm.vm.Name}).NeedsConfiguration
                    $row.ProtectionGroupName = $protectionGroupInfo.Name
                    $row.ProtectionGroupState = $protectionGroup.GetProtectionState()
                    $row.ProtectionGroupConfigured = $protectionGroup.CheckConfigured()
                    $ID = (Get-VM -Name $vm.VmName | Where-Object {$_.PowerState -eq "PoweredOn"}).ID
                    $row.RecoveryStatus = $recoveryplan.GetRecoverySettings($ID).Status
                    $row.RecoveryPriority = $recoveryplan.GetRecoverySettings($ID).RecoveryPriority
                    $row.SkipGuestShutDown = $recoveryplan.GetRecoverySettings($ID).SkipGuestShutDown
                    $row.PowerOnTimeoutSeconds = $recoveryplan.GetRecoverySettings($ID).PowerOnTimeoutSeconds
                    $row.PowerOnDelaySeconds = $recoveryplan.GetRecoverySettings($ID).PowerOnDelaySeconds
                    $row.PowerOffTimeoutSeconds = $recoveryplan.GetRecoverySettings($ID).PowerOffTimeoutSeconds
                    $row.FinalPowerState = $recoveryplan.GetRecoverySettings($ID).FinalPowerState
                    $row.RecoveryPlanName = $recoveryplanInfo.Name
                    $row.DestinationHost = $vm.vm.Config.RepConfig.Destination
                    $row.DestinationPort = $vm.vm.Config.RepConfig.Port
                    $row.QuiesceGuestEnabled = $vm.vm.Config.RepConfig.QuiesceGuestEnabled
                    $row.Paused = $vm.vm.Config.RepConfig.Paused
                    $row.OppUpdatesEnabled = $vm.vm.Config.RepConfig.OppUpdatesEnabled
                    $row.NetCompressionEnabled = $vm.vm.Config.RepConfig.NetCompressionEnabled
                    $row.NetEncryptionEnabled = $vm.vm.Config.RepConfig.NetEncryptionEnabled
                    $row.ConfiguredDisks = ($vm.vm.Config.RepConfig.Disk.Key).Count
                    $hostview = Get-view $vm.vm.Runtime.Host
                    $clusview = Get-View $hostview.Parent
                    $row.ClusterName = $clusview.Name
                    $row.ResourcePoolName = (Get-View $vm.Vm.ResourcePool).Name
                    $row.Datastore = $vm.vm.Config.DatastoreUrl.Name
                    $row.RPO = $vm.vm.Config.RepConfig.Rpo
                    $row.IPAddress = $vm.vm.Guest.IpAddress
                    $row.VMtoolStatus = $vm.vm.Guest.ToolsRunningStatus
                    $row.vCenterName = $vCName
                    $report += $row
                }
            }
        }
    }
}
$report | Out-GridView

 

However, I'm struggling to find a way to use the GetResourcePoolMappings Method in the InventoryMapping property, to integrate into the existing script. I'd like to be able to get the "Recovery Resource Pool" of a replica by using the above method.

(Get-View $srmApi.InventoryMapping.GetResourcePoolMappings().SecondaryObject[3]).Name

I'm able to get the desired output by calling the exact Index number in the array. But I'd like the script to get the SecondaryObject[] which contains the Recovery Resource Pool based on the replica VM.

Snag_3810688d.png

1 Solution

Accepted Solutions
winsolo
Enthusiast
Enthusiast
Jump to solution

I've been able to come up with a workaround which has worked the way I needed it. I've come up with a below snippet that's able to give me the "Recovery Network" and the "Recovery Resource Pool name" that's assigned to the replica VM in the recovery site.

 

$row.RecoveryResourcePool = (get-vm -Name $vm.VmName | Where-Object {$_.PowerState -eq "PoweredOff"}).ResourcePool.Name
$array = $srmApi.InventoryMapping.GetNetworkMappings() | ForEach-Object {$i=0} {$_ | Add-Member Index ($i++) -PassThru}
$PrimaryObject = (Get-VirtualPortgroup -Name (Get-NetworkAdapter -VM $vm.VmName).NetworkName).ID[0]
$index = ($array | Where-Object {$_.PrimaryObject -match $PrimaryObject}).Index
$row.RecoveryNetwork = (Get-View ($array[$index]).SecondaryObject[0]).Name

 

Snag_3e400863.png

 

View solution in original post

7 Replies
winsolo
Enthusiast
Enthusiast
Jump to solution

I've been able to come up with a workaround which has worked the way I needed it. I've come up with a below snippet that's able to give me the "Recovery Network" and the "Recovery Resource Pool name" that's assigned to the replica VM in the recovery site.

 

$row.RecoveryResourcePool = (get-vm -Name $vm.VmName | Where-Object {$_.PowerState -eq "PoweredOff"}).ResourcePool.Name
$array = $srmApi.InventoryMapping.GetNetworkMappings() | ForEach-Object {$i=0} {$_ | Add-Member Index ($i++) -PassThru}
$PrimaryObject = (Get-VirtualPortgroup -Name (Get-NetworkAdapter -VM $vm.VmName).NetworkName).ID[0]
$index = ($array | Where-Object {$_.PrimaryObject -match $PrimaryObject}).Index
$row.RecoveryNetwork = (Get-View ($array[$index]).SecondaryObject[0]).Name

 

Snag_3e400863.png

 

vishu_dear05
Contributor
Contributor
Jump to solution

Great! I did read through the SRM API guide to figure out how i can get recovery site details for the VM however was nly able to get references comeing from sRM DB ...
This recovery res pool and recovery network listing you show works being connected only to the Protected Site vCenter  right ? doesn't need a connection to remote site vcenter ? 

 

Reply
0 Kudos
winsolo
Enthusiast
Enthusiast
Jump to solution

The fact that there's no public API available for vSphere Replication, we can only rely on the SRM DB.

For the Recovery Resource Pool, this snippet gets the resource pool name of the replica VM (which is powered off) from the Recovery Site vCenter. Therefore, this works only when the current session is connected to the Recovery site vCenter as well.

$row.RecoveryResourcePool = (get-vm -Name $view.Name | Where-Object {$_.PowerState -eq "PoweredOff"}).ResourcePool.Name

 

 

For the Recovery network, as the replica VM in the Recovery Site vCenter won't have any network assigned, I decided to get the Port group of the protected VM in the Protected site's vCenter and cross check with the protected site's SRM to get the corresponding network mapping, which is the secondary object. Here's the slightly modified snippet (the VM name comes from the $view variable I've created in the beginning of the ForEach loop).

 

$NetMappingArray = ($srmApi.InventoryMapping.GetNetworkMappings()) | ForEach-Object {$i=0} {$_ | Add-Member Index ($i++) -PassThru}
$PrimaryObject = (Get-VirtualPortgroup -Name (Get-NetworkAdapter -VM $view.Name).NetworkName).ID
$index = ($NetMappingArray | Where-Object {$_.PrimaryObject -match $PrimaryObject}).Index
$row.RecoveryNetwork = (Get-View ($NetMappingArray[$index]).SecondaryObject[0]).Name

 

 

Reply
0 Kudos
vishu_dear05
Contributor
Contributor
Jump to solution

Okay Got it.. Thank you very much for the explanation ! 

Reply
0 Kudos
juanmunoz1
Contributor
Contributor
Jump to solution

Hi Am trying to run the script provided but am getting errors. 

$array = $srmApi.InventoryMapping.GetNetworkMappings() | ForEach-Object {$i=0} {$_ | Add-Member Index ($i++) -PassThru}
$PrimaryObject = (Get-VirtualPortgroup -Name (Get-NetworkAdapter -VM $vm.VmName).NetworkName).ID[0]
$index = ($array | Where-Object {$_.PrimaryObject -match $PrimaryObject}).Index
$row.RecoveryNetwork = (Get-View ($array[$index]).SecondaryObject[0]).Name

Get-View : 12/7/2023 9:29:01 AM Get-View View with Id 'OpaqueNetwork-network-o205' was not found on the server(s).
At line:47 char:45
+ ... RecoveryNetwork = (Get-View ($array[$index]).SecondaryObject[0]).Name
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (:) [Get-View], VimException
+ FullyQualifiedErrorId : Core_GetView_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.Ge
tVIView

Reply
0 Kudos
alex134a
Contributor
Contributor
Jump to solution

It seems that the error is occurring because the view with the ID 'OpaqueNetwork-network-o205' cannot be found on the server. This might be due to several reasons such as the view not existing or being inaccessible. Here's a revised version of your script with some suggestions:

```powershell
# Get the network mappings and add an index to each object in the array
$array = $srmApi.InventoryMapping.GetNetworkMappings() | ForEach-Object { $i=0 } { $_ | Add-Member Index $i -PassThru; $i++ }

# Get the ID of the primary object
$PrimaryObject = (Get-VirtualPortgroup -Name (Get-NetworkAdapter -VM $vm.VmName).NetworkName).ID[0]

# Find the index of the matching primary object in the array
$index = ($array | Where-Object { $_.PrimaryObject -match $PrimaryObject }).Index

# Check if the index is valid
if ($index -ge 0 -and $index -lt $array.Count) {
# Get the name of the recovery network from the secondary object at the specified index
$row.RecoveryNetwork = (Get-View ($array[$index]).SecondaryObject[0]).Name
} else {
Write-Host "Error: Index out of range"
}
```

This version includes error handling to check if the index is valid before attempting to access the array element. If the index is out of range, it will display an error message. Additionally, you may want to verify that the ID 'OpaqueNetwork-network-o205' exists and is accessible in the environment.

Reply
0 Kudos
juanmunoz1
Contributor
Contributor
Jump to solution

this is not returning anything.

$PrimaryObject = (Get-VirtualPortgroup -Name (Get-NetworkAdapter -VM $vm.VmName).NetworkName).ID[0]

Reply
0 Kudos