Script Center > Repository > Remote Desktop Services > Manage RD Connection Broker Cluster (Create, Add nodes)
TechNet Script Center logo

Welcome to the TechNet Script Center Repository!

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.

Manage RD Connection Broker Cluster (Create, Add nodes)

(Microsoft)
VERIFIED AND TESTED BY THE SCRIPT CENTER TEAM
Rate it:
 
 
 
 
 
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
Windows Server 2008 R2 Yes
Windows Server 2008 No
Windows Server 2003 No
Windows 7 No
Windows Vista No
Windows XP No
Windows 2000 No
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.