Using a hardware load balancer is very common to spread workload across multiple servers, as well as direct traffic to surviving servers when one goes down or is being patched. When using an HLB, there are several methods that can be used. The more conventional SNAT is quite popular, but another method, Direct Server Return, or DSR, provides for substantially increased performance. This can be key in environments where a lot of traffic from Exchange and/or Lync is going through the HLBs, or where the same HLBs are being used for many apps. Update:Tom Pacyk and John Cook pointed out that I neglected to mention that DSR based HLB is not supported on Lync Edge servers (and it won’t even work based on my testing). See Microsoft’s support statement at the bottom of http://technet.microsoft.com/en-us/library/gg425779.aspx. Sorry about the omission, guys!

The difference from a server side perspective, is that to use the DSR method, extra configuration is required when building the server. To configure a server for DSR based load balancing a loopback adapter is added and configured with the IP address of the load balancer VIP. This allows the server to accept packets targeted for the VIP address. Without it, the server would ignore them.

Add the Microsoft Loopback adapter

Unbind all services and protocols except IPv4

Rename the loopback adapter to “loopback” and rename the regular NIC to “net”

Assign an IP address and subnet mask (but no gateway)

Configure the adapter to not register its address in DNS

Set the adapter’s metric to 254

Adjust the adapter bindings so that it is lower than the normal NIC in the server

Set WeakHostSend and WeakHostReceive settings on both adapters

While adding and configuring the loopback adapter is simple enough, it’s a list of steps that is ideally suited for PowerShell – especially if you build a fair number of servers. Unfortunately, there is no straighforward methods to accomplish all of the required tasks. In order to configure the adapter bindings, a separate file must be downloaded. In order to even add the loopback adapter, yet another file needs to be downloaded. It’s almost more grief to try it through PowerShell than to just manually do it, right? Not so fast!

PowerShell is quite powerfull. We can download the required files, unzip them if needed, and then use them as required to fulfill our needs. Of course, this assumes that the server has Internet connectivity.

Run the script one of two ways. Run just the script itself by typing

.\New-LoopbackAdapter.ps1

and the script will prompt you for the VIP IP and subnet mask.

Or, type

.\New-LoopbackAdapter.ps1 -vipip [ip address] -vipsm [subnet mask]

for example

.\New-LoopbackAdapter.ps1 -vipip 10.1.0.100 -vipsm 255.255.255.0

As with most of my scripts, tab completion for the parameters works, and there is a full help section by typing:

Get-Help .\New-LoopbackAdapter.ps1

Once the script completes, Explorer will open to the network adapters section so that you can verify the various steps have completed:

No services or protocols other than IPv4 bound to the loopback adapter:

IP address and subnet mask configured:

Metric set to 254:

DNS registration unchecked:

Loopback adapter at the bottom of the adapter bindings:

The script also creates a full transcript in the same folder as the script.

Installation

Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.

Well, Lync Server MVP Ståle Hansen took that script and adapted it to installing the prerequisites for Lync Server 2010 and posted the results online. He did some neat things like installing the Best Practice Analyzer and the Resource Kit.

I took the script and added a bunch of functionality, including prerequisites for all Lync related roles, some added third-party tools such as the cool “Find Lync Versions” tool from Stephen Olsen, aka “Stumper”, was added as an option. Note: This automatically installs the .Net 4 framework.

I also added the ability to download some files that are needed – essentially automating some routine tasks. See the changelog file linked below for features added in each version.

For those of you doing Lync voice work, I haven’t done any deployments yet, so if there are tasks you’d like me to automate, please let me know and I can get them added when I have time.

Installation

Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.

If you write a lot of PowerShell code, you probably have a favorite text editor. Maybe you use Notepad, Notepad+, PowerShell ISE, etc. Mine is IDM Computer Solutions’ UltraEdit. I’ve been using UltraEdit for many years, including while doing web dev work. It’s feature packed and well worth the few dollars that it costs.

One of UltraEdit’s great features is the ability to do syntax highlighting, with support for many different languages. By default, UltraEdit doesn’t ship with a wordfile for PowerShell. There is a community that helps develop new syntax highlighting wordfiles, and lo and behold, someone created a PowerShell wordfile.

I’ve taken that file and added the Exchange 2010 and Lync 2010 cmdlets so that they are properly highlighted. The file can be downloaded from powershell.zip. Grab it and toss it into your %appdata%\IDMComp\UltraEdit\wordfiles folder. Enjoy!

Often we need to create file shares, and this is generally fairly boring. PowerShell can help streamline this process. This function will create the share, but does not set sharing permissions. We’ll cover that later.

When writing scripts that use variables, especially those that contain a fair amount of data, it’s best practice to clean up the environment when exiting. This frees up memory for other purposes, and allows you to leave the environment as clean as possible. This is accomplished using the Remove-Variable cmdlet.

As scripts become more complex and evolve over time, it can be tough to keep track of all variables in order to remove them at the end. I created this function to help deal with this. The function takes the path of the script file, inspects the file, compiles a list of variables in the script, and runs them through the Remove-Variable cmdlet. It builds on some of the code from Auto-Documenting Script Variables.

We then call the function, passing the built-in $MyInvocation.MyCommand.Name value, which automatically contains the path and name of the currently running script. Essentially, we tell the function to run against it’s own script file:

This is the changelog page for Get-CsConnections.ps1. You will find a complete list of released versions, their dates, and the features and issues addressed in each. Please refer to the script’s main page for more information including download links, installation details, and more.

v2.9 – 10-28-2014

Fixed an issue where PowerShell v2.0 machines would choke on one line. Thanks to Thierry for pointing it out.

New code-signing certificate to replace expired cert

v2.8 – 06-10-2014

Clarified ShowTotal output per Nate’s comment

Fixed an issue where LRS clients would show a leading space for the agent string

changed FE server info to be lower case to that it’s consistent

the -pool parameter is now -poolfqdn to align with other scripts and cmdlets

fine tuned some of the code used when specifying -SipAddress

v2.7 – 05-24-2014

fixed check for updates dialog border

defined OverallRecords as an array to avoid an issue. Thanks to Tristan for that info.

tweaked the MaxEndpointsPerUser section to always use the global configuration. This only matters in environments where multiple configurations exist (Get-CsRegistrarConfiguration). Thanks to Matt for pointing this out.

swaped in new version of Set-ModuleStatus function

cleanup of param block per best practices

cleanup of comment help per best practices

swaped in new verion of Test-ScriptUpdates

v2.5 – 11-26-2013

tweaked SQL query for case insensitivity per Jean-Luc

comment help updated to include info on Windows firewall config

tweaked code when getting info for a single user to fix missing data for pool connection order

v2.4 – 09-13-2013

Fixed output for unique users/clients

Now validates if UserHighConnectionFlag is specified, and does not exceed MaxEndPointsPerUser

v2.3 – 08-01-2013

intro code for script update check

better pool version detection. When using the -pool option, you no longer need to specify -Is2013 if it’s a 2013 pool

Added code to restart script in an elevated session if the current session isn’t elevated (previously the script just threw an error and exited)

v2.2 – 05-10-2013

Added support for Lync Server 2013 by using the -Is2013 switch. If I can find a better way of automatically detecting the version, I’ll incorporate that in a later build.

Some code optimization

Bug fix for an issue where the names of servers in a pool wouldn’t display if the script was run in PowerShell v3.

v2.1 – 12-13-2012

Minor formatting tweaks for better handling long client names, such as the Lync RT client.

Minor bug fixes

v2.0 – 10.16.2012

Added -IncludeHighUsers option. Similar to -IncludeUsers, but only shows those users who meet the UserHighConnectionFlag value (shown in white), or exceeds it (shown in red).

Added -ShowTotal option. When finished, shows statistics for the org, including total number of Lync enabled users, the total number of voice enabled users, and the percentage of enabled users that are currently connected.

Updated the code the assembles FQDNs when just a pool or server netbios name are specified.

Finally resolved the issue where some front end servers would have a different number for PrimaryRegistrarClusterId in SQL Express than others, causing some servers to not return data (and not throw an error). Special thanks to Dave Howe @ Microsoft for helping me identify a work around, and also to Bart, a SQL Engineer at a client site who helped me tweak the related SQL query.

A little code optimization

-Server option added that now allows you to target a specific server instead of an entire pool.

This version is code signed. You no longer are required to have a PowerShell Execution Policy of unrestricted or RemoteSigned. However, the script cannot be edited at all, or the code signature breaks.

-sipaddr now supports specifying just the left part of the SIP address, but only in organizations with ONE SIP domain. For example, -sipaddr bill.gates instead of -sipaddr bill.gates@microsoft.com.

-server supports specifying the netbios domain. The script will “guess” at the FQDN by using the domain name of the machine the script is running on and appending it to the netbios name.

v1.8 – 09-14-2012

Tons of formatting changes, mostly subtle

Server names in the pool list are sorted

Server names in the ‘Frontend Server’ list are now sorted

Connections are now sorted by client

Added -ShowFullClient switch to show extended client info.

If -pool is not specified, and only one registrar pool exists, the script will automatically use that pool.

Some additional verbose output added for troubleshooting

v1.7 – 09-07-2012

Minor display sorting cleanup

Streamlined some code

Removed -IncludeUsers from automatically being set when using -ClientVersion

v1.6 – 07-02-2012

Added feature to show just specific client versions and the connected users with that client