Make This a Priority
Whether we realize it or not, we prioritize just about everything we do throughout the day. It starts when we wake up in the morning: Do I sleep a little longer or do I get up so I can get to work on time? (That’s probably the toughest one right there.) When we get to work, is it more important to start answering those emails that came in overnight, or to get a cup of coffee so that our email answers are comprehensible? And which of those emails should we answer first?
This continues endlessly all day. Most of the time we don’t think too hard about those decisions and which task we need to do first – sometimes it’s pretty obvious. (Get the coffee first.) But when it comes to Windows PowerShell in Lync Server 2010, there are some decisions about priority we might want to give some serious thought to. For example, if a caller dials an unassigned number that falls within more than one unassigned number range, which announcement do we play? Or if a dialed number matches the pattern for more than one voice route, which route do we want the call to take? And of course the biggest question of all: How do we tell Lync Server how to prioritize these things?
That last question is easy, so we’ll answer that first, then go over some examples so you can see how this all works. The answer to “How do we tell Lync Server how to prioritize these things?” is this: set the Priority parameter of the appropriate cmdlet. Here’s a list of cmdlets that have a Priority parameter:
· New-CsClientVersionPolicyRule
· Set-CsClientVersionPolicyRule
· New-CsOutboundTranslationRule
· Set-CsOutboundTranslationRule
· New-CsServerApplication
· Set-CsServerApplication
· New-CsSipResponseCodeTranslationRule
· Set-CsSipResponseCodeTranslationRule
· New-CsUnassignedNumber
· Set-CsUnassignedNumber
· New-CsVoiceNormalizationRule
· Set-CsVoiceNormalizationRule
· New-CsVoiceRoute
· Set-CsVoiceRoute
· Set-CsDialInConferencingAccessNumber
How the Priority Parameter Works
The Priority parameter works the same (okay, mostly the same) no matter which cmdlet you use it with. We’ll start by explaining how to set and change the value, then we’ll talk about what it actually means to do that. We’re going to use the CsVoiceRoute cmdlets to walk you through this general discussion, then get into the specifics of the various other cmdlets.
The first time you call New-CsVoiceRoute to create a new route, that route will be given the Priority 0. For example, run this command to create a new voice route:
New-CsVoiceRoute -Identity Route1 -PstnUsages @{add="Local"} -PstnGatewayList @{add="PstnGateway:redmondpool.litwareinc.com"} -NumberPattern '^(\+1[0-9]\d+)$'
Here’s the new voice route object created by that command:
Identity: Route1
Priority: 0
Description:
NumberPattern: ^(\+1[0-9]\d+)$
PstnUsages: {Local}
PstnGatewayList: {PstnGateway:redmondpool.litwareinc.com}
Name: Route1
SuppressCalledId:
AlternateCallerId:
In this example we didn’t use the Priority parameter to explicitly set the priority. Since there were no other voice routes defined, the Priority was automatically set to 0.
Note. Your system may already have a default voice route in place. If that’s the case, the new route you just created will have a Priority value of 1. We’ll explain that next.
Now let’s create another route:
New-CsVoiceRoute -Identity Route2 -PstnUsages @{add="Long Distance"} -PstnGatewayList @{add="PstnGateway:redmondpool.litwareinc.com"} -NumberPattern '^(\+1[0-9]{7})$'
Here’s the object created by this command:
Identity: Route2
Priority: 1
Description:
NumberPattern: ^(\+1[0-9]{7})$
PstnUsages: {Long Distance}
PstnGatewayList: {PstnGateway:redmondpool.litwareinc.com}
Name: Route2
SuppressCalledId:
AlternateCallerId:
Notice the Priority value of this route. The first route created received a default Priority value of 0; the second route received a default Priority value of 1.
That seems pretty simple, right? But what happens if we create another voice route, but this time we set the Priority to 0? Let’s try it:
New-CsVoiceRoute -Identity Route3 -PstnUsages @{add="Local","Long Distance"} -PstnGatewayList @{add="PstnGateway:redmondpool.litwareinc.com"} -NumberPattern '^011(\d{7}\d+)$' –Priority 0
Here’s what Route3 looks like. (We’ll show only the Identity and Priority to keep things a little less cluttered. The rest isn’t important right now anyway. It will be in a few minutes, but it isn’t right now.)
Identity: Route3
Priority: 0
Notice that the Priority is set to 0, just like we specified in the command. But remember, Route1 already had a Priority of 0. Well, guess what? It doesn’t anymore. Here’s what we see when we call Get-CsVoiceRoute:
Identity: Route3
Priority: 0
Identity: Route1
Priority: 1
Identity: Route2
Priority: 2
Take a look at the Priority values of Route1 and Route2. Here’s what the Priority values looked like before and after we created Route3:
Identity |
Priority Before |
Priority After |
Route1 |
0 |
1 |
Route2 |
1 |
2 |
Route3 |
0 |
When we set Route3 to have a Priority of 0, the Priority values of Route1 and Route2 were automatically incremented to move them down in the priority list.
Don’t you wish it was that easy to set the priorities of your son’s baseball game, your daughter’s soccer game, and your dentist appointment, which all happen to be at the same time?
Let’s look at another example. This time we’re going to try changing the priority on an existing voice route. Suppose we want to make sure that Route3 always has the lowest priority (keeping in mind that the higher the Priority value, the lower the priority). We’re going to do this by setting the Priority value of Route3 to 9:
Set-CsVoiceRoute -Identity Route3 -Priority 9
Again, here are the Priority values before and then after running that command:
Identity |
Priority Before |
Priority After |
Route1 |
1 |
0 |
Route2 |
2 |
1 |
Route3 |
0 |
2 |
There are a couple of things to notice here. The first is that, because we moved Route3 down in the priority list, Route1 and Route2 automatically moved up: Route1 now has a value of 0 and Route2 a value of 1. The second is that, even though we set the Priority of Route3 to 9, the value is now 2. Setting the Priority to a value beyond the end of the ordered list simply sets it to the last number in the list. That means you can’t have voice routes with priorities of 0, 1, and 9. If there are two routes, with priorities 0 and 1, any number set higher than that will be reset to 2, the next number available.
What Does All This Really Mean?
We’ve seen how priorities are set by default, and how they automatically rearrange themselves when you change the values. But what does it mean to change these values? Well, that depends on the cmdlet. Let’s go through them.
Voice Route Priority
We’ll start with voice routes, since we’ve already been using those as examples. We’ll also start with our same examples. To pick up where our previous examples left off, here’s what we see when we call Get-CsVoiceRoute:
Identity: Route1
Priority: 0
Description:
NumberPattern: ^(\+1[0-9]\d+)$
PstnUsages: {Local}
PstnGatewayList: {PstnGateway:redmondpool.litwareinc.com}
Name: Route1
SuppressCalledId:
AlternateCallerId:
Identity: Route2
Priority: 1
Description:
NumberPattern: ^(\+1[0-9]{7})$
PstnUsages: {Long Distance}
PstnGatewayList: {PstnGateway:redmondpool.litwareinc.com}
Name: Route2
SuppressCalledId:
AlternateCallerId:
Identity: Route3
Priority: 2
Description:
NumberPattern: ^011(\d{7}\d+)$
PstnUsages: {Local, Long Distance}
PstnGatewayList: {PstnGateway:redmondpool.litwareinc.com}
Name: Route3
SuppressCalledId:
AlternateCallerId:
Take a look at the values for the NumberPattern properties. In case you’re not familiar with regular expressions, we’ll explain the values for you.
For Route1, the NumberPattern value of ^(\+1[0-9]\d+)$ will match phone numbers that begin with +1, followed by any number of digits, each digit containing a value of 0 through 9.
For Route2, the NumberPattern value of ^(\+1[0-9]{7})$ will match phone numbers beginning with +1, followed by exactly seven digits, each digit containing a value of 0 through 9.
For Route3, the NumberPattern ^011(\d{7}\d+)$ will match phone numbers that begin with 011, followed by at least seven digits, followed by one or more additional digits.
So, which route will the call take if the number is +15551212?
Let’s see, it starts with +1, so that rules out Route3, but Route1 and Route2 are still possible. For Route1, the +1 must be followed by any number of digits, each digit being 0 through 9. We have a match.
But wait a minute, look at Route2. Our number begins with +1, is then followed by exactly seven digits (5551212), each digit being 0 through 9.
Uh oh, looks like we have two matches. We’ve just broken our voice routing. Or at least we would have if it weren’t for the Priority value. Currently Route1 has the higher priority (the lower Priority value), with a Priority of 0. So this call will be routed through Route1.
If you look closely though, you might have noticed that with this set of rules and priorities, no rule will ever get past Route1 to use Route2: the Route1 rule encompasses any number that will match Route2. However, the opposite isn’t true: rules matching Route1 won’t always match Route2. For example, the number +12065551212 will match Route1 (+1 followed by any number of digits) but not Route2 (+1 followed by exactly seven digits).
So how do we make sure that a number such as +15551212 will be routed through Route2? We simply reset the priority of Route2 to make sure it comes before Route1:
Set-CsVoiceRoute -Identity Route2 -Priority 0
As we’ve seen, setting the Priority of Route2 to 0 will automatically move Route1 down to Priority 1. (Route3 will stay put at Priority 2; where else would it go?)
Voice Normalization Rule Priority
Priorities for voice normalization rules work pretty much the same as for voice routes: the priority determines which normalization rule will be applied if the Pattern value of more than one rule matches the given phone number.
The main difference you’ll notice with voice normalization rules is that there can be more than one rule with a given priority. Take a look at some sample output from a call to Get-CsVoiceNormalizationRule:
Identity : Global/Prefix All
Priority : 0
Description :
Pattern : ^(\d{11})$
Translation : +$1
Name : Prefix All
IsInternalExtension : False
Identity : Site:Redmond/Redmond Rule 1
Priority : 0
Description :
Pattern : ^(\d{11}\d+)$
Translation : +$1
Name : Redmond Rule 1
IsInternalExtension : False
Identity : Site:Redmond/Redmond Rule 2
Priority : 1
Description :
Pattern : ^(\d{11})$
Translation : +$1
Name : Redmond Rule 2
IsInternalExtension : False
As you can see, two of the Priority values for these rules are set to 0. The reason for this is that all voice normalization rules are associated with dial plans that have the same scope as the rule. The scope of the rule is the first part of the Identity value (the part before the /). So the first rule in the list is associated with the Global dial plan, while the next two rules are associated with the Site:Redmond dial plan. The priorities define the priority of the rule within the given dial plan. That means that within the Global scope you have one set of priorities (in this case there’s only one rule, with, of course, a Priority value of 0), and for the Site:Redmond scope you have another set of priorities (0 for the rule named Redmond Rule 1 and 1 for the rule named Redmond Rule 2).
Everything else works the same as we described for voice routes. If you set the Priority of the rule with the Identity Site:Redmond/Redmond Rule 1 to 1, then Site:Redmond/Redmond Rule 2 will be promoted to Priority 0 and Site:Redmond/Redmond Rule 1 will have the Priority of 1 that we gave it. Here’s the command that does that:
Set-CsVoiceNormalizationRule -Identity "Site:Redmond/Redmond Rule 1" -Priority 1
Outbound Translation Rule Priority
In terms of priority, outbound translation rules work exactly the same as voice normalization rules. While voice normalization rules are tied to a dial plan, outbound translation rules are tied to a trunk configuration. As with voice normalization rules, there can be multiple outbound translation rules with a Priority value of 0, but only one within each scope. Here’s some sample rules that come back when we call Get-CsOutboundTranslationRule:
Identity : Global/Rule1
Priority : 0
Description :
Pattern : ^\+(\d*)$
Translation : $1
Name : Rule1
Identity : Global/Rule2
Priority : 1
Description :
Pattern : ^\+1(\d*)$
Translation : $1
Name : Rule2
Identity : Site:Redmond/SiteRule1
Priority : 0
Description :
Pattern : ^\+1206(\d{7})$
Translation : $1
Name : SiteRule1
Once again, notice the Priority values. The first two rules are defined at the Global scope and have priorities of 0 and 1; the last rule is defined at the site scope (Site:Redmond) and has a priority of 0.
Unassigned Number Priority
Unassigned numbers define a range of telephone numbers that belong to an organization but are currently not assigned to a user or phone (thus the “unassigned number” term; clever, huh?). The CsUnassignedNumber cmdlets are used to either define announcement settings for a particular range of numbers or to assign that range to an Exchange UM Auto Attendant.
Priorities for unassigned numbers are used in the case where number ranges overlap. For example, you may have a range +12065551000 through +12065556000 set up to route calls to these numbers to an Exchange UM Auto Attendant, which leads the user through a series of voice prompts to get them to the person or department within the company that they were hoping to reach. However, for the number range +12065552000 through +12065552500, which is within our first range, you decide you don’t want those calls to go through Auto Attendant, you simply want to play a message to the caller. (This could be the case if, for example, that range of numbers used to belong to a division that has been discontinued or moved to a new location with new phone numbers. In such a case you could play a message that informs the caller of the change and give them a new number to dial for assistance.)
In this case, a call to the number +12065552300 would match both unassigned number ranges. To ensure it gets routed as expected, you’d need to set the priority of the smaller range higher (to a lower Priority value) than the larger range. Here are commands to set up those ranges:
New-CsUnassignedNumber -Identity UNSet1 -NumberRangeStart "+12065551000" -NumberRangeEnd "+12065556000" -ExUmAutoAttendantPhoneNumber "+12065550001"
New-CsUnassignedNumber -Identity UNSet2 -NumberRangeStart "+12065552000" -NumberRangeEnd "+12065552500" -AnnouncementService ApplicationServer:redmond.litwareinc.com -AnnouncementName "Moved Announcement" -Priority 0
Client Version Policy Rule Priority
Client version policy rules are used to determine which client applications are allowed to log on to Lync Server 2010. When a client attempts to connect, the rules will be checked to see whether that client is allowed access, denied access, or some action must be taken to gain access. The Priority value of a client version policy rules simply determines in what order the rules will be checked. Once a client version is found in the set of rules that matches the application requesting access, that rule is applied and no other rules are checked.
What this means is that it will be most efficient to assign the rule you expect to be used most to the highest priority (Priority 0).
Like voice normalization rules and outbound translation rules, client version policy rules apply the priority according to scope. So a rule at the global scope will have Priority 0, and a rule at the site scope will also have Priority 0.
SIP Response Code Translation Rule Priority
A SIP response code translation rule maps a SIP response code with a value anywhere from 400 through 699 to a value used by Lync Server 2010. Here’s an example of creating a new SIP response code translation rule:
New-CsSipResponseCodeTranslationRule -Identity "global/Rule404" -ReceivedResponseCode 434 -TranslatedResponseCode 404
This command sets up a global rule (named Rule404) that will translate the received code 434 to the SIP response code 404. Now take a look at this next command:
New-CsSipResponseCodeTranslationRule -Identity "global/Rule41028" -ReceivedResponseCode 434 -TranslatedResponseCode 410 -ReceivedISUPCauseCode 28 -Priority 0
The rule created by this command is also created at the global scope (this time with the name Rule41028), and translates the received code 434. However, in this command that code is translated to the SIP response code 410. In addition, we’ve added two parameters: ReceivedISUPCauseCode and Priority. By setting the ReceivedISUPCauseCode value, we’ve set up this rule to apply to received response codes of 434 that also must have an ISDN User Part (ISUP) cause code of 28 present in the SIP response message. A Priority value of 0 ensures that this rule is checked before Rule404.
Server Application Priority
Server applications are applications that are hosted on Lync Server 2010. These applications are hosted by Lync Server services. The priority for a server application determines in which order, on a given service, applications start. In other words: 1) there can be multiple applications at the same priority, but each must be on a different service and 2) the priority determines in what order applications are started on each service.
Make sense? Let’s create a couple of server applications just to make sure:
New-CsServerApplication -Identity "EdgeServer:atl-edge-001.litwareinc.com/EdgeMonitor" -Uri https://www.litwareinc.com/edgemonitor -Critical $False
New-CsServerApplication -Identity "EdgeServer:atl-edge-001.litwareinc.com/EdgeApp" -Uri https://www.litwareinc.com/edgeapp -Critical $False -Priority 0
These commands create two new server applications. They both reside on the edge server (EdgeServer:atl-edge-001.litwareinc.com). One is named EdgeMonitor, the other EdgeApp. In the second command, we added a Priority value of 0 to ensure that the EdgeApp application starts before any other application on that edge server.
Dial-in Conferencing Access Number Priority
The priority for dial-in conferencing access number works a little differently than the other Priority values we’ve seen so far. For one thing, you can’t set the priority when you create a new dial-in conferencing access number, the priority will be assigned automatically. Once you’ve created the dial-in conferencing access number you can modify the priority by calling Set-CsDialInConferencingAccessNumber. Here’s an example:
New-CsDialInConferencingAccessNumber -PrimaryUri "sip:RedmondDialIn@litwareinc.com" -DisplayNumber "1-800-555-1234" -LineUri "tel:+18005551234" -Pool atl-cs-001.litwareinc.com -PrimaryLanguage "en-US" -Regions "Redmond"
Set-CsDialInConferencingAccessNumber -Identity ""sip:RedmondDialIn@litwareinc.com"" -Priority 0 -ReorderedRegion Redmond
The first line calls the New-CsDialInConferencingAccessNumber cmdlet to create a new dial-in conferencing access number with the SIP address sip:RedmondDialIn@litwareinc.com. The second line then calls Set-CsDialInConferencingAccessNumber, passing the Identity (the SIP address) of the number we just created, to modify the Priority value of that number.
Another thing that’s a different with priorities for dial-in conferencing access numbers is the fact that the Priority parameter can’t be set by itself; in other words, it can’t be the only parameter being modified in the Set statement. If you set the Priority value, you must also set the ReorderedRegion parameter (as we did in our example). The Priority for a dial-in conferencing access number determines the order in which it’s displayed in the conference invitation. Those numbers are displayed according to region, which is why we also need to specify the ReorderedRegion parameter: we need to specify in which region we’re reordering the number.
That’s All for Now
That’s all there is to priorities in Lync Server 2010 PowerShell cmdlets. It really isn’t complicated, you just need to know what it is you’re prioritizing and the rest is easy.
Now it’s off to lunch. Or should we answer those emails from our manager first? Or maybe start on that next article…
Lunch it is.