Create Get-AVD-Usage.ps1
This commit is contained in:
Родитель
38e2898126
Коммит
3753302062
|
@ -0,0 +1,278 @@
|
|||
# Global Parameter
|
||||
$TenantIds = @("")
|
||||
$ExcelOutputFolder = "C:\Temp"
|
||||
$ExcelFileName = "AVD-Usage.xlsx" # Export Result to Excel file
|
||||
|
||||
# Script Variable
|
||||
if ($ExcelOutputFolder -notlike "*\") {$ExcelOutputFolder += "\"}
|
||||
$Global:ExcelFullPath = $ExcelOutputFolder + $ExcelFileName
|
||||
$Global:ScalingPlanAssignment = @()
|
||||
$Global:HostPools = @()
|
||||
$Global:HostPoolsSummary = @()
|
||||
$Global:SessionHosts = @()
|
||||
$Global:SessionHostsSummary = @()
|
||||
$Global:VmSizeSummary = @()
|
||||
$Global:Message = @()
|
||||
[int]$CurrentItem = 1
|
||||
$ErrorActionPreference = "Continue"
|
||||
|
||||
function Get-LocationDisplayName {
|
||||
param (
|
||||
[string]$Location
|
||||
)
|
||||
|
||||
if ($Location -like "* *") {
|
||||
return $Location
|
||||
} else {
|
||||
[string]$LocationDisplayName = $Global:NameReference | ? {$_.Location -eq $Location} | select -ExpandProperty DisplayName
|
||||
|
||||
return $LocationDisplayName
|
||||
}
|
||||
}
|
||||
|
||||
# Login and get list of subscription(s)
|
||||
$Global:Subscriptions = @()
|
||||
foreach ($TenantId in $TenantIds) {
|
||||
Connect-AzAccount -TenantId $TenantId
|
||||
$Global:Subscriptions += Get-AzSubscription -TenantId $TenantId | ? {$_.Name -like "*AVD*"} # Retrieve specific subscription(s) where AVD exists
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
$Global:Subscriptions = $Global:Subscriptions | Sort-Object TenantId, Name
|
||||
|
||||
# Disable breaking change warning messages
|
||||
Set-Item Env:\SuppressAzurePowerShellBreakingChangeWarnings -Value "true"
|
||||
|
||||
# Module
|
||||
Import-Module ImportExcel
|
||||
|
||||
# Get the Latest Location Name, Display Name, and Paired Region
|
||||
$Global:NameReference = Get-AzLocation | ? {$_.RegionType -eq "Physical" -and $_.DisplayName -notlike "*EUAP*"} | Sort-Object GeographyGroup, DisplayName
|
||||
|
||||
# Main
|
||||
$Global:StartTime = Get-Date
|
||||
Write-Host ("`n" + "=" * 70)
|
||||
Write-Host "`nCollect the utilization of AVD Host Pool, Scaling Plan Assignment, list of Session Host including Power / Update Status" -ForegroundColor Cyan
|
||||
|
||||
# Get Azure VM Sku
|
||||
$VmSku = Get-AzVMSize -Location "East Asia"
|
||||
|
||||
# Get Scaling Plan
|
||||
foreach ($Subscription in $Global:Subscriptions) {
|
||||
$AzContext = Set-AzContext -SubscriptionId $Subscription.Id -TenantId $Subscription.TenantId
|
||||
$ScalingPlans = Get-AzWvdScalingPlan
|
||||
|
||||
foreach ($ScalingPlan in $ScalingPlans) {
|
||||
if ($ScalingPlan.HostPoolReference.Count -gt 0) {
|
||||
foreach ($Assignment in $ScalingPlan.HostPoolReference) {
|
||||
$obj = New-Object -TypeName PSobject
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "ScalingPlan" -Value $ScalingPlan.Name
|
||||
|
||||
if ($ScalingPlan.Schedule.Name.Count -eq 1) {
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "ScheduleName" -Value $ScalingPlan.Schedule.Name
|
||||
} else {
|
||||
[string]$st = $ScalingPlan.Schedule.Name -join("; ")
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "ScheduleName" -Value ($st)
|
||||
}
|
||||
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "IsEnabled" -Value $Assignment.ScalingPlanEnabled
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "AssignedHostPool" -Value $Assignment.HostPoolArmPath.Split("/")[-1]
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "AssignedHostPoolResourceId" -Value $Assignment.HostPoolArmPath
|
||||
$Global:ScalingPlanAssignment += $obj
|
||||
}
|
||||
} else {
|
||||
$obj = New-Object -TypeName PSobject
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "ScalingPlan" -Value $ScalingPlan.Name
|
||||
|
||||
if ($ScalingPlan.Schedule.Name.Count -eq 1) {
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "ScheduleName" -Value $ScalingPlan.Schedule.Name
|
||||
} else {
|
||||
[string]$st = $ScalingPlan.Schedule.Name -join("; ")
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "ScheduleName" -Value ($st)
|
||||
}
|
||||
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "IsEnabled" -Value "N/A"
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "AssignedHostPool" -Value "N/A"
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "AssignedHostPoolResourceId" -Value "N/A"
|
||||
$Global:ScalingPlanAssignment += $obj
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Collection Information
|
||||
foreach ($Subscription in $Global:Subscriptions) {
|
||||
Write-Host ("`n")
|
||||
Write-Host ("[LOG] " + (Get-Date -Format "yyyy-MM-dd hh:mm")) -ForegroundColor White -BackgroundColor Black
|
||||
|
||||
# Set current subscription
|
||||
$AzContext = Set-AzContext -SubscriptionId $Subscription.Id -TenantId $Subscription.TenantId
|
||||
Write-Host ("`nProcessing " + $CurrentItem + " out of " + $Global:Subscriptions.Count + " Subscription: " + $Subscription.name) -ForegroundColor Yellow
|
||||
$CurrentItem++
|
||||
|
||||
# Get Host Pool
|
||||
$SubscriptionSessionHosts = @()
|
||||
$SubscriptionVmSizeSummary = @()
|
||||
$CurrentHostPools = Get-AzWvdHostPool
|
||||
$Global:HostPools += $CurrentHostPools
|
||||
|
||||
# Get Session Host of each Host Pool
|
||||
foreach ($CurrentHostPool in $CurrentHostPools) {
|
||||
$AvsRG = $CurrentHostPool.Id.Substring($CurrentHostPool.Id.IndexOf("/resourcegroups/") + 16)
|
||||
$AvsRG = $AvsRG.Substring(0, $AvsRG.IndexOf("/providers/Microsoft.DesktopVirtualization/"))
|
||||
$CurrentSessionHosts = Get-AzWvdSessionHost -ResourceGroupName $AvsRG -HostPoolName $CurrentHostPool.Name
|
||||
$SubscriptionSessionHosts += $CurrentSessionHosts
|
||||
Start-Sleep -Seconds 1
|
||||
|
||||
if ($CurrentSessionHosts.Count -gt 0) {
|
||||
# Get Session Host VM Size
|
||||
try {
|
||||
$ExistingHostName = $CurrentSessionHosts[-1].Id.Split("/")[-1]
|
||||
$currentVmInfo = Get-AzVM -ResourceGroupName $CurrentSessionHosts[-1].ResourceId.Split("/")[4] -Name $ExistingHostName.Split(".")[0]
|
||||
[string]$CurrentVmSize = $CurrentVmInfo.HardwareProfile.VmSize
|
||||
$Location = Get-LocationDisplayName -Location $currentVmInfo.Location
|
||||
}
|
||||
catch {
|
||||
Write-Host ($_ | ConvertTo-Json)
|
||||
}
|
||||
|
||||
# vCore
|
||||
[int]$NumberOfCores = $VmSku | ? {$_.Name -eq $CurrentVmSize} | select -ExpandProperty NumberOfCores
|
||||
if ($NumberOfCores -eq 0) {
|
||||
$CurrentVmSize = "Unknown"
|
||||
$msg = "[Error] Unable to retrieve information from Host Pool: " + $($CurrentHostPool.Name)
|
||||
Write-Host ("`n$msg`n") -ForegroundColor Red
|
||||
$Global:Message += $msg
|
||||
}
|
||||
|
||||
# Add Session Host and vCore status to temp array
|
||||
if ($SubscriptionVmSizeSummary.VmSize -notcontains $CurrentVmSize) {
|
||||
$obj = New-Object -TypeName PSobject
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "VmSize" -Value $CurrentVmSize
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "NumberOfCores" -Value $NumberOfCores
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "HostTotal" -Value $CurrentSessionHosts.Count
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "vCoreTotal" -Value ($NumberOfCores * $CurrentSessionHosts.Count)
|
||||
$SubscriptionVmSizeSummary += $obj
|
||||
} else {
|
||||
foreach ($item in $SubscriptionVmSizeSummary) {
|
||||
if ($item.VmSize -eq $CurrentVmSize) {
|
||||
# Calculate Session Host
|
||||
[int]$NewInstanceCount = $item.HostTotal + $CurrentSessionHosts.Count
|
||||
$item.HostTotal = $NewInstanceCount
|
||||
|
||||
# Calculate vCore
|
||||
[int]$NewVCoreCount = $item.vCoreTotal + ($NumberOfCores * $CurrentSessionHosts.Count)
|
||||
$item.vCoreTotal = $NewVCoreCount
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$msg = "[Info] Host Pool: " + $CurrentHostPool.Name + " has " + $CurrentSessionHosts.Count + " Session Host"
|
||||
Write-Host ("`n$msg`n") -ForegroundColor Yellow
|
||||
$Global:Message += $msg
|
||||
}
|
||||
}
|
||||
# Current Subscription Summary
|
||||
Write-Host ("`nSummary of Current Subscription`n" + "-" * 30)
|
||||
Write-Host ($($CurrentHostPools.Count).ToString() + " Host Pool(s)")
|
||||
Write-Host ($($SubscriptionSessionHosts.Count).ToString() + " Session Host(s)")
|
||||
Write-Host ($([int]$SubTotal = 0;$SubscriptionVmSizeSummary | % {$SubTotal += $_.vCoreTotal};$SubTotal).ToString() + " vCore(s)")
|
||||
$SubscriptionVmSizeSummary = $SubscriptionVmSizeSummary | Sort-Object VmSize
|
||||
$SubscriptionVmSizeSummary | ft -AutoSize
|
||||
|
||||
# Add to Global Array
|
||||
$Global:SessionHosts += $SubscriptionSessionHosts
|
||||
|
||||
foreach ($item in $SubscriptionVmSizeSummary) {
|
||||
if ($Global:VmSizeSummary.VmSize -notcontains $item.VmSize) {
|
||||
$obj = New-Object -TypeName PSobject
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "VmSize" -Value $item.VmSize
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "NumberOfCores" -Value $item.NumberOfCores
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "HostTotal" -Value $item.HostTotal
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "vCoreTotal" -Value $item.vCoreTotal
|
||||
$Global:VmSizeSummary += $obj
|
||||
} else {
|
||||
# Calculate Session Host
|
||||
$NewHost = $($Global:VmSizeSummary | ? {$_.VmSize -eq $item.VmSize}).HostTotal
|
||||
$NewHost += $item.HostTotal
|
||||
$($Global:VmSizeSummary | ? {$_.VmSize -eq $item.VmSize}).HostTotal = $NewHost
|
||||
|
||||
# Calculate vCore
|
||||
$NewCore = $($Global:VmSizeSummary | ? {$_.VmSize -eq $item.VmSize}).vCoreTotal
|
||||
$NewCore += $item.vCoreTotal
|
||||
$($Global:VmSizeSummary | ? {$_.VmSize -eq $item.VmSize}).vCoreTotal = $NewCore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Export
|
||||
Write-Host ("`nTotal`n" + "-" * 70)
|
||||
Write-Host ($($Global:HostPools.Count).ToString() + " Host Pool(s)")
|
||||
Write-Host ($($Global:SessionHosts.Count).ToString() + " Session Host(s)")
|
||||
Write-Host ($([int]$SubTotal = 0;$Global:VmSizeSummary | % {$SubTotal += $_.vCoreTotal};$SubTotal).ToString() + " vCore(s)")
|
||||
|
||||
# Provisioning and Utilization
|
||||
$Global:VmSizeSummary = $Global:VmSizeSummary | Sort-Object VmSize
|
||||
$Global:VmSizeSummary | ft -AutoSize
|
||||
$Global:VmSizeSummary | Export-Excel -Path $Global:ExcelFullPath -WorksheetName "AVD_Utilization" -TableName "AVD_Utilization" -TableStyle Medium16 -AutoSize -Append
|
||||
|
||||
# Session Hosts Power Status
|
||||
$Global:SessionHosts | group Status | select Name, Count | Sort-Object Name | Export-Excel -Path $Global:ExcelFullPath -WorksheetName "PowerStatus" -TableName "PowerStatus" -TableStyle Medium16 -AutoSize -Append
|
||||
|
||||
# Session Hosts Update Error
|
||||
$Global:SessionHosts | group UpdateErrorMessage | select Name, Count | ? {$_.Name -ne "" -and $_.Name -ne $null} | Sort-Object Name | Export-Excel -Path $Global:ExcelFullPath -WorksheetName "UpdateErrorMessage" -TableName "UpdateErrorMessage" -TableStyle Medium16 -AutoSize -Append
|
||||
|
||||
# Host Pools
|
||||
foreach ($item in $Global:HostPools) {
|
||||
|
||||
$AssignedScalingPlan = $Global:ScalingPlanAssignment | ? {$_.AssignedHostPoolResourceId -eq $item.Id} | select -ExpandProperty ScalingPlan
|
||||
if ($AssignedScalingPlan -eq $null) {
|
||||
$AssignedScalingPlan = "N/A"
|
||||
$ScalingPlanSchedule = "N/A"
|
||||
} else {
|
||||
$ScalingPlanSchedule = $Global:ScalingPlanAssignment | ? {$_.AssignedHostPoolResourceId -eq $item.Id} | select -ExpandProperty ScheduleName
|
||||
}
|
||||
|
||||
$obj = New-Object -TypeName PSobject
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "HostPool" -Value $item.Name
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "FriendlyName" -Value $item.FriendlyName
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "HostPoolType" -Value $item.HostPoolType
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "LoadBalancerType" -Value $item.LoadBalancerType
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "Location" -Value (Get-LocationDisplayName -Location $item.Location)
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "MaxSessionLimit" -Value $item.MaxSessionLimit
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "AssignedScalingPlan" -Value $AssignedScalingPlan
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "ScalingPlanSchedule" -Value $ScalingPlanSchedule
|
||||
$Global:HostPoolsSummary += $obj
|
||||
}
|
||||
|
||||
$Global:HostPoolsSummary | Sort-Object HostPool | Export-Excel -Path $Global:ExcelFullPath -WorksheetName "HostPool" -TableName "HostPool" -TableStyle Medium16 -AutoSize -Append
|
||||
|
||||
# Scaling Plan Assignment
|
||||
$Global:ScalingPlanAssignment | Sort-Object AssignedHostPoolResourceId, ScalingPlan | Export-Excel -Path $Global:ExcelFullPath -WorksheetName "ScalingPlan" -TableName "ScalingPlan" -TableStyle Medium16 -AutoSize -Append
|
||||
|
||||
# Section Hosts Full List with Power Status
|
||||
foreach ($item in $Global:SessionHosts) {
|
||||
$obj = New-Object -TypeName PSobject
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "SubscriptionName" -Value ($Global:Subscriptions | ? {$_.Id -eq $item.ResourceId.Split("/")[2]} | select -ExpandProperty Name)
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "SubscriptionId" -Value $item.ResourceId.Split("/")[2]
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "HostPool" -Value $item.Name.Split("/")[0]
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "SessionHost" -Value $item.ResourceId.Split("/")[-1]
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "OSVersion" -Value $item.OSVersion
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "Status" -Value $item.Status
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "StatusTimestamp" -Value $item.StatusTimestamp
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "UpdateState" -Value $item.UpdateState
|
||||
Add-Member -InputObject $obj -MemberType NoteProperty -Name "UpdateErrorMessage" -Value $item.UpdateErrorMessage
|
||||
$Global:SessionHostsSummary += $obj
|
||||
}
|
||||
|
||||
$Global:SessionHostsSummary | Sort-Object SubscriptionName, HostPool, SessionHost | Export-Excel -Path $Global:ExcelFullPath -WorksheetName "SessionHost" -TableName "SessionHost" -TableStyle Medium16 -AutoSize -Append
|
||||
|
||||
# Log
|
||||
$Global:Message | Export-Excel -Path $Global:ExcelFullPath -WorksheetName "Log" -TableName "Log" -TableStyle Medium16 -AutoSize -Append
|
||||
|
||||
# End
|
||||
Write-Host ("`n[LOG] " + (Get-Date -Format "yyyy-MM-dd hh:mm")) -ForegroundColor White -BackgroundColor Black
|
||||
Write-Host "`nCompleted"
|
||||
$Global:EndTime = Get-Date
|
||||
$Duration = $Global:EndTime - $Global:StartTime
|
||||
Write-Host ("`nTotal Process Time: " + $Duration.Hours + " Hours " + $Duration.Minutes + " Minutes " + $Duration.Seconds + " Seconds") -ForegroundColor Blue -BackgroundColor Black
|
||||
Start-Sleep -Seconds 1
|
||||
Write-Host "`n"
|
Загрузка…
Ссылка в новой задаче