Skip to content

Commit e54d61a

Browse files
authored
Merge pull request #1100 from anosov1960/master
Add modify-license-type script
2 parents 6a63a15 + e34a0b1 commit e54d61a

File tree

2 files changed

+260
-0
lines changed

2 files changed

+260
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
services: Azure Arc-enabled SQL Server
3+
platforms: Azure
4+
author: anosov1960
5+
ms.author: sashan
6+
ms.date: 2/09/2023
7+
---
8+
9+
10+
# Overview
11+
12+
13+
This script allows you to to set or change the license type on all Azure-connected SQL Servers
14+
on a specific resource, in a single resource group, a specific subscription, a list of subscriptions or the entire account. By default, it sets the specified license type value on the servers where it is undefined. But you can request to set it on all servers in the selected scope.
15+
16+
You can specify a single subscription to scan, or provide a list of subscriptions as a .CSV file.
17+
If not specified, all subscriptions your role has access to are scanned.
18+
19+
If the license type is not specified, the value "Paid" is used.
20+
21+
22+
# Required permissions
23+
24+
You must have at least a *Contributor* role in each subscription you modify.
25+
26+
# Launching the script
27+
28+
The script accepts the following command line parameters:
29+
30+
| **Parameter**                                         | **Value**                                                                       | **Description** |
31+
|:--|:--|:--|
32+
|-SubId|subscription_id *or* a file_name|Optional: subscription id or a .csv file with the list of subscriptions<sup>1</sup>|
33+
|-ResourceGroup |resource_group_name|Optional: Limit the scope to a specific resource group|
34+
|-MachineName |machine_name|Optional: Limit the scope to a specific machine|
35+
|-LicenceType | "Paid" (default), "PAYG" or "LicenseOnly"| Specifies the license type value |
36+
|-All|\$True or \$False (default)|Optional: Set the new license type value only if undefined|
37+
38+
<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.
39+
```PowerShell
40+
Get-AzSubscription | Export-Csv .\mysubscriptions.csv -NoTypeInformation
41+
```
42+
## Example 1
43+
44+
The following command will scan all the subscriptions to which the user has access to and set the license type to "PAYG".
45+
46+
```PowerShell
47+
.\update-license-type.ps1 -LicenseType "PAYG" -All
48+
```
49+
50+
## Example 2
51+
52+
The following command will scan the subscription `<sub_id>` and set the license type value to "Paid" on the servers where it is undefined.
53+
54+
```PowerShell
55+
.\update-license-type.ps1 -SubId <sub_id> -LicenseType "Paid"
56+
```
57+
58+
# Running the script using Cloud Shell
59+
60+
Use the following steps to run the script in Cloud Shell.
61+
62+
1. Launch the [Cloud Shell](https://shell.azure.com/). For details, [read more about PowerShell in Cloud Shell](https://aka.ms/pscloudshell/docs).
63+
64+
2. Upload the script to the shell using the following command:
65+
66+
```console
67+
curl https://raw.githubusercontent.com/microsoft/sql-server-samples/master/samples/manage/azure-arc-enabled-sql-server/modify-license-type/modify-license-type.ps1 -o /modify-license-type.ps1
68+
```
69+
70+
3. Run the script.
71+
72+
```console
73+
.//modify-license-type.ps1 -LicenseType "PAYG"
74+
```
75+
76+
> [!NOTE]
77+
> - To paste the commands into the shell, use `Ctrl-Shift-V` on Windows or `Cmd-v` on MacOS.
78+
> - The script will be uploaded directly to the home folder associated with your Cloud Shell session.
79+
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#
2+
# This script provides a scaleable solution to set or change the license type on all Azure-connected SQL Servers
3+
# in a specific subscription, a list of subscruiptions or the entire account. By default, it sets the new license
4+
# type value only on the servers where it is undefined.
5+
#
6+
# You can specfy a single subscription to scan, or provide subscriptions as a .CSV file with the list of IDs.
7+
# If not specified, all subscriptions your role has access to are scanned.
8+
#
9+
# The script accepts the following command line parameters:
10+
#
11+
# -SubId [subscription_id] | [csv_file_name] (Limit scope to specific subscriptions. Accepts a .csv file with the list of subscriptions)
12+
# -ResourceGroup [resource_goup] (Limit scope to a specific resoure group)
13+
# -MachineName [machine_name] (Limit scope to a specific machine)
14+
# -LicenseType [license_type_value] (Specific LT value)
15+
# -All (Optional. Set the new license type value only if undefined)
16+
#
17+
18+
param (
19+
[Parameter (Mandatory= $false)]
20+
[string] $SubId,
21+
[Parameter (Mandatory= $false)]
22+
[string] $ResourceGroup,
23+
[Parameter (Mandatory= $false)]
24+
[string] $MachineName,
25+
[Parameter (Mandatory= $false)]
26+
[string] $LicenseType="Paid",
27+
[Parameter (Mandatory= $false)]
28+
[boolean] $All=$false
29+
)
30+
31+
function CheckModule ($m) {
32+
33+
# This function ensures that the specified module is imported into the session
34+
# If module is already imported - do nothing
35+
36+
if (!(Get-Module | Where-Object {$_.Name -eq $m})) {
37+
# If module is not imported, but available on disk then import
38+
if (Get-Module -ListAvailable | Where-Object {$_.Name -eq $m}) {
39+
Import-Module $m
40+
}
41+
else {
42+
43+
# If module is not imported, not available on disk, but is in online gallery then install and import
44+
if (Find-Module -Name $m | Where-Object {$_.Name -eq $m}) {
45+
Install-Module -Name $m -Force -Verbose -Scope CurrentUser
46+
Import-Module $m
47+
}
48+
else {
49+
50+
# If module is not imported, not available and not in online gallery then abort
51+
write-host "Module $m not imported, not available and not in online gallery, exiting."
52+
EXIT 1
53+
}
54+
}
55+
}
56+
}
57+
58+
function ObjectToHashtable {
59+
[CmdletBinding()]
60+
[OutputType('hashtable')]
61+
param (
62+
[Parameter(ValueFromPipeline)]
63+
$InputObject
64+
)
65+
process {
66+
## Return null if the input is null. This can happen when calling the function
67+
## recursively and a property is null
68+
if ($null -eq $InputObject) {
69+
return $null
70+
}
71+
## Check if the input is an array or collection. If so, we also need to convert
72+
## those types into hash tables as well. This function will convert all child
73+
## objects into hash tables (if applicable)
74+
if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) {
75+
$collection = @(
76+
foreach ($object in $InputObject) {
77+
ObjectToHashtable -InputObject $object
78+
}
79+
)
80+
## Return the array but don't enumerate it because the object may be pretty complex
81+
Write-Output -NoEnumerate $collection
82+
} elseif ($InputObject -is [psobject]) {
83+
## If the object has properties that need enumeration, cxonvert it to its own hash table and return it
84+
$hash = @{}
85+
foreach ($property in $InputObject.PSObject.Properties) {
86+
$hash[$property.Name] = ObjectToHashtable -InputObject $property.Value
87+
}
88+
$hash
89+
} else {
90+
## If the object isn't an array, collection, or other object, it's already a hash table
91+
## So just return it.
92+
$InputObject
93+
}
94+
}
95+
}
96+
97+
#
98+
# Suppress warnings
99+
#
100+
Update-AzConfig -DisplayBreakingChangeWarning $false
101+
102+
# Load required modules
103+
$requiredModules = @(
104+
"Az.Accounts",
105+
"Az.ConnectedMachine",
106+
"Az.ResourceGraph"
107+
)
108+
$requiredModules | Foreach-Object {CheckModule $_}
109+
110+
# Subscriptions to scan
111+
112+
if ($SubId -like "*.csv") {
113+
$subscriptions = Import-Csv $SubId
114+
}elseif($SubId -ne $null){
115+
$subscriptions = [PSCustomObject]@{SubscriptionId = $SubId} | Get-AzSubscription
116+
}else{
117+
$subscriptions = Get-AzSubscription
118+
}
119+
120+
121+
Write-Host ([Environment]::NewLine + "-- Scanning subscriptions --")
122+
123+
# Scan arc-enabled servers in each subscription
124+
125+
foreach ($sub in $subscriptions){
126+
127+
if ($sub.State -ne "Enabled") {continue}
128+
129+
try {
130+
Set-AzContext -SubscriptionId $sub.Id
131+
}catch {
132+
write-host "Invalid subscription: $($sub.Id)"
133+
{continue}
134+
}
135+
136+
$query = "
137+
resources
138+
| where type =~ 'microsoft.hybridcompute/machines/extensions'
139+
| extend extensionPublisher = tostring(properties.publisher), extensionType = tostring(properties.type), provisioningState = tostring(properties.provisioningState)
140+
| where extensionPublisher =~ 'Microsoft.AzureData'
141+
| where provisioningState =~ 'Succeeded'
142+
| parse id with * '/providers/Microsoft.HybridCompute/machines/' machineName '/extensions/' *
143+
| project machineName, extensionName = name, resourceGroup, location, subscriptionId, extensionPublisher, extensionType, properties
144+
"
145+
146+
if ($MachineName) {$query += "| where machineName =~ '$($MachineName)'"}
147+
if ($ResourceGroup) {$query += "| where resourceGroup =~ '$($ResourceGroup)'"}
148+
149+
$resources = Search-AzGraph -Query "$($query) | where subscriptionId =~ '$($sub.Id)'"
150+
foreach ($r in $resources) {
151+
152+
$setID = @{
153+
MachineName = $r.MachineName
154+
Name = $r.extensionName
155+
ResourceGroup = $r.resourceGroup
156+
Location = $r.location
157+
SubscriptionId = $r.subscriptionId
158+
Publisher = $r.extensionPublisher
159+
ExtensionType = $r.extensionType
160+
}
161+
162+
$settings = @{}
163+
$settings = $r.properties.settings | ConvertTo-Json | ConvertFrom-Json | ObjectToHashtable
164+
165+
if ($settings.ContainsKey("LicenseType")) {
166+
if ($All) {
167+
if ($settings["LicenseType"] -ne $LicenseType ) {
168+
$settings["LicenseType"] = $LicenseType
169+
Write-Host "Resource group: [$($r.resourceGroup)] Connected machine: [$($r.MachineName)] : License type: [$($settings["LicenseType"])]"
170+
Set-AzConnectedMachineExtension @setId -Settings $settings -NoWait
171+
}
172+
}
173+
} else {
174+
$settings["LicenseType"] = $LicenseType
175+
Write-Host "Resource group: [$($r.resourceGroup)] Connected machine: [$($r.MachineName)] : License type: [$($settings["LicenseType"])]"
176+
Set-AzConnectedMachineExtension @setId -Settings $settings
177+
}
178+
}
179+
}
180+
181+

0 commit comments

Comments
 (0)