Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AVD Alerts v2.2.0 update - docs, sub opt for LAW & AzFiles, bug fixes #315 and #457 #466

Merged
merged 4 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions docs/content/patterns/specialized/avd/Known-Issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ geekdocCollapseSection: true
weight: 100
---

## Host Pool Capacity Remaining not reporting
## VM in Separate Resource Group option fails deployment (Issue #457)
Updated the custom UI definition to no longer hide the AVD Resource Resource Group selection when selecting option for VMs in seperate resource group(s). This will ensure the value is passed into the ARM template for processing verses the previously noted place holder value of 'Resource Group' with brackets.
(Fixed on 12/18/24 - v2.2.0)

## Action Group in subsequent deployment fails (Issue #315)
Action Group creation now gets appended with a unique 13 character value based on the hash of the Subscription Name and current time. This will allow for subsequent deployments to ensure the action group name is unique across subscriptions.
(Fixed on 12/18/24 - v2.1.8)

## Host Pool Capacity Remaining not reporting (Issue #288)
After 3/21/24 there was a permission missing that did not allow the automation account to gather the information.
(Fixed on: 12/10/2024)
(Fixed on: 12/10/2024 - v2.1.7)

Fix without Redeploying:
Simply assigning the identity tied to the Automation Account the Virtual Desktop Reader role on the Resource Group that houses the Host Pools.
Expand Down
4 changes: 4 additions & 0 deletions docs/content/patterns/specialized/avd/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ For information on what's new please refer to the [Releases](https://github.com/

To update your current deployment with the content from the latest release, please refer to the [Update to new release](Update-to-new-Release.md) page.

## 2024-12-18
Bug fixes [(See Known Issues Section)](Known-Issues.md)
Added option to select alternate subscription for Log Analytics and Storage as well as an initial prerequisites note on the first screen.

## 2024-12-10
### After 3/21/2024 Host Pool Capacity Alert Rule would not fire
An issue was discovered where the Automation Account Identity was not being assigned the Virtual Desktop Reader role on the Resource Group hosting all the AVD Resources. Thus, the output of the script was null which yielded no alerts, regardless of what the host pool capacity currently was. There was a condition on the role assignment that was adjusted so that it will be added at deployment.
Expand Down
2 changes: 1 addition & 1 deletion docs/content/patterns/specialized/avd/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ geekdocCollapseSection: true
This solution provides a baseline of alerts for AVD that are disabled by default and for ensuring administrators and staff get meaningful and timely alerts when there are problems related to an AVD deployment. The deployment has been tested in Azure Global and Azure US Government and will incorporate storage alerts for either or both Azure Files and/or Azure Netapp Files. This solution initially was part of the Azure Virtual Desktop Solution Accelerator as a brownfield and moved to this location.

**Current Version:**
v2.1.7 (Dec 10, 2024)
v2.2.0 (Dec 18, 2024)

## Alerts Table

Expand Down
21 changes: 11 additions & 10 deletions patterns/avd/avdArm.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"_generator": {
"name": "bicep",
"version": "0.31.92.45157",
"templateHash": "17094575244347820739"
"templateHash": "9307847103098609977"
}
},
"parameters": {
Expand Down Expand Up @@ -148,21 +148,21 @@
"variables": {
"copy": [
{
"name": "StorAcctRGsAll",
"name": "StorAcctsAll",
"count": "[length(parameters('StorageAccountResourceIds'))]",
"input": "[split(parameters('StorageAccountResourceIds')[copyIndex('StorAcctRGsAll')], '/')[4]]"
"input": "[format('{0},{1}', split(parameters('StorageAccountResourceIds')[copyIndex('StorAcctsAll')], '/')[2], split(parameters('StorageAccountResourceIds')[copyIndex('StorAcctsAll')], '/')[4])]"
}
],
"ActionGroupName": "[format('ag-avdmetrics-{0}-{1}', parameters('Environment'), parameters('Location'))]",
"AlertDescriptionHeader": "Automated AVD Alert Deployment Solution (v2.1.7)\n",
"ActionGroupName": "[format('ag-avdmetrics-{0}-{1}-{2}', parameters('Environment'), parameters('Location'), uniqueString(subscription().displayName, parameters('time')))]",
"AlertDescriptionHeader": "Automated AVD Alert Deployment Solution (v2.2.0)\n",
"AutomationAccountName": "[format('aa-avdmetrics-{0}-{1}-{2}', parameters('Environment'), parameters('Location'), parameters('AlertNamePrefix'))]",
"CloudEnvironment": "[environment().name]",
"ResourceGroupCreate": "[if(equals(parameters('ResourceGroupStatus'), 'New'), true(), false())]",
"RunbookNameGetStorage": "AvdStorageLogData",
"RunbookNameGetHostPool": "AvdHostPoolLogData",
"RunbookScriptGetStorage": "[format('Get-StorAcctInfo.ps1{0}', parameters('_ArtifactsLocationSasToken'))]",
"RunbookScriptGetHostPool": "[format('Get-HostPoolInfo.ps1{0}', parameters('_ArtifactsLocationSasToken'))]",
"StorAcctRGs": "[union(variables('StorAcctRGsAll'), createArray())]",
"StorAcctsSubRGs": "[union(variables('StorAcctsAll'), createArray())]",
"RoleAssignments": {
"DesktopVirtualizationRead": {
"Name": "Desktop-Virtualization-Reader",
Expand Down Expand Up @@ -6879,12 +6879,13 @@
{
"copy": {
"name": "roleAssignment_Storage",
"count": "[length(variables('StorAcctRGs'))]"
"count": "[length(variables('StorAcctsSubRGs'))]"
},
"type": "Microsoft.Resources/deployments",
"apiVersion": "2022-09-01",
"name": "[format('c_StorAcctContrib_{0}', variables('StorAcctRGs')[copyIndex()])]",
"resourceGroup": "[variables('StorAcctRGs')[copyIndex()]]",
"name": "[format('c_StorAcctContrib_{0}', split(variables('StorAcctsSubRGs')[copyIndex()], ',')[1])]",
"subscriptionId": "[split(variables('StorAcctsSubRGs')[copyIndex()], ',')[0]]",
"resourceGroup": "[split(variables('StorAcctsSubRGs')[copyIndex()], ',')[1]]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
Expand All @@ -6904,7 +6905,7 @@
"value": "ServicePrincipal"
},
"resourceGroupName": {
"value": "[variables('StorAcctRGs')[copyIndex()]]"
"value": "[split(variables('StorAcctsSubRGs')[copyIndex()], ',')[1]]"
}
},
"template": {
Expand Down
117 changes: 91 additions & 26 deletions patterns/avd/avdCustomUi.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
}
}
},
{
"name": "infoMessagePrereqs",
"type": "Microsoft.Common.InfoBox",
"visible": true,
"options": {
"text": "This page is for the Subscription and region to deploy the Alerts Solution in. The next page will prompt for alternate subscriptions for Log Analytics if it is NOT within this subscription. You will need to ensure you are deploying with an Account that has full Owner over the Resource Group with this resource to allow the proper role assignments for the Automation Account!",
"style": "Warning"
}
},
{
"name": "HostPoolsApi",
"type": "Microsoft.Solutions.ArmApiControl",
Expand All @@ -42,14 +51,6 @@
"method": "GET",
"path": "[concat(steps('basics').resourceScope.subscription.id, '/providers/Microsoft.Storage/storageAccounts?api-version=2022-09-01')]"
}
},
{
"name": "LogAnalyticsApi",
"type": "Microsoft.Solutions.ArmApiControl",
"request": {
"method": "GET",
"path": "[concat(steps('basics').resourceScope.subscription.id, '/providers/microsoft.operationalinsights/workspaces?api-version=2021-06-01')]"
}
}
]
},
Expand Down Expand Up @@ -250,16 +251,58 @@
"visible": true
},
{
"name": "LogAnalyticsWorkspaceResource",
"type": "Microsoft.Solutions.ResourceSelector",
"label": "Insights Log Analytics Workspace",
"toolTip": "Log Analytics Workspace in which AVD Insigts and diagnostics data resides in.",
"resourceType": "Microsoft.OperationalInsights/workspaces",
"constraints": {
"required": true
},
"infoMessages": [],
"visible": true
"name": "LAWSection",
"type": "Microsoft.Common.Section",
"label": "Log Analytics Selection",
"elements": [
{
"type": "Microsoft.Common.SubscriptionSelector",
"name": "LAWsubscription",
"label": "Log Analytics Subscription",
"resourceProviders": [
"Microsoft.OperationalInsights"
]
},
{
"name": "LogAnalyticsApi",
"type": "Microsoft.Solutions.ArmApiControl",
"request": {
"method": "GET",
"path": "[concat('/subscriptions/', steps('AlertsConfig').LAWSection.LAWsubscription.subscriptionId, '/providers/microsoft.operationalinsights/workspaces?api-version=2021-06-01')]",
"transforms": {
"list": "value[*].{label:name, value:id, description:location}"
}
}
},
{
"name": "LogAnalyticsWorkspaceResource",
"type": "Microsoft.Common.DropDown",
"label": "Insights Log Analytics Workspace NEW",
"toolTip": "Log Analytics Workspace in which AVD Insigts and diagnostics data resides in.",
"placeholder": "",
"defaultValue": "",
"multiselect": false,
"selectAll": false,
"filter": true,
"filterPlaceholder": "Filter items ...",
"multiLine": true,
"defaultDescription": "A value for selection",
"constraints": {
"allowedValues": "[steps('AlertsConfig').LAWSection.LogAnalyticsApi.transformed.list]",
"required": true
},
"visible": true
},
{
"name": "infoMessageLogAnalytics",
"type": "Microsoft.Common.InfoBox",
"visible": true,
"options": {
"text": "The Log Analytics Workspace in which AVD Insights and diagnostics data resides in.",
"style": "Info"
}
}
]
},
{
"name": "optionVMMetrics",
Expand All @@ -283,9 +326,9 @@
"defaultDescription": "A value for selection",
"constraints": {
"allowedValues": "[map(steps('basics').ResGroupsApi.value, (item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.id, '\"}')))]",
"required": "[if(steps('AlertsConfig').optionVMMetrics, false, true)]"
"required": true
},
"visible": "[if(steps('AlertsConfig').optionVMMetrics, false, true)]"
"visible": true
},
{
"name": "HostPools",
Expand Down Expand Up @@ -371,18 +414,40 @@
"type": "Microsoft.Common.Section",
"label": "Azure Files Storage",
"elements": [
{
"type": "Microsoft.Common.SubscriptionSelector",
"name": "StorageSubscription",
"label": "Azure Files Subscription",
"resourceProviders": [
"Microsoft.Storage"
]
},
{
"name": "StorageApi",
"type": "Microsoft.Solutions.ArmApiControl",
"request": {
"method": "GET",
"path": "[concat('/subscriptions/', steps('AlertsConfig').AzFilesStorageSection.StorageSubscription.subscriptionId, '/providers/Microsoft.Storage/storageAccounts?api-version=2023-05-01')]",
"transforms": {
"list": "value[*].{label: name, value: id, description: join(' | ', [sku.name, location])}"
}
}
},
{
"name": "StorageAccountResourceIds",
"type": "Microsoft.Common.DropDown",
"label": "AVD Related Storage Accounts",
"multiselect": true,
"selectAll": true,
"defaultValue": "[]",
"toolTip": "The Storage Accounts that are used for FSLogix or MSIX App attach.",
"filterPlaceholder": "Filter Storage Accounts...",
"placeholder": "",
"defaultValue": "[]",
"multiselect": true,
"selectAll": false,
"filter": true,
"filterPlaceholder": "Filter Storage Accounts ...",
"multiLine": true,
"defaultDescription": "A value for selection",
"constraints": {
"allowedValues": "[map(steps('basics').StorAcctsApi.value, (item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.id, '\"}')))]",
"allowedValues": "[steps('AlertsConfig').AzFilesStorageSection.StorageApi.transformed.list]",
"required": true
},
"visible": true
Expand Down Expand Up @@ -468,7 +533,7 @@
"Environment": "[steps('AlertsConfig').Environment]",
"HostPoolInfo": "[steps('AlertsConfig').hostPoolInfo]",
"HostPools": "[steps('AlertsConfig').HostPools]",
"LogAnalyticsWorkspaceResourceId": "[steps('AlertsConfig').LogAnalyticsWorkspaceResource.id]",
"LogAnalyticsWorkspaceResourceId": "[steps('AlertsConfig').LAWSection.LogAnalyticsWorkspaceResource]",
"ResourceGroupName": "[if(equals(steps('AlertsConfig').ResourceGroupStatus, 'New'), steps('AlertsConfig').resourceGroupNameNew, last(split(steps('AlertsConfig').resourceGroupNameExisting, '/')))]",
"ResourceGroupStatus": "[steps('AlertsConfig').ResourceGroupStatus]",
"StorageAccountResourceIds": "[steps('AlertsConfig').AzFilesStorageSection.StorageAccountResourceIds]",
Expand Down
12 changes: 9 additions & 3 deletions patterns/avd/scripts/Get-StorAcctInfo.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,28 @@ Connect-AzAccount -Identity -Environment $CloudEnvironment | Out-Null
Import-Module -Name 'Az.Accounts'
Import-Module -Name 'Az.Storage'

$SubName = (Get-azSubscription -SubscriptionId ($StorageAccountResourceIDs -split '/')[2]).Name
# $SubName = (Get-azSubscription -SubscriptionId ($StorageAccountResourceIDs -split '/')[2]).Name

# Foreach storage account
Foreach ($storageAcct in $storageAccountResourceIDs) {
$Subscription = Get-azSubscription -SubscriptionId ($storageAcct -split '/')[2]
$SubName = $Subscription.Name

#Get current context and switch if storage in different Subscription
$Context = Get-AzContext
if ($Context.Subscription.Id -ne $Subscription.Id) {Set-AzContext -SubscriptionId $Subscription.Id | Out-Null}

$resourceGroup = ($storageAcct -split '/')[4]
$storageAcctName = ($storageAcct -split '/')[8]
#Write-Host "Working on Storage:" $storageAcctName "in" $resourceGroup
#Write-Output "Working on Storage:" $storageAcctName "in" $SubName " \ " $resourceGroup

# $shares = Get-AzStorageShare -ResourceGroupName $resourceGroup -StorageAccountName $storageAcctName -Name 'profiles' -GetShareUsage
$shares = Get-AzRmStorageShare -ResourceGroupName $ResourceGroup -StorageAccountName $storageAcctName

# Foreach Share
Foreach ($share in $shares) {
$shareName = $share.Name
$share = Get-AzRmStorageShare -ResourceGroupName $ResourceGroup -StorageAccountName $storageAcctName -Name $shareName -GetShareUsage
$share = Get-AzRmStorageShare -ResourceGroupName $ResourceGroup -StorageAccountName $storageAcctName -Name $shareName -GetShareUsage -SubscriptionId $Subscription.Id
#Write-Host "Share: " $shareName
$shareQuota = $share.QuotaGiB #GB
$shareUsageInGB = $share.ShareUsageBytes / 1073741824 # Bytes to GB
Expand Down
16 changes: 8 additions & 8 deletions patterns/avd/templates/deploy.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,17 @@ param ANFVolumeResourceIds array = []

param Tags object = {}

var ActionGroupName = 'ag-avdmetrics-${Environment}-${Location}'
var AlertDescriptionHeader = 'Automated AVD Alert Deployment Solution (v2.1.7)\n' // DESCRIPTION HEADER AND VERSION <-----------------------------
var ActionGroupName = 'ag-avdmetrics-${Environment}-${Location}-${uniqueString(subscription().displayName, time)}'
var AlertDescriptionHeader = 'Automated AVD Alert Deployment Solution (v2.2.0)\n' // DESCRIPTION HEADER AND VERSION <-----------------------------
var AutomationAccountName = 'aa-avdmetrics-${Environment}-${Location}-${AlertNamePrefix}'
var CloudEnvironment = environment().name
var ResourceGroupCreate = ResourceGroupStatus == 'New' ? true : false
var RunbookNameGetStorage = 'AvdStorageLogData'
var RunbookNameGetHostPool = 'AvdHostPoolLogData'
var RunbookScriptGetStorage = 'Get-StorAcctInfo.ps1${_ArtifactsLocationSasToken}'
var RunbookScriptGetHostPool = 'Get-HostPoolInfo.ps1${_ArtifactsLocationSasToken}'
var StorAcctRGsAll = [for item in StorageAccountResourceIds: split(item, '/')[4]]
var StorAcctRGs = union(StorAcctRGsAll, [])
var StorAcctsAll = [for item in StorageAccountResourceIds: '${split(item, '/')[2]},${split(item, '/')[4]}'] //format of SubscriptionId,ResourceGroup
var StorAcctsSubRGs = union(StorAcctsAll, [])
// var UsrManagedIdentityName = 'id-ds-avdAlerts-Deployment'

var RoleAssignments = {
Expand Down Expand Up @@ -2281,15 +2281,15 @@ module roleAssignment_LogAnalytics 'carml/1.3.0/Microsoft.Authorization/roleAssi
// Assign role to Automation Account for Storage Account Contributor to allow Automation Account to gather Storage Statistics
// (Needed for Automation Account)
module roleAssignment_Storage 'carml/1.3.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep' = [
for StorAcctRG in StorAcctRGs: {
scope: resourceGroup(StorAcctRG)
name: 'c_StorAcctContrib_${StorAcctRG}'
for StorAcctInfo in StorAcctsSubRGs: {
scope: resourceGroup(split(StorAcctInfo, ',')[0],split(StorAcctInfo, ',')[1])
name: 'c_StorAcctContrib_${split(StorAcctInfo, ',')[1]}'
params: {
enableDefaultTelemetry: false
principalId: automationAccount.outputs.systemAssignedPrincipalId
roleDefinitionIdOrName: '/providers/Microsoft.Authorization/roleDefinitions/${RoleAssignments.StoreAcctContrib.GUID}'
principalType: 'ServicePrincipal'
resourceGroupName: StorAcctRG
resourceGroupName: split(StorAcctInfo, ',')[1]
}
dependsOn: [
automationAccount
Expand Down
Loading