Kategorien
IT SharePoint

SharePoint – Tenant-OU wieder freigeben

SharePoint 2016 hat (anders als SharePoint 2019) noch Multi-Tenancy-Unterstützung. Das heisst, man kann einige Service-Applikationen, wie z.B. den Managed Metadata Service oder den User Profile Service für verschiedene Tenants Partitionieren – im Prinzip das, was Microsoft auch in SharePoint Online macht, um verschiedenen Kunden einen eigenen Bereich in den Service-Applikationen zu geben.

Beim erstellen eines Tenants, wird mit New-SPSiteSubscription so eine Partition für den Tenant registriert.

Mann kann dann mit dieser Subscription z.B. den People Picker auf eine OU (Organizational Unit im Active Directory) einschränken:

Set-SPSiteSubscriptionConfig -identity $siteSubscription -FeaturePack $defaultfeaturePackId -UserAccountDirectoryPath "OU=UserAccounts,DC=FABRIKAM,DC=COM"

Beim Erstellen einer Site Collection für den Tenant wird diese Subscription auch mitgegeben:

New-SPSite -Url https://fabrikam.sptest.local" -SiteSubscription $siteSubscription -HostHeaderWebApplication "https://root.sptest.local"

Und mit folgendem Befehl Add-SPSiteSubscriptionProfileConfig wird eingestellt, dass für diese Subscription die AD-Benutzer mit der entsprechenden OU synchronisiert werden (für die User Profile Service Application).

$upaProxy = Get-SPServiceApplicationProxy | where-object { $_.DisplayName -eq "MT User Profile Service Application" }
Add-SPSiteSubscriptionProfileConfig -Identity $siteSubscription -SynchronizationOU "OU=UserAccounts,DC=FABRIKAM,DC=COM" -ProfileServiceApplicationProxy $upaProxy

Wenn man zu einem späteren Zeitpunkt den Tenant löschen möchte, zum Beispiel weil beim Erstellungsprozess etwas schief gelaufen ist, dann muss man schlau vorgehen, damit die OU wiederverwendet werden kann. Eine OU kann nämlich nicht von mehr als einer Subscription verwendet werden.

Mit folgenden Schritten (in der SharePoint Management Shell) kann man eine Subscription und die zugehörige Subscription-Profile-Config löschen. Achtung: es werden dabei alle Site Collections gelöscht, welche zur jeweiligen Subscription gehören!

Zuerst holt man sich die jeweilige Subscription, welche gelöscht werden soll, zum Beispiel über den URL der Site:

# Site holen
$site = Get-SPSite "http://fabrikam.sptest.local"

# subscription der Site holen
$subscription = $site.SiteSubscription

Dann muss man sich die User Profile Service Application holen (darauf achten, dass die richtige Multi-Tenancy-fähige Service-Applikation geholt wird, falls ihr mehere, z.B. auch eine normale, in der Farm habt).

# Namen des UPA Proxys angeben
$upaProxyName = "MT User Profile Service Application"

# UPA Proxy holen
$upaProxy = Get-SPServiceApplicationProxy | where-object { $_.DisplayName -eq $upaProxyName }

Nun kann man als erstes die OU-Synchronisierung entfernen, es darf auf keinen Fall zuerst die Subscription direkt gelöscht werden, denn das wäre möglich und würde das ausführen dieses Befehls verunmöglichen, was dazu führt, dass man die OU nur noch über die manuelle Bearbeitung der Datenbank erledigen kann (was Microsoft nicht gerne hat):

# UPA Subscription Eintrag entfernen (aus UPA Profile DB für Profile Sync.)
Remove-SPSiteSubscriptionProfileConfig -Identity $subscription -ProfileServiceApplicationProxy $upaProxy

Nun kann die Subscription gelöscht werden. Um Sicherzugehen, welche Sites betroffen sind, kann man zuerst $subscription.Sites aufrufen:

# Site subscription und alle assozierten Sites löschen
Remove-SPSiteSubscription -Identity $subscription

Am Ende kann noch die Inhaltsdatenbank gelöscht werden, in welcher die Site Collection für den Tenant gespeichert war (sinnvoll falls man pro Tenant eine eigene Inhaltsdatenbank verwendet):

# Zum Schluss die Inhaltsdatenbank entfernen. Auch hier sollte man zuerst prüfen, dass keine anderen Sites in der Inhaltsdatenbank sind! (Befehl geht auch, wennd die Site zuvor gelöscht wurde, das Objekt hat noch den Wert der Datenbank und den Datenbanknamen)
$databaseName = $site.ContentDatabase.Name
Remove-SPContentDatabase -Identity $databaseName

Dies war der Weg um einen Tenant sauber zu löschen, so dass die OU die verwendet wurde, auch später wieder neu verwendet werden kann.

Falls man diesen Weg nicht eingehalten hat und z.B. die Site-Subscription schon gelöscht hat, ohne zuerst Remove-SPSiteSubscriptionProfileConfig auszuführen, dann bleibt einem nur noch der Weg, die Subscription manuell aus der Datenbank zu entfernen, dies führt gemäss Microsoft zum Verlust der Garantie!

Es handelt sich dabei um die Profile DB der User Profile Service Application, in welcher in diversen Tabellen die Einträge für unsere Subscription (Partition-ID) gelöscht werden müssen.

Nachfolgend ein SQL-Script, mit welchem man dies machen könnte, Verwendung aber auf eigene Gefahr. Wichtig ist, dass ihr in der ersten Zeile den Wert der Variable SubscriptionId auf die entsprechende Subscription-ID setzt und danach natürlich [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa] mit der ensprechenden Datenbank und dem entsprechenden Schema für euren Fall:

DECLARE @SubscriptionId AS Varchar(255) = '6d947c20-f876-4d4b-b680-1f0cd0a78c6f'

Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ProfileSubtypeList WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].PersonalSite WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Orgle_Stats WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Orgle_OpList WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Orgle_List WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Orgle_ErrorMsg WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].InternalDetail WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].DataTypeList WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].DataServiceList WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].BucketInfo WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].MicrofeedPostDefinitions WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ActivityTemplate WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ActivityApplication WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ActivityType WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ActivityApplication WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Profile_SearchStopwords WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Profile_SearchUserTable WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].OrganizationProfileValue WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].OrganizationProfile WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].UserProfileEventLog WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].UserProfileValue WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].UserProfile_Full WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].UserPrivacyPolicy WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ADImportConstantPropertyMapping WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ADImportPropertyMapping WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ProfileSubtypePropertyAttributes WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ProfileTypePropertyAttributes WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].PropertyList WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].[Profile_Stats] WHERE PartitionID = @SubscriptionId
Delete
  FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Tenants WHERE PartitionID = @SubscriptionId

Es empfiehlt sich danach etwas zu warten, da diese Änderungen nicht sofort ziehen. Im Idealfall könnt ihr danach einen IISReset auf allen SharePoint-Servern durchführen und ich würde auch die Instanz auf dem Datenbankserver neu starten.

Kategorien
IT SharePoint

SharePoint: Fehler beim Aktivieren einer Enterprise-Lizenz

Ich hatte letzthin einen Fall, wo ein Kunde von einer SharePoint (2013) Standard-Lizenz auf eine Enterprise-Lizenz wechseln wollte, da er neu einige der Enterprise-Features benötigte (z.B. für die Anzeige von Visio-Dateien).

Die Umstellung auf der Test-Farm funktionierte ohne Probleme. „Enable Enterprise Features“ in der „Central Administration“ gewählt, auf „Enterprise“ gewechselt und den Key eingegeben, nach einigen Sekunden Wartezeit kam die Erfolgsmeldung.

Doch als ich die selben Schritte auf der produktiven Farm durchführte, ging auf einmal nichts mehr. Die Websites waren nicht mehr verfügbar. Einige SharePoint-Services (z.B. der Timer-Service oder der Service für die Administration) waren gestoppt. Zur Sicherheit bootete ich die Server neu (es gab ja ein Wartungsfenster) und die Webseiten liefen wieder, allerdings war die Lizenz noch immer auf „Standard“.

Dann habe ich einen erneuten Versuch unternommen und es funktionierte leider wieder nicht. Zumindest brachte die Central Administration nun eine Fehlermeldung und sagte mir, dass ich in den Logs nachschauen sollte für mehr Details – auch stürzten die Webseiten nicht mehr ab.

In den ULS-Logs (zumindest auf dem Application Server) fand ich keine nützlichen Hinweise bezüglich der Fehlerursache. Ein Blick in den „Event Viewer“ zeigte mir einen Eintrag mit Source „SharePoint 2010 Products Configuration Wizard“ (auf einem „SharePoint 2013“-Server 🙂 ) mit der Mitteilung, dass der Wizard mit Erfolg durchgelaufen ist.

Da die Produktion aus 3 SharePoint-Servern bestand (1x App, 2x Web Frontend), ging ich via RDP auch auf die beiden WFE und öffnete auch dort den Event Viewer, auf dem ersten WFE gab es auch einen erfolgreichen „Product Configuration Wizard“-Eintrag, jedoch auf dem zweiten WFE gab es einen Fehler-Eintrag, mit folgendem Text:

„Failed to register SharePoint services.

An exception of type Microsoft.SharePoint.Administration.SPUpdatedConcurrencyException was thrown. Additional Information: An update conflict has occurred, and you must re-try this action. The object SearchAdminWebService was updated by Domain\AccountXy, in the PSCONFIG (9444) process on machine SERVER01. View the tracing log for more information about the conflict.

…“

Gemäss Fehlermeldung ist also ein Konflikt aufgetreten, es scheint so, als hätte ein Prozess auf dem einen SharePoint-Server den Prozess auf diesen Server gestört, da beide Prozesse etwas mit dem Objekt „SearchAdminWebService“ ändern wollten.

Die Suche im Internet lieferte zu diesem Problem leider nicht viele Lösungsvorschläge, jedoch ein Eintrag war vielversprechend. Ein Benutzer hatte eine Ähnliche Fehlermeldung (zumindest auch mit der Rückmeldung bezüglich „SPUpdatedConcurrencyException„) und er konnte das Problem lösen, in dem er die SharePoint-Timer-Services auf den SharePoint-Servern stoppte und dann (im Erfolgsfall) nach und nach aktivierte, so wurde verhindert, dass sich die Prozesse gegenseitig störten.

Ich habe also auf den beiden WFE-Servern den SharePoint-Timer-Service gestoppt. Dann habe ich auf dem App-Server den Lizenz-Key erneut eingegeben und auf OK geklickt. Sobald im Event-Viewer des App-Servers (Source: „SharePoint 2010 Products Configuration Wizard“) der Eintrag mit der Erfolgsmeldung für den „Product Configuration Wizard“ kam, habe ich auf dem ersten WFE-Server den Timerjob gestartet, als auch dort die Erfolgsmeldung kam, habe ich auf dem zweiten WFE den Timerjob gestartet und nach etwas Wartezeit kam dann auch dort die Erfolgsmeldung im „Event Viewer“.

Nach dem Zurückwechseln auf den App-Server wurde mir dort die Meldung präsentiert, dass die Lizenz erfolgreich eingespielt wurde und die CA fragte mich, ob ich auf den bestehenden Site-Collections das Enterprise-Feature aktivieren wollte – was ich verneinte.

Das Timing-Problem konnte also durch das serielle Starten der Timer-Jobs umgangen werden.