Private/Checks/Aria/Test-VcfVrslcmDiskSpace.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. # # ============================================================================= #region Aria function ConvertTo-VcfCheckBytes { <# .SYNOPSIS Converts size strings (e.g., '9.8G', '853M') to bytes. .PARAMETER Size The size string to convert. .OUTPUTS [Double] the value in bytes. #> [CmdletBinding()] [OutputType([Double])] Param ( [Parameter(Mandatory = $true)] [String]$Size ) if ([String]::IsNullOrWhiteSpace($Size)) { return 0 } if ($Size -match '^([\d\.]+)\s*([KMGTPE]?B?)$') { $val = [Double]$Matches[1] switch ($Matches[2].ToUpper().TrimEnd('B')) { 'M' { return $val * 1MB } 'G' { return $val * 1GB } 'T' { return $val * 1TB } default { return $val } } } return 0 } function Test-VcfVrslcmDiskSpace { <# .SYNOPSIS Verifies that the root filesystem on the Aria Suite Lifecycle Manager (vRSLCM) appliance has at least 3 GB of free space. .DESCRIPTION Queries mounted filesystems on the vRSLCM appliance using Get-VcfCheckVrslcmConnection and Invoke-VcfCheckVrslcmApi against '/lcm/lcops/api/v2/settings/system-details/disks' (falling back to '/lcm/lcops/api/v2/settings/system-details' if the disks endpoint is unavailable). Evaluates free space on the root volume ('/' or '/root') against a 3.0 GB threshold. Outcome behavior: - Skipped: Returns 'Skipped' if Aria Suite Lifecycle Manager is not deployed in the environment. - Pass: Returns 'Pass' if the root filesystem has at least 3.0 GB of free space. - Warning: Returns 'Warning' if the root filesystem has less than 3.0 GB of free space. - Error: Returns 'Error' if connection to vRSLCM fails, disk endpoints return no data, or size strings cannot be parsed. Constructs a detailed breakdown table ('Rows') of all reported filesystems (Total, Used, UsedPercent), assigning 'Pass'/'Warning' to the root filesystem and 'N/A' to non-root volumes. .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] A single VcfCheck.Result object. #> [CmdletBinding()] [OutputType([PSObject])] Param ( [Parameter(Mandatory = $true)] [PSObject]$Context, [Parameter(Mandatory = $false)] [String]$DisplayName = '' ) $startedAt = Get-Date $checkId = 'vrslcm_disk_space_report' $requiredFreeGB = 3.0 try { $connection = Get-VcfCheckVrslcmConnection -Context $Context } catch { return New-VcfCheckResult -CheckId $checkId -Status Error ` -Exception $_.Exception.Message ` -StartedAt $startedAt -CompletedAt (Get-Date) -DisplayName $DisplayName } if (-not $connection) { return New-VcfCheckResult -CheckId $checkId -Status Skipped ` -Detail 'Aria Suite Lifecycle Manager is not deployed in this environment.' -SkipReasonTag 'vRSLCM not deployed' ` -StartedAt $startedAt -CompletedAt (Get-Date) -DisplayName $DisplayName } try { Write-LogMessage -Type DEBUG -Message "Attempting to query /lcm/lcops/api/v2/settings/system-details/disks endpoint." $disks = Invoke-VcfCheckVrslcmApi -Connection $connection -Path '/lcm/lcops/api/v2/settings/system-details/disks' } catch { Write-LogMessage -Type DEBUG -Message "Disks endpoint failed ($_), falling back to system-details endpoint." try { $systemDetails = Invoke-VcfCheckVrslcmApi -Connection $connection -Path '/lcm/lcops/api/v2/settings/system-details' if ($systemDetails -and $systemDetails.storagePercentage) { $disks = @([PSCustomObject]@{ diskName = '/' storagePercentage = $systemDetails.storagePercentage usedStorage = $systemDetails.usedStorage totalStorage = $systemDetails.totalStorage }) } } catch { return New-VcfCheckResult -CheckId $checkId -Status Error ` -TargetComponent $connection.Fqdn ` -Exception (ConvertTo-VcfCheckFriendlyVrslcmError -Fqdn $connection.Fqdn -ErrorMessage $_.Exception.Message) ` -StartedAt $startedAt -CompletedAt (Get-Date) -DisplayName $DisplayName } } if (-not $disks) { return New-VcfCheckResult -CheckId $checkId -Status Error ` -TargetComponent $connection.Fqdn ` -Exception 'No disk information returned from the API.' ` -StartedAt $startedAt -CompletedAt (Get-Date) -DisplayName $DisplayName } # Normalize disk array handling across API responses and fallback $diskArray = if ($disks.diskStorageDTO) { @($disks.diskStorageDTO) } else { @($disks) } if (-not $diskArray -or $diskArray.Count -eq 0) { return New-VcfCheckResult -CheckId $checkId -Status Error ` -TargetComponent $connection.Fqdn ` -Exception 'No disk storage data found in the API response.' ` -StartedAt $startedAt -CompletedAt (Get-Date) -DisplayName $DisplayName } Write-LogMessage -Type DEBUG -Message "Found $($diskArray.Count) disk(s) from API: $(($diskArray | ForEach-Object { $_.diskName }) -join ', ')" # Identify the root filesystem (accepts either '/root' or '/') $rootDisk = $diskArray | Where-Object { $_.diskName -in @('/root', '/') } | Select-Object -First 1 if (-not $rootDisk) { $availableDisks = ($diskArray | ForEach-Object { $_.diskName }) -join ', ' return New-VcfCheckResult -CheckId $checkId -Status Error ` -TargetComponent $connection.Fqdn ` -Exception "Root filesystem ('/root' or '/') was not found in the disk space report. Available disks: $availableDisks" ` -StartedAt $startedAt -CompletedAt (Get-Date) -DisplayName $DisplayName } # Calculate free space in bytes $totalBytes = ConvertTo-VcfCheckBytes $rootDisk.totalStorage $usedBytes = ConvertTo-VcfCheckBytes $rootDisk.usedStorage if ($totalBytes -gt 0) { if ($usedBytes -gt 0) { $freeBytes = $totalBytes - $usedBytes } elseif ($rootDisk.storagePercentage) { $usedPercent = [double]($rootDisk.storagePercentage -replace '[^\d\.]', '') $freeBytes = $totalBytes * (1 - ($usedPercent / 100)) } else { $freeBytes = 0 } } else { return New-VcfCheckResult -CheckId $checkId -Status Error ` -TargetComponent $connection.Fqdn ` -Exception "Unable to parse total storage size for /root volume ('$($rootDisk.totalStorage)')." ` -StartedAt $startedAt -CompletedAt (Get-Date) -DisplayName $DisplayName } $freeGB = [math]::Round($freeBytes / 1GB, 2) # Return Pass if >= 3GB free, Warning if under 3GB free if ($freeGB -ge $requiredFreeGB) { $status = 'Pass' $detail = "The /root filesystem has $freeGB GB of free space available." } else { $status = 'Warning' $detail = "The /root filesystem has only $freeGB GB of free space available (recommended minimum: $requiredFreeGB GB)." } # Build results table with row-specific status $rows = @($diskArray | ForEach-Object { $isRoot = $_.diskName -in @('/root', '/') $rowStatus = if ($isRoot) { if ($freeGB -ge $requiredFreeGB) { 'Pass' } else { 'Warning' } } else { 'N/A' } [PSCustomObject]@{ Filesystem = $_.diskName Total = $_.totalStorage Used = $_.usedStorage UsedPercent = $_.storagePercentage Status = $rowStatus } }) return New-VcfCheckResult -CheckId $checkId -Status $status ` -TargetComponent $connection.Fqdn -Detail $detail -Rows $rows ` -StartedAt $startedAt -CompletedAt (Get-Date) -DisplayName $DisplayName } #endregion |