mirror of
https://github.com/Microsoft/sql-server-samples.git
synced 2025-12-08 14:58:54 +00:00
Merge pull request #1310 from anosov1960/master
Merge activate-pcore-license
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
---
|
||||
services: Azure SQL
|
||||
platforms: Azure
|
||||
author: anosov1960
|
||||
ms.author: sashan
|
||||
ms.date: 06/24/2024
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
This script performes a scheduled activation of a SQL Server p-core license.
|
||||
|
||||
# Required permissions
|
||||
|
||||
Your RBAC role must include the following permissions:
|
||||
|
||||
- Microsoft.AzureArcData/SqlLicenses/read
|
||||
- Microsoft.AzureArcData/SqlLicenses/write
|
||||
- Microsoft.Management/managementGroups/read
|
||||
- Microsoft.Resources/subscriptions/read
|
||||
- Microsoft.Resources/subscriptions/resourceGroups/read
|
||||
- Microsoft.Support/supporttickets/write
|
||||
|
||||
# Creating a Azure runbook
|
||||
|
||||
You can scahedule to run the the command as a runbook. To set it up using Azure Portal, follow these steps.
|
||||
|
||||
1. Open a command shell on your device and run this command. It will copy the script to your local folder.
|
||||
```console
|
||||
curl https://raw.githubusercontent.com/microsoft/sql-server-samples/master/samples/manage/azure-arc-enabled-sql-server/activate-pcore-license/activate-pcore-license.md -o activate-pcore-license.ps1
|
||||
```
|
||||
2. [Create a new automation account](https://ms.portal.azure.com/#create/Microsoft.AutomationAccount) or open an existing one.
|
||||
1. Select *Run as accounts* in the **Account Settings** group, open the automatically created *Azure Run As Account* and note or copy the Display Name property.
|
||||
1. Select *Runbooks* in the **Process automation** group and click on *Import a runbook*, select the file you downloaded in Step 1 and click **Create**.
|
||||
1. When import is completed, click the *Publish* button.
|
||||
1. From the runbook blade, click on the *Link to schedule* button and select an existing schedule or create a new one withand spesify the designed launch time.
|
||||
1. Click on *Parameters and run settings* and specify the following parameters:
|
||||
- LICENSEID. Put in teh resourec URI
|
||||
1. Click **OK** to link to the schedule and **OK** again to create the job.
|
||||
|
||||
For more information about the runbooks, see the [Runbook tutorial](https://docs.microsoft.com/en-us/azure/automation/learn/automation-tutorial-runbook-textual-powershell)
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<#
|
||||
.DESCRIPTION
|
||||
This runbook activates a SQL Server license using the Managed Identity
|
||||
The runbook accepts the following parameters:
|
||||
|
||||
-LicenseID (The license resource URI)
|
||||
|
||||
.NOTES
|
||||
AUTHOR: Alexander (Sasha) Nosov
|
||||
LASTEDIT: June 24, 2024
|
||||
#>
|
||||
|
||||
param (
|
||||
[Parameter (Mandatory= $true)]
|
||||
[string] $LicenseId,
|
||||
)
|
||||
|
||||
#
|
||||
# Suppress warnings
|
||||
#
|
||||
Update-AzConfig -DisplayBreakingChangeWarning $false
|
||||
|
||||
# Logging in to Azure..."
|
||||
try
|
||||
{
|
||||
Connect-AzAccount -Identity
|
||||
}
|
||||
catch {
|
||||
Write-Error -Message $_.Exception
|
||||
throw $_.Exception
|
||||
}
|
||||
|
||||
$currentLicense = Get-AzResource -ResourceId $LicenseId
|
||||
$currentLicense.properties.activationState = "Activated"
|
||||
$currentLicense | Set-AzResource -Force
|
||||
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
param (
|
||||
[Parameter (Mandatory=$true)]
|
||||
[string]$AzureSubscriptionId,
|
||||
[Parameter (Mandatory=$true)]
|
||||
[string]$AzureResourceGroupUri,
|
||||
[Parameter (Mandatory=$true)]
|
||||
[string]$AzureRegion,
|
||||
[Parameter (Mandatory=$false)]
|
||||
[string]$SqlServerInstanceName,
|
||||
[Parameter (Mandatory=$true)]
|
||||
[string]$SqlServerAdminAccounts,
|
||||
[Parameter (Mandatory=$true)]
|
||||
[string]$SqlServerSvcAccount,
|
||||
[Parameter (Mandatory=$true)]
|
||||
[string]$SqlServerSvcPassword,
|
||||
[Parameter (Mandatory=$true)]
|
||||
[string]$SqlServerVersion,
|
||||
[Parameter (Mandatory=$true)]
|
||||
[string]$SqlServerEdition,
|
||||
[Parameter (Mandatory=$true)]
|
||||
[string]$SqlServerProductKey,
|
||||
[Parameter (Mandatory=$true)]
|
||||
[string]$isoURL
|
||||
)
|
||||
|
||||
# This function checks if the specified module is imported into the session and if not installes and/or imports it
|
||||
function LoadModule
|
||||
{
|
||||
param (
|
||||
[parameter(Mandatory = $true)][string] $name
|
||||
)
|
||||
|
||||
$retVal = $true
|
||||
|
||||
if (!(Get-Module -Name $name))
|
||||
{
|
||||
$retVal = Get-Module -ListAvailable | Where-Object {$_.Name -eq $name}
|
||||
|
||||
if ($retVal)
|
||||
{
|
||||
try
|
||||
{
|
||||
Import-Module $name -ErrorAction SilentlyContinue
|
||||
}
|
||||
catch
|
||||
{
|
||||
write-host "The request to lload module $($name) failed with the following error:"
|
||||
write-host $_.Exception.Message
|
||||
$retVal = $false
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
# If module is not imported, not available on disk, but is in online gallery then install and import
|
||||
if (Find-Module -Name $name) {
|
||||
Install-Module -Name $name -Force -Verbose -Scope CurrentUser
|
||||
try
|
||||
{
|
||||
Import-Module $name -ErrorAction SilentlyContinue
|
||||
}
|
||||
catch
|
||||
{
|
||||
write-host "The request to lload module $($name) failed with the following error:"
|
||||
write-host $_.Exception.Message
|
||||
$retVal = $false
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
# If module is not imported, not available and not in online gallery then abort
|
||||
write-host "Module $($name) not imported, not available and not in online gallery, exiting."
|
||||
EXIT 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $retVal
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
#Step 0: Ensure PS version and load missing Azure modules
|
||||
#
|
||||
# Suppress warnings
|
||||
#
|
||||
Update-AzConfig -DisplayBreakingChangeWarning $false
|
||||
|
||||
# Load required modules
|
||||
$requiredModules = @(
|
||||
"AzureAD",
|
||||
"Az.Accounts",
|
||||
"Az.ConnectedMachine",
|
||||
"Az.ResourceGraph"
|
||||
)
|
||||
$requiredModules | Foreach-Object {LoadModule $_}
|
||||
|
||||
# Step 1: Check if setup.exe is already running and kill it if so
|
||||
if (Get-Process setup -ErrorAction SilentlyContinue) {
|
||||
Stop-Process -Name setup -Force
|
||||
Write-Host "Existing setup.exe process terminated."
|
||||
}
|
||||
|
||||
# Step 2: Log in to Azure
|
||||
Connect-AzAccount
|
||||
$subscription = Get-AzSubscription -SubscriptionId $AzureSubscriptionId -ErrorAction SilentlyContinue
|
||||
if (-not $subscription) {
|
||||
Write-Error "Azure subscription with ID '$AzureSubscriptionId' does not exist."
|
||||
exit
|
||||
}
|
||||
|
||||
# Step 2: Block auto-onboarding to Arc by tagging the resource group
|
||||
$existingResourceGroup = Get-AzResourceGroup -Name $AzureResourceGroupUri -ErrorAction SilentlyContinue
|
||||
|
||||
if ($existingResourceGroup) {
|
||||
Write-Host "Resource group '$AzureResourceGroupUri' exists."
|
||||
} else {
|
||||
Write-Error "Resource group '$AzureResourceGroupUri' does not exist."
|
||||
exit
|
||||
}
|
||||
$tags = @{"ArcOnboarding" = "Blocked"}
|
||||
Set-AzResourceGroup -Name $AzureResourceGroupUri -Tag $tags
|
||||
|
||||
# Step 3: Onboard the VM to Azure Arc
|
||||
$hostName = (Get-WmiObject Win32_ComputerSystem).Name
|
||||
|
||||
New-AzConnectedMachine -ResourceGroupName $AzureResourceGroupUri -Name $hostName -Location $AzureRegion
|
||||
|
||||
# Step 4: Automatically download installable media
|
||||
|
||||
$isoLocation = "C:\download\SQLServer.iso"
|
||||
if (!(Test-Path -Path $isoLocation)) {
|
||||
$freeSpace = (Get-PSDrive -Name C).Free
|
||||
$isoSize = (Invoke-WebRequest -Uri $isoURL -Method Head).Headers.'Content-Length'
|
||||
if ($freeSpace -gt $isoSize) {
|
||||
Start-BitsTransfer -Source $isoURL -Destination $isoLocation
|
||||
} else {
|
||||
throw "Not enough free space to download the ISO."
|
||||
}
|
||||
}
|
||||
|
||||
# Step 5: Mount the ISO file as a volume
|
||||
$volumeInfo = Mount-DiskImage -ImagePath $isoLocation -PassThru | Get-Volume
|
||||
|
||||
# Step 6: Run unattended SQL Server setup from the mounted volume
|
||||
$setupPath = ($volumeInfo.DriveLetter + ":\setup.exe")
|
||||
$argumentList = "
|
||||
/q
|
||||
/ACTION=Install
|
||||
/FEATURES=SQL
|
||||
/INSTANCEDIR=C:\SQL
|
||||
/SQLSYSADMINACCOUNTS='$($SqlServerAdminAccounts)'
|
||||
/SQLSVCACCOUNT='$($SqlServerSvcAccount)'
|
||||
/SQLSVCPASSWORD='$($SqlServerSvcPassword)'
|
||||
/AGTSVCACCOUNT='$($SqlServerSvcAccount)'
|
||||
/AGTSVCPASSWORD='$($SqlServerSvcPassword)'
|
||||
/IACCEPTSQLSERVERLICENSETERMS
|
||||
/PID='$($SqlServerProductKey)'
|
||||
/Edition='$($SqlServerEdition)'
|
||||
"
|
||||
if ($SqlServerInstanceName) {
|
||||
$argumentList += "/INSTANCENAME='$($SqlServerInstanceName)'"
|
||||
}
|
||||
|
||||
Start-Process -FilePath $setupPath -ArgumentList $argumentList
|
||||
|
||||
# Step 7: Install SQL Arc extension with LT=PAYG
|
||||
$Settings = @{
|
||||
SqlManagement = @{ IsEnabled = $true };
|
||||
LicenseType = "PAYG";
|
||||
enableExtendedSecurityUpdates = $True;
|
||||
esuLastUpdatedTimestamp = [DateTime]::UtcNow.ToString('yyyy-MM-ddTHH:mm:ss.fffZ')
|
||||
}
|
||||
New-AzConnectedMachineExtension -ResourceGroupName $AzureResourceGroupUri -MachineName $hostName -Name "WindowsAgent.SqlServer" -Publisher "Microsoft.AzureData" -Type "WindowsAgent.SqlServer" -TypeHandlerVersion "1.0" -Settings $settings
|
||||
|
||||
# Step 9: Dismount the ISO file after installation
|
||||
Dismount-DiskImage -ImagePath $isoLocation
|
||||
|
||||
# Step 10: Remove the media from the local file system
|
||||
Remove-Item -Path $isoLocation
|
||||
|
||||
# Step 8: Display the status of the Azure resource for Arc-enabled SQL Server
|
||||
$query = "
|
||||
resources
|
||||
| where type =~ 'microsoft.hybridcompute/machines'
|
||||
| where resourceGroup =~ '$($AzureResourceGroupUri)'
|
||||
| where properties.detectedProperties.mssqldiscovered == 'true'
|
||||
| extend machineIdHasSQLServerDiscovered = id
|
||||
| project name, machineIdHasSQLServerDiscovered, resourceGroup, subscriptionId
|
||||
| join kind= leftouter (
|
||||
resources
|
||||
| where type == 'microsoft.hybridcompute/machines/extensions' | where properties.type in ('WindowsAgent.SqlServer','LinuxAgent.SqlServer')
|
||||
| extend machineIdHasSQLServerExtensionInstalled = iff(id contains '/extensions/WindowsAgent.SqlServer' or id contains '/extensions/LinuxAgent.SqlServer', substring(id, 0, indexof(id, '/extensions/')), '')
|
||||
| project Extension_State = properties.provisioningState,
|
||||
License_Type = properties.settings.LicenseType,
|
||||
ESU = iff(notnull(properties.settings.enableExtendedSecurityUpdates), iff(properties.settings.enableExtendedSecurityUpdates == true,'enabled','disabled'), ''),
|
||||
Extension_Version = properties.instanceView.typeHandlerVersion,
|
||||
machineIdHasSQLServerExtensionInstalled)on $left.machineIdHasSQLServerDiscovered == $right.machineIdHasSQLServerExtensionInstalled
|
||||
| where isnotempty(machineIdHasSQLServerExtensionInstalled)
|
||||
| project-away machineIdHasSQLServerDiscovered, machineIdHasSQLServerExtensionInstalled
|
||||
"
|
||||
Search-AzGraph -Query "$($query)"
|
||||
|
||||
} catch {
|
||||
Write-Error "An error occurred: $_"
|
||||
# You can add additional error handling logic here
|
||||
} finally {
|
||||
# Cleanup or other actions that should always run
|
||||
Write-Host "Script execution completed."
|
||||
}
|
||||
Reference in New Issue
Block a user