diff --git a/DSCResources/MSFT_xSQLAOGroupEnsure/MSFT_xSQLAOGroupEnsure.psm1 b/DSCResources/MSFT_xSQLAOGroupEnsure/MSFT_xSQLAOGroupEnsure.psm1 new file mode 100644 index 000000000..6a693a4da --- /dev/null +++ b/DSCResources/MSFT_xSQLAOGroupEnsure/MSFT_xSQLAOGroupEnsure.psm1 @@ -0,0 +1,352 @@ +$currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path +Write-Verbose -Message "CurrentPath: $currentPath" + +# Load Common Code +Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAction Stop + +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [parameter(Mandatory = $true)] + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [parameter(Mandatory = $true)] + [System.String] + $AvailabilityGroupName, + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [ValidateNotNull()] + [System.String] + $SQLInstanceName= "MSSQLSERVER", + + [parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $SetupCredential + ) + + if(!$SQL) + { + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + } + + $vConfigured = Test-TargetResource -Ensure $Ensure -AvailabilityGroupName $AvailabilityGroupName -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + + $returnValue = @{ + Ensure = $vConfigured + AvailabilityGroupName = $sql.AvailabilityGroups[$AvailabilityGroupName] + AvailabilityGroupNameListener = $sql.AvailabilityGroups[$AvailabilityGroupName].AvailabilityGroupListeners.name + AvailabilityGroupNameIP = $sql.AvailabilityGroups[$AvailabilityGroupName].AvailabilityGroupListeners.availabilitygrouplisteneripaddresses.IPAddress + AvailabilityGroupSubMask = $sql.AvailabilityGroups[$AvailabilityGroupName].AvailabilityGroupListeners.availabilitygrouplisteneripaddresses.SubnetMask + AvailabilityGroupPort = $sql.AvailabilityGroups[$AvailabilityGroupName].AvailabilityGroupListeners.portnumber + AvailabilityGroupNameDatabase = $sql.AvailabilityGroups[$AvailabilityGroupName].AvailabilityDatabases.name + BackupDirectory = "" + SQLServer = $SQLServer + SQLInstanceName = $SQLInstanceName + } + + $returnValue +} + + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [parameter(Mandatory = $true)] + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [parameter(Mandatory = $true)] + [System.String] + $AvailabilityGroupName, + + [System.String] + $AvailabilityGroupNameListener = $AvailabilityGroupName, + + [System.String[]] + $AvailabilityGroupNameIP, + + [System.String[]] + $AvailabilityGroupSubMask, + + [System.UInt32] + $AvailabilityGroupPort ="1433", + + [ValidateSet("None","ReadOnly","ReadIntent")] + [System.String] + $ReadableSecondary="ReadOnly", + + [ValidateSet("Primary","Secondary")] + [System.String] + $AutoBackupPrefernce ="Primary", + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [System.String] + $SQLInstanceName= "MSSQLSERVER", + + [parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $SetupCredential + ) + + $null = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') + $null = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") + + if(!$SQL) + { + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName -SetupCredential $SetupCredential + } + + if (($AvailabilityGroupNameIP -and !$AvailabilityGroupSubMask) -or (!$AvailabilityGroupNameIP -and $AvailabilityGroupSubMask)) + { + Throw "AvailabilityGroupNameIP and AvailabilityGroupSubMask must both be passed for Static IP assignment." + Exit + } + + Switch ($Ensure) + { + "Present" + { + Grant-ServerPerms -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName -AuthorizedUser "NT AUTHORITY\SYSTEM" -SetupCredential $SetupCredential + New-ListenerADObject -AvailabilityGroupNameListener $AvailabilityGroupNameListener -SetupCredential $SetupCredential + + $FailoverCondition = 3 + $HealthCheckTimeout = 30000 + $ConnectionModeInPrimary ="AllowAllConnections" + $ConnectionModeInSecondaryRole = switch ($ReadableSecondary) + { + 'None' {"AllowNoConnections"} + 'ReadOnly' {"AllowAllConnections"} + 'ReadIntent'{"AllowReadIntentConnectionsOnly"} + Default {"AllowAllConnections"} + } + + #Get Servers participating in the cluster + #First two nodes will account for Syncronous Automatic Failover, Any additional will be Asyncronous + try + { + $nodes= Get-ClusterNode -cluster $sql.ClusterName -Verbose:$false | select -ExpandProperty name + $syncNodes = $nodes | Select-Object -First 2 + $asyncNodes = $nodes | Select-Object -Skip 2 + $availabilityGroup = New-Object -typename Microsoft.SqlServer.Management.Smo.AvailabilityGroup -ArgumentList $SQL, $AvailabilityGroupName + $availabilityGroup.AutomatedBackupPreference="Primary" + $availabilityGroup.FailureConditionLevel = $FailoverCondition + $availabilityGroup.HealthCheckTimeout =$HealthCheckTimeout + } + Catch + { + Throw "Failed to connect to Cluster Nodes from $sql.ClusterName" + Exit + } + + #Loop through Sync nodes Create Replica Object Assign properties and add it to AvailabilityGroup + foreach ($node in $syncNodes) + { + Try + { + $Replica = New-Object -typename Microsoft.SqlServer.Management.Smo.AvailabilityReplica -ArgumentList $availabilityGroup, $node + $Replica.EndpointUrl = "TCP://$($node):5022" + $Replica.FailoverMode = [Microsoft.SqlServer.Management.Smo.AvailabilityReplicaFailoverMode]::Automatic + $Replica.AvailabilityMode = [Microsoft.SqlServer.Management.Smo.AvailabilityReplicaAvailabilityMode]::SynchronousCommit + #Backup Priority Gives the ability to set a priority of one secondany over another valid values are from 1 - 100 + $Replica.BackupPriority = 50 + $Replica.ConnectionModeInPrimaryRole = $ConnectionModeInPrimary + $replica.ConnectionModeInSecondaryRole = $ConnectionModeInSecondaryRole + $availabilityGroup.AvailabilityReplicas.Add($Replica) + } + Catch + { + Throw "Failed to add $Replica to the Availability Group $AvailabilityGroupName" + Exit + } + + } + + #Loop through ASync nodes Create Replica Object Assign properties and add it to AvailabilityGroup + foreach ($node in $AsyncNodes) + { + Try + { + $asyncReplica = New-Object -typename Microsoft.SqlServer.Management.Smo.AvailabilityReplica -ArgumentList $availabilityGroup, $node + $asyncReplica.EndpointUrl = "TCP://$($node):5022" + $asyncReplica.FailoverMode = [Microsoft.SqlServer.Management.Smo.AvailabilityReplicaFailoverMode]::Manual + $asyncReplica.AvailabilityMode = [Microsoft.SqlServer.Management.Smo.AvailabilityReplicaAvailabilityMode]::ASynchronousCommit + $asyncReplica.BackupPriority = 50 + $asyncReplica.ConnectionModeInPrimaryRole = $ConnectionModeInPrimary + $asyncReplica.ConnectionModeInSecondaryRole = $ConnectionModeInSecondaryRole + $AvailabilityGroup.AvailabilityReplicas.Add($asyncReplica) + } + Catch + { + Write-Error "Failed to add $asyncReplica to the Availability Group $AvailabilityGroupName" + } + } + + Try{ + $AgListener = New-Object -typename Microsoft.SqlServer.Management.Smo.AvailabilityGroupListener -ArgumentList $AvailabilityGroup, $AvailabilityGroupNameListener + $AgListener.PortNumber =$AvailabilityGroupPort + } + Catch{ + Write-Error -Message ((Get-Date -format yyyy-MM-dd_HH-mm-ss) + ": Failed to Create AG Listener Object"); + } + + + If($AvailabilityGroupNameIP) + { + Foreach ($IP in $AvailabilityGroupNameIP) + { + $AgListenerIp = New-Object -typename Microsoft.SqlServer.Management.Smo.AvailabilityGroupListenerIPAddress -ArgumentList $AgListener + $AgListenerIp.IsDHCP = $false + $AgListenerIp.IPAddress = $IP + $AgListenerIp.SubnetMask = $AvailabilityGroupSubMask + $AgListener.AvailabilityGroupListenerIPAddresses.Add($AgListenerIp) + New-VerboseMessage -Message "Added Static IP $IP to $AvailabilityGroupNameListener..." + + } + } + Else + { + #Utilize Dynamic IP since no Ip was passed + $AgListenerIp = New-Object -typename Microsoft.SqlServer.Management.Smo.AvailabilityGroupListenerIPAddress -ArgumentList $AgListener + $AgListenerIp.IsDHCP = $true + $AgListener.AvailabilityGroupListenerIPAddresses.Add($AgListenerIp) + New-VerboseMessage -Message "Added DynamicIP to $AvailabilityGroupNameListener..." + } + + Try{ + $AvailabilityGroup.AvailabilityGroupListeners.Add($AgListener); + } + Catch{ + Throw "Failed to Add $AvailabilityGroupNameListener to $AvailabilityGroupName..." + Exit + } + + #Add Availabilty Group to the SQL connection + Try{ + $SQL.AvailabilityGroups.Add($availabilityGroup) + New-VerboseMessage -Message "Added $availabilityGroupName Availability Group to Connection" + } + Catch{ + Throw "Unable to Add $AvailabilityGroup to $SQLServer\$SQLInstanceName" + Exit + } + + #Create Availability Group + Try + { + $availabilityGroup.Create() + New-VerboseMessage -Message "Created Availability Group $availabilityGroupName" + } + Catch + { + Throw "Unable to Create $AvailabilityGroup on $SQLServer\$SQLInstanceName" + Exit + } + + } + "Absent" + { + Try + { + $sql.AvailabilityGroups[$AvailabilityGroupName].Drop() + NNew-VerboseMessage -Message "Dropped $AvailabilityGroupName" + } + Catch{ + Throw "Unable to Drop $AvailabilityGroup on $SQLServer\$SQLInstanceName" + } + } + } + + + +} + + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [parameter(Mandatory = $true)] + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [parameter(Mandatory = $true)] + [System.String] + $AvailabilityGroupName, + + [System.String] + $AvailabilityGroupNameListener, + + [System.String[]] + $AvailabilityGroupNameIP, + + [System.String[]] + $AvailabilityGroupSubMask, + + [System.UInt32] + $AvailabilityGroupPort, + + [ValidateSet("None","ReadOnly","ReadIntent")] + [System.String] + $ReadableSecondary ="ReadOnly", + + [ValidateSet("Primary","Secondary")] + [System.String] + $AutoBackupPrefernce="Primary", + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [System.String] + $SQLInstanceName= "MSSQLSERVER", + + [parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $SetupCredential + ) + + if(!$SQL) + { + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + } + + Switch ($Ensure) + { + "Present" + { + + $AGPresent=$sql.AvailabilityGroups.Contains($AvailabilityGroupName) + + if ($AGPresent) + {$Return = $true} + else + {$Return = $false} + } + "Absent" + { + if(!$sql.AvailabilityGroups[$AvailabilityGroupName]) + {$Return = $true} + else{$Return = $false} + } + } + $Return + +} + + +Export-ModuleMember -Function *-TargetResource + diff --git a/DSCResources/MSFT_xSQLAOGroupEnsure/MSFT_xSQLAOGroupEnsure.schema.mof b/DSCResources/MSFT_xSQLAOGroupEnsure/MSFT_xSQLAOGroupEnsure.schema.mof new file mode 100644 index 000000000..378472877 --- /dev/null +++ b/DSCResources/MSFT_xSQLAOGroupEnsure/MSFT_xSQLAOGroupEnsure.schema.mof @@ -0,0 +1,17 @@ + +[ClassVersion("1.0.0.0"), FriendlyName("xSQLAOGroupEnsure")] +class MSFT_xSQLAOGroupEnsure : OMI_BaseResource +{ + [Key, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Key] String AvailabilityGroupName; + [Write] String AvailabilityGroupNameListener; + [Write] String AvailabilityGroupNameIP[]; + [Write] String AvailabilityGroupSubMask[]; + [Write] Uint32 AvailabilityGroupPort; + [Write, ValueMap{"None","ReadOnly","ReadIntent"}, Values{"None","ReadOnly","ReadIntent"}] String ReadableSecondary; + [Write, ValueMap{"Primary","Secondary"}, Values{"Primary","Secondary"}] String AutoBackupPrefernce; + [Write] String SQLServer; + [Write] String SQLInstanceName; + [Required, EmbeddedInstance("MSFT_Credential"), Description("Credential to be used to Grant Permissions in SQL.")] String SetupCredential; +}; + diff --git a/DSCResources/MSFT_xSQLAOGroupJoin/MSFT_xSQLAOGroupJoin.psm1 b/DSCResources/MSFT_xSQLAOGroupJoin/MSFT_xSQLAOGroupJoin.psm1 new file mode 100644 index 000000000..64ffd0c21 --- /dev/null +++ b/DSCResources/MSFT_xSQLAOGroupJoin/MSFT_xSQLAOGroupJoin.psm1 @@ -0,0 +1,160 @@ +$currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path +Write-Verbose -Message "CurrentPath: $currentPath" + +# Load Common Code +Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAction Stop + +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [parameter(Mandatory = $true)] + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [parameter(Mandatory = $true)] + [System.String] + $AvailabilityGroupName, + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [System.String] + $SQLInstanceName= "MSSQLSERVER", + + [parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $SetupCredential + ) + + if(!$SQL) + { + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + } + + $vConfigured = Test-TargetResource -Ensure $Ensure -AvailabilityGroupName $AvailabilityGroupName -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + + + $returnValue = @{ + Ensure = $vConfigured + AvailabilityGroupName = $sql.AvailabilityGroups[$AvailabilityGroupName] + AvailabilityGroupNameListener = $sql.AvailabilityGroups[$AvailabilityGroupName].AvailabilityGroupListeners.name + AvailabilityGroupNameIP = $sql.AvailabilityGroups[$AvailabilityGroupName].AvailabilityGroupListeners.availabilitygrouplisteneripaddresses.IPAddress + AvailabilityGroupSubMask = $sql.AvailabilityGroups[$AvailabilityGroupName].AvailabilityGroupListeners.availabilitygrouplisteneripaddresses.SubnetMask + AvailabilityGroupPort = $sql.AvailabilityGroups[$AvailabilityGroupName].AvailabilityGroupListeners.portnumber + AvailabilityGroupNameDatabase = $sql.AvailabilityGroups[$AvailabilityGroupName].AvailabilityDatabases.name + BackupDirectory = "" + SQLServer = $SQLServer + SQLInstanceName = $SQLInstanceName + } + + $returnValue +} + + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [parameter(Mandatory = $true)] + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [parameter(Mandatory = $true)] + [System.String] + $AvailabilityGroupName, + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [System.String] + $SQLInstanceName= "MSSQLSERVER", + + [parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $SetupCredential + ) + + + + $null = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') + $null = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") + + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName -SetupCredential $SetupCredential + Grant-ServerPerms -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName -AuthorizedUser "NT AUTHORITY\SYSTEM" -SetupCredential $SetupCredential + + + Try + {$SQL.JoinAvailabilityGroup($AvailabilityGroupName) + New-VerboseMessage -Message "Joined $SQLServer\$SQLInstanceName to $AvailabilityGroupName" + } + Catch + {Throw "Unable to Join $AvailabilityGroup on $SQLServer\$SQLInstanceName" + Exit + } + +} + + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [parameter(Mandatory = $true)] + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [parameter(Mandatory = $true)] + [System.String] + $AvailabilityGroupName, + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [System.String] + $SQLInstanceName= "MSSQLSERVER", + + [parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $SetupCredential + ) + + if(!$SQL) + { + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + } + + Switch ($Ensure) + { + "Present" + { + + $AGPresent=$sql.AvailabilityGroups.Contains($AvailabilityGroupName) + + if ($AGPresent) + {$Return = $true} + else + {$Return = $false} + } + "Absent" + { + if(!$sql.AvailabilityGroups[$AvailabilityGroupName]) + {$Return = $true} + else{$Return = $false} + } + } + $Return + +} + + +Export-ModuleMember -Function *-TargetResource + diff --git a/DSCResources/MSFT_xSQLAOGroupJoin/MSFT_xSQLAOGroupJoin.schema.mof b/DSCResources/MSFT_xSQLAOGroupJoin/MSFT_xSQLAOGroupJoin.schema.mof new file mode 100644 index 000000000..60cd92ffe --- /dev/null +++ b/DSCResources/MSFT_xSQLAOGroupJoin/MSFT_xSQLAOGroupJoin.schema.mof @@ -0,0 +1,11 @@ + +[ClassVersion("1.0.0.0"), FriendlyName("xSQLAOGroupJoin")] +class MSFT_xSQLAOGroupJoin : OMI_BaseResource +{ + [Key, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Key] String AvailabilityGroupName; + [Write] String SQLServer; + [Write] String SQLInstanceName; + [Required, EmbeddedInstance("MSFT_Credential"), Description("Credential to be used to Grant Permissions in SQL.")] String SetupCredential; +}; + diff --git a/DSCResources/MSFT_xSQLDatabaseRecoveryModel/MSFT_xSQLDatabaseRecoveryModel.psm1 b/DSCResources/MSFT_xSQLDatabaseRecoveryModel/MSFT_xSQLDatabaseRecoveryModel.psm1 index 9e5bd874f..567195c87 100644 --- a/DSCResources/MSFT_xSQLDatabaseRecoveryModel/MSFT_xSQLDatabaseRecoveryModel.psm1 +++ b/DSCResources/MSFT_xSQLDatabaseRecoveryModel/MSFT_xSQLDatabaseRecoveryModel.psm1 @@ -1,5 +1,5 @@ $currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path -Write-Debug -Message "CurrentPath: $currentPath" +Write-Verbose -Message "CurrentPath: $currentPath" # Load Common Code Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAction Stop @@ -25,11 +25,11 @@ function Get-TargetResource ) $SqlServerInstance = $SqlServerInstance.Replace('\MSSQLSERVER','') - Write-Verbose -Message "Checking Database $DatabaseName recovery mode for $RecoveryModel." -Verbose + New-VerboseMessage -Message "Checking Database $DatabaseName recovery mode for $RecoveryModel" $db = Get-SqlDatabase -ServerInstance $SqlServerInstance -Name $DatabaseName $value = ($db.RecoveryModel -eq $RecoveryModel) - Write-Verbose -Message "Database $DatabaseName recovery mode comparison $value." -Verbose + New-VerboseMessage -Message "Database $DatabaseName recovery mode comparison $value." $returnValue = @{ RecoveryModel = $db.RecoveryModel @@ -62,14 +62,13 @@ function Set-TargetResource $SqlServerInstance = $SqlServerInstance.Replace('\MSSQLSERVER','') $db = Get-SqlDatabase -ServerInstance $SqlServerInstance -Name $DatabaseName - Write-Verbose -Message "Database $DatabaseName recovery mode is $db.RecoveryModel." -Verbose + New-VerboseMessage -Message "Database $DatabaseName recovery mode is $db.RecoveryModel." if($db.RecoveryModel -ne $RecoveryModel) { - Write-Verbose -Message "Changing $DatabaseName recovery mode to $RecoveryModel." -Verbose $db.RecoveryModel = $RecoveryModel; $db.Alter(); - Write-Verbose -Message "DB $DatabaseName recovery mode is changed to $RecoveryModel." -Verbose + New-VerboseMessage -Message "DB $DatabaseName recovery mode is changed to $RecoveryModel." } if(!(Test-TargetResource @PSBoundParameters)) diff --git a/DSCResources/MSFT_xSQLServerAlwaysOnService/MSFT_xSQLServerAlwaysOnService.psm1 b/DSCResources/MSFT_xSQLServerAlwaysOnService/MSFT_xSQLServerAlwaysOnService.psm1 new file mode 100644 index 000000000..f3202dd9a --- /dev/null +++ b/DSCResources/MSFT_xSQLServerAlwaysOnService/MSFT_xSQLServerAlwaysOnService.psm1 @@ -0,0 +1,150 @@ +$currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path +Write-Verbose -Message "CurrentPath: $currentPath" + +# Load Common Code +Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAction Stop + +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [parameter(Mandatory = $true)] + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [System.String] + $SQLInstanceName= "MSSQLSERVER" + ) + $vConfigured = Test-TargetResource -Ensure $Ensure -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + + $returnValue = @{ + Ensure = $vConfigured + SQLServer = $SQLServer + SQLInstanceName = $SQLInstanceName + } + + $returnValue + +} + + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [parameter(Mandatory = $true)] + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [System.String] + $SQLInstanceName= "MSSQLSERVER" + ) + + if ($Ensure ="Present") + { + + if($SQLInstanceName -eq "MSSQLSERVER") + { + Try + { + Enable-SqlAlwaysOn -ServerInstance $SQLServer -Force + New-VerboseMessage -Message "Enabled AlwaysOn on $SQLServer" + } + Catch + { + Throw "Unable to enable AlwaysOn on $SQLServer" + Exit + } + } + else + { + Try + { + Enable-SqlAlwaysOn -ServerInstance $SQLServer\$SQLInstanceName -Force + New-VerboseMessage -Message "Enabled AlwaysOn on $SQLServer\$SQLInstanceName" + } + Catch + { + Throw "Unable to disable AlwaysOn on $SQLServer\$SQLInstanceName" + Exit + } + } + + + } + else + { + if($SQLInstanceName -eq "MSSQLSERVER") + { + Try + { + Disable-SqlAlwaysOn -ServerInstance $SQLServer -Force + New-VerboseMessage -Message "Disabled AlwaysOn on $SQLServer" + } + Catch + { + Throw "Unable to disable AlwaysOn on $SQLServer" + Exit + } + } + else + { + Try + { + Disable-SqlAlwaysOn -ServerInstance $SQLServer\$SQLInstanceName -Force + New-VerboseMessage -Message "Disabled AlwaysOn on $SQLServer\$SQLInstanceName" + } + Catch + { + Throw "Unable to disable AlwaysOn on $SQLServer\$SQLInstanceName" + Exit + } + } + } +} + + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [parameter(Mandatory = $true)] + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [System.String] + $SQLInstanceName= "MSSQLSERVER" + ) + + + if(!$SQL) + { + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + } + + $result = $sql.IsHadrEnabled + New-VerboseMessage -Message "AlwaysOn status of $SQLServer\$SQLInstanceName is $result" + + $result +} + + +Export-ModuleMember -Function *-TargetResource + diff --git a/DSCResources/MSFT_xSQLServerAlwaysOnService/MSFT_xSQLServerAlwaysOnService.schema.mof b/DSCResources/MSFT_xSQLServerAlwaysOnService/MSFT_xSQLServerAlwaysOnService.schema.mof new file mode 100644 index 000000000..bc60893ed --- /dev/null +++ b/DSCResources/MSFT_xSQLServerAlwaysOnService/MSFT_xSQLServerAlwaysOnService.schema.mof @@ -0,0 +1,9 @@ + +[ClassVersion("1.0.0.0"), FriendlyName("xSQLServerAlwaysOnService")] +class MSFT_xSQLServerAlwaysOnService : OMI_BaseResource +{ + [Key, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write] String SQLServer; + [Write] String SQLInstanceName; +}; + diff --git a/DSCResources/MSFT_xSQLServerDatabase/MSFT_xSQLServerDatabase.psm1 b/DSCResources/MSFT_xSQLServerDatabase/MSFT_xSQLServerDatabase.psm1 index aaa6d9813..72d41ee24 100644 --- a/DSCResources/MSFT_xSQLServerDatabase/MSFT_xSQLServerDatabase.psm1 +++ b/DSCResources/MSFT_xSQLServerDatabase/MSFT_xSQLServerDatabase.psm1 @@ -1,5 +1,5 @@ $currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path -Write-Debug -Message "CurrentPath: $currentPath" +Write-Verbose -Message "CurrentPath: $currentPath" # Load Common Code Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAction Stop @@ -8,42 +8,6 @@ Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAct # NOTE: This resource requires WMF5 and PsDscRunAsCredential -function ConnectSQL -{ - param - ( - [System.String] - $SQLServer = $env:COMPUTERNAME, - - [System.String] - $SQLInstanceName = "MSSQLSERVER" - ) - - $null = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') - - if($SQLInstanceName -eq "MSSQLSERVER") - { - $ConnectSQL = $SQLServer - } - else - { - $ConnectSQL = "$SQLServer\$SQLInstanceName" - } - - Write-Verbose "Connecting to SQL $ConnectSQL" - $SQL = New-Object Microsoft.SqlServer.Management.Smo.Server $ConnectSQL - - if($SQL) - { - Write-Verbose "Connected to SQL $ConnectSQL" - $SQL - } - else - { - Write-Verbose "Failed connecting to SQL $ConnectSQL" - } -} - function Get-TargetResource { [CmdletBinding()] @@ -60,7 +24,7 @@ function Get-TargetResource ) if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) @@ -102,21 +66,21 @@ function Set-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) { if($Ensure -eq "Present") { - Write-Verbose "Ensure = $Ensure so Create Database requested" $Db = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Database -ArgumentList $SQL,$Database $db.Create() + New-VerboseMessage -Message "Created Database $Database" } else { - Write-Verbose "Drop Database $Database requested" $sql.Databases[$Database].Drop() + New-VerboseMessage -Messaged "Dropped Database $Database" } } } @@ -146,7 +110,7 @@ function Test-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) diff --git a/DSCResources/MSFT_xSQLServerDatabaseOwner/MSFT_xSQLServerDatabaseOwner.psm1 b/DSCResources/MSFT_xSQLServerDatabaseOwner/MSFT_xSQLServerDatabaseOwner.psm1 index 7efc1ed9b..c3ffc3f02 100644 --- a/DSCResources/MSFT_xSQLServerDatabaseOwner/MSFT_xSQLServerDatabaseOwner.psm1 +++ b/DSCResources/MSFT_xSQLServerDatabaseOwner/MSFT_xSQLServerDatabaseOwner.psm1 @@ -1,5 +1,5 @@ $currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path -Write-Debug -Message "CurrentPath: $currentPath" +Write-Verbose -Message "CurrentPath: $currentPath" # Load Common Code Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAction Stop @@ -8,43 +8,6 @@ Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAct # NOTE: This resource requires WMF5 and PsDscRunAsCredential -function ConnectSQL -{ - param - ( - [System.String] - $SQLServer = $env:COMPUTERNAME, - - [System.String] - $SQLInstanceName = "MSSQLSERVER" - ) - - $null = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') - - if($SQLInstanceName -eq "MSSQLSERVER") - { - $ConnectSQL = $SQLServer - } - else - { - $ConnectSQL = "$SQLServer\$SQLInstanceName" - } - - Write-Verbose "Connecting to SQL $ConnectSQL" - $SQL = New-Object Microsoft.SqlServer.Management.Smo.Server $ConnectSQL - - if($SQL) - { - Write-Verbose "Connected to SQL $ConnectSQL" - $SQL - } - else - { - Write-Verbose "Failed connecting to SQL $ConnectSQL" - } -} - - function Get-TargetResource { [CmdletBinding()] @@ -68,7 +31,7 @@ function Get-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) @@ -119,7 +82,7 @@ function Set-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) @@ -162,4 +125,4 @@ function Test-TargetResource } -Export-ModuleMember -Function *-TargetResource \ No newline at end of file +Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xSQLServerDatabaseOwner/MSFT_xSQLServerDatabaseOwner.schema.mof b/DSCResources/MSFT_xSQLServerDatabaseOwner/MSFT_xSQLServerDatabaseOwner.schema.mof index bfd74df87..7b6c6ddaa 100644 --- a/DSCResources/MSFT_xSQLServerDatabaseOwner/MSFT_xSQLServerDatabaseOwner.schema.mof +++ b/DSCResources/MSFT_xSQLServerDatabaseOwner/MSFT_xSQLServerDatabaseOwner.schema.mof @@ -5,4 +5,4 @@ class MSFT_xSQLServerDatabaseOwner : OMI_BaseResource [Required, Description("The name of the SQL login for the owner.")] String Name; [Write, Description("The SQL Server for the database.")] String SQLServer; [Write, Description("The SQL instance for the database.")] String SQLInstanceName; -}; \ No newline at end of file +}; diff --git a/DSCResources/MSFT_xSQLServerDatabasePermissions/MSFT_xSQLServerDatabasePermissions.psm1 b/DSCResources/MSFT_xSQLServerDatabasePermissions/MSFT_xSQLServerDatabasePermissions.psm1 index 263c13d30..6645d6ccc 100644 --- a/DSCResources/MSFT_xSQLServerDatabasePermissions/MSFT_xSQLServerDatabasePermissions.psm1 +++ b/DSCResources/MSFT_xSQLServerDatabasePermissions/MSFT_xSQLServerDatabasePermissions.psm1 @@ -8,43 +8,6 @@ Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAct # NOTE: This resource requires WMF5 and PsDscRunAsCredential -function ConnectSQL -{ - param - ( - [System.String] - $SQLServer = $env:COMPUTERNAME, - - [System.String] - $SQLInstanceName = "MSSQLSERVER" - ) - - $null = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') - - if($SQLInstanceName -eq "MSSQLSERVER") - { - $ConnectSQL = $SQLServer - } - else - { - $ConnectSQL = "$SQLServer\$SQLInstanceName" - } - - Write-Verbose "Connecting to SQL $ConnectSQL" - $SQL = New-Object Microsoft.SqlServer.Management.Smo.Server $ConnectSQL - - if($SQL) - { - Write-Verbose "Connected to SQL $ConnectSQL" - $SQL - } - else - { - Write-Verbose "Failed connecting to SQL $ConnectSQL" - } -} - - function Get-TargetResource { [CmdletBinding()] @@ -72,7 +35,7 @@ function Get-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) @@ -146,7 +109,7 @@ function Set-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) @@ -235,4 +198,4 @@ function Test-TargetResource } -Export-ModuleMember -Function *-TargetResource \ No newline at end of file +Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xSQLServerDatabasePermissions/MSFT_xSQLServerDatabasePermissions.schema.mof b/DSCResources/MSFT_xSQLServerDatabasePermissions/MSFT_xSQLServerDatabasePermissions.schema.mof index 14c3e6652..0b2d24a1f 100644 --- a/DSCResources/MSFT_xSQLServerDatabasePermissions/MSFT_xSQLServerDatabasePermissions.schema.mof +++ b/DSCResources/MSFT_xSQLServerDatabasePermissions/MSFT_xSQLServerDatabasePermissions.schema.mof @@ -6,4 +6,4 @@ class MSFT_xSQLServerDatabasePermissions : OMI_BaseResource [Required, Description("The set of permissions for the SQL database.")] String Permissions[]; [Write, Description("The SQL Server for the database.")] String SQLServer; [Write, Description("The SQL instance for the database.")] String SQLInstanceName; -}; \ No newline at end of file +}; diff --git a/DSCResources/MSFT_xSQLServerDatabaseRole/MSFT_xSQLServerDatabaseRole.psm1 b/DSCResources/MSFT_xSQLServerDatabaseRole/MSFT_xSQLServerDatabaseRole.psm1 index 418389ea8..1d90ce5a0 100644 --- a/DSCResources/MSFT_xSQLServerDatabaseRole/MSFT_xSQLServerDatabaseRole.psm1 +++ b/DSCResources/MSFT_xSQLServerDatabaseRole/MSFT_xSQLServerDatabaseRole.psm1 @@ -8,43 +8,6 @@ Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAct # NOTE: This resource requires WMF5 and PsDscRunAsCredential -function ConnectSQL -{ - param - ( - [System.String] - $SQLServer = $env:COMPUTERNAME, - - [System.String] - $SQLInstanceName = "MSSQLSERVER" - ) - - $null = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') - - if($SQLInstanceName -eq "MSSQLSERVER") - { - $ConnectSQL = $SQLServer - } - else - { - $ConnectSQL = "$SQLServer\$SQLInstanceName" - } - - Write-Verbose "Connecting to SQL $ConnectSQL" - $SQL = New-Object Microsoft.SqlServer.Management.Smo.Server $ConnectSQL - - if($SQL) - { - Write-Verbose "Connected to SQL $ConnectSQL" - $SQL - } - else - { - Write-Verbose "Failed connecting to SQL $ConnectSQL" - } -} - - function Get-TargetResource { [CmdletBinding()] @@ -76,7 +39,7 @@ function Get-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) @@ -166,7 +129,7 @@ function Set-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) @@ -262,4 +225,4 @@ function Test-TargetResource } -Export-ModuleMember -Function *-TargetResource \ No newline at end of file +Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xSQLServerEndpoint/MSFT_xSQLServerEndpoint.psm1 b/DSCResources/MSFT_xSQLServerEndpoint/MSFT_xSQLServerEndpoint.psm1 new file mode 100644 index 000000000..f6bf87aa4 --- /dev/null +++ b/DSCResources/MSFT_xSQLServerEndpoint/MSFT_xSQLServerEndpoint.psm1 @@ -0,0 +1,163 @@ +$currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path +Write-Verbose -Message "CurrentPath: $currentPath" + +# Load Common Code +Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAction Stop + +# DSC resource to manage SQL Endpoint + +# NOTE: This resource requires WMF5 and PsDscRunAsCredential + +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [parameter(Mandatory = $true)] + [System.String] + $EndPointName, + + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [System.UInt32] + $Port, + + [System.String] + $AuthorizedUser, + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [System.String] + $SQLInstanceName = "MSSQLSERVER" + ) + + $vConfigured = Test-TargetResource -EndPointName $EndPointName -Ensure $Ensure -Port $Port -AuthorizedUser $AuthorizedUser + if(!$SQL) + { + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + } + + $returnValue = @{ + EndPointName = $EndPointName + Ensure = $vConfigured + Port = $sql.Endpoints[$EndPointName].Protocol.Tcp.ListenerPort + AuthorizedUser = $sql.Endpoints[$EndPointName].EnumObjectPermissions().grantee + } + + $returnValue +} + + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [parameter(Mandatory = $true)] + [System.String] + $EndPointName, + + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [System.UInt32] + $Port, + + [System.String] + $AuthorizedUser, + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [System.String] + $SQLInstanceName = "MSSQLSERVER" + ) + + if(!$SQL) + { + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + } +Write-Verbose "Connected to Server" + + if($Ensure -eq "Present") + { + Write-Verbose "Check to see login $AuthorizedUser exist on the server" + + if(!$SQL.Logins.Contains($AuthorizedUser)) + { + throw New-TerminatingError -ErrorType NoAuthorizedUser -FormatArgs @($AuthorizedUser,$SQLServer,$SQLInstanceName) -ErrorCategory InvalidResult + } + $Endpoint = New-Object -typename Microsoft.SqlServer.Management.Smo.Endpoint -ArgumentList $Sql,$EndpointName + $Endpoint.EndpointType = [Microsoft.SqlServer.Management.Smo.EndpointType]::DatabaseMirroring + $Endpoint.ProtocolType = [Microsoft.SqlServer.Management.Smo.ProtocolType]::Tcp + $Endpoint.Protocol.Tcp.ListenerPort = $Port + $Endpoint.Payload.DatabaseMirroring.ServerMirroringRole = [Microsoft.SqlServer.Management.Smo.ServerMirroringRole]::All + $Endpoint.Payload.DatabaseMirroring.EndpointEncryption = [Microsoft.SqlServer.Management.Smo.EndpointEncryption]::Required + $Endpoint.Payload.DatabaseMirroring.EndpointEncryptionAlgorithm = [Microsoft.SqlServer.Management.Smo.EndpointEncryptionAlgorithm]::Aes + $Endpoint.Create() + $Endpoint.Start() + $ConnectPerm = New-Object -TypeName Microsoft.SqlServer.Management.SMO.ObjectPermissionSet + $ConnectPerm.Connect= $true + $Endpoint.Grant($ConnectPerm,$AuthorizedUser) + } + elseif($Ensure -eq "Absent") + { + Write-Verbose "Drop $EndPointName" + $SQL.Endpoints[$EndPointName].Drop() + } +} + + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [parameter(Mandatory = $true)] + [System.String] + $EndPointName, + + [ValidateSet("Present","Absent")] + [System.String] + $Ensure, + + [System.UInt32] + $Port, + + [System.String] + $AuthorizedUser, + + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [System.String] + $SQLInstanceName = "MSSQLSERVER" + ) + + if(!$SQL) + { + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + } + + $result = [System.Boolean] + + + if(($sql.Endpoints[$EndPointName].Name -eq $EndPointName)-and($ensure -eq "Present") ) + { + $Result = $true + } + else + {$result = $false} + + $result +} + + +Export-ModuleMember -Function *-TargetResource + diff --git a/DSCResources/MSFT_xSQLServerEndpoint/MSFT_xSQLServerEndpoint.schema.mof b/DSCResources/MSFT_xSQLServerEndpoint/MSFT_xSQLServerEndpoint.schema.mof new file mode 100644 index 000000000..85f4c2773 --- /dev/null +++ b/DSCResources/MSFT_xSQLServerEndpoint/MSFT_xSQLServerEndpoint.schema.mof @@ -0,0 +1,12 @@ + +[ClassVersion("1.0.0.0"), FriendlyName("xSQLServerEndpoint")] +class MSFT_xSQLServerEndpoint : OMI_BaseResource +{ + [Key] String EndPointName; + [Write, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write] Uint32 Port; + [Write] String AuthorizedUser; + [Write] String SQLServer; + [Write] String SQLInstanceName; +}; + diff --git a/DSCResources/MSFT_xSQLServerFailoverClusterSetup/MSFT_xSQLServerFailoverClusterSetup.psm1 b/DSCResources/MSFT_xSQLServerFailoverClusterSetup/MSFT_xSQLServerFailoverClusterSetup.psm1 index b2e59d83d..d79f9aa25 100644 --- a/DSCResources/MSFT_xSQLServerFailoverClusterSetup/MSFT_xSQLServerFailoverClusterSetup.psm1 +++ b/DSCResources/MSFT_xSQLServerFailoverClusterSetup/MSFT_xSQLServerFailoverClusterSetup.psm1 @@ -1011,4 +1011,4 @@ function ConvertDecimalIP } -Export-ModuleMember -Function *-TargetResource \ No newline at end of file +Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xSQLServerFailoverClusterSetup/MSFT_xSQLServerFailoverClusterSetup.schema.mof b/DSCResources/MSFT_xSQLServerFailoverClusterSetup/MSFT_xSQLServerFailoverClusterSetup.schema.mof index e7eaae572..1de6c3315 100644 --- a/DSCResources/MSFT_xSQLServerFailoverClusterSetup/MSFT_xSQLServerFailoverClusterSetup.schema.mof +++ b/DSCResources/MSFT_xSQLServerFailoverClusterSetup/MSFT_xSQLServerFailoverClusterSetup.schema.mof @@ -48,4 +48,4 @@ class MSFT_xSQLServerFailoverClusterSetup : OMI_BaseResource [Write, EmbeddedInstance("MSFT_Credential"), Description("Service account for Integration Services service.")] String ISSvcAccount; [Read, Description("Output username for the Integration Services service.")] String ISSvcAccountUsername; [Write, Description("File system folder for Integration Services.")] String ISFileSystemFolder; -}; \ No newline at end of file +}; diff --git a/DSCResources/MSFT_xSQLServerFirewall/MSFT_xSQLServerFirewall.schema.mof b/DSCResources/MSFT_xSQLServerFirewall/MSFT_xSQLServerFirewall.schema.mof index affaf511b..e2b7dc1ad 100644 --- a/DSCResources/MSFT_xSQLServerFirewall/MSFT_xSQLServerFirewall.schema.mof +++ b/DSCResources/MSFT_xSQLServerFirewall/MSFT_xSQLServerFirewall.schema.mof @@ -11,4 +11,5 @@ class MSFT_xSQLServerFirewall : OMI_BaseResource [Read, Description("Is the firewall rule for Reporting Services enabled?")] boolean ReportingServicesFirewall; [Read, Description("Is the firewall rule for Analysis Services enabled?")] boolean AnalysisServicesFirewall; [Read, Description("Is the firewall rule for the Integration Services enabled?")] boolean IntegrationServicesFirewall; - }; \ No newline at end of file + }; + \ No newline at end of file diff --git a/DSCResources/MSFT_xSQLServerLogin/MSFT_xSQLServerLogin.psm1 b/DSCResources/MSFT_xSQLServerLogin/MSFT_xSQLServerLogin.psm1 index 13773a44a..0a03183a1 100644 --- a/DSCResources/MSFT_xSQLServerLogin/MSFT_xSQLServerLogin.psm1 +++ b/DSCResources/MSFT_xSQLServerLogin/MSFT_xSQLServerLogin.psm1 @@ -8,43 +8,6 @@ Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAct # NOTE: This resource requires WMF5 and PsDscRunAsCredential -function ConnectSQL -{ - param - ( - [System.String] - $SQLServer = $env:COMPUTERNAME, - - [System.String] - $SQLInstanceName = "MSSQLSERVER" - ) - - $null = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') - - if($SQLInstanceName -eq "MSSQLSERVER") - { - $ConnectSQL = $SQLServer - } - else - { - $ConnectSQL = "$SQLServer\$SQLInstanceName" - } - - Write-Verbose "Connecting to SQL $ConnectSQL" - $SQL = New-Object Microsoft.SqlServer.Management.Smo.Server $ConnectSQL - - if($SQL) - { - Write-Verbose "Connected to SQL $ConnectSQL" - $SQL - } - else - { - Write-Verbose "Failed connecting to SQL $ConnectSQL" - } -} - - function Get-TargetResource { [CmdletBinding()] @@ -75,7 +38,7 @@ function Get-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) @@ -154,7 +117,7 @@ function Set-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) @@ -242,4 +205,4 @@ function Test-TargetResource } -Export-ModuleMember -Function *-TargetResource \ No newline at end of file +Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xSQLServerLogin/MSFT_xSQLServerLogin.schema.mof b/DSCResources/MSFT_xSQLServerLogin/MSFT_xSQLServerLogin.schema.mof index cc31d2acf..beeb050f6 100644 --- a/DSCResources/MSFT_xSQLServerLogin/MSFT_xSQLServerLogin.schema.mof +++ b/DSCResources/MSFT_xSQLServerLogin/MSFT_xSQLServerLogin.schema.mof @@ -7,4 +7,4 @@ class MSFT_xSQLServerLogin : OMI_BaseResource [Write, Description("The SQL login type."), ValueMap{"SqlLogin","WindowsUser","WindowsGroup"}, Values{"SqlLogin","WindowsUser","WindowsGroup"}] String LoginType; [Write, Description("The SQL Server for the login.")] String SQLServer; [Write, Description("The SQL instance for the login.")] String SQLInstanceName; -}; \ No newline at end of file +}; diff --git a/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.psm1 b/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.psm1 index c4a456cf6..7f78c005c 100644 --- a/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.psm1 +++ b/DSCResources/MSFT_xSQLServerMaxDop/MSFT_xSQLServerMaxDop.psm1 @@ -1,47 +1,9 @@ $currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path -Write-Debug -Message "CurrentPath: $currentPath" - -# DSC resource to manage SQL Server MaxDop Value Dynamically or Statically +Write-Verbose -Message "CurrentPath: $currentPath" # Load Common Code Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAction Stop -function ConnectSQL -{ - param - ( - [System.String] - $SQLServer = $env:COMPUTERNAME, - - [System.String] - $SQLInstanceName = "MSSQLSERVER" - ) - - $null = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') - - if($SQLInstanceName -eq "MSSQLSERVER") - { - $ConnectSQL = $SQLServer - } - else - { - $ConnectSQL = "$SQLServer\$SQLInstanceName" - } - - Write-Verbose "Connecting to SQL $ConnectSQL" - $SQL = New-Object Microsoft.SqlServer.Management.Smo.Server $ConnectSQL - - if($SQL) - { - Write-Verbose "Connected to SQL $ConnectSQL" - $SQL - } - else - { - Write-Verbose "Failed connecting to SQL $ConnectSQL" - } -} - function Get-TargetResource { [CmdletBinding()] @@ -68,16 +30,15 @@ function Get-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) { - Write-Verbose "Getting Current MaxDop Configuration" $GetMaxDop = $sql.Configuration.MaxDegreeOfParallelism.ConfigValue If($GetMaxDop) { - Write-Verbose "MaxDop is $GetMaxDop" + New-VerboseMessage -Message "MaxDop is $GetMaxDop" } Switch ($Ensure) { @@ -132,7 +93,7 @@ function Set-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) @@ -171,13 +132,13 @@ function Set-TargetResource try { - Write-Verbose -Message "Setting MaxDop to $MaxDop" $sql.Configuration.MaxDegreeOfParallelism.ConfigValue =$MaxDop $sql.alter() + New-VerboseMessage -Message "Set MaxDop to $MaxDop" } catch { - Write-Verbose "Failed setting MaxDop to $MaxDop" + New-VerboseMessage -Message "Failed setting MaxDop to $MaxDop" } } } @@ -209,7 +170,7 @@ function Test-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } $GetMaxDop = $SQL.Configuration.MaxDegreeOfParallelism.ConfigValue @@ -222,12 +183,12 @@ function Test-TargetResource If ($GetMaxDop -eq 0) { - Write-verbose -message "Current MaxDop is $GetMaxDop should be updated to $MaxDop" + New-VerboseMessage -Message "Current MaxDop is $GetMaxDop should be updated to $MaxDop" return $false } else { - Write-verbose -message "Current MaxDop is configured at $GetMaxDop." + New-VerboseMessage -Message "Current MaxDop is configured at $GetMaxDop." return $True } } @@ -235,12 +196,12 @@ function Test-TargetResource { If ($GetMaxDop -eq $MaxDop) { - Write-verbose -message "Current MaxDop is at Requested value. Do nothing." + New-VerboseMessage -Message "Current MaxDop is at Requested value. Do nothing." return $true } else { - Write-verbose -message "Current MaxDop is $GetMaxDop should be updated to $MaxDop" + New-VerboseMessage -Message "Current MaxDop is $GetMaxDop should be updated to $MaxDop" return $False } } @@ -249,12 +210,12 @@ function Test-TargetResource { If ($GetMaxDop -eq 0) { - Write-verbose -message "Current MaxDop is at Requested value. Do nothing." + New-VerboseMessage -Message "Current MaxDop is at Requested value. Do nothing." return $true } else { - Write-verbose -message "Current MaxDop is $GetMaxDop should be updated" + New-VerboseMessage -Message "Current MaxDop is $GetMaxDop should be updated" return $False } } diff --git a/DSCResources/MSFT_xSQLServerMemory/MSFT_xSQLServerMemory.psm1 b/DSCResources/MSFT_xSQLServerMemory/MSFT_xSQLServerMemory.psm1 index 538f82f9c..78e35459f 100644 --- a/DSCResources/MSFT_xSQLServerMemory/MSFT_xSQLServerMemory.psm1 +++ b/DSCResources/MSFT_xSQLServerMemory/MSFT_xSQLServerMemory.psm1 @@ -1,47 +1,9 @@ $currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path -Write-Debug -Message "CurrentPath: $currentPath" - -# DSC resource to manage SQL Server Instance Memory Dynamically or Statically +Write-Verbose -Message "CurrentPath: $currentPath" # Load Common Code Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAction Stop -function ConnectSQL -{ - param - ( - [System.String] - $SQLServer = $env:COMPUTERNAME, - - [System.String] - $SQLInstanceName = "MSSQLSERVER" - ) - - $null = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') - - if($SQLInstanceName -eq "MSSQLSERVER") - { - $ConnectSQL = $SQLServer - } - else - { - $ConnectSQL = "$SQLServer\$SQLInstanceName" - } - - Write-Verbose "Connecting to SQL $ConnectSQL" - $SQL = New-Object Microsoft.SqlServer.Management.Smo.Server $ConnectSQL - - if($SQL) - { - Write-Verbose "Connected to SQL $ConnectSQL" - $SQL - } - else - { - Write-Verbose "Failed connecting to SQL $ConnectSQL" - } -} - function Get-TargetResource { [CmdletBinding()] @@ -71,12 +33,11 @@ function Get-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) { - Write-Verbose "Getting Current Min and Max Server Memory Settings" $GetMinMemory = $sql.Configuration.MinServerMemory.ConfigValue $GetMaxMemory = $sql.Configuration.MaxServerMemory.ConfigValue } @@ -128,7 +89,7 @@ function Set-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } If($SQL) @@ -180,19 +141,18 @@ function Set-TargetResource } } try - { - Write-Verbose -message "Dynamic Alloc is $DynamicAlloc. MaxMem will be set to $MaxMemory." - Write-Verbose -message "Server Memory is $serverMem and should be capped." + { $sql.Configuration.MaxServerMemory.ConfigValue = $MaxMemory if($MinMemory) { $sql.Configuration.MinServerMemory.ConfigValue = $MinMemory } $sql.alter() + New-VerboseMessage -Message "SQL Server Memory has been capped to $MaxMemory." } catch { - Write-Verbose -Message "Failed setting Min and Max SQL Memory" + New-VerboseMessage -Message "Failed setting Min and Max SQL Memory" } } } @@ -227,7 +187,7 @@ function Test-TargetResource if(!$SQL) { - $SQL = ConnectSQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName } if($SQL) @@ -242,12 +202,12 @@ function Test-TargetResource { if ($GetMaxMemory -eq 2147483647) { - Write-Verbose -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" + New-VerboseMessage -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" return $true } else { - Write-Verbose -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" + New-VerboseMessage -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" return $false } } @@ -258,12 +218,12 @@ function Test-TargetResource { if ($GetMaxMemory -eq 2147483647) { - Write-Verbose -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" + New-VerboseMessage -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" return $false } else { - Write-Verbose -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" + New-VerboseMessage -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" return $true } } @@ -271,12 +231,12 @@ function Test-TargetResource { If($MinMemory -ne $GetMinMemory -or $MaxMemory -ne $GetMaxMemory) { - Write-Verbose -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" + New-VerboseMessage -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" return $false } else { - Write-Verbose -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" + New-VerboseMessage -Message "Current Max Memory is $GetMaxMemory. Min Memory is $GetMinMemory" return $true } } diff --git a/DSCResources/MSFT_xSQLServerPowerPlan/MSFT_xSQLServerPowerPlan.psm1 b/DSCResources/MSFT_xSQLServerPowerPlan/MSFT_xSQLServerPowerPlan.psm1 index acf472f99..19f884531 100644 --- a/DSCResources/MSFT_xSQLServerPowerPlan/MSFT_xSQLServerPowerPlan.psm1 +++ b/DSCResources/MSFT_xSQLServerPowerPlan/MSFT_xSQLServerPowerPlan.psm1 @@ -1,3 +1,9 @@ +$currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path +Write-Verbose -Message "CurrentPath: $currentPath" + +# Load Common Code +Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAction Stop + function Get-TargetResource { [CmdletBinding()] @@ -57,12 +63,12 @@ function Set-TargetResource {$PlanName = "Balanced"} } - Write-Verbose -Message "Setting Powerplan to $PlanName" Try { $ReqPerf = powercfg -l | %{if($_.contains($PlanName)) {$_.split()[3]}} $CurrPlan = $(powercfg -getactivescheme).split()[3] if ($CurrPlan -ne $ReqPerf) {powercfg -setactive $ReqPerf} + New-VerboseMessage -Message "Powerplan has been set to $PlanName" } Catch @@ -111,12 +117,12 @@ function Test-TargetResource } If($ElementGuid -eq $ReqPerfGuid) { - Write-Verbose -Message "PowerPlan is set to $PlanName Already" + New-VerboseMessage -Message "PowerPlan is set to $PlanName Already" return $true } else { - Write-Verbose -Message "PowerPlan is $CurrPerfName Expect $PlanName" + New-VerboseMessage -Message "PowerPlan is $CurrPerfName Expect $PlanName" return $false } } diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 index 3877fe4ff..6265f171c 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 @@ -226,4 +226,4 @@ function Test-TargetResource } -Export-ModuleMember -Function *-TargetResource \ No newline at end of file +Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof index 6df01737e..5891a288e 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof @@ -6,4 +6,4 @@ class MSFT_xSQLServerRSConfig : OMI_BaseResource [Required, Description("Name of the SQL Server instance to host the Reporting Service database.")] String RSSQLInstanceName; [Required, EmbeddedInstance("MSFT_Credential"), Description("Credential to be used to perform the configuration.")] String SQLAdminCredential; [Read, Description("Is the Reporting Services instance initialized.")] Boolean IsInitialized; -}; \ No newline at end of file +}; diff --git a/DSCResources/MSFT_xSQLServerRSSecureConnectionLevel/MSFT_xSQLServerRSSecureConnectionLevel.psm1 b/DSCResources/MSFT_xSQLServerRSSecureConnectionLevel/MSFT_xSQLServerRSSecureConnectionLevel.psm1 index b0cd89349..6771f2ad9 100644 --- a/DSCResources/MSFT_xSQLServerRSSecureConnectionLevel/MSFT_xSQLServerRSSecureConnectionLevel.psm1 +++ b/DSCResources/MSFT_xSQLServerRSSecureConnectionLevel/MSFT_xSQLServerRSSecureConnectionLevel.psm1 @@ -111,4 +111,4 @@ function Test-TargetResource } -Export-ModuleMember -Function *-TargetResource \ No newline at end of file +Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xSQLServerRSSecureConnectionLevel/MSFT_xSQLServerRSSecureConnectionLevel.schema.mof b/DSCResources/MSFT_xSQLServerRSSecureConnectionLevel/MSFT_xSQLServerRSSecureConnectionLevel.schema.mof index 1ffe1cf29..9539097ed 100644 --- a/DSCResources/MSFT_xSQLServerRSSecureConnectionLevel/MSFT_xSQLServerRSSecureConnectionLevel.schema.mof +++ b/DSCResources/MSFT_xSQLServerRSSecureConnectionLevel/MSFT_xSQLServerRSSecureConnectionLevel.schema.mof @@ -4,4 +4,4 @@ class MSFT_xSQLServerRSSecureConnectionLevel : OMI_BaseResource [Key, Description("SQL instance to set secure connection level for.")] String InstanceName; [Key, Description("SQL Server Reporting Service secure connection level.")] Uint16 SecureConnectionLevel; [Required, EmbeddedInstance("MSFT_Credential"), Description("Credential with administrative permissions to the SQL instance.")] String SQLAdminCredential; -}; \ No newline at end of file +}; diff --git a/DSCResources/MSFT_xWaitForAvailabilityGroup/MSFT_xWaitForAvailabilityGroup.psm1 b/DSCResources/MSFT_xWaitForAvailabilityGroup/MSFT_xWaitForAvailabilityGroup.psm1 new file mode 100644 index 000000000..323889edb --- /dev/null +++ b/DSCResources/MSFT_xWaitForAvailabilityGroup/MSFT_xWaitForAvailabilityGroup.psm1 @@ -0,0 +1,126 @@ +$currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path +Write-Verbose -Message "CurrentPath: $currentPath" + +# Load Common Code +Import-Module $currentPath\..\..\xSQLServerHelper.psm1 -Verbose:$false -ErrorAction Stop + +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [parameter(Mandatory = $true)] + [System.String] + $Name, + + [UInt64] $RetryIntervalSec = 10, + [UInt32] $RetryCount = 50 + ) + + @{ + Name = $Name + RetryIntervalSec = $RetryIntervalSec + RetryCount = $RetryCount + } +} + + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [parameter(Mandatory = $true)] + [System.String] + $Name, + + [System.UInt64] + $RetryIntervalSec =20, + + [System.UInt32] + $RetryCount = 6 + ) + + $AGFound = $false + New-VerboseMessage -Message "Checking for Availaibilty Group $Name ..." + + for ($count = 0; $count -lt $RetryCount; $count++) + { + try + { + $clusterGroup = Get-ClusterGroup -Name $Name -ErrorAction Ignore + + if ($clusterGroup -ne $null) + { + New-VerboseMessage -Message "Found Availability Group $Name" + $AGFound = $true + Start-Sleep -Seconds $RetryIntervalSec + break; + } + + } + catch + { + New-VerboseMessage -Message "Availability Group $Name not found. Will retry again after $RetryIntervalSec sec" + } + + New-VerboseMessage -Message "Availability Group $Name not found. Will retry again after $RetryIntervalSec sec" + Start-Sleep -Seconds $RetryIntervalSec + } + + if (! $AGFound) + { + throw "Availability Group $Name not found after $count attempts with $RetryIntervalSec sec interval" + Exit + } + + +} + + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [parameter(Mandatory = $true)] + [System.String] + $Name, + + [System.UInt64] + $RetryIntervalSec = 10, + + [System.UInt32] + $RetryCount = 50 + ) + + New-VerboseMessage -Message "Checking for Availability Group $Name ..." + + try + { + + $clusterGroup = Get-ClusterGroup -Name $Name -ErrorAction Ignore + + if ($clusterGroup -eq $null) + { + New-VerboseMessage -Message "Availability Group $Name not found" + $false + } + else + { + New-VerboseMessage -Message "Found Availabilty Group $Name" + $true + } + } + catch + { + New-VerboseMessage -Message "Availability Group $Name not found" + $false + } +} + + +Export-ModuleMember -Function *-TargetResource + diff --git a/DSCResources/MSFT_xWaitForAvailabilityGroup/MSFT_xWaitForAvailabilityGroup.schema.mof b/DSCResources/MSFT_xWaitForAvailabilityGroup/MSFT_xWaitForAvailabilityGroup.schema.mof new file mode 100644 index 000000000..08be80882 --- /dev/null +++ b/DSCResources/MSFT_xWaitForAvailabilityGroup/MSFT_xWaitForAvailabilityGroup.schema.mof @@ -0,0 +1,9 @@ + +[ClassVersion("1.0.0.0"), FriendlyName("xWaitForAvailabilityGroup")] +class MSFT_xWaitForAvailabilityGroup : OMI_BaseResource +{ + [Key, Description("Availability Group Name")] String Name; + [Write, Description("Interval to check for Availability Group")] Uint64 RetryIntervalSec; + [Write, Description("Maximum number of retries to check Availabilty group creation")] Uint32 RetryCount; +}; + diff --git a/DSCResources/xSQLServerNetwork/xSQLServerNetwork.psm1 b/DSCResources/xSQLServerNetwork/xSQLServerNetwork.psm1 index 9a3fc5320..5c8fb2e25 100644 --- a/DSCResources/xSQLServerNetwork/xSQLServerNetwork.psm1 +++ b/DSCResources/xSQLServerNetwork/xSQLServerNetwork.psm1 @@ -284,4 +284,4 @@ Function GetVersion $sqlVersion.Split(".")[0] } -Export-ModuleMember -Function *-TargetResource \ No newline at end of file +Export-ModuleMember -Function *-TargetResource diff --git a/Examples/DSCClusterSqlBuild.ps1 b/Examples/DSCClusterSqlBuild.ps1 new file mode 100644 index 000000000..bcd246d4e --- /dev/null +++ b/Examples/DSCClusterSqlBuild.ps1 @@ -0,0 +1,423 @@ +#requires -Version 5 +$StartTime = [System.Diagnostics.Stopwatch]::StartNew() +Function check-even($num){[bool]!($num%2)} + +$computers = 'OHSQL9013','OHSQL9014' +$OutputPath = 'F:\DSCConfig' + + +$cim = New-CimSession -ComputerName $computers + +[DSCLocalConfigurationManager()] +Configuration LCM_Push +{ + Param( + [string[]]$ComputerName + ) + Node $ComputerName + { + Settings + { + AllowModuleOverwrite = $True + ConfigurationMode = 'ApplyAndAutoCorrect' + RefreshMode = 'Push' + RebootNodeIfNeeded = $True + } + } +} + +foreach ($computer in $computers) +{ + $GUID = (New-Guid).Guid + LCM_Push -ComputerName $Computer -OutputPath $OutputPath + Set-DSCLocalConfigurationManager -Path $OutputPath -CimSession $computer -Verbose +} + +Configuration AlwaysOnCluster +{ + Import-DscResource –Module PSDesiredStateConfiguration + Import-DscResource -Module xSQLServer + Import-DscResource -Module xFailoverCluster + + Node $AllNodes.Where{$_.Role -eq "PrimaryClusterNode" }.NodeName + { + # Set LCM to reboot if needed + LocalConfigurationManager + { + AllowModuleOverwrite = $true + RefreshMode = 'Push' + ConfigurationMode = 'ApplyAndAutoCorrect' + RebootNodeIfNeeded = $true + DebugMode = "All" + } + + WindowsFeature "NET" + { + Ensure = "Present" + Name = "NET-Framework-Core" + Source = $Node.NETPath + } + + WindowsFeature "ADTools" + { + Ensure = "Present" + Name = "RSAT-AD-PowerShell" + Source = $Node.NETPath + } + + if($Node.Features) + { + xSqlServerSetup ($Node.NodeName) + { + SourcePath = $Node.SourcePath + SetupCredential = $Node.InstallerServiceAccount + InstanceName = $Node.InstanceName + Features = $Node.Features + SQLSysAdminAccounts = $Node.AdminAccount + SQLSvcAccount = $Node.InstallerServiceAccount + InstallSharedDir = "G:\Program Files\Microsoft SQL Server" + InstallSharedWOWDir = "G:\Program Files (x86)\Microsoft SQL Server" + InstanceDir = "G:\Program Files\Microsoft SQL Server" + InstallSQLDataDir = "G:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLUserDBDir = "G:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLUserDBLogDir = "L:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLTempDBDir = "T:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLTempDBLogDir = "L:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLBackupDir = "G:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + + DependsOn = '[WindowsFeature]NET' + } + + xSqlServerFirewall ($Node.NodeName) + { + SourcePath = $Node.SourcePath + InstanceName = $Node.InstanceName + Features = $Node.Features + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + + xSQLServerPowerPlan ($Node.Nodename) + { + Ensure = "Present" + } + + xSQLServerMemory ($Node.Nodename) + { + Ensure = "Present" + DynamicAlloc = $True + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + + xSQLServerMaxDop($Node.Nodename) + { + Ensure = "Present" + DynamicAlloc = $true + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + } + + WindowsFeature FailoverFeature + { + Ensure = "Present" + Name = "Failover-clustering" + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + + WindowsFeature RSATClusteringMgmt + { + Ensure = "Present" + Name = "RSAT-Clustering-Mgmt" + + DependsOn = "[WindowsFeature]FailoverFeature" + } + + WindowsFeature RSATClusteringPowerShell + { + Ensure = "Present" + Name = "RSAT-Clustering-PowerShell" + + DependsOn = "[WindowsFeature]FailoverFeature" + } + + WindowsFeature RSATClusteringCmdInterface + { + Ensure = "Present" + Name = "RSAT-Clustering-CmdInterface" + + DependsOn = "[WindowsFeature]RSATClusteringPowerShell" + } + + xCluster ensureCreated + { + Name = $Node.ClusterName + StaticIPAddress = $Node.ClusterIPAddress + DomainAdministratorCredential = $Node.InstallerServiceAccount + + DependsOn = “[WindowsFeature]RSATClusteringCmdInterface” + } + xSQLServerAlwaysOnService($Node.Nodename) + { + Ensure = "Present" + + DependsOn = ("[xCluster]ensureCreated"),("[xSqlServerSetup]" + $Node.NodeName) + } + + xSQLServerEndpoint($Node.Nodename) + { + Ensure = "Present" + Port = 5022 + AuthorizedUser = "CORP\AutoSvc" + EndPointName = "Hadr_endpoint" + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + + xSQLAOGroupEnsure($Node.Nodename) + { + Ensure = "Present" + AvailabilityGroupName = "MyAG" + AvailabilityGroupNameListener = "MyAGList" + AvailabilityGroupNameIP = "10.0.75.201" + AvailabilityGroupSubMask ="255.255.255.0" + SetupCredential = $Node.InstallerServiceAccount + PsDscRunAsCredential = $Node.InstallerServiceAccount + DependsOn = ("[xSQLServerEndpoint]" + $Node.NodeName),("[xSQLServerAlwaysOnService]" + $Node.NodeName),("[WindowsFeature]ADTools") + } + } + Node $AllNodes.Where{$_.Role -eq "ReplicaServerNode" }.NodeName + { + # Set LCM to reboot if needed + LocalConfigurationManager + { + AllowModuleOverwrite = $true + RefreshMode = 'Push' + ConfigurationMode = 'ApplyAndAutoCorrect' + RebootNodeIfNeeded = $true + DebugMode = "All" + } + + WindowsFeature "NET" + { + Ensure = "Present" + Name = "NET-Framework-Core" + Source = $Node.NETPath + } + + if($Node.Features) + { + xSqlServerSetup ($Node.NodeName) + { + SourcePath = $Node.SourcePath + SetupCredential = $Node.InstallerServiceAccount + InstanceName = $Node.InstanceName + Features = $Node.Features + SQLSysAdminAccounts = $Node.AdminAccount + SQLSvcAccount = $Node.InstallerServiceAccount + InstallSharedDir = "G:\Program Files\Microsoft SQL Server" + InstallSharedWOWDir = "G:\Program Files (x86)\Microsoft SQL Server" + InstanceDir = "G:\Program Files\Microsoft SQL Server" + InstallSQLDataDir = "G:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLUserDBDir = "G:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLUserDBLogDir = "L:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLTempDBDir = "T:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLTempDBLogDir = "L:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLBackupDir = "G:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + + DependsOn = '[WindowsFeature]NET' + } + + xSqlServerFirewall ($Node.NodeName) + { + SourcePath = $Node.SourcePath + InstanceName = $Node.InstanceName + Features = $Node.Features + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + xSQLServerPowerPlan ($Node.Nodename) + { + Ensure = "Present" + } + xSQLServerMemory ($Node.Nodename) + { + Ensure = "Present" + DynamicAlloc = $True + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + xSQLServerMaxDop($Node.Nodename) + { + Ensure = "Present" + DynamicAlloc = $true + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + + } + + WindowsFeature FailoverFeature + { + Ensure = "Present" + Name = "Failover-clustering" + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + + WindowsFeature RSATClusteringPowerShell + { + Ensure = "Present" + Name = "RSAT-Clustering-PowerShell" + + DependsOn = "[WindowsFeature]FailoverFeature" + } + + WindowsFeature RSATClusteringMgmt + { + Ensure = "Present" + Name = "RSAT-Clustering-Mgmt" + + DependsOn = "[WindowsFeature]FailoverFeature" + } + + WindowsFeature RSATClusteringCmdInterface + { + Ensure = "Present" + Name = "RSAT-Clustering-CmdInterface" + + DependsOn = "[WindowsFeature]RSATClusteringPowerShell" + } + + xWaitForCluster waitForCluster + { + Name = $Node.ClusterName + RetryIntervalSec = 10 + RetryCount = 6 + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + + xCluster joinCluster + { + Name = $Node.ClusterName + StaticIPAddress = $Node.ClusterIPAddress + DomainAdministratorCredential = $Node.InstallerServiceAccount + + DependsOn = "[xWaitForCluster]waitForCluster" + } + xSQLServerAlwaysOnService($Node.Nodename) + { + Ensure = "Present" + + DependsOn = ("[xCluster]joinCluster"),("[xSqlServerSetup]" + $Node.NodeName) + } + xSQLServerEndpoint($Node.Nodename) + { + Ensure = "Present" + Port = 5022 + AuthorizedUser = "CORP\AutoSvc" + EndPointName = "Hadr_endpoint" + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + + xWaitForAvailabilityGroup waitforAG + { + Name = "MyAG" + RetryIntervalSec = 20 + RetryCount = 6 + + DependsOn = (“[xSQLServerEndpoint]" +$Node.Nodename),(“[xSQLServerAlwaysOnService]" +$Node.Nodename) + } + + xSQLAOGroupJoin ($Node.Nodename) + { + Ensure = "Present" + AvailabilityGroupName = "MyAG" + SetupCredential = $Node.InstallerServiceAccount + PsDscRunAsCredential = $Node.InstallerServiceAccount + + DependsOn = ("[xWaitForAvailabilityGroup]waitforAG") + } + + } +} +$ConfigurationData = @{ + AllNodes = @( + @{ + NodeName = "*" + PSDscAllowPlainTextPassword = $true + PSDscAllowDomainUser =$true + NETPath = "\\ohdc9000\SQLAutoBuilds\SQL2014\WindowsServer2012R2\sources\sxs" + SourcePath = "\\ohdc9000\SQLAutoBuilds\SQL2014\" + InstallerServiceAccount = Get-Credential -UserName CORP\AutoSvc -Message "Credentials to Install SQL Server" + AdminAccount = "Corp\user1" + ClusterName = "DevCluster" + ClusterIPAddress = "10.0.75.199/24" + } + ) +} +$firstComputer = $computers | Select-Object -First 1 +ForEach ($computer in $computers) { + + if($firstComputer -eq $computer) + { + $ConfigurationData.AllNodes += @{ + NodeName = $computer + InstanceName = "MSSQLSERVER" + Features = "SQLENGINE,IS,SSMS,ADV_SSMS" + Role = "PrimaryClusterNode" + } + } + else + { + $ConfigurationData.AllNodes += @{ + NodeName = $computer + InstanceName = "MSSQLSERVER" + Features = "SQLENGINE,IS,SSMS,ADV_SSMS" + Role = "ReplicaServerNode" + } + } + $Destination = "\\"+$computer+"\\c$\Program Files\WindowsPowerShell\Modules" + if (Test-Path "$Destination\xFailoverCluster"){Remove-Item -Path "$Destination\xFailoverCluster" -Recurse -Force} + if (Test-Path "$Destination\xSqlServer"){Remove-Item -Path "$Destination\xSqlServer"-Recurse -Force} + Copy-Item 'C:\Program Files\WindowsPowerShell\Modules\xFailoverCluster' -Destination $Destination -Recurse -Force + Copy-Item 'C:\Program Files\WindowsPowerShell\Modules\xSqlServer' -Destination $Destination -Recurse -Force +} + +AlwaysOnCluster -ConfigurationData $ConfigurationData -OutputPath $OutputPath + +#Push################################ + +Workflow StartConfigs +{ + param([string[]]$computers, + [System.string] $Path) + + foreach –parallel ($Computer in $Computers) + { + + Start-DscConfiguration -ComputerName $Computer -Path $Path -Verbose -Wait -Force + } +} + +StartConfigs -Computers $computers -Path $OutputPath + +$StartTime.Elapsed + +############Validate############## +<# +Workflow TestConfigs +{ + param([string[]]$computers) + foreach -parallel ($Computer in $Computers) + { + Write-verbose "$Computer :" + test-dscconfiguration -ComputerName $Computer + } +} + +TestConfigs -computers $computers +#> + diff --git a/Examples/DSCSQLBuildEncrypted.ps1 b/Examples/DSCSQLBuildEncrypted.ps1 new file mode 100644 index 000000000..135260490 --- /dev/null +++ b/Examples/DSCSQLBuildEncrypted.ps1 @@ -0,0 +1,202 @@ +#requires -Version 5 +$StartTime = [System.Diagnostics.Stopwatch]::StartNew() + +$computers = 'OHSQL9012' +$OutputPath = 'F:\DSCConfig' +$KeyPath = 'F:\publicKeys' + + +$cim = New-CimSession -ComputerName $computers +Function check-even($num){[bool]!($num%2)} + + +Function Get-Cert +{ + Param + ( + [System.String]$RemoteMachine, + [System.String]$SaveLocation = "F:\publicKeys" + ) + if (!(test-path $SaveLocation)) + { + new-item -path $SaveLocation -type Directory + } + $CertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList "\\$($RemoteMachine)\My", "LocalMachine" + $CertStore.Open('ReadOnly') + $certificate = $CertStore.Certificates | Where-Object {$_.EnhancedKeyUsageList.friendlyName -eq "Document Encryption"} + [byte[]]$Bytes = $certificate.Export('Cert') + [string]$SaveLiteralPath = "$SaveLocation\$RemoteMachine.$env:UserDNSDomain.cer" + Remove-Item -Path $SaveLiteralPath -Force -ErrorAction Ignore + Set-Content -Path $SaveLiteralPath -Value $Bytes -Encoding Byte -Force | out-null +} + +foreach ($computer in $computers) +{ + Get-Cert -RemoteMachine $computer -SaveLocation $KeyPath +} + +Get-cert -RemoteMachine $env:COMPUTERNAME -SaveLocation $KeyPath + +[DSCLocalConfigurationManager()] +Configuration LCM_Reboot_CentralConfig +{ + Param( + [string[]]$ComputerName + ) + Node $computers + { + Settings + { + ConfigurationID = $GUID + CertificateID =(Get-PfxCertificate -FilePath "$KeyPath\$computers.$env:USERDNSDOMAIN.cer").Thumbprint + RefreshFrequencyMins = 30 + ConfigurationModeFrequencyMins = 15 + RefreshMode = "Push" + AllowModuleOverwrite = $true + RebootNodeIfNeeded = $True + ConfigurationMode = 'ApplyAndAutoCorrect' + } + } +} +#LCM_Reboot_CentralConfig -OutputPath $OutputPath + +foreach ($computer in $computers) +{ + $GUID = (New-Guid).Guid + LCM_Reboot_CentralConfig -ComputerName $Computer -OutputPath $OutputPath + Set-DSCLocalConfigurationManager -Path $OutputPath -CimSession $cim –Verbose +} + +Configuration SQLBuild +{ + Import-DscResource –Module PSDesiredStateConfiguration + Import-DscResource -Module xSQLServer + + Node $AllNodes.NodeName + { + LocalConfigurationManager + { + CertificateId = $Node.Thumbprint + } + + WindowsFeature "NET" + { + Ensure = "Present" + Name = "NET-Framework-Core" + Source = $Node.NETPath + } + + if($Features -ne "") + { + xSqlServerSetup ($Node.NodeName) + { + DependsOn = '[WindowsFeature]NET' + SourcePath = $Node.SourcePath + SetupCredential = $Node.InstallerServiceAccount + InstanceName = $Node.InstanceName + Features = $Features + SQLSysAdminAccounts = $Node.AdminAccount + InstallSharedDir = "G:\Program Files\Microsoft SQL Server" + InstallSharedWOWDir = "G:\Program Files (x86)\Microsoft SQL Server" + InstanceDir = "G:\Program Files\Microsoft SQL Server" + InstallSQLDataDir = "G:\MSSQL\Data" + SQLUserDBDir = "G:\MSSQL\Data" + SQLUserDBLogDir = "L:\MSSQL\Data" + SQLTempDBDir = "T:\MSSQL\Data" + SQLTempDBLogDir = "L:\MSSQL\Data" + SQLBackupDir = "G:\MSSQL\Backup" + } + xSqlServerFirewall ($Node.NodeName) + { + SourcePath = $Node.SourcePath + InstanceName = $Node.InstanceName + Features = $Node.Features + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + xSQLServerPowerPlan ($Node.Nodename) + { + Ensure = "Present" + } + xSQLServerMemory ($Node.Nodename) + { + Ensure = "Present" + DynamicAlloc = $True + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + xSQLServerMaxDop($Node.Nodename) + { + Ensure = "Present" + DynamicAlloc = $true + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + } + } +} + +$ConfigurationData = @{ + AllNodes = @( + @{ + NodeName = "*" + PSDscAllowPlainTextPassword = $false + PSDscAllowDomainUser =$true + NETPath = "\\ohdc9000\SQLBuilds\SQLAutoInstall\WIN2012R2\sxs" + SourcePath = "\\ohdc9000\SQLAutoBuilds\SQL2014" + InstallerServiceAccount = Get-Credential -UserName CORP\AutoSvc -Message "Credentials to Install SQL Server" + AdminAccount = "CORP\user1" + # For build server encryption + CertificateFile =(Get-PfxCertificate -FilePath "$KeyPath\$env:COMPUTERNAME.$env:USERDNSDOMAIN.cer").Thumbprint + } + + ) +} + +ForEach ($computer in $computers) { + $ConfigurationData.AllNodes += @{ + NodeName = $computer + InstanceName = "MSSQLSERVER" + Features = "SQLENGINE,IS,SSMS,ADV_SSMS" + CertificateFile = "$KeyPath\$computer.$env:USERDNSDOMAIN.cer" + Thumbprint = (Get-PfxCertificate -FilePath "$KeyPath\$computer.$env:USERDNSDOMAIN.cer").Thumbprint + } + + + $Destination = "\\"+$computer+"\\c$\Program Files\WindowsPowerShell\Modules" + if (Test-Path "$Destination\xSqlServer"){Remove-Item -Path "$Destination\xSqlServer"-Recurse -Force} + Copy-Item 'C:\Program Files\WindowsPowerShell\Modules\xSqlServer' -Destination $Destination -Recurse -Force +} + + +SQLBuild -ConfigurationData $ConfigurationData -OutputPath $OutputPath + +Workflow StartConfigs +{ + param([string[]]$computers, + [System.string] $Path) + + foreach –parallel ($Computer in $Computers) + { + Start-DscConfiguration -ComputerName $Computer -Path $Path -Verbose -Wait -Force + } +} + +StartConfigs -Computers $computers -Path $OutputPath + +#Ttest +<# +Workflow TestConfigs +{ + param([string[]]$computers) + foreach -parallel ($Computer in $Computers) + { + Write-verbose "$Computer :" + test-dscconfiguration -ComputerName $Computer + } +} + +TestConfigs -computers $computers +#> + +$StartTime.Elapsed diff --git a/Examples/DSCSqlBuild.ps1 b/Examples/DSCSqlBuild.ps1 new file mode 100644 index 000000000..8ad31dc7e --- /dev/null +++ b/Examples/DSCSqlBuild.ps1 @@ -0,0 +1,188 @@ +#requires -Version 5 +$StartTime = [System.Diagnostics.Stopwatch]::StartNew() + +$computers = 'OHSQL9015' +$OutputPath = 'F:\DSCConfig' + +$cim = New-CimSession -ComputerName $computers +Function check-even($num){[bool]!($num%2)} + +[DSCLocalConfigurationManager()] +Configuration LCM_Push +{ + Param( + [string[]]$ComputerName + ) + Node $ComputerName + { + Settings + { + AllowModuleOverwrite = $True + ConfigurationMode = 'ApplyAndAutoCorrect' + RefreshMode = 'Push' + RebootNodeIfNeeded = $True + } + } +} + +foreach ($computer in $computers) +{ + $GUID = (New-Guid).Guid + LCM_Push -ComputerName $Computer -OutputPath $OutputPath + Set-DSCLocalConfigurationManager -Path $OutputPath -CimSession $computer -Verbose +} + +Configuration SQLBuild +{ + Import-DscResource –ModuleName PSDesiredStateConfiguration + Import-DscResource -ModuleName xSQLServer + + + Node $AllNodes.NodeName + { + + # Set LCM to reboot if needed + LocalConfigurationManager + { + AllowModuleOverwrite = $true + RefreshMode = 'Push' + ConfigurationMode = 'ApplyAndAutoCorrect' + RebootNodeIfNeeded = $true + DebugMode = "All" + } + + WindowsFeature "NET" + { + Ensure = "Present" + Name = "NET-Framework-Core" + Source = $Node.NETPath + } + + WindowsFeature "ADTools" + { + Ensure = "Present" + Name = "RSAT-AD-PowerShell" + Source = $Node.NETPath + } + + if($Node.Features) + { + xSqlServerSetup ($Node.NodeName) + { + SourcePath = $Node.SourcePath + SetupCredential = $Node.InstallerServiceAccount + InstanceName = $Node.InstanceName + Features = $Node.Features + SQLSysAdminAccounts = $Node.AdminAccount + SQLSvcAccount = $Node.InstallerServiceAccount + InstallSharedDir = "G:\Program Files\Microsoft SQL Server" + InstallSharedWOWDir = "G:\Program Files (x86)\Microsoft SQL Server" + InstanceDir = "G:\Program Files\Microsoft SQL Server" + InstallSQLDataDir = "G:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLUserDBDir = "G:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLUserDBLogDir = "L:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLTempDBDir = "T:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLTempDBLogDir = "L:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + SQLBackupDir = "G:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data" + + DependsOn = '[WindowsFeature]NET' + } + + xSqlServerFirewall ($Node.NodeName) + { + SourcePath = $Node.SourcePath + InstanceName = $Node.InstanceName + Features = $Node.Features + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + xSQLServerPowerPlan ($Node.Nodename) + { + Ensure = "Present" + } + xSQLServerMemory ($Node.Nodename) + { + Ensure = "Present" + DynamicAlloc = $True + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + xSQLServerMaxDop($Node.Nodename) + { + Ensure = "Present" + DynamicAlloc = $true + + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + } + + xSQLServerEndpoint($Node.Nodename) + { + Ensure = "Present" + Port = 5022 + AuthorizedUser = "CORP\AutoSvc" + EndPointName = "Hadr_endpoint" + DependsOn = ("[xSqlServerSetup]" + $Node.NodeName) + } + + } +} +$ConfigurationData = @{ + AllNodes = @( + @{ + NodeName = "*" + PSDscAllowPlainTextPassword = $true + PSDscAllowDomainUser =$true + NETPath = "\\ohdc9000\SQLBuilds\SQLAutoInstall\WIN2012R2\sxs" + SourcePath = "\\ohdc9000\SQLAutoBuilds\SQL2014\" + InstallerServiceAccount = Get-Credential -UserName CORP\AutoSvc -Message "Credentials to Install SQL Server" + AdminAccount = "CORP\user1" + } + ) +} + +ForEach ($computer in $computers) { + $ConfigurationData.AllNodes += @{ + NodeName = $computer + InstanceName = "MSSQLSERVER" + Features = "SQLENGINE,IS,SSMS,ADV_SSMS" + } + + $Destination = "\\"+$computer+"\\c$\Program Files\WindowsPowerShell\Modules" + if (Test-Path "$Destination\xSqlServer"){Remove-Item -Path "$Destination\xSqlServer"-Recurse -Force} + Copy-Item 'C:\Program Files\WindowsPowerShell\Modules\xSqlServer' -Destination $Destination -Recurse -Force +} + +SQLBuild -ConfigurationData $ConfigurationData -OutputPath $OutputPath + +#Push################################ + +Workflow StartConfigs +{ + param([string[]]$computers, + [System.string] $Path) + + foreach –parallel ($Computer in $Computers) + { + + Start-DscConfiguration -ComputerName $Computer -Path $Path -Verbose -Wait -Force + } +} + +StartConfigs -Computers $computers -Path $OutputPath + + +#Ttest +Workflow TestConfigs +{ + param([string[]]$computers) + foreach -parallel ($Computer in $Computers) + { + Write-verbose "$Computer :" + test-dscconfiguration -ComputerName $Computer + } +} + +TestConfigs -computers $computers + +$StartTime.Elapsed diff --git a/README.md b/README.md index 7f2509301..aedc41cfe 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,11 @@ Please check out common DSC Resources [contributing guidelines](https://github.c * **xSQLServerPowerPlan** resource to manage windows powerplan on SQL Server * **xSQLServerNetwork** resource to manage SQL Server Network Protocols * **xSQLServerDatabase** resource to manage ensure database is present or absent +* **xSQLAOGroupEnsure** resource to ensure availability group is present or absent +* **xSQLAOGroupJoin** resource to join a replica to an existing availability group +* **xSQLServerAlwaysOnService** resource to enable always on on a SQL Server +* **xSQLServerEndpoint** resource to ensure database endpoint is present or absent +* **xWaitForAvailabilityGroup** resource to wait till availability group is created on primary server ### xSQLServerSetup @@ -215,10 +220,86 @@ Please check out common DSC Resources [contributing guidelines](https://github.c * **Ensure**: An enumerated value that describes if Database is to be present or absent. * **SQLServer**: The SQL Server for the database * **SQLInstance**: The SQL instance for the database + +###xSQLAOGroupEnsure +* **Ensure**: (key) An enumerated value that describes if Availability Group is to be present or absent. +* **AvailabilityGroupName** (key) Name for availability group +* **AvailabilityGroupNameListener** Listener name for availability group +* **AvailabilityGroupNameIP** List of IP addresses associated with listener +* **AvailabilityGroupSubMask** Network subnetmask for listener +* **AvailabilityGroupPort** Port availability group should listen on +* **ReadableSecondary** Mode secondaries should operate under (None, ReadOnly, ReadIntent) +* **AutoBackupPreference** Where backups should be backed up from (Primary,Secondary) +* **SQLServer**: The SQL Server for the database +* **SQLInstance**: The SQL instance for the database +* **SetupCredential**: (Required) Credential to be used to Grant Permissions on SQL Server + +###xSQLServerAOJoin +* **Ensure**: (key) An enumerated value that describes if Replica is to be present or absent from availability group +* **AvailabilityGroupName** (key) Name for availability group +* **SQLServer**: The SQL Server for the database +* **SQLInstance**: The SQL instance for the database +* **SetupCredential**: (Required) Credential to be used to Grant Permissions on SQL Server + +###xSQLServerAlwaysOnService +* **Ensure**: (key) An enumerated value that describes if SQL server should have AlwaysOn property present or absent. +* **SQLServer**: The SQL Server for the database +* **SQLInstance**: The SQL instance for the database + +###xSQLServerEndpoint +* **EndPointName**: Name for endpoint to be created on SQL Server +* **Ensure**: (key) An enumerated value that describes if endpoint is to be present or absent on SQL Server +* **Port**: Port Endpoint should listen on +* **AuthorizedUser**: User who should have connect ability to endpoint +* **SQLServer**: The SQL Server for the database +* **SQLInstance**: The SQL instance for the database + +###xWaitforAvailabilityGroup +* **Name**: (key) Name for availability group +* **RetryIntervalSec**: Interval to check for availability group +* **RetryCount**: Maximum number of retries to check availability group creation + ## Versions ### Unreleased +### 1.6.0.0 + +* Resources Added + - xSQLAOGroupEnsure + - xSQLAOGroupJoin + - xWaitForAvailabilityGroup + - xSQLServerEndPoint + - xSQLServerAlwaysOnService +* xSQLServerHelper + - added functions + - Connect-SQL + - New-VerboseMessage + - Grant-ServerPerms + - Grant-CNOPerms + - New-ListenerADObject +* xSQLDatabaseRecoveryModel + - Updated Verbose statements to use new function New-VerboseMessage +* xSQLServerDatabase + - Updated Verbose statements to use new function New-VerboseMessage + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerDatabaseOwner + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerDatabasePermissions + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerDatabaseRole + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerLogin + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerMaxDop + - Updated Verbose statements to use new function New-VerboseMessage + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerMemory + - Updated Verbose statements to use new function New-VerboseMessage + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerPowerPlan + - Updated Verbose statements to use new function New-VerboseMessage + ### 1.5.0.0 * Added new resource xSQLServerDatabase that allows adding an empty database to a server @@ -226,7 +307,7 @@ Please check out common DSC Resources [contributing guidelines](https://github.c ### 1.4.0.0 * Resources Added - - xSQLDatabaseReoveryModeAdded + - xSQLDatabaseRecoveryModeAdded - xSQLServerDatabaseOwner - xSQLServerDatabasePermissions - xSQLServerDatabaseRole diff --git a/appveyor.yml b/appveyor.yml index 21f81fb55..833bc4728 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ #---------------------------------# # environment configuration # #---------------------------------# -version: 1.5.{build}.0 +version: 1.6.{build}.0 install: - cinst -y pester - git clone https://github.com/PowerShell/DscResource.Tests @@ -39,7 +39,7 @@ deploy_script: # Creating project artifact $stagingDirectory = (Resolve-Path ..).Path $manifest = Join-Path $pwd "xSQLServer.psd1" - (Get-Content $manifest -Raw).Replace("1.5.0.0", $env:APPVEYOR_BUILD_VERSION) | Out-File $manifest + (Get-Content $manifest -Raw).Replace("1.6.0.0", $env:APPVEYOR_BUILD_VERSION) | Out-File $manifest $zipFilePath = Join-Path $stagingDirectory "$(Split-Path $pwd -Leaf).zip" Add-Type -assemblyname System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::CreateFromDirectory($pwd, $zipFilePath) diff --git a/en-US/xPDT.strings.psd1 b/en-US/xPDT.strings.psd1 index bf078236e..0411cbba1 100644 --- a/en-US/xPDT.strings.psd1 +++ b/en-US/xPDT.strings.psd1 @@ -8,4 +8,4 @@ ErrorStarting=Failure starting process matching path '{0}'. Message: {1} FailureWaitingForProcessesToStart=Failed to wait for processes to start ProcessStarted=Process matching path '{0}' started in process ID {1} ProcessAlreadyStarted=Process matching path '{0}' already started in process ID {1} -'@ \ No newline at end of file +'@ diff --git a/xPDT.psm1 b/xPDT.psm1 index 46a5e90ad..6f22564c1 100644 --- a/xPDT.psm1 +++ b/xPDT.psm1 @@ -733,4 +733,4 @@ function GetxPDTVariable $xPDT.SelectSingleNode("//xPDT/Component[@Name='$Component' and @Version='$Version']/Role[@Name='$Role']/Update[@Name='$Update']/Variable[@Name='$Name']").Value } -Export-ModuleMember ResolvePath,StartWin32Process,WaitForWin32ProcessEnd,NetUse,GetxPDTVariable \ No newline at end of file +Export-ModuleMember ResolvePath,StartWin32Process,WaitForWin32ProcessEnd,NetUse,GetxPDTVariable diff --git a/xPDT.xml b/xPDT.xml index b3ad57aa7..c0219c805 100644 --- a/xPDT.xml +++ b/xPDT.xml @@ -1088,4 +1088,4 @@ - \ No newline at end of file + diff --git a/xSQLServer.psd1 b/xSQLServer.psd1 index 274b1a96a..ed2aca7a4 100644 --- a/xSQLServer.psd1 +++ b/xSQLServer.psd1 @@ -1,6 +1,6 @@ @{ # Version number of this module. -ModuleVersion = '1.5.0.0' +ModuleVersion = '1.6.0.0' # ID used to uniquely identify this module GUID = '74e9ddb5-4cbc-4fa2-a222-2bcfb533fd66' @@ -47,7 +47,42 @@ PrivateData = @{ # IconUri = '' # ReleaseNotes of this module - # ReleaseNotes = '' + ReleaseNotes = '* Resources Added + - xSQLAOGroupEnsure + - xSQLAOGroupJoin + - xWaitForAvailabilityGroup + - xSQLServerEndPoint + - xSQLServerAlwaysOnService +* xSQLServerHelper + - added functions + - Connect-SQL + - New-VerboseMessage + - Grant-ServerPerms + - Grant-CNOPerms + - New-ListenerADObject +* xSQLDatabaseRecoveryModel + - Updated Verbose statements to use new function New-VerboseMessage +* xSQLServerDatabase + - Updated Verbose statements to use new function New-VerboseMessage + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerDatabaseOwner + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerDatabasePermissions + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerDatabaseRole + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerLogin + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerMaxDop + - Updated Verbose statements to use new function New-VerboseMessage + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerMemory + - Updated Verbose statements to use new function New-VerboseMessage + - Removed ConnectSQL function and replaced with new Connect-SQL function +* xSQLServerPowerPlan + - Updated Verbose statements to use new function New-VerboseMessage + +' } # End of PSData hashtable diff --git a/xSQLServerHelper.psm1 b/xSQLServerHelper.psm1 index 170519979..6521499f8 100644 --- a/xSQLServerHelper.psm1 +++ b/xSQLServerHelper.psm1 @@ -2,9 +2,61 @@ $VerbosePreference = 'Continue' # Load Localization Data -Import-LocalizedData LocalizedData -filename xSQLServer.strings.psd1 -ErrorAction SilentlyContinue +Import-LocalizedData LocalizedData -filename xSQLServer.strings.psd1 -ErrorAction SilentlyContinue Import-LocalizedData USLocalizedData -filename xSQLServer.strings.psd1 -UICulture en-US -ErrorAction SilentlyContinue +function Connect-SQL +{ +[CmdletBinding()] + param + ( [ValidateNotNull()] + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [ValidateNotNull()] + [System.String] + $SQLInstanceName = "MSSQLSERVER", + + [ValidateNotNull()] + [System.Management.Automation.PSCredential] + $SetupCredential + ) + + $null = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') + + if($SQLInstanceName -eq "MSSQLSERVER") + { + $ConnectSQL = $SQLServer + } + else + { + $ConnectSQL = "$SQLServer\$SQLInstanceName" + } + if ($SetupCredential) + { + $SQL = New-Object Microsoft.SqlServer.Management.Smo.Server + $SQL.ConnectionContext.ConnectAsUser = $true + $SQL.ConnectionContext.ConnectAsUserPassword = $SetupCredential.GetNetworkCredential().Password + $SQL.ConnectionContext.ConnectAsUserName = $SetupCredential.GetNetworkCredential().UserName + $SQL.ConnectionContext.ServerInstance = $ConnectSQL + $SQL.ConnectionContext.connect() + } + else + { + $SQL = New-Object Microsoft.SqlServer.Management.Smo.Server $ConnectSQL + } + if($SQL) + { + New-VerboseMessage -Message "Connected to SQL $ConnectSQL" + $SQL + } + else + { + Throw -Message "Failed connecting to SQL $ConnectSQL" + Exit + } +} + function New-TerminatingError { [CmdletBinding()] @@ -66,4 +118,198 @@ function New-TerminatingError $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $ErrorCategory, $TargetObject return $errorRecord -} \ No newline at end of file +} + + +function New-VerboseMessage +{ + [CmdletBinding()] + [Alias()] + [OutputType([string])] + Param + ( + [Parameter(Mandatory=$true)] + $Message + ) + Write-Verbose -Message ((Get-Date -format yyyy-MM-dd_HH-mm-ss) + ": $Message"); + +} + +function Grant-ServerPerms +{ +[CmdletBinding()] + param + ( + [ValidateNotNull()] + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [ValidateNotNull()] + [System.String] + $SQLInstanceName= "MSSQLSERVER", + + [ValidateNotNullOrEmpty()] + [parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $SetupCredential, + + [ValidateNotNullOrEmpty()] + [parameter(Mandatory = $true)] + [System.String] + $AuthorizedUser + ) + + if(!$SQL) + { + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName -SetupCredential $SetupCredential + } + Try{ + $sps = New-Object Microsoft.SqlServer.Management.Smo.ServerPermissionSet([Microsoft.SqlServer.Management.Smo.ServerPermission]::AlterAnyAvailabilityGroup) + $sps.Add([Microsoft.SqlServer.Management.Smo.ServerPermission]::ViewServerState) + $SQL.Grant($sps,$AuthorizedUser) + New-VerboseMessage -Message "Granted Permissions to $AuthorizedUser" + } + Catch{ + Write-Error "Failed to grant Permissions to $AuthorizedUser." + } +} + +function Grant-CNOPerms +{ +[CmdletBinding()] + Param + ( + [ValidateNotNullOrEmpty()] + [parameter(Mandatory = $true)] + [System.String] + $AvailabilityGroupNameListener, + + [ValidateNotNullOrEmpty()] + [parameter(Mandatory = $true)] + [System.String] + $CNO + ) + + #Verify Active Directory Tools are installed, if they are load if not Throw Error + If (!(Get-Module -ListAvailable | Where-Object {$_.Name -eq "ActiveDirectory"})){ + Throw "Active Directory Module is not installed and is Required." + Exit + } + else{Import-Module ActiveDirectory -ErrorAction Stop -Verbose:$false} + Try{ + $AG = Get-ADComputer $AvailabilityGroupNameListener + + $comp = $AG.DistinguishedName # input AD computer distinguishedname + $acl = Get-Acl "AD:\$comp" + $u = Get-ADComputer $CNO # get the AD user object given full control to computer + $SID = [System.Security.Principal.SecurityIdentifier] $u.SID + + $identity = [System.Security.Principal.IdentityReference] $SID + $adRights = [System.DirectoryServices.ActiveDirectoryRights] "GenericAll" + $type = [System.Security.AccessControl.AccessControlType] "Allow" + $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "All" + $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType + + $acl.AddAccessRule($ace) + Set-Acl -AclObject $acl "AD:\$comp" + New-VerboseMessage -Message "Granted privileges on $comp to $CNO" + } + Catch{ + Throw "Failed to grant Permissions on $comp." + Exit + } +} + +function New-ListenerADObject +{ +[CmdletBinding()] + Param + ( + [ValidateNotNullOrEmpty()] + [parameter(Mandatory = $true)] + [System.String] + $AvailabilityGroupNameListener, + + [ValidateNotNull()] + [System.String] + $SQLServer = $env:COMPUTERNAME, + + [ValidateNotNull()] + [System.String] + $SQLInstanceName = "MSSQLSERVER", + + [ValidateNotNullOrEmpty()] + [parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $SetupCredential + ) + + if(!$SQL) + { + $SQL = Connect-SQL -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName -SetupCredential $SetupCredential + } + + $CNO= $SQL.ClusterName + + #Verify Active Directory Tools are installed, if they are load if not Throw Error + If (!(Get-Module -ListAvailable | Where-Object {$_.Name -eq "ActiveDirectory"})){ + Throw "Active Directory Module is not installed and is Required." + Exit + } + else{Import-Module ActiveDirectory -ErrorAction Stop -Verbose:$false} + try{ + $CNO_OU = Get-ADComputer $CNO + #Accounts for the comma and CN= at the start of Distinguished Name + #We want to remove these plus the ClusterName to get the actual OU Path. + $AdditionalChars = 4 + $Trim = $CNO.Length+$AdditionalChars + $CNOlgth = $CNO_OU.DistinguishedName.Length - $trim + $OUPath = $CNO_OU.ToString().Substring($Trim,$CNOlgth) + } + catch{ + Throw ": Failed to find Computer in AD" + exit + } + + + $m = Get-ADComputer -Filter {Name -eq $AvailabilityGroupNameListener} -Server $env:USERDOMAIN | Select-Object -Property * | Measure-Object + + If ($m.Count -eq 0) + { + Try{ + #Create Computer Object for the AgListenerName + New-ADComputer -Name $AvailabilityGroupNameListener -SamAccountName $AvailabilityGroupNameListener -Path $OUPath -Enabled $false -Credential $SetupCredential + New-VerboseMessage -Message "Created Computer Object $AvailabilityGroupNameListener" + } + Catch{ + Throw "Failed to Create $AvailabilityGroupNameListener in $OUPath" + Exit + } + + $SucccessChk =0 + + #Check for AD Object Validate at least three successful attempts + $i=1 + While ($i -le 5) { + Try{ + $ListChk = Get-ADComputer -filter {Name -like $AvailabilityGroupNameListener} + If ($ListChk){$SuccessChk++} + Start-Sleep -Seconds 10 + If($SuccesChk -eq 3){break} + } + Catch{ + Throw "Failed Validate $AvailabilityGroupNameListener was created in $OUPath" + Exit + } + $i++ + } + } + Try{ + Grant-CNOPerms -AvailabilityGroupNameListener $AvailabilityGroupNameListener -CNO $CNO + } + Catch{ + Throw "Failed Validate grant permissions on $AvailabilityGroupNameListener in location $OUPAth to $CNO" + Exit + } + +}