Private/Checks/VCenter/Test-VcfVcenterCheckReplication.ps1
|
# Copyright (c) 2026 Broadcom. All Rights Reserved. # Broadcom Confidential. The term "Broadcom" refers to Broadcom Inc. # and/or its subsidiaries. # # ============================================================================= # # SOFTWARE LICENSE AGREEMENT # # Copyright (c) CA, Inc. All rights reserved. # # You are hereby granted a non-exclusive, worldwide, royalty-free license # under CA, Inc.'s copyrights to use, copy, modify, and distribute this # software in source code or binary form for use in connection with CA, Inc. # products. # # This copyright notice shall be included in all copies or substantial # portions of the software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # # ============================================================================= function Test-VcfVcenterCheckReplication { <# .SYNOPSIS Checks for Enhanced Linked Mode (ELM) topology membership and reports vmdir replication health. .DESCRIPTION Queries vmdir replication partners and partner status on each vCenter appliance attached to SDDC Manager via Invoke-VcfApplianceCommand using `/usr/lib/vmware-vmdir/bin/vdcrepadmin`. Evaluates topology membership and replication health: - Pass: Standalone vCenters with no replication partners (not participating in an ELM topology). - Warning: vCenters participating in an ELM topology. Detail reports whether vmdir replication among partners is healthy ("0 changes behind") or degraded. - Skipped: VMware Tools is not running on the target appliance VM. - Error: Appliance command execution fails or errors occur during execution. Executes commands against vCenter appliance VMs via the management vCenter and delegates per-domain result aggregation to New-VcfCheckPerDomainResults. .PARAMETER Context The VcfCheck.Context object. Must already be connected to SDDC Manager. .PARAMETER DisplayName Optional friendly display name for the check result. .OUTPUTS [PSObject[]] Array of per-domain result objects generated by New-VcfCheckPerDomainResults. #> [CmdletBinding()] [OutputType([PSObject])] Param ( [Parameter(Mandatory = $true)] [PSObject]$Context, [Parameter(Mandatory = $false)] [String]$DisplayName = '' ) $startedAt = Get-Date $checkId = 'vcenter_check_replication' $catalogEntry = (Get-VcfCheckCatalog)[$checkId] $displayName = if ([String]::IsNullOrEmpty($DisplayName)) { $catalogEntry.displayName } else { $DisplayName } $validationCriteria = $catalogEntry.validationCriteria $remediation = $catalogEntry.remediation try { $vcenterFqdns = Get-VcfCheckAllVCenterFqdns -Context $Context $managementVCenterFqdn = Get-VcfCheckManagementVCenterFqdn -Context $Context } catch { return New-VcfCheckResult -CheckId $checkId -Area vCenter -Status Error ` -Exception $_.Exception.Message -ValidationCriteria $validationCriteria -Remediation $remediation -StartedAt $startedAt -CompletedAt (Get-Date) -DisplayName $displayName } $outcomes = foreach ($vcenterFqdn in $vcenterFqdns) { $iterationStartedAt = Get-Date $outcome = & { try { Connect-VcfCheckVCenter -Context $Context -Fqdn $managementVCenterFqdn $rootCredential = Get-VcfCheckComponentCredential -Context $Context -ResourceType VCENTER -AccountType USER -Fqdn $vcenterFqdn -Username 'root' $ssoCredential = Get-VcfCheckVCenterSsoCredential -Context $Context -Fqdn $vcenterFqdn $vmName = ($vcenterFqdn -split '\.')[0] $ssoPlainText = ConvertFrom-SecureStringViaBstr -SecureString $ssoCredential.Password try { $partnersResult = Invoke-VcfApplianceCommand -VmName $vmName -Server $managementVCenterFqdn -Credential $rootCredential ` -ScriptText "/usr/lib/vmware-vmdir/bin/vdcrepadmin -f showpartners -h $vcenterFqdn -u administrator -w '$ssoPlainText'" if (-not $partnersResult.Success) { if ($partnersResult.ErrorCategory -eq 'ToolsNotRunning') { $detail = "This check cannot run without VMware Tools running on the target appliance - skipped for now. $($partnersResult.ErrorMessage)" return [PSCustomObject]@{ VCenterFqdn = $vcenterFqdn; Status = 'Skipped'; Detail = $detail; SkipReasonTag = 'VMware Tools not running'; Blocking = $false; Rows = @() } } return [PSCustomObject]@{ VCenterFqdn = $vcenterFqdn; Status = 'Error'; Detail = $partnersResult.ErrorMessage; Blocking = $false; Rows = @() } } if ([String]::IsNullOrWhiteSpace($partnersResult.ScriptOutput)) { return [PSCustomObject]@{ VCenterFqdn = $vcenterFqdn; Status = 'Pass'; Detail = 'No replication partners found - this vCenter is not part of an Enhanced Linked Mode (ELM) topology.'; Blocking = $false; Rows = @() } } $statusResult = Invoke-VcfApplianceCommand -VmName $vmName -Server $managementVCenterFqdn -Credential $rootCredential ` -ScriptText "/usr/lib/vmware-vmdir/bin/vdcrepadmin -f showpartnerstatus -h $vcenterFqdn -u administrator -w '$ssoPlainText'" } finally { Remove-Variable -Name ssoPlainText -ErrorAction SilentlyContinue } if (-not $statusResult.Success) { if ($statusResult.ErrorCategory -eq 'ToolsNotRunning') { $detail = "This check cannot run without VMware Tools running on the target appliance - skipped for now. $($statusResult.ErrorMessage)" return [PSCustomObject]@{ VCenterFqdn = $vcenterFqdn; Status = 'Skipped'; Detail = $detail; SkipReasonTag = 'VMware Tools not running'; Blocking = $false; Rows = @() } } return [PSCustomObject]@{ VCenterFqdn = $vcenterFqdn; Status = 'Error'; Detail = $statusResult.ErrorMessage; Blocking = $false; Rows = @() } } $elmWarning = 'This vCenter is part of an Enhanced Linked Mode (ELM) topology - see Remediation to deactivate it via cmsso-util break-elm before upgrading to VCF 9.x.' if ([String]::IsNullOrWhiteSpace($statusResult.ScriptOutput)) { return [PSCustomObject]@{ VCenterFqdn = $vcenterFqdn; Status = 'Warning'; Detail = "$elmWarning`nshowpartners reported partners but showpartnerstatus returned no output - unable to determine replication health."; Blocking = $false; Rows = @() } } $partnerStatusLines = @($statusResult.ScriptOutput -split "`n" | Where-Object { -not [String]::IsNullOrWhiteSpace($_) }) $rows = @($partnerStatusLines | ForEach-Object { [PSCustomObject]@{ PartnerStatus = $_ } }) $allPartnersHealthy = ($partnerStatusLines | Where-Object { $_ -match 'Partner is \d+ changes behind' }).Count -gt 0 ` -and -not ($partnerStatusLines | Where-Object { $_ -match 'Partner is \d+ changes behind' -and $_ -notmatch 'Partner is 0 changes behind' }) if ($allPartnersHealthy) { return [PSCustomObject]@{ VCenterFqdn = $vcenterFqdn; Status = 'Warning'; Detail = "$elmWarning`nReplication is currently healthy (0 changes behind)."; Blocking = $false; Rows = $rows } } return [PSCustomObject]@{ VCenterFqdn = $vcenterFqdn; Status = 'Warning'; Detail = "$elmWarning`nAdditionally, replication status might not be as expected."; Blocking = $false; Rows = $rows } } catch { return [PSCustomObject]@{ VCenterFqdn = $vcenterFqdn; Status = 'Error'; Detail = $_.Exception.Message; Exception = $_.Exception.Message; Blocking = $false; Rows = @() } } } $outcome | Add-Member -NotePropertyName StartedAt -NotePropertyValue $iterationStartedAt -Force $outcome | Add-Member -NotePropertyName CompletedAt -NotePropertyValue (Get-Date) -Force $outcome } return New-VcfCheckPerDomainResults -Context $Context -PerVCenterOutcome $outcomes -CheckId $checkId -Area vCenter ` -ValidationCriteria $validationCriteria -Remediation $remediation -StartedAt $startedAt -DisplayName $displayName } |