vm-report.ps1
# vm-report.ps1 - Returns detailed report of vApp/VM replications # Requires PowerCLI, PowerVCAV and must have connected sessions to both # vCD (Connect-CIServer) and VCAV (Connect-VCAV) prior to running this script. param( [string]$OrgName # Optionally filter the results to a single vCloud Organization ) Function ByteUnits($value) { if ($value -lt 1024) { return "$value B" } $value = $value / 1024 if ($value -lt 1024) { return "$([math]::round($value,1)) KB" } $value = $value / 1024 if ($value -lt 1024) { return "$([math]::round($value,1)) MB" } $value = $value / 1024 return "$([math]::round($value,1)) GB" } Function LocalTime($timestamp) { return([timezone]::CurrentTimeZone.ToLocalTime((([System.DateTimeOffset]::FromUnixTimeMilliseconds($timestamp)).DateTime)).ToString()) } $session = Invoke-VCAVQuery -QueryPath 'sessions' if (! ($session.roles -contains 'ADMINISTRATORS')) { Write-Error("Storage report is only available to system administrators.") Exit } $sites = Invoke-VCAVQuery -QueryPath 'sites' $local_site = ($sites | Where-Object { $_.isLocal -eq 'True' }) if (!$local_site) { Write-Error("Unable to determine the local site.") Exit } $diagnostics = Invoke-VCAVQuery -QueryPath 'diagnostics/health' if ($diagnostics.managerHealth.offlineReplicators.Count -gt 0) { Write-Warning("One or more replicators are down. This can render the report incorrect.") } $unique_replications = @{} $replications = Invoke-VCAVPagedQuery -QueryPath 'vm-replications' foreach ($replication in $replications) { if ($OrgName) { if ($replication.destination.org -eq $OrgName) { $unique_replications.Add($replication.id,$replication) } } else { # No Organization specified, include all unique inbound replications: if ($replication.destination.org) { $unique_replications.Add($replication.id,$replication) } } } $reps = @() foreach ($rep in $unique_replications.Values) { $instances = Invoke-VCAVQuery -QueryPath "vm-replications/$($rep.id)/instances" # Calculate average daily xfer size based on recorded instances and RPO # NOTE: This will give innaccurate results during the first 24hrs of # replication due to the generally large size of initial VM sync. $numinstances = $instances.Count $repsperday = (24 / ($rep.settings.rpo / 60)) $totalxfer = ($instances | Measure-Object -Property transferBytes -Sum).Sum $avgxfer = $totalxfer / $numinstances $avgxferday = $avgxfer * $repsperday if ($rep.destinationState.currentRpoViolation -eq 0) { $rpoViolated = "No" } else { $rpoViolated = $rep.destinationState.currentRpoViolation.toString() + " mins" } $repObj = [PSCustomObject]@{ Org = $rep.destination.org Vdc = $rep.destination.vdcname StoragePolicy = $rep.storageProfileName vAppName = $rep.source.vAppName VMName = $rep.vmName RPO = ($rep.settings.rpo).toString() + " mins" Paused = $rep.isPaused RPOviolated = $rpoViolated Quiesced = $rep.settings.quiesced LastStatus = LocalTime($rep.destinationState.latestInstance.timestamp).toString() LastXfer = ByteUnits($rep.destinationState.latestInstance.transferBytes).toString() LastXferTime = ($rep.destinationState.latestInstance.transferSeconds).toString() + " sec" DataConnection = $rep.dataConnectionState Migration = $rep.isMigration overallHealth = $rep.overallHealth Instances = $numinstances AverageXfer = (ByteUnits($avgxferday)).toString() + "/day" SpaceRequired = ByteUnits($rep.destinationState.spaceRequirement) } $reps += $repObj } return $reps |