|
Each contribution is licensed to you under a License Agreement by its owner, not Microsoft. Microsoft does not guarantee the contribution or purport to grant rights to it.
|
Categories |
Manage RD Connection Broker Cluster (Create, Add nodes)(Microsoft)
Script Code
Windows PowerShell
<#
.Synopsis
Adds node(s) to a RD Connection Broker(CB) Fail-Over cluster that has already been created.
Creates a RD Connection Broker(CB) Fail-Over cluster if '-Create' switch has been specified.
.Description
Adds node(s) to a RD Connection Broker(CB) Fail-Over cluster that has already been created.
Creates a RD Connection Broker(CB) Fail-Over cluster if '-Create' switch is specified. While creating a RD Connection Broker(CB) Fail-Over cluster, it also installs the required roles/features.
NOTE:
1. To add a node to an existing RD Connection Broker Fail-Over cluster, the script should be executed on the ownernode of the cluster.
2. To create a RD Connection Broker Fail-Over cluster, the script should be executed on one of the nodes that is intended to be part of the cluster.
3. The script should be executed with domain user credentials that has administrative privileges on all the nodes of the cluster.
.Parameter ClusterName
Name of the RD Connection Broker Fail-Over cluster.
.Parameter ClientAccessName
Client access Name of RD Connection Broker Fail-Over cluster. Client access name can be found in the services and applications pane of the Fail-Over cluster manager.
.Parameter Node
Names of the servers that are a part of the RD Connection Broker Fail-Over cluster.
.Parameter Create
Switch: If provided, the RD Connection Broker Fail-Over cluster is created.
.Example
PS C:\> Set-ConnectionBrokerCluster.ps1 -Node cb1,cb2 -ClusterName "My-Cluster" -ClientAccessName "HA-CB" -Create
Creates the RD Connection Broker Fail-Over cluster "My-Cluster" with nodes cb1 and cb2.
.Example
PS C:\> Set-ConnectionBrokerCluster.ps1 -Node cb1,cb2 -ClusterName "My-Cluster" -ClientAccessName "HA-CB"
Adds nodes cb1 and cb2 to already created cluster(with the current machine as one of the nodes).
.Notes
Name : Set-ConnectionBrokerCluster.ps1
#>
param(
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$TRUE, HelpMessage="Name of the RD Connection Broker Fail-Over cluster.")]
[System.String]$ClusterName,
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$TRUE, HelpMessage="Client access Name of RD Connection Broker Fail-Over cluster. Client access name can be found in the services and applications pane of the Fail-Over cluster manager.")]
[System.String]$ClientAccessName,
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$TRUE, HelpMessage="Names of the servers that are a part of the RD Connection Broker Fail-Over cluster.")]
[System.String[]]$Node,
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$FALSE, HelpMessage="Switch to specify if the RD Connection Broker Fail-Over cluster needs to be created.")]
[Switch]$Create
)
function Get-HostName([Bool]$IsFqdn)
{
$WmiObj = Get-WmiObject -Class Win32_ComputerSystem -Property Name,Domain
if($IsFqdn)
{
return $WmiObj.Name + "." + $WmiObj.Domain
}
else
{
return $WmiObj.Name
}
}
function Print-Error([System.String]$Msg)
{
Write-Host -ForegroundColor Red -BackgroundColor White $Msg
Exit(1)
}
function Invoke-MyCommand([System.String]$Computer, [System.Management.Automation.ScriptBlock]$ScriptBlock, [System.Object[]]$ArgumentList)
{
$RetVal = @()
$RetVal = [System.Object[]](Invoke-Command -ComputerName $Computer -ScriptBlock $ScriptBlock -ArgumentList $ArgumentList)
return $RetVal
}
function Ping-Comp([System.String]$Computer)
{
$RetVal = $null
$RetVal = Invoke-MyCommand $Computer {"Ping"}
if($RetVal)
{
return $TRUE
}
else
{
return $FALSE
}
}
function Validate-AccessName([String]$AccessName)
{
if( ($AccessName.Split(".").Length) -gt 1 )
{
return $FALSE
}
else
{
return $TRUE
}
}
# Check if the script is being executed with appropriate privileges
$LoggedInUser = New-Object -TypeName System.Security.Principal.WindowsPrincipal -ArgumentList ([System.Security.Principal.WindowsIdentity]::GetCurrent())
if(!($LoggedInUser.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)))
{
Print-Error "Please execute the script with administrative privileges."
}
if(!($LoggedInUser.IsInRole("Domain Users")))
{
Print-Error "Please execute the script with domain user credentials that has administrative privileges on all the nodes of the cluster."
}
if( -not (Validate-AccessName $ClusterName) )
{
Print-Error "Please provide the Cluster Name of RD Connection Broker Fail-Over cluster, not it's FQDN."
}
if( -not (Validate-AccessName $ClientAccessName) )
{
Print-Error "Please provide the Client access Name of RD Connection Broker Fail-Over cluster, not it's FQDN."
}
if( $ClusterName -eq $ClientAccessName )
{
Print-Error "The 'ClientAccessName' should not be the same as the 'ClusterName'."
}
#Check if the node list contains the localhost.
$AllComputers = [String[]]($Node)
$LocalHostName = Get-HostName $false
$LocalHostFQDN = Get-HostName $true
$NotFound = $True
$MasterConfigNode = $null
foreach($Comp in $AllComputers)
{
if( ($Comp -eq $LocalHostName) -or ($Comp -eq $LocalHostFQDN) )
{
$NotFound = $False
$MasterConfigNode = $Comp
}
}
if($NotFound -and $Create.IsPresent)
{
Print-Error "The 'Node' list should contain the local computer as the parameter '-Create' is provided."
}
if(!$Create.IsPresent -and !$NotFound)
{
Print-Error "The 'Node' list contains the local computer which is not a part of the already created cluster. Please use '-Create' switch to create a new cluster and add nodes to it. Please execute the script on the 'OwnerNode' of the cluster, if the node is to be added to an already created cluster."
}
#Check to see if all computers are accessible for Remote PowerShell script execution.
foreach($Comp in $AllComputers)
{
if(!(Ping-Comp $Comp))
{
Print-Error "Unable to ping $Comp. Exiting..!"
}
}
$ScriptBlock = {
Import-Module -Name ServerManager -ErrorAction Stop
$RetVal = $TRUE
$HostName = hostname
if(!(Get-WindowsFeature RDS-Connection-Broker).Installed)
{
Add-WindowsFeature -Name RDS-Connection-Broker
if($?)
{
Write-Host "Installed RD Connection Broker role service on '$HostName'"
}
else
{
Write-Host -ForegroundColor Red -BackgroundColor White "Failed to install RD Connection Broker role service on '$HostName'"
$RetVal = $FALSE
}
}
if(!(Get-WindowsFeature Failover-Clustering).Installed)
{
Add-WindowsFeature -Name Failover-Clustering
if($?)
{
Write-Host "Installed 'Fail-Over-Clustering' feature on '$HostName'"
}
else
{
Write-Host -ForegroundColor Red -BackgroundColor White "Failed to install 'Fail-Over-Clustering' feature on '$HostName'"
$RetVal = $FALSE
}
}
$RetVal
}
#Install RD Connection Broker role service and failover-cluster feature if not installed
foreach($Comp in $Node)
{
$ShouldStop = $FALSE
$RetValue = Invoke-MyCommand $Comp $ScriptBlock
if(!$RetValue)
{
Print-Error "Error on server: '$Comp'. Either the 'ServerManager' module could not be loaded or one of the roles/features failed to install. Exiting..!"
}
}
#Add cluster resources
#Load the FailOverClusters module
Import-Module -Name FailoverClusters -ErrorAction Stop
if($Create.IsPresent)
{
#Create a new cluster
New-Cluster -Name $ClusterName -Node $Node -ErrorAction Stop
#Add RD Connection Broker role service and create a resource group
Add-ClusterGenericServiceRole -Name $ClientAccessName -ServiceName "Tssdis" -CheckpointKey "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Session Broker" -ErrorAction Stop
#Also add publishing service to the group
Add-ClusterResource -Name "RemoteApp and Desktop Connection Management" -Group $ClientAccessName -ResourceType "Generic Service" -ErrorAction Stop
Get-ClusterResource -Name "RemoteApp and Desktop Connection Management" | Set-ClusterParameter -Name ServiceName -Value "TScPubRPC"
Get-ClusterResource -Name "RemoteApp and Desktop Connection Management" | Set-ClusterParameter -Name StartupParameters -Value "-k NetworkServiceRemoteDesktopPublishing"
#Stop & Start the cluster group on this node
Stop-ClusterGroup -Name $ClientAccessName
Start-ClusterGroup -Name $ClientAccessName -ErrorAction Stop
#Move the resource across the nodes atleast once so that the services are stopped and started atleast once
$OtherNodes = @()
foreach($Comp in $AllComputers)
{
if( $Comp -ne $MasterConfigNode )
{
$OtherNodes += $Comp
}
}
if($OtherNodes)
{
foreach($CurrNode in $OtherNodes)
{
Move-ClusterGroup -Name $ClientAccessName -Node $CurrNode
if(!$?)
{
Write-Warning "Moving the cluster ownership to server '$CurrNode' failed!"
}
else
{
Write-Host "Moving the cluster ownership to server '$CurrNode' passed!"
}
}
}
Move-ClusterGroup -Name $ClientAccessName -Node $MasterConfigNode
if(!$?)
{
Write-Warning "Moving the cluster ownership to server '$MasterConfigNode' failed!"
}
else
{
Write-Host "Moving the cluster ownership to server '$MasterConfigNode' passed!"
}
Write-Host "Successfully created cluster '$ClusterName'!"
}
else
{
$ClusterObj = Get-Cluster -Name $ClusterName
if(!$ClusterObj)
{
Print-Error "Cluster '$ClusterName' does not exist!"
}
foreach($Comp in $Node)
{
Add-ClusterNode -Cluster $ClusterName -Name $Comp
if(!$?)
{
Print-Error "Failed to add '$Comp' to the cluster '$ClusterName'"
}
else
{
Write-Host "Successfully added '$Comp' to the cluster '$ClusterName'"
}
}
}
Platforms
For online peer support, join
The Official Scripting Guys Forum!
To provide feedback or report bugs in sample scripts, please start a new discussion on the Discussions tab for this script.
Disclaimer
The sample scripts are not supported under any Microsoft standard support program or service. The sample scripts are provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.
Be the first to create a discussion.
|