cloud-foundation-fabric/blueprints/data-solutions/sqlserver-alwayson/scripts/windows-startup-node.ps1

182 lines
6.6 KiB
PowerShell

# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
${functions}
$ErrorActionPreference = "stop"
$InitialSetup = 'c:\InitialSetupDone.txt'
if (-not(Test-Path -Path $InitialSetup -PathType Leaf)) {
Write-Log "Performing initial setup"
$DatabaseName = Invoke-SqlCmd -Query "SELECT serverproperty('ServerName') AS ServerName"
if (($DatabaseName | Select -ExpandProperty ServerName) -ne $env:computername) {
Write-Log "Setting up SQL server database..."
Invoke-Sqlcmd -Query "
sp_dropserver 'INST-INSTALL-SQ';
GO
sp_addserver '$env:computername', local;
GO"
}
All-Instances-Ready
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SqlWmiManagement") | out-null
$SMOWmiserver = New-Object ("Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer") $env:computername
$ChangeService = $SMOWmiserver.Services | where {$_.name -eq "MSSQLSERVER"}
$UName = "${ad_netbios}\${sql_user_name}"
$Secret = gcloud --quiet secrets versions access latest --secret="${sql_admin_password_secret}"
$Password = ConvertTo-SecureString $Secret -AsPlainText -Force
if ($env:computername -eq "${node_netbios_1}") {
$SetupScript = @'
$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$root = $dom.GetDirectoryEntry()
$searcher = [ADSISearcher] $root
$searcher.Filter = "(sAMAccountName=${sql_user_name})"
if ($null -eq $searcher.FindOne())
{
$Secret = gcloud --quiet secrets versions access latest --secret="${sql_admin_password_secret}"
$Password = ConvertTo-SecureString $Secret -AsPlainText -Force
Write-Output "Adding domain user: ${sql_user_name}"
New-ADUser -Name "${sql_user_name}" -Description "SQL Admin account" -AccountPassword $Password -Enabled $true -PasswordNeverExpires $true ${managed_ad_dn_path}
}
try {
Get-ADComputer -Identity "${sql_cluster_name}"
} catch {
Write-Output "Creating cluster: ${sql_cluster_full} (NB: ${sql_cluster_name})"
New-Cluster -Name ${sql_cluster_full} -Node ${node_netbios_1},${node_netbios_2} -NoStorage -StaticAddress ${cluster_ip}
Start-Sleep -s 45
%{ if managed_ad_dn != "" }
Write-Output "Adding ${sql_cluster_name}$ to Cloud Service Domain Join Accounts"
Add-ADGroupMember -Identity "Cloud Service Domain Join Accounts" -Members ${sql_cluster_name}$
%{ endif }
}
$spn = "MSSQLSvc/" + "${node_netbios_1}.$env:userdnsdomain".ToLower()
SetSPN -d "$${spn}:1433" ${node_netbios_1}
SetSPN -d "$${spn}" ${node_netbios_1}
$spn = "MSSQLSvc/" + "${node_netbios_2}.$env:userdnsdomain".ToLower()
SetSPN -d "$${spn}:1433" ${node_netbios_2}
SetSPN -d "$${spn}" ${node_netbios_2}
'@
$InitializeClusterScript = "C:\InitializeCluster.ps1"
Write-Log "Writing initial setup script to $InitializeClusterScript"
$SetupScript | Out-File -FilePath $InitializeClusterScript
}
Wait-For-User
if ($ChangeService.ServiceAccount -ne $UName) {
Write-Log "Changing SQL server to run under new account..."
$ChangeService.SetServiceAccount($UName, $Secret)
Write-Log "Restarting SQL Server..."
Restart-Service -Name MSSQLSERVER
Start-Sleep -s 15
}
Write-Log "Waiting for cluster to appear..."
Cluster-Ready
Node-Up
Start-Sleep -s 10
$HADROn = Invoke-SqlCmd -Query "SELECT SERVERPROPERTY('IsHadrEnabled') AS IsHadrEnabled"
if (($HADROn | Select -ExpandProperty IsHadrEnabled) -ne 1) {
Write-Log "Enabling HA/DR functionality in SQL Server..."
Enable-SqlAlwaysOn -ServerInstance $env:computername -Force
Start-Sleep -s 15
Invoke-SqlCmd -Query "CREATE LOGIN [${ad_netbios}\${sql_user_name}] FROM WINDOWS"
Start-Sleep -s 5
}
# Wait for other node to finish
Start-Sleep -s 30
if ($env:computername -eq "${node_netbios_1}") {
$Quorum = Get-ClusterQuorum
if ($Quorum.QuorumResource.State -ne "Online") {
while ($true) {
try {
Write-Log "Turning on witness quorum in cluster..."
Set-ClusterQuorum -FileShareWitness \\${witness_netbios}\QWitness
break
} catch {}
Start-Sleep -s 5
}
}
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
while ($true) {
$svr = New-Object Microsoft.SqlServer.Management.Smo.Server
$AllFound = $true
%{ for aog in split(",", always_on_groups) }
Write-Log "Waiting for Always On Group: ${aog}..."
if (($svr.AvailabilityGroups.Count -eq 0) -or (($svr.AvailabilityGroups | Select -ExpandProperty Name) -notmatch "${aog}")) {
$AllFound = $false
}
%{ endfor }
if ($AllFound) {
break
}
Start-Sleep -s 10
}
# Wait until AOGs have settled
Start-Sleep -s 30
%{ for aog in split(",", always_on_groups) }
Write-Log "Configuring Always On Group: ${aog}..."
$LoadBalancerIP = "${jsondecode(loadbalancer_ips)[aog]}"
$SqlIpAddress = Get-ClusterResource |
Where-Object {$_.ResourceType -eq "IP Address"} |
Where-Object {$_.Name.StartsWith("${aog}")}
$ClusterParameters = $SqlIpAddress | Get-ClusterParameter
$ConfiguredIP = $ClusterParameters | Where-Object Name -eq "Address" | Select Value
if ($ConfiguredIP -ne $LoadBalancerIP) {
Write-Log "Configuring Always on Group ${aog} with load balancer IP: $LoadBalancerIP"
$SqlIpAddress | Set-ClusterParameter -Multiple @{
'Address' = $LoadBalancerIP;
'ProbePort' = ${health_check_port};
'SubnetMask' = '255.255.255.255';
'Network' = (Get-ClusterNetwork).Name;
'EnableDhcp' = 0;
}
Write-Log "Stopping and starting cluster resource..."
$SqlIpAddress | Stop-ClusterResource
$SqlIpAddress = Get-ClusterResource | Where-Object {$_.Name.StartsWith("${aog}")} | Start-ClusterResource
Start-Sleep -s 10
}
%{ endfor }
}
while ($true) {
Write-Log "Waiting for Hadr_endpoint for GRANT CONNECT..."
try {
Invoke-SqlCmd -Query "GRANT CONNECT ON ENDPOINT::Hadr_endpoint TO [${ad_netbios}\${sql_user_name}]"
break
} catch {}
Start-Sleep -s 3
}
Write-Log "Setup finished completely."
New-Item $InitialSetup
}