Skip to content

Commit ad6dc43

Browse files
authored
Merge pull request #1395 from anosov1960/PAYG-transition
Cleaned up and added transcript
2 parents 4f1cafb + 72d2782 commit ad6dc43

4 files changed

Lines changed: 89 additions & 37 deletions

File tree

samples/manage/azure-arc-enabled-sql-server/modify-license-type/README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,23 @@ The script accepts the following command line parameters:
4848
|`-UsePcoreLicense` | `Yes`, `No` | *Optional*. Enables unlimited virtualization license if the value is "Yes" or disables it if the value is "No". To enable, the license type must be "Paid" or "PAYG"|
4949
|`-EnableESU` | `Yes`, `No` | *Optional*. Enables the ESU policy the value is "Yes" or disables it if the value is "No". To enable, the license type must be "Paid" or "PAYG"|
5050
|`-Force`| |*Optional*. Forces the change of the license type to the specified value on all installed extensions. If `-Force` is not specified, the `-LicenseType` value is set only if undefined. Ignored if `-LicenseType` is not specified|
51-
|`-ExclusionTags`| `{"name":"value","name":"value"}` |*Optional*. If specified, excludes the resources that have this tag assigned.|
51+
|`-ExclusionTags`| `{"tag1":"value1","tag2":"value2"}` |*Optional*. If specified, excludes the resources that have these tags assigned.|
5252
|`-TenantId`| `tenant_id` |*Optional*. If specified, uses this tenant id to log in. Otherwise, the current context is used.|
5353
|`-ReportOnly`| |*Optional*. If true, generates a csv file with the list of resources that are to be modified, but doesn't make the actual change.|
5454
|`-UseManagedIdentity`| |*Optional*. If true, logs in both PowerShell and CLI using managed identity. Required to run the script as a runbook.|
5555

56-
<sup>1</sup>You can create a .csv file using the following command and then edit to remove the subscriptions you don't want to scan.
56+
<sup>1</sup>You can generate a .csv file that lists only specific subscriptions. E.g., the following command will include only production subscriptions (exclude dev/test).
5757
```PowerShell
58-
Get-AzSubscription | Export-Csv .\mysubscriptions.csv -NoTypeInformation
58+
$tenantId = "<your-tenant-id>"
59+
Get-AzSubscription -TenantId $tenantId | Where-Object {
60+
$sub = $_
61+
$details = Get-AzSubscription -SubscriptionId $sub.Id -TenantId $tenantId
62+
if ($details -and $details.ExtendedProperties -and $details.ExtendedProperties.SubscriptionPolicies) {
63+
$quotaId = ($details.ExtendedProperties.SubscriptionPolicies | ConvertFrom-Json).quotaId
64+
return $quotaId -notmatch 'MSDN|DEV|VS|TEST'
65+
}
66+
return $false
67+
} | Export-Csv .\mysubscriptions.csv -NoTypeInformation
5968
```
6069
<sup>2</sup>The .csv file must include a column *MachineName*. E.g.:
6170
```

samples/manage/azure-arc-enabled-sql-server/modify-license-type/modify-arc-sql-license-type.ps1

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ param (
9393
[int] $batchSize = 500
9494
)
9595

96+
Start-Transcript -Path ".\modify-arc-sql-license-type.log"
9697
$scriptStartTime = Get-Date
9798
Write-Output "Script execution started at: $($scriptStartTime.ToString('yyyy-MM-dd HH:mm:ss'))"
9899

@@ -139,7 +140,7 @@ function Connect-Azure {
139140
}
140141
}
141142
else {
142-
Write-Output "Not connected to Az PowerShell—authenticating..."
143+
Write-Output "Not connected to Azure PowerShell. Running Connect-AzAccount..."
143144
if ($UseManagedIdentity) {
144145
if ($TenantId) {
145146
Connect-AzAccount -Identity -Tenant $TenantId | Out-Null
@@ -461,4 +462,5 @@ write-Output "Arc SQL Update Script completed"
461462
$scriptEndTime = Get-Date
462463
$executionDuration = $scriptEndTime - $scriptStartTime
463464
Write-Output "Script execution ended at: $($scriptEndTime.ToString('yyyy-MM-dd HH:mm:ss'))"
464-
Write-Output "Total execution time: $($executionDuration.ToString('hh\:mm\:ss'))"
465+
Write-Output "Total execution time: $($executionDuration.ToString('hh\:mm\:ss'))"
466+
Stop-Transcript

samples/manage/azure-hybrid-benefit/modify-license-type/README.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ This script is designed to help administrators standardize SQL licensing across
3232
- SQL Databases & Elastic Pools: Scans individual SQL servers to locate databases and elastic pools with a different license type and updates them accordingly.
3333
- SQL Instance Pools: Locates instance pools that require an update.
3434
- DataFactory SSIS Integration Runtimes: Checks for integration runtimes with an out-of-date license setting and updates them.
35+
36+
> [!IMPORTANT]
37+
> - SQL Virtual Machines must be in PowerState = "VM running" to be updated
38+
> - SQL Managed Instances must be in State = "Ready" to be updated
39+
> - DataFactory SSIS Integration Runtimes must be in State = "Stopped" to be updated
40+
3541

3642
# Required Permissions
3743
The automation account needs to have the bellow permissions in order to be able to successfully run the Runbook and update all the SQL Server resources license type:
@@ -42,7 +48,7 @@ The automation account needs to have the bellow permissions in order to be able
4248
1. **Data Factory Contributor**: *Data Factory Contributor role*.
4349
1. **Virtual Machine Contributor**: *Virtual Machine Contributor role*.
4450

45-
A *Subscription Contributor* role has sufficient permissions to mdify any of the above resources.
51+
A *Subscription Contributor* role has sufficient permissions to modify any of the above resources.
4652

4753
# Interactive Reporting
4854

@@ -59,13 +65,27 @@ The scripts is seamlessly integrated with Azure Authentication. It uses managed
5965
|:--|:--|:--|
6066
|`-SubId`|`subscription_id` *or* a file_name|Optional: Subscription id or a .csv file with the list of subscriptions<sup>1</sup>. If not specified all subscriptions will be scanned|
6167
|`-ResourceGroup` |`resource_group_name`|Optional: Limits the scope to a specific resource group|
62-
|`-ResourceName` |`resource_name`|Optional: Limits the scope to resouyrces associated with this name. For SQL Server - updates all databases under the specified server. For SQL Managed Instance - updates the specified instance. For SQL VM - updates the specified VM |
68+
|`-ResourceName` |`resource_name`|Optional: Limits the scope to resources associated with this name. For SQL Server - updates all databases under the specified server. For SQL Managed Instance - updates the specified instance. For SQL VM - updates the specified VM |
6369
|`-LicenseType` | `LicenseIncluded` (default) or `BasePrice` | Optional: Sets the license type to the specified value |
64-
|`-ExclusionTags`| `{"name":"value","name":"value"}` |*Optional*. If specified, excludes the resources that have this tag assigned.|
70+
|`-ExclusionTags`| `{"tag1":"value1","tag2":"value2"}` |*Optional*. If specified, excludes the resources that have these tags assigned.|
6571
|`-TenantId`| `tenant_id` |*Optional*. If specified, uses this tenant id to log in. Otherwise, the current context is used.|
6672
|`-ReportOnly`| |*Optional*. If true, generates a csv file with the list of resources that are to be modified, but doesn't make the actual change.|
6773
|`-UseManagedIdentity`| |*Optional*. If true, logs in both PowerShell and CLI using managed identity. Required to run the script as a runbook.|
6874

75+
<sup>1</sup>You can generate a .csv file that lists only specific subscriptions. E.g., the following command will include only production subscriptions (exclude dev/test).
76+
```PowerShell
77+
$tenantId = "<your-tenant-id>"
78+
Get-AzSubscription -TenantId $tenantId | Where-Object {
79+
$sub = $_
80+
$details = Get-AzSubscription -SubscriptionId $sub.Id -TenantId $tenantId
81+
if ($details -and $details.ExtendedProperties -and $details.ExtendedProperties.SubscriptionPolicies) {
82+
$quotaId = ($details.ExtendedProperties.SubscriptionPolicies | ConvertFrom-Json).quotaId
83+
return $quotaId -notmatch 'MSDN|DEV|VS|TEST'
84+
}
85+
return $false
86+
} | Export-Csv .\mysubscriptions.csv -NoTypeInformation
87+
```
88+
6989
# Logging & Error Handling
7090

7191
The script logs key actions to the console and captures error messages using Write-Error. Check the console output for a summary report detailing which resources were updated.

samples/manage/azure-hybrid-benefit/modify-license-type/modify-azure-sql-license-type.ps1

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ param (
7474
)
7575

7676

77+
Start-Transcript -Path "$env:TEMP\modify-azure-sql-license-type.log"
7778
$scriptStartTime = Get-Date
7879
Write-Output "Script execution started at: $($scriptStartTime.ToString('yyyy-MM-dd HH:mm:ss'))"
7980

@@ -135,7 +136,8 @@ $finalStatus = @()
135136

136137
# Convert to hashtable explicitly
137138
$tagTable = @{}
138-
if($null -ne $ExclusionTags){
139+
if(
140+
$null -ne $ExclusionTags){
139141
if($ExclusionTags.GetType().Name -eq "Hashtable"){
140142
$tagTable = $ExclusionTags
141143
}else{
@@ -169,23 +171,23 @@ if (-not (Get-PackageProvider -Name NuGet -ErrorAction SilentlyContinue)) {
169171
$installedModule = Get-InstalledModule -Name Az -ErrorAction SilentlyContinue
170172

171173
if (-not $installedModule) {
172-
Write-Host "Az module not found. Installing latest version..."
174+
Write-Output "Az module not found. Installing latest version..."
173175
Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force
174176
} else {
175177
# Get the latest version available in the PSGallery
176178
$latestVersion = (Find-Module -Name Az -Repository PSGallery).Version
177179
if ($installedModule.Version -lt $latestVersion) {
178-
Write-Host "Az module is outdated. Updating to latest version..."
180+
Write-Output "Az module is outdated. Updating to latest version..."
179181
Update-Module -Name Az -Force
180182
} else {
181-
Write-Host "Az module is already up to date. No action needed."
183+
Write-Output "Az module is already up to date. No action needed."
182184
}
183185
}
184186

185187
# Import Az.Accounts with minimum version requirement
186188
try {
187189
Import-Module Az.Accounts -MinimumVersion 4.2.0 -Force
188-
Write-Host "Az.Accounts module imported successfully."
190+
Write-Output "Az.Accounts module imported successfully."
189191
} catch {
190192
Write-Error "Failed to import Az.Accounts: $_"
191193
return
@@ -194,10 +196,10 @@ try {
194196
# Ensure Az.DataFactory is available and import it
195197
try {
196198
if (-not (Get-Module -ListAvailable -Name Az.DataFactory)) {
197-
Write-Host "Az.DataFactory module not found. Installing..."
199+
Write-Output "Az.DataFactory module not found. Installing..."
198200
Install-Module -Name Az.DataFactory -Scope CurrentUser -Force
199201
} else {
200-
Write-Host "Az.DataFactory module is already installed."
202+
Write-Output "Az.DataFactory module is already installed."
201203
}
202204
Import-Module Az.DataFactory -Force
203205
} catch {
@@ -425,6 +427,7 @@ foreach ($sub in $subscriptions) {
425427
}
426428
}
427429

430+
428431
# Add tag filter if specified
429432
if ($tagsFilter -and $filterAdded) {
430433
$serverQuery += "$tagsFilter"
@@ -441,20 +444,22 @@ foreach ($sub in $subscriptions) {
441444
# Output the query for debugging
442445
Write-Output "SQL Server query: $serverQuery"
443446

444-
# Get all servers first as a fallback in case the query fails
447+
<# Get all servers first as a fallback in case the query fails
445448
$allServers = az sql server list -o json | ConvertFrom-Json
446449
Write-Output "Found a total of $($allServers.Count) SQL Servers in subscription"
450+
#>
447451

448452
# Now try the filtered query
449453
$servers = az sql server list --query "$serverQuery" -o json | ConvertFrom-Json
450454

451455
# Verify if we got any results
452456
if ($null -eq $servers -or $servers.Count -eq 0) {
453457
Write-Output "WARNING: No SQL Servers found with the specified filters."
454-
Write-Output "Available SQL Servers in subscription:"
458+
<# Write-Output "Available SQL Servers in subscription:"
455459
$allServers | ForEach-Object {
456460
Write-Output " - $($_.name) (Resource Group: $($_.resourceGroup))"
457461
}
462+
#>
458463

459464
# Use all servers if no specific resource name was provided
460465
if (-not $ResourceName) {
@@ -666,31 +671,46 @@ foreach ($sub in $subscriptions) {
666671
# --- Section: Update DataFactory SSIS Integration Runtimes ---
667672
try {
668673
Write-Output "Processing DataFactory SSIS Integration Runtime resources..."
669-
Get-AzDataFactoryV2 | Where-Object { $_.ProvisioningState -eq "Succeeded" } | ForEach-Object {
674+
Set-AzContext -Subscription $sub.id | Out-Null
675+
Get-AzDataFactoryV2 |
676+
Where-Object {
677+
$_.ProvisioningState -eq "Succeeded" -and
678+
($null -eq $ResourceGroup -or $_.ResourceGroupName -eq $ResourceGroup)
679+
} |
680+
ForEach-Object {
670681
$df = $_
671-
Get-AzDataFactoryV2IntegrationRuntime -ResourceGroupName $df.ResourceGroupName -DataFactoryName $df.DataFactoryName |
682+
$IRs = Get-AzDataFactoryV2IntegrationRuntime -ResourceGroupName $df.ResourceGroupName -DataFactoryName $df.DataFactoryName |
672683
Where-Object {
673684
$_.Type -eq "Managed" -and
674685
$_.State -ne "Starting" -and
675686
$_.LicenseType -ne $LicenseType -and
676687
($null -eq $ResourceName -or $_.Name -eq $ResourceName)
677-
} | ForEach-Object {
678-
# Collect data before modification
679-
$modifiedResources += [PSCustomObject]@{
680-
TenantID = $TenantId
681-
SubID = ($_.Id -split '/')[2]
682-
ResourceName = $_.Name
683-
ResourceType = "Microsoft.DataFactory/factories/integrationRuntimes"
684-
Status = $_.State
685-
OriginalLicenseType = $_.LicenseType
686-
ResourceGroup = $df.ResourceGroupName
687-
Location = $df.Location
688-
}
689-
# Update the license type to $LicenseType.
690-
if (-not $ReportOnly) {
691-
$result = Set-AzDataFactoryV2IntegrationRuntime -ResourceGroupName $df.ResourceGroupName -DataFactoryName $df.DataFactoryName -Name $_.Name -LicenseType $LicenseType -Force
692-
$finalStatus += $result
693-
Write-Host ([Environment]::NewLine + "-- DataFactory '$($df.DataFactoryName)' integration runtime updated to license type $LicenseType")
688+
}
689+
690+
if ($IRs.Count -eq 0) {
691+
Write-Output "No matching integration runtimes found."
692+
} else {
693+
$IRs | ForEach-Object {
694+
$modifiedResources += [PSCustomObject]@{
695+
TenantID = $TenantId
696+
SubID = ($_.Id -split '/')[2]
697+
ResourceName = $_.Name
698+
ResourceType = "Microsoft.DataFactory/factories/integrationRuntimes"
699+
Status = $_.State
700+
OriginalLicenseType = $_.LicenseType
701+
ResourceGroup = $df.ResourceGroupName
702+
Location = $df.Location
703+
}
704+
705+
if (-not $ReportOnly) {
706+
if (-not [string]::IsNullOrEmpty($ResourceName) -and $_.State -ne "Stopped") {
707+
Write-Output "ADF Integration Service '$($_.Name)' is not in stopped state"
708+
} else {
709+
$result = Set-AzDataFactoryV2IntegrationRuntime -ResourceGroupName $df.ResourceGroupName -DataFactoryName $df.DataFactoryName -Name $_.Name -LicenseType $LicenseType -Force
710+
$finalStatus += $result
711+
Write-Output "-- DataFactory '$($df.DataFactoryName)' integration runtime updated to license type $LicenseType"
712+
}
713+
}
694714
}
695715
}
696716
}
@@ -728,4 +748,5 @@ Write-Output "Azure SQL Update Script completed"
728748
$scriptEndTime = Get-Date
729749
$executionDuration = $scriptEndTime - $scriptStartTime
730750
Write-Output "Script execution ended at: $($scriptEndTime.ToString('yyyy-MM-dd HH:mm:ss'))"
731-
Write-Output "Total execution time: $($executionDuration.ToString('hh\:mm\:ss'))"
751+
Write-Output "Total execution time: $($executionDuration.ToString('hh\:mm\:ss'))"
752+
Stop-Transcript

0 commit comments

Comments
 (0)