182 lines
6.6 KiB
PowerShell
182 lines
6.6 KiB
PowerShell
# Copyright 2022 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
|
|
} |