Dialplan mit Skype for Business Online

On Premise gehört es zum guten Ton, dass ein Administrator entsprechende "Dialpläne" für die Anwender angelegt und zugewiesen hat. Vielleicht ist es in den USA so ,dass dort jeder eh eine 7 oder 10 Stellige Nummer wählt und es ausserhalb der USA keine Teilnehmer gibt. Speziell in Deutschland haben wir schon immer Ortsnetze mit unterschiedlichen Vorwahlnummern (089 , 0621, 05251) und auch die internen Nebenstellen nutzen Firmen intensiv. Wenn ich bei Net at Work eine dreistellige interne nummer wähle, dann muss natürlich Skype for Business daraus eine vollwertige E.164-Rufnummer machen, damit das weltweite Routing zuverlässig funktioniert. Und genau dazu sind Dialpläne erforderlich und sind in Skype for Business Online verfügbar.

Powershell oder GUI ?

Aktuell die die Verwaltung noch auf die Powershell (O365 Powershell) beschränkt. Ich denke dass über kurz oder lang diese Einstellungen natürlich auch per Browser in Skype for Business Online CSCP möglich sein oder sogar durch einen Assistenten begleitet werden. Bis dahin ist allerding Powershell an

Achtung: Sie sehen an diesem Beispiel, dass ich auch einen lokale Skype for Business PowerShell eingebunden habe und die Befehle damit nicht eindeutig sind.

# Zuerst gültige Office 365 Anmeldedaten eingeben
$cred = Get-Credential
# Verbindung zu Office 365 herstellen
$session = New-CsOnlineSession -Credential $cred -verbose
# Session in die aktuelle Umgebung importren
Import-PSSession $session -AllowClobber Get-Command *-*dialplan* CommandType Name ModuleName ----------- ---- ---------- Function Get-CsDialPlan tmp_t4jxnqad.1rp Function Get-CsEffectiveTenantDialPlan tmp_t4jxnqad.1rp Function Get-CsOnlineUMDialplan tmp_t4jxnqad.1rp Function Get-CsTenantDialPlan tmp_t4jxnqad.1rp Function Grant-CsDialPlan tmp_t4jxnqad.1rp Function Grant-CsTenantDialPlan tmp_t4jxnqad.1rp Function New-CsOnlineUMDialplan tmp_t4jxnqad.1rp Function New-CsTenantDialPlan tmp_t4jxnqad.1rp Function Remove-CsOnlineUMDialplan tmp_t4jxnqad.1rp Function Remove-CsTenantDialPlan tmp_t4jxnqad.1rp Function Set-CsOnlineUMDialplan tmp_t4jxnqad.1rp Function Set-CsTenantDialPlan tmp_t4jxnqad.1rp Function Test-CsEffectiveTenantDialPlan tmp_t4jxnqad.1rp Cmdlet Get-CsDialPlan SkypeForBusiness Cmdlet Grant-CsDialPlan SkypeForBusiness Cmdlet New-CsDialPlan SkypeForBusiness Cmdlet Remove-CsDialPlan SkypeForBusiness Cmdlet Set-CsDialPlan SkypeForBusiness Cmdlet Test-CsDialPlan SkypeForBusiness

Insofern sollten Sie wirklich eine "reine" PowerShell nutzen oder beim Import-PSSession die Option "AllowClobber"

Dialplan-Hierarchie

Vergleichbar zu Skype for Business gibt es auch in Skype for Business Online die Möglichkeit, mehrere Dialpläne zu definieren. Die Anwendung der Regeln unterscheidet sich aber zwischen Skype for Business Online und Skype for Business On-Prem.

In Skype for Business On-Prem gibt es vier mögliche Stellen einen Dialplan zu definieren:

  • Global
  • Site
  • Pool
  • User

Effektiv ist aber immer nur der Dialplan, der am "nächsten" beim Benutzer definiert wurde. Bei Skype for Business Online gibt es drei Dialpläne

  • Office 365 Country Dialplan (Service, unveränderbar)
    Davon gib es aktuell (Stand Dez 2016) 221 Dialpläne, womit für jedes Land ein eigener Dialplan vordefiniert ist. Jeder Benutzer bekommt abhängig von seiner Region genau einen dieser Dialpläne zugeordnet. Es kann also nie passieren, dass ein Anwender überhaupt keinen Dialplan hat.
  • Tenant Global
    Dann kann der Administrator auf dem Tenant einen globalen Dialplan mit Normalisierungsregeln verwalten. Dieser Dialplan gilt für alle Skype for Business Online Benutzer in diesem Tenant, die keinen "Tenant User Dialplan" haben.
  • Tenant User Dialplan
    Zudem kann er noch "User Dialpläne" im Tenant anlegen. Jedem Benutzer kann genau einer dieser Dialpläne zugewiesen werden. Er ersetzt den Tenant Global Dialplan für diesen Anwender

Der Service Dialplan, der anhand des Landes des Anwenders bestimmt wird, greift immer, wenn keine Regel eines der beiden pro Tenant pflegbaren Dialpläne greift.

Anders als On-Prem ersetzt hier ein näher am Benutzer definierter Dialplan nicht die vorherigen Regeln, sondern die Regeln werden nacheinander abgearbeitet, bis eine "passt". Das hat den Vorteil, dass Sie nicht alle Dialpläne komplett durchkonfigurieren müssen sondern z.B. einen Dialplan für die Region anlegen, der nur die internen Rufnummern und die Anrufe in das lokale "Ortsnetz" normalisiert. Alles andere überlassen Sie dann entweder ihrem globalen Dialplan, der die Welt und Deutschland abdeckt oder direkt den Office 365 Country Dialplänen, die für Deutschland die Normalisierung von nationalen und internationalen Anrufen umsetzt

Wer mag, kann die Anwendung der Office 365 Country Dialpläne unterbinden, indem es in seinem globalen Tenant Dialplan einfach eine Regel pflegt, die immer zutrifft. Sie könnten es so z.B. erreichen, dass ein Benutzer ohne standortspezifischem Tenant User Dialplan gar nicht telefonieren kann und immer auf dem Support oder der Zentrale landet. So erkennen Sie Fehler im Provisioning-Prozess sehr schnell.

Basiseinstellungen CsTenantDialPlan

Wenn Sie sich per Skype for Business Online Powershell (Siehe O365 Powershell) verbunden haben, können Sie schnell die aktuelle Einstellung sehen. Mein Tenant lief lange mit einem leeren Dialplan.

PS C:\> Get-CsTenantDialPlan

Identity              : Global
Description           :
NormalizationRules    : {}
ExternalAccessPrefix  :
SimpleName            : DefaultTenantDialPlan
OptimizeDeviceDialing : False

Damit ist natürlich klar, dass keiner meiner Clients irgendwie eine Rufnummer normalisiert.

Basiseinstellungen CsDialPlan

Aber es gibt natürlich noch den "Get-CSDialPlan", der durchaus interessante Daten liefert.

Hinweis: Wenn Sie auf dem Client auch eine Skype for Business PowerShell haben, dann müssen Sie "Import-PSSession" mit dem Parameter "-AllowClobber" aufrufen, damit auch die Befehle zu Skype for Business Online gehen und nicht die lokale Konfiguration ausgelesen wird.

Es gibt nämlich noch weitere 221 vordefinierte Dialpläne, die Sie direkt verwenden könnten

PS C:\> (Get-CsDialPlan ).count
221

Über die Identity "Tag:DE" bekommen wir den deutschen Plan

PS C:\> Get-CsDialPlan -Identity "Tag:DE"

Identity                 : Tag:DE
Description              : DE DialPlan
DialinConferencingRegion :
NormalizationRules       : {Description=DE International Dialing Rule;Pattern=^00(\d+)$;Translation=+$1;Name=DE Intl
                           Dialing;IsInternalExtension=False, Description=DE Long Distance Dialing
                           Rule;Pattern=^0(\d+)$;Translation=+49$1;Name=DE Long Distance;IsInternalExtension=False, Description=DE
                           Default Rule;Pattern=^(\d+)$;Translation=+49$1;Name=DE Default;IsInternalExtension=False,
                           Description=DE Extensions
                           rule;Pattern=^((\+)?(\d+))(;)?(ext|extn|EXT|EXTN|x|X)(=)?(\d+)$;Translation=$1;ext=$7;Name=DE Extension
                           Rule;IsInternalExtension=False}
CountryCode              : DE
State                    :
City                     :
ExternalAccessPrefix     :
SimpleName               : DE
OptimizeDeviceDialing    : False
ITUCountryPrefix         : 49

Die voreingestellten Normalisierungsregeln habe ich noch einmal extra erstellt.

PS C:\> (Get-CsDialPlan -Identity "Tag:DE").normalizationrules

Description         : DE International Dialing Rule
Pattern             : ^00(\d+)$
Translation         : +$1
Name                : DE Intl Dialing
IsInternalExtension : False

Description         : DE Long Distance Dialing Rule
Pattern             : ^0(\d+)$
Translation         : +49$1
Name                : DE Long Distance
IsInternalExtension : False

Description         : DE Default Rule
Pattern             : ^(\d+)$
Translation         : +49$1
Name                : DE Default
IsInternalExtension : False

Description         : DE Extensions rule
Pattern             : ^((\+)?(\d+))(;)?(ext|extn|EXT|EXTN|x|X)(=)?(\d+)$
Translation         : $1;ext=$7
Name                : DE Extension Rule
IsInternalExtension : False

Microsoft geht erst mal nicht davon aus, dass es "Nebenstellen" gibt und damit auch das Thema "Amtsholung" entfällt. Damit passen die beiden ersten Regeln zur Normalisierung von internationalen und nationalen Nummer. Die dritte Regel aber bringt unsere Anwender nicht weiter. Wenn jemand eine Rufnummer ohne führende "0" wählt, dann erwartet er einen Anschluss in seinem Ortsnetz. Hier sollten Sie auf jeden Fall etwas anpassen. Auch die verte Regel ist für deutsche Verhältnisse ungewöhnlich. Ich habe es ganz selten gesehen, dass jemand mit "EXT" oder "EXTN" arbeitet, um eine Nebenstelle zu adressieren. Auch diese Regel würde ich eher einfach weg lassen.

Diese Pläne werden sogar per Default an den Benutzer schon zugewiesen:

PS C:\> Get-CsOnlineUser sip:user1@msxfaq.onmicrosoft.com | fl *dial*


OnlineDialinConferencingPolicy : ServiceAllowed
DialPlan : DE
TenantDialPlan :

Soweit findet also schon eine erste Normalisierung statt. Die wollen wir aber natürlich auch auf deutsche Verhältnisse anpassen.

Tenant-Dialplan für Paderborn

Exemplarisch lege ich mir nun einen Dialplan an, mit dem ich in Deutschland eine Firma im Ortsnetz 5251 und einer "Stammnummer  304 annehme. Zudem sind 3-stellige Nummern "intern" und eine "0" soll als Amtsholung dienen. Da ein Benutzer immer nur genau einen Dialplan haben kann. Für die eigenen Belange gibt es zusätzlich einen eigenen "globalen" Tenant-Dialplan und weiterhin können mehrere "User-Dialpläne" pro Tenant angelegt werden. Zur Anwendung kommt zuerst ein User-TenantDialplan, so er denn zugewiesen ist. Ansonsten greift der globale Tenant-Dialplan, so er denn vorhanden ist. Wenn beide nicht da sind, dann wird der Default von Microsoft genutzt.

# Anlegen eines neuen Dialplans

New-CsTenantDialPlan `
   -Identity "UCLabor495251304" `
   -Description "DialPlan UCLabor" `
   -ExternalAccessPrefix 0 `
   -SimpleName "UCLabor495251304"

$Rule1 = New-CsVoiceNormalizationRule `
   -Identity Global/UCLabor495251304 `
   -Description "DE Paderborn Intern" `
   -Pattern '^(\d{3})$' -Translation '+495251304$1' `
   -InMemory

# Erstellen und addieren der Normalisierungsregeln
$Rule2 = New-CsVoiceNormalizationRule `
   -Identity Global/UCLabor495251 `
   -Description "DE Paderborn Local" `
   -Pattern '^(\d{2}\d+)$' -Translation '+495251$1' `
   -InMemory

Set-CsTenantDialPlan  `
   -Identity "UCLabor495251304" `
   -NormalizationRules $rule1,$rule2

# alternativ können Sie Rules auch mit ADD addieren
#Set-CsTenantDialPlan  `
#   -Identity "UCLabor495251304" `
#   -NormalizationRules @{Add=$rule2} 

Im eigenen "globalen" Diaplan möchte ich nun alle nicht zugeordneten Benutzer mit der Zentrale beglücken:

$Rule3 = New-CsVoiceNormalizationRule `
   -Identity Global/UCLabor495251304600 `
   -Description "DE Paderborn Zentrale" `
   -Pattern '^(\d+)$' -Translation '+495251304600' `
   -InMemory

Set-CsTenantDialPlan  `
   -Identity "Global" `
   -NormalizationRules $rule3

Das Ergebnis für einen Standort und den Default Dialplan können Sie hier sehen:

PS C:\Windows\System32\WindowsPowerShell\v1.0> Get-CsTenantDialPlan

Identity              : Global
Description           :
NormalizationRules    : {Description=DE Paderborn
                        Zentrale;Pattern=^(\d+)$;Translation=+495251304600;Name=UCLabor495251304600;IsInternalExtension=False}
ExternalAccessPrefix  :
SimpleName            : DefaultTenantDialPlan
OptimizeDeviceDialing : False

Identity              : Tag:UCLabor495251304
Description           : DialPlan UCLabor
NormalizationRules    : {Description=DE Paderborn
                        Local;Pattern=^(\d{2}\d+)$;Translation=+495251$1;Name=UCLabor495251;IsInternalExtension=False,
                        Description=DE Paderborn
                        Intern;Pattern=^(\d{3})$;Translation=+495251304$1;Name=UCLabor495251304;IsInternalExtension=False}
ExternalAccessPrefix  : 0
SimpleName            : UCLabor495251304
OptimizeDeviceDialing : False

Soweit sieht das ganz gut aus

Dialplan testen

Ähnlich wie in Premise gibt es auch in der Cloud die Funktion um eine Rufnummer gegen einen Dialplan zu testen. Das möchte ich natürlich hier auch tun. Sie können einmal eine Nummer gegen explizit einen Dialplan testen oder eine Nummer gegen den einem User zugewiesenen Dialplan überprüfen. ich nutze dazu meinen Office 365 Admin User, der zwar eine Skype for Business Lizenz aber noch keinen Tenant Dialplan zugewiesen hat. Die Ausgabe habe ich zur Lesbarkeit umgebrochen

(Get-CsEffectiveTenantDialPlan -Identity fcarius.admin@fcarius.onmicrosoft.com).NormalizationRules

Description=DE Paderborn Zentrale;
  Pattern=^(\d+)$;
  Translation=+495251304600;
  Name=UCLabor495251304600;
  IsInternalExtension=False;
  LegacyPointer=
Description=US International Dialing Rule;
  Pattern=^011(\d+)$;
  Translation=+$1;
  Name=US Intl Dialing;
  IsInternalExtension=False;
  LegacyPointer=
Description=US Long Distance Dialing Rule;
  Pattern=^1(\d+)$;
  Translation=+1$1;
  Name=US Long Distance;
  IsInternalExtension=False;
  LegacyPointer=
Description=US Default Rule;
  Pattern=^(\d+)$;
  Translation=+1$1;
  Name=US Default;
  IsInternalExtension=False;
LegacyPointer=
Description=US Extensions rule;
  Pattern=^((\+)?(\d+))(;)?(ext|extn|EXT|EXTN|x|X)(=)?(\d+)$;
  Translation=$1;ext=$7;
  Name=US Extension Rule;
  IsInternalExtension=False;
  LegacyPointer=

Es ist gut zu sehen, dass ganz oben meine eigener "Global"-TenantDialplan eingebunden ist und der durch seine allumfassende Matchregel meine Anrufe nun immer auf die Nebenstelle 600 lenkt.

Get-CsEffectiveTenantDialPlan `
   -Identity user1@uclabor.de `
| Test-CsEffectiveTenantDialPlan `
   -DialedNumber 12345

RunspaceId       : <guid>
TranslatedNumber : +495251304600
MatchingRule     : Description=DE Paderborn
                   Zentrale;Pattern=^(\d+)$;Translation=+495251304600;Name=UCLabor495251304600;IsInternalExtension=False

Das Beispiel zeigt, dass ein nicht konfigurierter Benutzer die Wählregeln des Tenant-globalen Dialplans nutzt.

Zuweisen an Benutzer und prüfen

Nun soll der Anwender natürlich durchaus auch gemäß seines Standortes "telefonieren" können. Daher weise ich dem Anwender den passenden Tenant-Dialplan zu:

Grant-CsTenantDialPlan `
   -Identity user1@uclabor.de `
   -PolicyName Tag:UCLabor495251304

Die Einstellungen sind mit Get-CSOnlineUser sichtbar

Get-CsOnlineUser user1@uclabor.de |fl *dial*

OnlineDialinConferencingPolicy : ServiceAllowed
DialPlan : US
TenantDialPlan : UCLabor495251304

Und nun kann ich den Test von vorher einfach noch mal wiederholen:

Get-CsEffectiveTenantDialPlan `
   -Identity user1@uclabor.de `
| Test-CsEffectiveTenantDialPlan `
   -DialedNumber 12345

RunspaceId : 0a206064-279a-4cef-a2c3-92d45cf210dc
TranslatedNumber : +49525112345
MatchingRule : Description=DE Paderborn
Local;Pattern=^(\d{2}\d+)$;Translation=+495251$1;Name=UCLabor495251;IsInternalExtension=False

Diesmal wird aus der 12345 eine Rufnummer im Ortsnetz Paderborn.

Vertane Chance ?

Microsoft liefert mit 221 vordefinierten Dialplänen eine nette Vorarbeiten, die aber zumindest für deutsche Verhältnisse nicht ausreichend ist. Jed Firma in Deutschland, die ihren Mitarbeitern eine brauchbare Normalisierung von "lokalen Rufnummern" anbieten will. muss den Weg über einen eigenen Tenant-Dialplan gehen. Wenn es ihnen reicht meine Vorlage von oben einfach anzupassen, dann müssen Sie dennoch mit der PowerShell daran arbeiten.

Es gibt aber eine aus meiner Sicht viel bessere Lösung: Jedem Anwender, der CloudPBX nutzen will, muss in Skype for Business Online auch eine "Emergency Location" zugewiesen werden. Es geht darum, dass im Fall eines Notrufs die Helfer die richtige Adresse anfahren können. Jeder dieser Standorte muss in Skype for Business Online gepflegt werden und enthält schon sehr viele Informationen. Hier ein Beispiel:

PS C:\> Get-CsOnlineLisLocation

RunspaceId         : <guid>
TenantId           : <guid>
LocationId         : <guid>
CivicAddressId     : <guid>
Location           :
CompanyName        : Test
CompanyTaxId       :
HouseNumber        : 11412
HouseNumberSuffix  :
PreDirectional     : NW
StreetName         : 2ND PL
StreetSuffix       :
PostDirectional    :
City               : BELLEVUE
CityAlias          : Bellevue
PostalCode         : 12345
StateOrProvince    : WA
CountryOrRegion    : US
Description        : Test
ValidationStatus   : Validated

Neben der Straße und Hausnummer ist hier schon das Land im Feld "CountryOrRegion" codiert. Eigentlich müsste Microsoft diesen Datensatz einfach noch um drei Informationen erweitern:

  • Ortsnetz
    Damit man bei einer Nummer ohne "0" diese Vorwahl davor hängt
  • Amtsholung
    Bei einigen Firmen ist es üblich, dass man eine weitere "0" wählt, um erst mal ein Amt zu bekommen.
  • Anschlussleitung
    Der Teil der Nummer, mit der die Firma im Ortsnetz erreichbar ist.

Würden diese Daten mit in die Location eingehen, könnte Microsoft im Rahmen des Provisioning für jeden Tenant und jede "Location" eine passende Normalisierung als eigenen Dialplan für eben diese Location erstellen, die zudem dem Benutzer im Rahmen der Aktivierung für CloudPBX zugewiesen wird. Ich möchte wetten, dass es damit bei vielen Kunden gar nicht mehr erforderlich wäre, von Hand eigene Dialpläne zu pflegen.

Weitere Links

Tenant Dial Plans (Preview) training
http://aka.ms/sa-tdp 
https://techcommunity.microsoft.com/t5/Skype-Operations-Framework-Skype/Tenant-Dial-Plans-Preview-training/ba-p/43521?attachment-id=1080