Public/cloud-host.ps1
|
function Get-CloudHost { <# .SYNOPSIS Gets hosts from the Cloud Server. .DESCRIPTION Retrieves a list of hosts. Automatically handles token refresh. .PARAMETER Name Optional. Filter by host name. .PARAMETER ID Optional. Filter by host ID .EXAMPLE # Get all hosts Get-CloudHost .EXAMPLE # Get a host by specifying an ID Get-CloudHost -ID 5 .EXAMPLE # Get hosts that match the specified name string Get-CloudHost -Name si-overlapped-2 #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$Name, [Parameter(Mandatory = $false)] [int]$ID ) # Build the URI #$uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/metal/host" $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/host" # Filter by ID if specified if ($ID) { #$hosturi = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/host/${ID}" $hosturi = "$uri/${ID}" $response = Invoke-CloudApiRequest -Uri $hosturi -Method Get # Extract host from the response $host = $response.host # Likely singular when querying by ID return $host } else { # Use the helper function which handles token refresh automatically $response = Invoke-CloudApiRequest -Uri $uri -Method Get # Extract hosts from the response $hosts = $response.hosts # Filter by name if specified if ($Name) { $hosts = $hosts | Where-Object { $_.name -like "*$Name*" } } return $hosts } } function Get-CloudCluster { <# .SYNOPSIS Gets Clusters from the Cloud Server. .DESCRIPTION Retrieves a list of Clusters. Automatically handles token refresh. .PARAMETER Name Optional. Filter by Cluster name. .PARAMETER ID Optional. Filter by Cluster ID .EXAMPLE # Get all clusters Get-CloudCluster .EXAMPLE # Get a specific cluster by ID Get-CloudCluster -ID 5 .EXAMPLE # Get clusters that match the specified name string Get-CloudCluster -Name "default" #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$Name, [Parameter(Mandatory = $false)] [int]$ID ) # Build the URI $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/cluster" # Filter by ID if specified if ($ID) { $Clusteruri = "$uri/${ID}" $response = Invoke-CloudApiRequest -Uri $Clusteruri -Method Get # Extract Cluster from the response $Cluster = $response.Cluster # Likely singular when querying by ID return $Cluster } else { # Use the helper function which handles token refresh automatically $response = Invoke-CloudApiRequest -Uri $uri -Method Get # Extract Clusters from the response $Clusters = $response.Cluster # Filter by name if specified if ($Name) { $Clusters = $Clusters | Where-Object { $_.name -like "*$Name*" } } return $Clusters } } function Get-CloudDatacenter { <# .SYNOPSIS Gets Datacenters from the Cloud Server. .DESCRIPTION Retrieves a list of Datacenters. Automatically handles token refresh. .PARAMETER Name Optional. Filter by Datacenter name. .PARAMETER ID Optional. Filter by Datacenter ID .EXAMPLE # Get all datacenters Get-CloudDatacenter .EXAMPLE # Get a specific datacenter by ID Get-CloudDatacenter -ID 5 .EXAMPLE # Get datacenters that match the specified name string Get-CloudDatacenter -Name "default" #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$Name, [Parameter(Mandatory = $false)] [int]$ID ) # Build the URI $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/datacenter" # Filter by ID if specified if ($ID) { $Datacenteruri = "$uri/${ID}" $response = Invoke-CloudApiRequest -Uri $Datacenteruri -Method Get # Extract Datacenter from the response $Datacenter = $response.Datacenter # Likely singular when querying by ID return $Datacenter } else { # Use the helper function which handles token refresh automatically $response = Invoke-CloudApiRequest -Uri $uri -Method Get # Extract Datacenters from the response $Datacenters = $response.Datacenters # Filter by name if specified if ($Name) { $Datacenters = $Datacenters | Where-Object { $_.name -like "*$Name*" } } return $Datacenters } } function Get-CloudCompute { <# .SYNOPSIS Gets compute-only from the Cloud Server. Try Get-CloudHost to return all hosts .DESCRIPTION Retrieves a list of computes. Automatically handles token refresh. .PARAMETER Name Optional. Filter by compute name. .PARAMETER ID Optional. Filter by compute ID .EXAMPLE # Get all compute hosts Get-CloudCompute .EXAMPLE # Get a specific compute host by ID Get-CloudCompute -ID 5 .EXAMPLE # Get compute hosts that match the specified name string Get-CloudCompute -Name "si-overlapped-2" #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$Name, [Parameter(Mandatory = $false)] [int]$ID ) # Build the URI #$uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/metal/compute" $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/compute" # Filter by ID if specified if ($ID) { #$computeuri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/compute/${ID}" $computeuri = "$uri/${ID}" $response = Invoke-CloudApiRequest -Uri $computeuri -Method Get # Extract compute from the response $compute = $response#.compute # Likely singular when querying by ID return $compute } else { # Use the helper function which handles token refresh automatically $response = Invoke-CloudApiRequest -Uri $uri -Method Get # Extract computes from the response $computes = $response#.computes # Filter by name if specified if ($Name) { $computes = $computes | Where-Object { $_.name -like "*$Name*" } } return $computes } } function Get-CloudHostPerformance { <# .SYNOPSIS Gets and displays host performance metrics from the Cloud Server. .DESCRIPTION Retrieves host performance metrics with optional graphical display. Shows CPU and memory utilization with visual percentage graphs. Automatically handles token refresh. .PARAMETER Graph Optional. Display metrics with visual percentage graphs .PARAMETER Seconds Optional. Value in seconds to collect metrics - i.e. 60 will pull stats for the past minute .PARAMETER ID Optional. Filter by host ID .PARAMETER GroupByHost Optional. When using -Graph, group results by host ID and show average utilization .PARAMETER GB Display memory in Gigabytes (default) .PARAMETER TB Display memory in Terabytes .EXAMPLE # Get host performance Get-CloudHostPerformance .EXAMPLE # Get host performance displayed graphically Get-CloudHostPerformance -Graph .EXAMPLE # Get host performance displayed graphically for a specific host Get-CloudHostPerformance -Graph -ID 5 .EXAMPLE # Get host performance displayed graphically for the a specified time period only Get-CloudHostPerformance -Seconds 90 -Graph .EXAMPLE # Get host performance displayed graphically and average the per-host values out over the time period Get-CloudHostPerformance -Seconds 60 -Graph -GroupByHost .EXAMPLE # Get host performance displayed graphically and change the display units Get-CloudHostPerformance -Graph -TB #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [switch]$Graph, [Parameter(Mandatory = $false)] [int]$Seconds, [Parameter(Mandatory = $false)] [int]$ID, [Parameter(Mandatory = $false)] [switch]$GroupByHost, [Parameter(Mandatory = $false)] [switch]$GB, [Parameter(Mandatory = $false)] [switch]$TB ) # Get monitoring data using the existing function $monitoringParams = @{} if ($PSBoundParameters.ContainsKey('Seconds')) { $monitoringParams['Seconds'] = $Seconds } if ($PSBoundParameters.ContainsKey('ID')) { $monitoringParams['ID'] = $ID } $monitoring = Get-CloudHostMonitoring @monitoringParams if (-not $monitoring) { Write-Warning "No monitoring data returned" return } # Determine target unit and conversion factor $targetUnit = "GB" # Default to GB $conversionFactors = @{ 'GB' = @{ fromKB = 1/1048576; label = 'GB'; decimals = 2; format = 'N2' } 'TB' = @{ fromKB = 1/1073741824; label = 'TB'; decimals = 4; format = 'N4' } } if ($TB) { $targetUnit = 'TB' } $unitConfig = $conversionFactors[$targetUnit] if ($Graph) { Write-Host ("=" * 70) if ($GroupByHost) { # Group by host and calculate averages $grouped = $monitoring | Group-Object -Property id foreach ($group in $grouped | Sort-Object Name) { $hostId = $group.Name $samples = $group.Group # Calculate averages $avgUsedCpu = ($samples.capacity.used_cpu | Measure-Object -Average).Average $avgFreeCpu = ($samples.capacity.free_cpu | Measure-Object -Average).Average $avgUsedMemory = ($samples.capacity.used_memory | Measure-Object -Average).Average $avgFreeMemory = ($samples.capacity.free_memory | Measure-Object -Average).Average $totalCpu = $avgUsedCpu + $avgFreeCpu $totalMemory = $avgUsedMemory + $avgFreeMemory # Calculate percentages $cpuPercent = if ($totalCpu -gt 0) { [math]::Round(($avgUsedCpu / $totalCpu) * 100) } else { 0 } $memPercent = if ($totalMemory -gt 0) { [math]::Round(($avgUsedMemory / $totalMemory) * 100) } else { 0 } # Convert memory values $usedMemConverted = [math]::Round($avgUsedMemory * $unitConfig.fromKB, $unitConfig.decimals) $totalMemConverted = [math]::Round($totalMemory * $unitConfig.fromKB, $unitConfig.decimals) Write-Host "`nHost ID: $hostId (averaged over $($samples.Count) sample$(if($samples.Count -ne 1){'s'}))" -ForegroundColor Cyan # CPU Graph Write-Host " cpu " -NoNewline Show-PercentageGraph -percent $cpuPercent $cpuDisplay = " - {0,8:N0} / {1,8:N0} threads" -f $avgUsedCpu, $totalCpu Write-Host $cpuDisplay # Memory Graph Write-Host " memory " -NoNewline Show-PercentageGraph -percent $memPercent $memDisplay = " - {0} / {1} {2}" -f ("{0:$($unitConfig.format)}" -f $usedMemConverted), ("{0:$($unitConfig.format)}" -f $totalMemConverted), $unitConfig.label Write-Host $memDisplay } } else { # Show individual snapshots foreach ($sample in $monitoring) { # Convert Unix timestamp to DateTime (PowerShell 5.1 compatible) $timestamp = if ($sample.timestamp) { $origin = New-Object DateTime(1970, 1, 1, 0, 0, 0, [DateTimeKind]::Utc) $origin.AddSeconds($sample.timestamp).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") } else { "Unknown" } $totalCpu = $sample.capacity.used_cpu + $sample.capacity.free_cpu $totalMemory = $sample.capacity.used_memory + $sample.capacity.free_memory # Calculate percentages $cpuPercent = if ($totalCpu -gt 0) { [math]::Round(($sample.capacity.used_cpu / $totalCpu) * 100) } else { 0 } $memPercent = if ($totalMemory -gt 0) { [math]::Round(($sample.capacity.used_memory / $totalMemory) * 100) } else { 0 } # Convert memory values $usedMemConverted = [math]::Round($sample.capacity.used_memory * $unitConfig.fromKB, $unitConfig.decimals) $totalMemConverted = [math]::Round($totalMemory * $unitConfig.fromKB, $unitConfig.decimals) Write-Host "`nHost ID: $($sample.id) | Time: $timestamp" -ForegroundColor Cyan # CPU Graph Write-Host " cpu " -NoNewline Show-PercentageGraph -percent $cpuPercent $cpuDisplay = " - {0,8:N0} / {1,8:N0} threads" -f $sample.capacity.used_cpu, $totalCpu Write-Host $cpuDisplay # Memory Graph Write-Host " memory " -NoNewline Show-PercentageGraph -percent $memPercent $memDisplay = " - {0} / {1} {2}" -f ("{0:$($unitConfig.format)}" -f $usedMemConverted), ("{0:$($unitConfig.format)}" -f $totalMemConverted), $unitConfig.label Write-Host $memDisplay } } Write-Host "" } else { # Return normal object output return $monitoring } } function Get-CloudHostMonitoring { <# .SYNOPSIS Gets host metrics from the Cloud Server. .DESCRIPTION Retrieves host metrics. Automatically handles token refresh. .PARAMETER Seconds Optional. Value in seconds to collect metrics - i.e. 60 will pull stats for the past minute .PARAMETER ID Optional. Filter by host ID .PARAMETER Graph Optional. Display metrics with visual percentage graphs .PARAMETER GroupByHost Optional. When using -Graph, group results by host ID and show average utilization .PARAMETER ExportCSV Optional. Path to export the monitoring data as a CSV file. Data will be flattened for CSV format. .PARAMETER GB Display memory in Gigabytes (default) .PARAMETER TB Display memory in Terabytes .EXAMPLE # Get host metrics for all hosts Get-CloudHostMonitoring .EXAMPLE # Get host metrics for a specific host Get-CloudHostMonitoring -ID 5 .EXAMPLE # Get host metrics for a specific period of time Get-CloudHostMonitoring -Seconds 90 .EXAMPLE # Get host metrics for all hosts for a specific period of time and graph them Get-CloudHostMonitoring -Seconds 90 -Graph .EXAMPLE # Get host metrics for all hosts for a specific period of time, average the metrics out per-host, and graph them Get-CloudHostMonitoring -Seconds 300 -Graph -GroupByHost .EXAMPLE # Get host metrics for a specific host for a specific period of time and graph them Get-CloudHostMonitoring -Seconds 60 -ID 5 -Graph .EXAMPLE # Get all most metrics for the past 5 minutes and export them to CSV Get-CloudHostMonitoring -Seconds 300 -ExportCSV "C:\Temp\host-monitoring.csv" .EXAMPLE # Get most metrics for a certain host, for the past hour and export them to CSV Get-CloudHostMonitoring -Seconds 3600 -ID 2 -ExportCSV "C:\Temp\host2-monitoring.csv" #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [int]$Seconds, [Parameter(Mandatory = $false)] [int]$ID, [Parameter(Mandatory = $false)] [switch]$Graph, [Parameter(Mandatory = $false)] [switch]$GroupByHost, [Parameter(Mandatory = $false)] [string]$ExportCSV, [Parameter(Mandatory = $false)] [switch]$GB, [Parameter(Mandatory = $false)] [switch]$TB ) # Build base URI based on parameters if ($PSBoundParameters.ContainsKey('Seconds')) { # If Seconds is specified, always use the monitoring endpoint with seconds param $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/host/monitoring?seconds=$Seconds" } elseif ($PSBoundParameters.ContainsKey('ID')) { # If only ID is specified (no Seconds), use the specific host monitoring endpoint $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/host/$ID/monitoring" } else { # No parameters - get all monitoring data $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/host/monitoring" } Write-Verbose "Request URI: $uri" # Use the helper function which handles token refresh automatically $response = Invoke-CloudApiRequest -Uri $uri -Method Get # Extract monitoring data from the response $monitoring = $response.monitoring # If both Seconds and ID were specified, filter the results if ($PSBoundParameters.ContainsKey('Seconds') -and $PSBoundParameters.ContainsKey('ID')) { $monitoring = $monitoring | Where-Object { $_.id -eq $ID } } # Handle CSV export if requested if ($PSBoundParameters.ContainsKey('ExportCSV')) { # Flatten the nested objects for CSV export $flattenedData = $monitoring | ForEach-Object { # Convert Unix timestamp to readable format $readableTime = if ($_.timestamp) { $origin = New-Object DateTime(1970, 1, 1, 0, 0, 0, [DateTimeKind]::Utc) $origin.AddSeconds($_.timestamp).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") } else { "Unknown" } [PSCustomObject]@{ Timestamp = $_.timestamp DateTime = $readableTime HostID = $_.id FreeCPU = $_.capacity.free_cpu UsedCPU = $_.capacity.used_cpu TotalCPU = $_.capacity.free_cpu + $_.capacity.used_cpu CPUUsagePercent = if (($_.capacity.free_cpu + $_.capacity.used_cpu) -gt 0) { [math]::Round(($_.capacity.used_cpu / ($_.capacity.free_cpu + $_.capacity.used_cpu)) * 100, 2) } else { 0 } FreeMemoryKB = $_.capacity.free_memory UsedMemoryKB = $_.capacity.used_memory TotalMemoryKB = $_.capacity.free_memory + $_.capacity.used_memory MemoryUsagePercent = if (($_.capacity.free_memory + $_.capacity.used_memory) -gt 0) { [math]::Round(($_.capacity.used_memory / ($_.capacity.free_memory + $_.capacity.used_memory)) * 100, 2) } else { 0 } NetworkRX = $_.system.netrx NetworkTX = $_.system.nettx } } # Export to CSV try { $flattenedData | Export-Csv -Path $ExportCSV -NoTypeInformation Write-Host "Successfully exported $($flattenedData.Count) record(s) to: $ExportCSV" -ForegroundColor Green } catch { Write-Error "Failed to export CSV: $_" } # Return nothing to avoid screen output return } # Handle graphing if requested if ($Graph) { # Determine target unit and conversion factor $targetUnit = "GB" # Default to GB $conversionFactors = @{ 'GB' = @{ fromKB = 1/1048576; label = 'GB'; decimals = 2; format = 'N2' } 'TB' = @{ fromKB = 1/1073741824; label = 'TB'; decimals = 4; format = 'N4' } } if ($TB) { $targetUnit = 'TB' } $unitConfig = $conversionFactors[$targetUnit] Write-Host ("=" * 70) if ($GroupByHost) { # Group by host and calculate averages $grouped = $monitoring | Group-Object -Property id foreach ($group in $grouped | Sort-Object Name) { $hostId = $group.Name $samples = $group.Group # Calculate averages $avgUsedCpu = ($samples.capacity.used_cpu | Measure-Object -Average).Average $avgFreeCpu = ($samples.capacity.free_cpu | Measure-Object -Average).Average $avgUsedMemory = ($samples.capacity.used_memory | Measure-Object -Average).Average $avgFreeMemory = ($samples.capacity.free_memory | Measure-Object -Average).Average $totalCpu = $avgUsedCpu + $avgFreeCpu $totalMemory = $avgUsedMemory + $avgFreeMemory # Calculate percentages $cpuPercent = if ($totalCpu -gt 0) { [math]::Round(($avgUsedCpu / $totalCpu) * 100) } else { 0 } $memPercent = if ($totalMemory -gt 0) { [math]::Round(($avgUsedMemory / $totalMemory) * 100) } else { 0 } # Convert memory values $usedMemConverted = [math]::Round($avgUsedMemory * $unitConfig.fromKB, $unitConfig.decimals) $totalMemConverted = [math]::Round($totalMemory * $unitConfig.fromKB, $unitConfig.decimals) Write-Host "`nHost ID: $hostId (averaged over $($samples.Count) sample$(if($samples.Count -ne 1){'s'}))" -ForegroundColor Cyan # CPU Graph Write-Host " cpu " -NoNewline Show-PercentageGraph -percent $cpuPercent $cpuDisplay = " - {0,8:N0} / {1,8:N0} threads" -f $avgUsedCpu, $totalCpu Write-Host $cpuDisplay # Memory Graph Write-Host " memory " -NoNewline Show-PercentageGraph -percent $memPercent $memDisplay = " - {0} / {1} {2}" -f ("{0:$($unitConfig.format)}" -f $usedMemConverted), ("{0:$($unitConfig.format)}" -f $totalMemConverted), $unitConfig.label Write-Host $memDisplay } } else { # Show individual snapshots foreach ($sample in $monitoring) { # Convert Unix timestamp to DateTime (PowerShell 5.1 compatible) $timestamp = if ($sample.timestamp) { $origin = New-Object DateTime(1970, 1, 1, 0, 0, 0, [DateTimeKind]::Utc) $origin.AddSeconds($sample.timestamp).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") } else { "Unknown" } $totalCpu = $sample.capacity.used_cpu + $sample.capacity.free_cpu $totalMemory = $sample.capacity.used_memory + $sample.capacity.free_memory # Calculate percentages $cpuPercent = if ($totalCpu -gt 0) { [math]::Round(($sample.capacity.used_cpu / $totalCpu) * 100) } else { 0 } $memPercent = if ($totalMemory -gt 0) { [math]::Round(($sample.capacity.used_memory / $totalMemory) * 100) } else { 0 } # Convert memory values $usedMemConverted = [math]::Round($sample.capacity.used_memory * $unitConfig.fromKB, $unitConfig.decimals) $totalMemConverted = [math]::Round($totalMemory * $unitConfig.fromKB, $unitConfig.decimals) Write-Host "`nHost ID: $($sample.id) | Time: $timestamp" -ForegroundColor Cyan # CPU Graph Write-Host " cpu " -NoNewline Show-PercentageGraph -percent $cpuPercent $cpuDisplay = " - {0,8:N0} / {1,8:N0} threads" -f $sample.capacity.used_cpu, $totalCpu Write-Host $cpuDisplay # Memory Graph Write-Host " memory " -NoNewline Show-PercentageGraph -percent $memPercent $memDisplay = " - {0} / {1} {2}" -f ("{0:$($unitConfig.format)}" -f $usedMemConverted), ("{0:$($unitConfig.format)}" -f $totalMemConverted), $unitConfig.label Write-Host $memDisplay } } Write-Host "" } else { # Return normal object output return $monitoring } } |