Failover forzato

Microsoft.SQLServer.Windows.ConsoleTask.AvailabilityReplica.ForcedFailover (ConsoleTask)

Aprire la console SQLPS ed effettuare il failover nella replica di disponibilità di destinazione in modo che quest'ultima diventi la nuova replica primaria del gruppo di disponibilità. In questa attività viene usato il parametro AllowDataLoss.

Element properties:

TargetMicrosoft.SQLServer.Windows.AvailabilityReplica
Applicationpowershell.exe
WorkingDirectory
isRequireOutputFalse
AccessibilityInternal
EnabledTrue

Source Code:

<ConsoleTask ID="Microsoft.SQLServer.Windows.ConsoleTask.AvailabilityReplica.ForcedFailover" Accessibility="Internal" Target="SqlDiscW!Microsoft.SQLServer.Windows.AvailabilityReplica" RequireOutput="false">
<Assembly>Res.Microsoft.SQLServer.Windows.ConsoleTask.AvailabilityReplica.ForcedFailover</Assembly>
<Handler>ShellHandler</Handler>
<Parameters>
<Argument Name="Application">powershell.exe</Argument>
<Argument Name="WorkingDirectory"/>
<Argument>-NoExit -NoLogo -NoProfile -Command Invoke-Command {
$isForcedFailover = $true
# PsTaskCommon.ps1

$arAssemblies = @(,'\PowerShell\Modules\SQLPS\SQLPS.psd1');

function ImportModuleActionSqlModules($arAssemblies){
$paths = GetSqlToolsPaths
if (!(ImportSQLModules $arAssemblies $paths)) {
Import-Module SQLPS -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
if(!(IsModuleLoaded 'SQLPS'))
{
throw 'Unable to load SQLPS modules'
}
}
}

function GetSqlToolsPaths(){
$pathVersions = @('140','130','120','110')
$pathTemplates = @('HKLM:\Software\Microsoft\Microsoft SQL Server\{0}\Tools\ClientSetup\',
'HKLM:\Software\Wow6432Node\Microsoft\Microsoft SQL Server\{0}\Tools\ClientSetup\')
$includeTemplate = '{0}\Tools'
$paths = @()

foreach($version in $pathVersions){
$checkInclude = $includeTemplate -f $version
foreach($template in $pathTemplates){
$path = $template -f $version
$sqlPathObj = Get-ItemProperty -Path $path -Name 'SQLPath' -ErrorAction SilentlyContinue
if($sqlPathObj -ne $null){
$sqlPath = $sqlPathObj.SQLPath
if(![string]::IsNullOrEmpty($sqlPath) -and $sqlPath.Contains($checkInclude)){
$paths += $sqlPath
}
}
}
}
return $paths
}

function IsModuleLoaded([string] $sqlModuleName) {
$modules = Get-Module
foreach($module in $modules){
if($module.Name.Contains($sqlModuleName)) {
return $true
}
}
return $false
}

function ImportSQLModules($arAssemblies, $paths) {
$assembliesToLoad = New-Object System.Collections.ArrayList ((,$arAssemblies))
foreach($path in $paths){
foreach($assemblyName in $assembliesToLoad.ToArray()){
$filename = $path + $assemblyName
if(Test-Path $filename){
$module = Import-Module $filename -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -PassThru
if($module -eq $null){
continue
}
$assembliesToLoad.Remove($assemblyName)
if($assembliesToLoad.Count -eq 0){
return $true
}
}
}
}
return $false
}

function GetInstancePathName([string] $name){
if ($name -ilike '*\*') {
return $name
}
else {
return '{0}\DEFAULT' -f $name
}
}

function EncodeSqlName([string] $name){
$sb = New-Object 'System.Text.StringBuilder'

for($ind = 0; $ind -lt $name.Length; ++$ind){
if([char]::IsControl($name[$ind]) -or [int]$name[$ind] -eq 46 -or '\\/:%&lt;&gt;*?[]|'.Contains($name[$ind].ToString())){
[void]$sb.Append(('%{0:X2}' -f [byte]$name[$ind]))
}
else{
[void]$sb.Append($name[$ind])
}
}
return $sb.ToString()
}

ImportModuleActionSqlModules $arAssemblies
# FailoverTaskCommon.ps1

#Depends on:
# PsTaskCommon.ps1

$p = 0
$destInstanceNameParam = @'
$Target/Property[Type="System!System.Entity"]/DisplayName$
'@
$p = 0
$agNameParam = @'
$Target/Property[Type="SqlCoreLib!Microsoft.SQLServer.Core.AvailabilityReplica"]/AvailabilityGroupName$
'@
$p = 0
$arNameParam = @'
$Target/Property[Type="System!System.Entity"]/DisplayName$
'@

$destInstanceName = GetInstancePathName $destInstanceNameParam
$agPathName = EncodeSqlName $agNameParam
$arPathName = EncodeSqlName $arNameParam

cd ('sqlserver:\SQL\{0}\AvailabilityGroups\{1}\AvailabilityReplicas\{2}\' -f $destInstanceName, $agPathName, $arPathName)

$ag = (Get-Item ('..\..\..\{0}' -f $agPathName))

try{
if($isForcedFailover){
Switch-SqlAvailabilityGroup -InputObject $ag -AllowDataLoss -Confirm
}
else{
Switch-SqlAvailabilityGroup -InputObject $ag -Confirm;
}
}
catch{
Write-Host -ForegroundColor Red $_.Exception.Message
}

Write-Host "Press any key to exit..."
[void][Console]::ReadKey($true)

}</Argument>
</Parameters>
</ConsoleTask>