VMware.Community.VPlus.psm1
Function Connect-VPlus { <# .NOTES =========================================================================== Created by: William Lam Date: 02/06/2023 Organization: VMware Blog: http://www.williamlam.com Twitter: @lamw =========================================================================== .SYNOPSIS Acquire CSP Access Token to interact with vSphere+/vSAN+ Cloud Service .DESCRIPTION This cmdlet creates $global:vplusConnection object containing the vSphere+/vSAN+ URL along with CSP Token .EXAMPLE Connect-VPlus -RefreshToken $RefreshToken -OrgName $OrgName #> Param ( [Parameter(Mandatory=$true)][String]$RefreshToken, [Parameter(Mandatory=$true)][String]$OrgId, [Parameter(Mandatory=$false)][String]$CSPServer="console.cloud.vmware.com", [Parameter(Mandatory=$false)][String]$VMCServer="vmc.vmware.com" ) $requests = Invoke-WebRequest -Uri "https://${CSPServer}/csp/gateway/am/api/auth/api-tokens/authorize" -Method POST -ContentType "application/x-www-form-urlencoded" -Body "refresh_token=$REFRESH_TOKEN&grant_type=refresh_token" if($requests.StatusCode -ne 200) { Write-Host -ForegroundColor Red "Failed to retrieve Access Token, please ensure your VMC Refresh Token is valid and try again" break } $accessToken = ($requests | ConvertFrom-Json).access_token $headers = @{ "csp-auth-token"="$accessToken" "Content-Type"="application/json" "Accept"="application/json" } $global:vplusConnection = new-object PSObject -Property @{ 'csp_server' = $CSPServer 'vmc_server' = $VMCServer 'org_id' = $OrgId 'headers' = $headers } $global:vplusConnection } Function Get-VPlusDeployment { <# .NOTES =========================================================================== Created by: William Lam Date: 02/05/2023 Organization: VMware Blog: http://www.williamlam.com Twitter: @lamw =========================================================================== .SYNOPSIS List all vSphere+/vSAN+ Deployments .DESCRIPTION List all vSphere+/vSAN+ Deployments .EXAMPLE Get-VPlusDeployment .EXAMPLE Get-VPlusDeployment -DeploymentName vc1.onprem.local #> Param ( [Parameter(Mandatory=$False)][String]$DeploymentName, [Parameter(Mandatory=$False)][Boolean]$DemoMode=$false, [Switch]$Troubleshoot ) If (-Not $global:vplusConnection) { Write-error "No vSphere+/vSAN+ Connection found, please use Connect-VPlus" } Else { $method = "GET" $deploymentsURL = "https://" + $global:vplusConnection.vmc_server + "/api/entitlement/v2/orgs/" + $global:vplusConnection.org_id + "/deployments?deployment_entitlement_type=SUBSCRIPTION&deployment_type=VSPHERE,VCF&with_eligibility=false&with_usages=true" if($Troubleshoot) { Write-Host -ForegroundColor cyan "`n[DEBUG] - $METHOD`n$deploymentsURL`n" } try { if($PSVersionTable.PSEdition -eq "Core") { $requests = Invoke-WebRequest -Uri $deploymentsURL -Method $method -Headers $global:vplusConnection.headers -SkipCertificateCheck } else { $requests = Invoke-WebRequest -Uri $deploymentsURL -Method $method -Headers $global:vplusConnection.headers } } catch { if($_.Exception.Response.StatusCode -eq "Unauthorized") { Write-Host -ForegroundColor Red "`nThe vSphere+/vSAN+ session is no longer valid, please re-run the Connect-VPlus cmdlet to retrieve a new token`n" break } else { Write-Error "Error in retrieving vSphere+/vSAN+ deployments" Write-Error "`n($_.Exception.Message)`n" break } } if($requests.StatusCode -eq 200) { $results = ($requests.Content | ConvertFrom-Json).Content if($results -eq $NULL) { break } if ($PSBoundParameters.ContainsKey("DeploymentName")){ $results = $results | where {$_.deployment_name -eq $DeploymentName} } $deployments = @() foreach ($result in $results) { foreach ($usage in $result.subscription_usages) { if($usage.product_id -eq "VSPHERE") { $vsphere_usage = $usage.value } if($usage.product_id -eq "VSAN") { $vsan_usage = $usage.value } } $tmp = [pscustomobject] [ordered]@{ DeploymentId =$Demomode ? ([guid]::NewGuid()) : $result.deployment_id DeploymentName = $DemoMode ? (-join ((48..57) + (97..122) | Get-Random -Count 10 | % {[char]$_})) : $result.deployment_name Vsphere = $vsphere_usage Vsan = $vsan_usage } $deployments+=$tmp } $deployments Write-Host "Total vSphere+ Core Usage: $(($deployments.vsphere | measure -Sum).Sum)" Write-Host "Total vSAN+ Core Usage: $(($deployments.vsan | measure -Sum).Sum)`n" } } } Function Get-VPlusSubscription { <# .NOTES =========================================================================== Created by: William Lam Date: 02/06/2023 Organization: VMware Blog: http://www.williamlam.com Twitter: @lamw =========================================================================== .SYNOPSIS List all vSphere+/vSAN+ Subscriptions .DESCRIPTION List all vSphere+/vSAN+ Subscriptions .EXAMPLE Get-VPlusSubscription .EXAMPLE Get-VPlusSubscription -SubscriptionId AABBCCDD #> Param ( [Parameter(Mandatory=$False)][String]$SubscriptionId, [Parameter(Mandatory=$False)][Boolean]$Summarize=$true, [Switch]$Troubleshoot ) If (-Not $global:vplusConnection) { Write-error "No vSphere+/vSAN+ Connection found, please use Connect-VPlus" } Else { $method = "GET" $subscriptionsURL = "https://" + $global:vplusConnection.vmc_server + "/api/subscription/" + $global:vplusConnection.org_id + "/core/subscriptions" if($Troubleshoot) { Write-Host -ForegroundColor cyan "`n[DEBUG] - $METHOD`n$subscriptionsURL`n" } try { if($PSVersionTable.PSEdition -eq "Core") { $requests = Invoke-WebRequest -Uri $subscriptionsURL -Method $method -Headers $global:vplusConnection.headers -SkipCertificateCheck } else { $requests = Invoke-WebRequest -Uri $subscriptionsURL -Method $method -Headers $global:vplusConnection.headers } } catch { if($_.Exception.Response.StatusCode -eq "Unauthorized") { Write-Host -ForegroundColor Red "`nThe vSphere+/vSAN+ session is no longer valid, please re-run the Connect-VPlus cmdlet to retrieve a new token`n" break } else { Write-Error "Error in retrieving vSphere+/vSAN+ subscriptions" Write-Error "`n($_.Exception.Message)`n" break } } if($requests.StatusCode -eq 200) { $results = ($requests.Content | ConvertFrom-Json).Content if($results -eq $NULL) { break } if ($PSBoundParameters.ContainsKey("SubscriptionId")){ $results = $results | where {$_.display_id -eq $SubscriptionId} } if($Summarize -eq $false) { $results } else { $subscriptions = @() foreach ($result in $results) { # Handle scenario where subscription contains multiple product/services if($result.purchase_quantity -ne -1) { $tmp = [pscustomobject] [ordered]@{ SubscriptionId = $result.display_id Status = $result.Status Quantity = $result.purchase_quantity Units = $result.license_unit_display_name Type = $result.product_display_name Flexible = $result.flexible Seller = $result.seller_of_record BillingOption = $result.billing_frequency_display_name Term = $result.billing_term_display_name Location = $result.location.name | select -First 1 StartDate = $result.subscription_start_date_time EndDate = $result.subscription_end_date_time } $subscriptions+=$tmp } else { foreach ($context in ($result.context|Get-Member -MemberType NoteProperty).Name) { $count,$rest = $result.context.$context -split ' ' $tmp = [pscustomobject] [ordered]@{ SubscriptionId = $result.display_id Status = $result.Status Quantity = $count Units = $result.license_unit_display_name Type = $context Flexible = $result.flexible Seller = $result.seller_of_record BillingOption = $result.billing_frequency_display_name Term = $result.billing_term_display_name Location = $result.location.name | select -First 1 StartDate = $result.subscription_start_date_time EndDate = $result.subscription_end_date_time } $subscriptions+=$tmp } } } $subscriptions } } } } |