Public/Repair-DisasterRecoveryReadiness.ps1

function Repair-DisasterRecoveryReadiness {
    <#
    .SYNOPSIS
        Remediates minor DR readiness violations (e.g., disconnected ISOs, missing CBT).
 
    .DESCRIPTION
        Accepts the [PSCustomObject] from Test-DisasterRecoveryReadiness and safely remediates configuration
        issues on the source VMs that violate DR readiness protocols.
 
    .PARAMETER DRResult
        The validation object(s) generated by Test-DisasterRecoveryReadiness.
 
    .PARAMETER SourceServer
        VIServer connection to the source vCenter to execute the repairs.
 
    .EXAMPLE
        $results = Test-DisasterRecoveryReadiness -SourceServer $src -TargetServer $tgt ...
        $results | Where-Object { -not $_.DRReady } | Repair-DisasterRecoveryReadiness -SourceServer $src
    #>

    [CmdletBinding(SupportsShouldProcess=$true)]
    param(
        [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
        [psobject[]]$DRResult,
        
        [Parameter(Mandatory=$true)]
        $SourceServer
    )
    process {
        $ErrorActionPreference = 'Stop'
        foreach ($res in $DRResult) {
            if (-not $res.DRReady) {
                Write-Verbose "Attempting automated repairs for $($res.VMName)..."
                
                try {
                    $vmView = Get-View -Server $SourceServer -ViewType VirtualMachine -Filter @{"Name"="^$($res.VMName)$"} -Property Config.ChangeTrackingEnabled,Config.Hardware.Device,Runtime.PowerState -ErrorAction Stop
                    
                    if (-not $vmView) {
                        Write-Warning "Could not retrieve VM View for $($res.VMName). Skipping."
                        continue
                    }

                    # 1. Enable CBT
                    if (-not $res.CBTEnabled -and $PSCmdlet.ShouldProcess($res.VMName, "Enable Change Block Tracking (CBT)")) {
                        $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
                        $spec.ChangeTrackingEnabled = $true
                        $vmView.ReconfigVM_Task($spec) | Out-Null
                        Write-Host "[REPAIRED] Enabled CBT for $($res.VMName)" -ForegroundColor Green
                    }
                    
                    # 2. Disconnect Connected ISOs
                    if ($res.StorageBlockers -match "Connected ISO" -and $PSCmdlet.ShouldProcess($res.VMName, "Disconnect Virtual CD-ROM ISO")) {
                        $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
                        $spec.DeviceChange = @()

                        foreach ($dev in $vmView.Config.Hardware.Device) {
                            if ($dev.GetType().Name -eq "VirtualCdrom" -and $dev.Connectable.Connected) {
                                $devSpec = New-Object VMware.Vim.VirtualDeviceConfigSpec
                                $devSpec.Operation = "edit"
                                $devSpec.Device = $dev
                                $devSpec.Device.Connectable.Connected = $false
                                $devSpec.Device.Connectable.StartConnected = $false
                                $spec.DeviceChange += $devSpec
                            }
                        }
                        if ($spec.DeviceChange.Count -gt 0) {
                            $vmView.ReconfigVM_Task($spec) | Out-Null
                            Write-Host "[REPAIRED] Disconnected ISO from $($res.VMName)" -ForegroundColor Green
                        }
                    }

                    # Hard Blockers Warning
                    if ($res.StorageBlockers -match "Physical RDM" -or $res.StorageBlockers -match "Multi-Writer VMDK") {
                        Write-Warning "VM $($res.VMName) has unrepairable Storage Blockers (pRDMs or Multi-Writer). Manual intervention required."
                    }
                }
                catch {
                    Write-Error "Failed to repair $($res.VMName): $($_.Exception.Message)"
                }
            }
            else {
                Write-Verbose "$($res.VMName) is already DR Ready. No repairs needed."
            }
        }
    }
}