Skip to content

Commit 8dc1b71

Browse files
authored
Added modify-license-type for Azure SQL
1 parent e74af02 commit 8dc1b71

3 files changed

Lines changed: 388 additions & 174 deletions

File tree

Lines changed: 88 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,10 @@
1-
#
2-
# This script scan each VM in scope to detect if SQL server insstalled and if it is regsitered with IaaS extension.
3-
# The report includes the following information for each VM.
4-
#
5-
# Subscription Name
6-
# Subscription ID
7-
# ResourceGroupName
8-
# Server Name
9-
# Location
10-
# Server SKU
11-
# Size in vCores
12-
# OS Type
13-
# OS Version
14-
# SQL Version
15-
# SQL Edition
16-
# IaaS registration status
17-
#
18-
# The script accepts the following command line parameters:
19-
#
20-
# -SubId [subscription_id] (Optional. If not specified all subscription the user has access to Accepts a .csv file with the list of subscriptions)
21-
# -FilePath [csv_file_name] (Optional. Sprcifies a .csv file to save the data. if not specified, saves it in sql-vcm-inventory.csv)
22-
#
23-
24-
param (
1+
param (
252
[Parameter (Mandatory= $false)]
263
[string] $SubId,
274
[Parameter (Mandatory= $false)]
5+
[PSCredential] $Cred,
6+
[Parameter (Mandatory= $false)]
287
[string] $FilePath
29-
308
)
319

3210
function CheckModule ($m) {
@@ -56,76 +34,10 @@ function CheckModule ($m) {
5634
}
5735
}
5836

59-
function GetVCores {
60-
# This function translates each VM or Host sku type and name into vCores
61-
62-
[CmdletBinding()]
63-
param (
64-
[Parameter(Mandatory)]
65-
[string]$type,
66-
[Parameter(Mandatory)]
67-
[string]$name
68-
)
69-
70-
if ($global:VM_SKUs.Count -eq 0){
71-
$global:VM_SKUs = Get-AzComputeResourceSku "westus" | where-object {$_.ResourceType -in 'virtualMachines','hostGroups/hosts'}
72-
}
73-
# Select first size and get the VCPus available
74-
$size_info = $global:VM_SKUs | Where-Object {$_.ResourceType.Contains($type) -and ($_.Name -eq $name)} | Select-Object -First 1
75-
76-
# Save the VCPU count
77-
switch ($type) {
78-
"hosts" {$vcpu = $size_info.Capabilities | Where-Object {$_.name -eq "Cores"} }
79-
"virtualMachines" {$vcpu = $size_info.Capabilities | Where-Object {$_.name -eq "vCPUsAvailable"} }
80-
}
81-
82-
if ($vcpu){
83-
return $vcpu.Value
84-
}
85-
else {
86-
return 0
87-
}
88-
}
89-
90-
function DiscoveryOnWindows {
91-
92-
# This script checks if SQL Server is installed on Windows
93-
94-
[string] $SqlInstalled = ""
95-
$regPath = 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server'
96-
if (Test-Path $regPath) {
97-
$inst = (get-itemproperty $regPath).InstalledInstances
98-
#$SqlInstalled = ($inst.Count -gt 0)
99-
foreach ($i in $inst) {
100-
# Read registry data
101-
#
102-
$p = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL').$i
103-
$setupValues = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$p\Setup")
104-
$edition = ($setupValues.Edition -split ' ')[0]
105-
$version = ($setupValues.Version)
106-
$SqlInstalled = $version, $edition -join ':'
107-
}
108-
}
109-
Write-Output $SqlInstalled
110-
}
111-
112-
#
113-
# This script checks if SQL Server is installed on Linux
11437
#
38+
# Suppress warnings
11539
#
116-
$DiscoveryOnLinux =
117-
'if ! systemctl is-active --quiet mssql-server.service; then dir
118-
119-
echo "False"
120-
exit
121-
else
122-
echo "True"
123-
fi'
124-
125-
126-
127-
# Ensure that the required modules are imported
128-
# In Runbooks these modules must be added to the automation account manually
40+
Update-AzConfig -DisplayBreakingChangeWarning $false
12941

13042
$requiredModules = @(
13143
"Az.Accounts",
@@ -137,37 +49,27 @@ $requiredModules = @(
13749
)
13850
$requiredModules | Foreach-Object {CheckModule $_}
13951

140-
# Save the function definitions to run in parallel loops
141-
$GetVCoresDef = $function:GetVCores.ToString()
142-
143-
# Create a script file with the SQL server discovery logic
144-
New-Item -ItemType file -path DiscoverSql.ps1 -value $function:DiscoveryOnWindows.ToString() -Force | Out-Null
145-
New-Item -ItemType file -path DiscoverSql.sh -value $DiscoveryOnLinux -Force | Out-Null
146-
14752
# Subscriptions to scan
14853

149-
15054
if ($SubId -like "*.csv") {
15155
$subscriptions = Import-Csv $SubId
152-
}elseif($SubId.length -gt 0){
56+
}elseif($SubId -ne $null){
15357
$subscriptions = [PSCustomObject]@{SubscriptionId = $SubId} | Get-AzSubscription
15458
}else{
15559
$subscriptions = Get-AzSubscription
15660
}
15761

158-
159-
#File setup
62+
#Log file setup
16063
if (!$PSBoundParameters.ContainsKey("FilePath")) {
161-
$FilePath = '.\sql-vm-inventory.csv'
64+
$FilePath = '.\sql-change-log.csv'
16265
}
16366

164-
[System.Collections.ArrayList]$inventoryTable = @()
165-
$inventoryTable += ,(@("Subscription Name", "Subscription ID", "ResourceGroupName", "Name", "Location", "SKU", "vCores", "OS Type", "OS Version", "SQL Version", "SQL Edition", "IaaS registration"))
166-
167-
$global:VM_SKUs = @{} # To hold the VM SKU table for future use
168-
16967
Write-Host ([Environment]::NewLine + "-- Scanning subscriptions --")
17068

69+
# Record the start time
70+
$startTime = Get-Date
71+
Write-Host ("Script execution started at: $startTime")
72+
17173
# Calculate usage for each subscription
17274

17375
foreach ($sub in $subscriptions){
@@ -178,78 +80,90 @@ foreach ($sub in $subscriptions){
17880
Set-AzContext -SubscriptionId $sub.Id
17981
}catch {
18082
write-host "Invalid subscription: " $sub.Id
181-
{continue}
83+
continue
18284
}
18385

184-
# Reset the subtotals
185-
#$subtotal.psobject.properties.name | Foreach-object {$subtotal.$_ = 0}
186-
18786
# Get all resource groups in the subscription
188-
#$rgs = Get-AzResourceGroup
189-
190-
# Scan all VMs with SQL server installed using a parallel loop (up to 10 at a time).
191-
# NOTE: ForEach-Object -Parallel requires PS v7.1 or higher
192-
if ($PSVersionTable.PSVersion.Major -ge 7){
193-
#Get-AzVM -Status | Where-Object { $_.powerstate -eq 'VM running' } | ForEach-Object -ThrottleLimit 10 -Parallel {
194-
Get-AzVM -Status | Where-Object { $_.powerstate -eq 'VM running' } | ForEach-Object {
195-
#$function:GetVCores = $using:GetVCoresDef
196-
$SqlEdition = ''
197-
$SqlVersion = ''
198-
$vCores = GetVCores -type 'virtualMachines' -name $_.HardwareProfile.VmSize
199-
$sql_vm = Get-AzSqlVm -ResourceGroupName $_.ResourceGroupName -Name $_.Name -ErrorAction Ignore
200-
201-
202-
if ($sql_vm) {
203-
$RegStatus = 'SQL Server registered'
204-
$SqlEdition = $Sql_vm.Sku
205-
$SqlVersion = $Sql_vm.Offer
206-
}
207-
else {
208-
if ($_.StorageProfile.OSDisk.OSType -eq "Windows"){
209-
$params =@{
210-
ResourceGroupName = $_.ResourceGroupName
211-
Name = $_.Name
212-
CommandId = 'RunPowerShellScript'
213-
ScriptPath = 'DiscoverSql.ps1'
214-
ErrorAction = 'Stop'
215-
}
216-
}
217-
else {
218-
$params =@{
219-
ResourceGroupName = $_.ResourceGroupName
220-
Name = $_.Name
221-
CommandId = 'RunShellScript'
222-
ScriptPath = 'DiscoverSql.sh'
223-
ErrorAction = 'Stop'
224-
}
225-
}
226-
try {
227-
$out = Invoke-AzVMRunCommand @params
228-
if (!$out.Value[0].Message){
229-
$RegStatus = 'SQL Server not installed'
230-
}
231-
else {
232-
$SqlVersion, $SqlEdition = $out.Value[0].Message -split ':', 2
233-
$RegStatus = 'SQL Server not registered'
234-
}
235-
}
236-
catch {
237-
$RegStatus = 'No VM access'
238-
}
87+
$rgs = Get-AzResourceGroup
88+
89+
# Get all logical servers
90+
$servers = Get-AzSqlServer
91+
92+
# Scan all vCore-based SQL database resources in the subscription
93+
$servers | Get-AzSqlDatabase | Where-Object { $_.SkuName -ne "ElasticPool" -and $_.Edition -in @("GeneralPurpose", "BusinessCritical", "Hyperscale") } | ForEach-Object {
94+
if ($_.LicenseType -ne "LicenseIncluded") {
95+
Set-AzSqlDatabase -ResourceGroupName $_.ResourceGroupName -ServerName $_.ServerName -DatabaseName $_.DatabaseName -LicenseType "LicenseIncluded"
96+
Write-Host ([Environment]::NewLine + "-- Database $_.DatabaseName is set to \"LicenseIncluded\"")
97+
}
98+
}
99+
[system.gc]::Collect()
100+
101+
# Scan all vCore-based SQL elastic pool resources in the subscription
102+
$servers | Get-AzSqlElasticPool | Where-Object { $_.Edition -in @("GeneralPurpose", "BusinessCritical", "Hyperscale") } | ForEach-Object {
103+
if ($_.LicenseType -ne "LicenseIncluded") {
104+
Set-AzSqlElasticPool -ResourceGroupName $_.ResourceGroupName -ServerName $_.ServerName -ElasticPoolName $_.ElasticPoolName -LicenseType "LicenseIncluded"
105+
Write-Host ([Environment]::NewLine + "-- ElasticPool $_.ElasticPoolName is set to \"LicenseIncluded\"")
106+
}
107+
}
108+
[system.gc]::Collect()
109+
110+
# Scan all SQL managed instance resources in the subscription
111+
Get-AzSqlInstance | Where-Object { $_.InstancePoolName -eq $null } | ForEach-Object {
112+
if ($_.LicenseType -ne "LicenseIncluded") {
113+
Set-AzSqlInstance -ResourceGroupName $_.ResourceGroupName -ServerName $_.ServerName -InstanceName $_.InstanceName -LicenseType "LicenseIncluded"
114+
Write-Host ([Environment]::NewLine + "-- Instance $_.InstanceName is set to \"LicenseIncluded\"")
115+
}
116+
}
117+
[system.gc]::Collect()
118+
119+
# Scan all instance pool resources in the subscription
120+
Get-AzSqlInstancePool | Foreach-Object {
121+
if ($_.LicenseType -ne "LicenseIncluded") {
122+
Set-AzSqlInstancePool -ResourceGroupName $_.ResourceGroupName -ServerName $_.ServerName -InstanceName $_.InstanceName -LicenseType "LicenseIncluded"
123+
Write-Host ([Environment]::NewLine + "-- InstancePool $_.InstanceName is set to \"LicenseIncluded\"")
124+
}
125+
}
126+
[system.gc]::Collect()
127+
128+
# Scan all SSIS integration runtime resources in the subscription
129+
$rgs | Get-AzDataFactoryV2 | Get-AzDataFactoryV2IntegrationRuntime | Where-Object { $_.State -eq "Started" -and $_.NodeSize -ne $null } | ForEach-Object {
130+
if ($_.LicenseType -ne "LicenseIncluded") {
131+
# Set the license type to "LicenseIncluded"
132+
Set-AzDataFactoryV2IntegrationRuntime -ResourceGroupName $_.ResourceGroupName -DataFactoryName $_.DataFactoryName -Name $_.Name -LicenseType "LicenseIncluded"
133+
Write-Host ([Environment]::NewLine + "-- DataFactory $_.DataFactoryName is set to \"LicenseIncluded\"")
134+
}
135+
}
136+
[system.gc]::Collect()
137+
138+
# Scan all SQL VMs in the subscription
139+
$rgs | Get-AzVM | Where-Object { $_.StorageProfile.ImageReference.Offer -like "*sql*" -and $_.ProvisioningState -eq "Succeeded" } | ForEach-Object {
140+
$vmName = $_.Name
141+
$resourceGroupName = $_.ResourceGroupName
142+
143+
# Get the SQL configuration for the VM
144+
$sqlConfig = Get-AzVMExtension -ResourceGroupName $resourceGroupName -VMName $vmName -Name "SqlIaaSAgent"
145+
146+
if ($sqlConfig -ne $null) {
147+
$licenseType = $sqlConfig.Settings.LicenseType
148+
149+
if ($licenseType -ne "LicenseIncluded") {
150+
# Set the license type to "LicenseIncluded"
151+
Set-AzVMExtension -ResourceGroupName $resourceGroupName -VMName $vmName -Name "SqlIaaSAgent" -Publisher "Microsoft.SqlServer.Management" -ExtensionType "SqlIaaSAgent" -TypeHandlerVersion "1.5" -Settings @{ "LicenseType" = "LicenseIncluded" }
152+
Write-Host ([Environment]::NewLine + "-- SQL VM $vmName is set to \"LicenseIncluded\"")
239153
}
240-
$inventoryTable += ,(@( $sub.Name, $sub.Id, $_.ResourceGroupName, $_.Name, $_.Location, $_.HardwareProfile.VmSize, $vCores, $_.StorageProfile.ImageReference.Offer, $_.StorageProfile.ImageReference.Sku, $SqlVersion, $SqlEdition, $RegStatus))
241-
#write-host $_.ResourceGroupName $_.Name $_.Location $_.HardwareProfile.VmSize $vCores $_.StorageProfile.ImageReference.Offer $_.StorageProfile.ImageReference.Sku $SqlVersion $SqlEdition $RegStatus
154+
242155
}
243156
}
244157
[system.gc]::Collect()
158+
245159
}
246160

161+
# Record the end time
162+
$endTime = Get-Date
163+
Write-Host ("Script execution ended at: $endTime")
247164

248-
# Write usage data to the .csv file
249-
if ($FilePath){
250-
(ConvertFrom-Csv ($inventoryTable | %{$_ -join ','})) | Export-Csv $FilePath -NoType #-Append
251-
Write-Host ([Environment]::NewLine + "-- Added the usage data to $FilePath --")
252-
} else {
253-
Write-Host $inventoryTable
254-
}
165+
# Calculate the duration of script execution
166+
$executionDuration = $endTime - $startTime
167+
Write-Host ("Script execution duration: $executionDuration")
255168

169+
Write-Host ([Environment]::NewLine + "-- Script execution completed --")

0 commit comments

Comments
 (0)