Scopes and Filters

 

Suppose you’re a typical English-speaking American and you get the opportunity to live and work in Rome for a year. Could you survive without learning to speak Italian? Maybe. Would you be better off if you took a little time to sit down and learn some Italian? Definitely. When in Rome, do as the Romans do.

 

Oh: and talk like the Romans talk.

 

True story. Several years ago, one of the authors accompanied his son to Japan (his son was playing on an all-star baseball team that was touring the Tokyo area). One night the author was talking to a Japanese mother whose family was serving as a “host family” for two nights. (Instead of staying in hotels, the players stayed with host families.) This mother was a trifle nervous about hosting three American children: would they like the food; would they be bored; would they be able to communicate? After chatting in English the author – who had learned a little Japanese prior to the trip – wished the woman “Good luck” in Japanese. The mother just stood and stared at him. “I’m sorry,” said the author. “I was trying to say ‘Good luck,’ but I guess I said it wrong.” “Oh,” said the woman. “I get it: you were speaking Japanese. No, you said it correctly. You’re an American, though, so I never expected you to speak Japanese. I assumed you were speaking English, so I had no idea what you were saying.”

 

As it turns out, Microsoft Lync Server 2010 introduces a whole new language and a whole new vocabulary all its own. Can you survive without learning this new vocabulary? Maybe. Would you be better off if you took a little time to sit down and learn this new vocabulary? Well, you know what they say: when in Rome ….

 

With that in mind, let’s take a minute and talk about three important new terms being introduced along with the new Lync Server implementation of Windows PowerShell: identities, scopes, and filters.

 

Oh, my!

 

Identities

 

At the risk of tooting our own horns, we went to great lengths to explain identities in our Identities article, which means that we’re not going to do it again here. Instead, let’s move on to Scopes.

 

Man, if all the sections turn out like this one this article will be a cinch to write.

 

Scopes

 

To explain what a scope let’s start by listing the available scopes:

 

         Global. The global scope is for configuration settings or policies you want enforced throughout your entire Microsoft Lync Server infrastructure. For example, when you configure a policy at the global scope that policy will be applied to every user in the organization. (Well, unless you have configured a policy “downstream.” But more on that in a minute.)

         Site. The site scope is for, well, sites. In Lync Server 2010, sites are typically based on geographic locations: a Redmond site, a Dublin site, etc.

         Service. The service scope represents a service. For example, the Registrar service is one Microsoft Lync Server service; user services is another. In the new Lync Server architecture, a given service might be carried out by a single computer or by all the computers in a pool.

         Tenant. The Tenant scope deals with Lync Server as a service (the so-called “in-the-cloud” scenario). At this point in time the Microsoft Lync Server cmdlets cannot be used “in the cloud.” In turn, that means that it is irrelevant to our needs, and thus won’t be discussed in this article. We mention this only because – as you’ll see in the next section – you might stumble upon a reference to the Tenant scope when trying to determine the allowed scopes for an object.

         Per-User. To be honest, “per-user” isn’t really the name of the scope, it’s more a description of the scope. (We have yet to come up with a good name for this scope.) The basic concept behind the per-user scope is pretty straightforward. The per-user scope (which applies only to policies, and not to configurations) is reserved for policies that can be directly applied to a user or a group of users. This makes the per-user (or, more simply, “user”) scope very different from the global, site, and service scopes, all of which are tied to your Microsoft Lync Server infrastructure. For example, if you don’t have a site named Redmond then you can’t create a policy at the site:Redmond scope; a site-scoped policy must be tied to an actual site. The Identity of a site-scoped policy or a service-scoped policy is simply the Identity of the site or service – period.

Oh, and each site is limited to one voice policy, one client policy, and so on: you can’t have two site-scoped voice policies at the Redmond site.

By comparison, you can create a per-user policy and give it pretty much any Identity. That’s because these policies do not have to be anchored to real objects such as sites or services. In turn, that means you can create as many per-user voice policies as you want, even if you don’t ever actually use those policies.

 

Scopes are primarily used for policy (and configuration) resolution. For example, if a user wants to make a phone call Lync Server needs to check to see such things as which voice policy is used to determine how (or even if) the user makes a call. Microsoft Lync Server applies policies and configurations in this order:

 

1.    First, the system checks to see if something has been applied at the user scope. If so, then that policy (configurations can’t be applied at the user scope) is used.

2.    If nothing can be found at the user scope then the system checks to see if something has been applied at the service scope. If so, then that policy or configuration is applied.

3.    If nothing can found at the service scope then the system checks to see if something has been applied at the site scope. If so, then that policy or configuration is applied

4.    If nothing can be found at the site scope then the system checks to see if something has been applied at the global scope. If so, then that policy or configuration is applied.

 

Note that there will always be a global policy or a global configuration setting. Global policies and configuration settings are automatically created for you when you install Microsoft Lync Server 2010, and these global objects can never be removed.

 

Never.

 

Got all that? Good, because now we can talk about how you specify an identity and, equally important, when you specify an identity.

 

Important. This discussion pertains to Microsoft Lync Server policies and configurations; it does not pertain to user accounts. For more information on user account identities see Retrieving Active Directory and Microsoft Lync Server User Accounts.

 

As we explained in the Identities section of this manual, identities are specified at the time you create a new object; the identity you give that object will depend on both the type of object and on the scope of the object. For example, suppose you want to create a new conferencing policy for use at the site level; what identity will you give that policy? That’s an easy one: a site policy always has an Identity that consists of the string value site: followed by the name of the site. For example, if this conferencing policy is to be assigned to the Redmond site then you would use the following code to create the new policy:

 

New-CsConferencingPolicy –Identity site:Redmond

 

OK, then what about a policy that’s supposed to be assigned to a service? That’s another easy one: the Identity is simply the string value service: followed by the service name (i.e., Registrar) followed by the fully qualified domain name of the pool where that service is located. You know, like this:

 

New-CsClientVersionPolicy –Identity service:Registrar:atl-cs-001.litwareinc.com

 

As you can see, when you are working at the site scope or the service scope there is no need to assign (or grant) a policy; instead, the policy is automatically assigned based on the Identity you give it. Give a policy the Identity site:Redmond and it will automatically be assigned to the Redmond site.

 

Note. You might have noticed we skipped the Global policy. Lync Server ships with default policies and configurations at the global scope. However, and because you can’t re-create a policy or configuration that already exists, you won’t be able to call a New cmdlet using the Global identity. You can use verbs like Get and Set when working with a global policy or a global collection of configuration settings, but you’ll receive an error if you try to create a new global object.

 

That leaves us with one last identity/scope to deal with: per-user. Per-user policies (and, again, only policies can be applied at the per-user scope) represent the one time (for the most part) you get to be a little creative: with per-user policies, you get to pick out the Identity. (Hurray!) That’s because per-user policies aren’t automatically assigned to a portion of the Microsoft Lync Server infrastructure; in fact, per-user policies aren’t automatically assigned to anyone or anything. Upon creation they simply exist; they do nothing more than wait for you to explicitly assign them to a user or group of users.

 

So what does all that look like? It looks a little something like this:

 

New-CsConferencingPolicy –Identity RedmondConferencingPolicy

 

In this case, the Identity consists of a string value that is the policy “name”: RedmondConferencingPolicy. You can give your user policy any name you wish.

 

Note. Why did we say “name,” with the word name in quotation marks? Well, this value isn’t really a name; it’s – well, we don’t know exactly what to call it. When you grant a policy to a user one of the parameters you have to specify is –PolicyName. The value for the parameter is the policy “name,” the same as the Identity:

 

Grant-CsConferencingPolicy –Identity "Pilar Ackerman" –PolicyName RedmondConferencingPolicy

 

So why not just call this the policy name and be done with it? Well, the problem is that some policies (such as voice policies) actually have a Name property; to make matters worse, the true policy Name does not have to be the same as the policy “name.” But the Name property is really more of a description; it is not the value supplied when you assign a policy. Supply a Name (description) if you want. But keep your focus on the “name” that makes up the Identity.

 

In other words, the Name is not the name. And who is on first?

 

Is there a way to determine the allowed scopes for an object?

 

Yes: scope information is included in the Help topic for each cmdlet where this information is relevant. You can determine the allowed scopes simply by perusing the help file for a given cmdlet. That’s the recommended way to determine the allowed scopes for an object.

 

Note. Before we go any further we should point out a small oddity in the scoping of per-user policies. Early in the development of Lync Server 2010 the per-user scope was called the tag scope. Why “tag?” Well, we never did figure that out. But in spite of the fact that everyone agreed that “tag” wasn’t a particularly great scope name, it didn’t go away completely. For example, “tag” hasn’t been removed from the error messages; in addition, when you call a cmdlet like Get-CsVoicePolicy the Identity property is still displayed like this:

 

Tag:UserVoicePolicy

 

So in spite of the fact that we’re not calling this a tag policy, things still appear as tag policies.

 

Suppose you type the command Get-Help New-CsConferencingPolicy –full | more. Do that and then scroll down until you find the section labeled Parameters. In that section you should find the following information:

 

-Identity <XdsIdentity>

    Unique identifier for the conferencing policy to be created.

    Conferencing policies can be created at the site or per-use

    r scopes.

 

Notice that the global scope isn’t mentioned. That’s because a global conferencing policy always exists, you can’t create a new one. If you look at the description of the Identity parameter in the help for Set-CsConferencingPolicy, you’ll see this:

 

-Identity <XdsIdentity>

    Unique identifier for the conferencing policy to be modified.

    Conferencing policies can be configured at the global, site,

    or per-user scopes.

 

Filters

 

Suppose you have a dial plan with the Identity site:Redmond. As it turns out, this dial plan is the only dial plan that has an Identity that starts with the string value site:R. Consequently, you might find yourself thinking, “I bet I could use a wildcard character to identify this dial plan.” With that in mind, you try to retrieve the dial plan using a command like this:

 

Get-CsDialPlan –Identity site:R*

 

We hate to be the ones to rain on your parade, but this isn’t going to work; if you try running the preceding command all you’ll get back is the following error message:

 

Get-CsDialPlan : Cannot get “DialPLan” “Site:R*” because it does not exist.

At line:1 char:15

+ Get-CsDialPlan <<<< -Identity site:R*

+ CategoryInfo : ResourceUnavailable: (Site:*:XdsIdentity) [Get-C

sDialPlan], KeyNotFoundException

+ FullyQualifiedErrorId : MissingItem,Microsoft.Rtc.Management.Internal.Ge

tDialPlanCmdlet

 

So why didn’t this work? One reason and one reason only: you can’t use wildcards when specifying an object’s Identity. If you gave your dial plan the Identity site:Redmond then you’re going to have to type that entire string each time you need to retrieve that plan. And that’s all there is to it; there’s no way to work around this issue, none whatsoever.

 

Well, unless you use the –Filter parameter, of course.

 

The -What parameter? The -Filter parameter. For example, the following command will return the dial plan site:Redmond; in fact, it will return any dial plan that has an Identity that begins with the string value site:R:

 

Get-CsDialPlan –Filter site:R*

 

In other words, if you’ve been wondering what the –Filter parameter is for, well, now you know: -Filter enables you to use wildcards when specifying the policies or configurations that you want to retrieve. For example, suppose you have the following dial plans in your organization:

 

         Global

         site:Cairo

         site:Redmond

         site:Dublin

         site:Singapore

         tag:Administrators

         tag:Contractors

         tag:Sales

 

To return all the dial plans you can just call Get-CsDialPlan without any additional parameters:

 

Get-CsDialPlan

 

Now, what if you wanted all the dial plans that were configured at the site scope? This command will do the trick:

 

Get-CsDialPlan –Filter Site:*

 

See how that works? We used the wildcard Site:* to find all the dial plans that begin with the string value Site: (which, by definition, makes them site policies). It’s just that easy.

 

OK, so now what if you want to find all the dial plans configured at the per-user scope? Remember that, when we created an object at the per-user scope, we simply gave the identity a unique name, we didn’t have to include a scope. For example, to create the per-user dial plan NorthAmericaHeadquartersDialPlan, we use a command like this:

 

New-CsDialPlan –Identity NorthAmericaHeadquartersDialPlan

 

And we can use -Filter to retrieve that particular dial plan:

 

Get-CsDialPlan –Filter *North*

 

Of course, the preceding command will retrieve all the dial plans (regardless of scope) that contain the string North. For example, suppose we also had a dial plan defined for a site named NorthRedmond (Identity site:NorthRedmond). The preceding command would retrieve the dial plan with the identity NorthAmericaHeadquartersDialPlan and the dial plan site:NorthRedmond.

 

Bummer.

 

So how do you retrieve only the per-user (tag) dial plans? Well, even though we didn’t include the scope when creating an Identity for our per-user dial plan, we can still use tag: to retrieve these dial plans. In other words, we can run a command like this:

 

Get-CsDialPlan –Filter tag:*

 

By including the tag: prefix in our Filter value, we can retrieve all the dial plans that were defined using just a name; in other words, all the dial plans that must be explicitly granted to users in order to take effect (the ones configured at the per-user, or tag scope). The reason we can do this is because even though we defined the identity with just a name, the tag: prefix is added in the background. And it’s added for just this reason – so we can continue to filter on these values.

 

The moral of the story is this: if you want to retrieve policies or settings by using wildcard values then you will need to use –Filter rather than –Identity.

 

-- The End –

 

Note. Well, OK, not quite the end. We should add that while the –Filter parameter applies to most Microsoft Lync Server cmdlets, there are two major exceptions: Get-CsAdUser and Get-CsUser. These cmdlets have a –Filter parameter all their own, one that’s very different from the –Filter parameter we just discussed. (And yes, we probably should have given these parameters different names. But we didn’t.) For more information, see Retrieving Active Directory and Microsoft Lync Server User Accounts.