diff --git a/CHANGELOG.md b/CHANGELOG.md index 03790fd95..af1af4874 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,10 @@ - Changes to xSQLServerAvailabilityGroupListener - Fixed a problem when running the tests locally in a PowerShell console it would ask for parameters ([issue #897](https://github.com/PowerShell/xSQLServer/issues/897)). +- Changes to xSQLServerMaxDop + - Made the resource cluster aware. When ProcessOnlyOnActiveNode is specified, + the resource will only determine if a change is needed if the target node + is the active host of the SQL Server instance ([issue #882](https://github.com/PowerShell/xSQLServer/issues/882)). ## 8.2.0.0 diff --git a/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.psm1 b/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.psm1 index 206d8db23..1eb7d49f7 100644 --- a/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.psm1 +++ b/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.psm1 @@ -30,6 +30,9 @@ function Get-TargetResource $sqlServerObject = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + # Is this node actively hosting the SQL instance? + $isActiveNode = Test-ActiveNode -ServerObject $sqlServerObject + if ($sqlServerObject) { Write-Verbose -Message 'Getting the max degree of parallelism server configuration option' @@ -40,6 +43,7 @@ function Get-TargetResource SQLInstanceName = $SQLInstanceName SQLServer = $SQLServer MaxDop = $currentMaxDop + IsActiveNode = $isActiveNode } $returnValue @@ -65,6 +69,10 @@ function Get-TargetResource .PARAMETER MaxDop A numeric value to limit the number of processors used in parallel plan execution. + + .PARAMETER ProcessOnlyOnActiveNode + Specifies that the resource will only determine if a change is needed if the target node is the active host of the SQL Server Instance. + Not used in Set-TargetResource. #> function Set-TargetResource { @@ -93,7 +101,11 @@ function Set-TargetResource [Parameter()] [System.Int32] - $MaxDop + $MaxDop, + + [Parameter()] + [System.Boolean] + $ProcessOnlyOnActiveNode ) $sqlServerObject = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName @@ -166,6 +178,9 @@ function Set-TargetResource .PARAMETER MaxDop A numeric value to limit the number of processors used in parallel plan execution. + + .PARAMETER ProcessOnlyOnActiveNode + Specifies that the resource will only determine if a change is needed if the target node is the active host of the SQL Server Instance. #> function Test-TargetResource { @@ -195,7 +210,11 @@ function Test-TargetResource [Parameter()] [System.Int32] - $MaxDop + $MaxDop, + + [Parameter()] + [System.Boolean] + $ProcessOnlyOnActiveNode ) Write-Verbose -Message 'Testing the max degree of parallelism server configuration option' @@ -206,13 +225,24 @@ function Test-TargetResource } $currentValues = Get-TargetResource @parameters + $getMaxDop = $currentValues.MaxDop $isMaxDopInDesiredState = $true + <# + If this is supposed to process only the active node, and this is not the + active node, don't bother evaluating the test. + #> + if ( $ProcessOnlyOnActiveNode -and -not $getTargetResourceResult.IsActiveNode ) + { + New-VerboseMessage -Message ( 'The node "{0}" is not actively hosting the instance "{1}". Exiting the test.' -f $env:COMPUTERNAME,$SQLInstanceName ) + return $isMaxDopInDesiredState + } + switch ($Ensure) { 'Absent' - { + { if ($getMaxDop -ne 0) { New-VerboseMessage -Message "Current MaxDop is $getMaxDop should be updated to 0" @@ -260,17 +290,17 @@ function Test-TargetResource function Get-SqlDscDynamicMaxDop { $cimInstanceProc = Get-CimInstance -ClassName Win32_Processor - + # init variables $numProcs = 0 $numCores = 0 - + # Loop through returned objects foreach ($processor in $cimInstanceProc) { # increment number of processors $numProcs += $processor.NumberOfLogicalProcessors - + # increment number of cores $numCores += $processor.NumberOfCores } diff --git a/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.schema.mof b/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.schema.mof index c89512c3e..91efe692c 100644 --- a/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.schema.mof +++ b/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.schema.mof @@ -6,4 +6,6 @@ class MSFT_xSQLServerMaxDop : OMI_BaseResource [Write, Description("A numeric value to limit the number of processors used in parallel plan execution.")] Sint32 MaxDop; [Write, Description("The host name of the SQL Server to be configured. Default value is $env:COMPUTERNAME.")] String SQLServer; [Key, Description("The name of the SQL instance to be configured.")] String SQLInstanceName; + [Write, Description("Specifies that the resource will only determine if a change is needed if the target node is the active host of the SQL Server instance.")] Boolean ProcessOnlyOnActiveNode; + [Read, Description("Determines if the current node is actively hosting the SQL Server instance.")] Boolean IsActiveNode; }; diff --git a/Examples/Resources/xSQLServerMaxDop/2-SetMaxDopToAuto.ps1 b/Examples/Resources/xSQLServerMaxDop/2-SetMaxDopToAuto.ps1 index 4d3f30772..4cfd75451 100644 --- a/Examples/Resources/xSQLServerMaxDop/2-SetMaxDopToAuto.ps1 +++ b/Examples/Resources/xSQLServerMaxDop/2-SetMaxDopToAuto.ps1 @@ -2,6 +2,11 @@ .EXAMPLE This example shows how to set max degree of parallelism server configuration option with the automatic configuration. + + In the event this is applied to a Failover Cluster Instance (FCI), the + ProcessOnlyOnActiveNode property will tell the Test-TargetResource function + to evaluate if any changes are needed if the node is actively hosting the + SQL Server instance. #> Configuration Example { @@ -19,11 +24,12 @@ Configuration Example { xSQLServerMaxDop Set_SQLServerMaxDop_ToAuto { - Ensure = 'Present' - DynamicAlloc = $true - SQLServer = 'SQLServer' - SQLInstanceName = 'DSC' - PsDscRunAsCredential = $SysAdminAccount + Ensure = 'Present' + DynamicAlloc = $true + SQLServer = 'SQLServer' + SQLInstanceName = 'DSC' + PsDscRunAsCredential = $SysAdminAccount + ProcessOnlyOnActiveNode = $true } } } diff --git a/README.md b/README.md index c8010639d..499516b9c 100644 --- a/README.md +++ b/README.md @@ -935,6 +935,14 @@ Read more about max degree of parallelism in this article parameter MaxDop must be set to $null or not be configured. * **`[Sint32]` MaxDop** _(Write)_: A numeric value to limit the number of processors used in parallel plan execution. +* **`[Boolean]` ProcessOnlyOnActiveNode** _(Write)_: Specifies that the resource + will only determine if a change is needed if the target node is the active + host of the SQL Server instance. + +#### Read-Only Property from Get-TargetResource + +* **`[Boolean]` IsActiveNode** _(Read)_: Determines if the current node is + actively hosting the SQL Server instance. #### Examples diff --git a/Tests/Unit/MSFT_xSQLServerMaxDop.Tests.ps1 b/Tests/Unit/MSFT_xSQLServerMaxDop.Tests.ps1 index 7e33afdc5..ca3092649 100644 --- a/Tests/Unit/MSFT_xSQLServerMaxDop.Tests.ps1 +++ b/Tests/Unit/MSFT_xSQLServerMaxDop.Tests.ps1 @@ -13,6 +13,9 @@ if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCR Import-Module (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1') -Force +# Loading mocked classes +Add-Type -Path ( Join-Path -Path ( Join-Path -Path $PSScriptRoot -ChildPath Stubs ) -ChildPath SMO.cs ) + $TestEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:DSCModuleName ` -DSCResourceName $script:DSCResourceName ` @@ -40,6 +43,7 @@ try $mockInvalidOperationForAlterMethod = $false $mockNumberOfLogicalProcessors = 4 $mockNumberOfCores = 4 + $mockProcessOnlyOnActiveNode = $true # Default parameters that are used for the It-blocks $mockDefaultParameters = @{ @@ -52,9 +56,9 @@ try $mockConnectSQL = { return @( ( - New-Object Object | - Add-Member -MemberType NoteProperty -Name InstanceName -Value $mockSQLServerInstanceName -PassThru | - Add-Member -MemberType NoteProperty -Name ComputerNamePhysicalNetBIOS -Value $mockSQLServerName -PassThru | + New-Object Object -TypeName Microsoft.SqlServer.Management.Smo.Server | + Add-Member -MemberType NoteProperty -Name InstanceName -Value $mockSQLServerInstanceName -PassThru -Force | + Add-Member -MemberType NoteProperty -Name ComputerNamePhysicalNetBIOS -Value $mockSQLServerName -PassThru -Force | Add-Member -MemberType ScriptProperty -Name Configuration -Value { return @( ( New-Object Object | Add-Member -MemberType ScriptProperty -Name MaxDegreeOfParallelism -Value { @@ -96,6 +100,7 @@ try Describe "MSFT_xSQLServerMaxDop\Get-TargetResource" -Tag 'Get'{ Mock -CommandName Connect-SQL -MockWith $mockConnectSQL -Verifiable + Mock -CommandName Test-ActiveNode -MockWith { return $mockProcessOnlyOnActiveNode } -Verifiable Context 'When the system is either in the desired state or not in the desired state' { $testParameters = $mockDefaultParameters @@ -114,6 +119,10 @@ try It 'Should call the mock function Connect-SQL' { Assert-MockCalled Connect-SQL -Exactly -Times 1 -Scope Context } + + It 'Should call the mock function Test-ActiveNode' { + Assert-MockCalled Test-ActiveNode -Exactly -Times 1 -Scope Context + } } Assert-VerifiableMock @@ -123,6 +132,10 @@ try BeforeEach { Mock -CommandName Connect-SQL -MockWith $mockConnectSQL -Verifiable + Mock -CommandName Test-ActiveNode -MockWith { + $mockProcessOnlyOnActiveNode + } -Verifiable + Mock -CommandName Get-CimInstance -MockWith $mockCimInstance_Win32Processor -ParameterFilter { $ClassName -eq 'Win32_Processor' } -Verifiable @@ -290,6 +303,31 @@ try } } + Context 'When the ProcessOnlyOnActiveNode parameter is passed' { + AfterAll { + $mockProcessOnlyOnActiveNode = $true + } + + BeforeAll { + $testParameters = $mockDefaultParameters + $testParameters += @{ + Ensure = 'Absent' + ProcessOnlyOnActiveNode = $true + } + + $mockProcessOnlyOnActiveNode = $false + } + + It 'Should return $true when ProcessOnlyOnActiveNode is "$true" and the current node is not actively hosting the instance' { + $result = Test-TargetResource @testParameters + $result | Should -Be $true + } + + It 'Should call the mock function Connect-SQL' { + Assert-MockCalled Connect-SQL -Exactly -Times 1 -Scope Context + } + } + $mockMaxDegreeOfParallelism = 0 Context 'When the system is in the desired state and Ensure is set to absent' {