Komplette Datei-Bibliothek eines Nutzers in HCL Connections 6.5 umziehen (z.B. nach Mitarbeiterwechsel)

Komplette Datei-Bibliothek eines Nutzers in HCL Connections 6.5 umziehen (z.B. nach Mitarbeiterwechsel)

Durch die recht mächtige Teilen-Funktionalität kann man anderen Benutzern oder sogar Communitys Zugriff auf Dateien gewähren, die in der persönlichen Bibliothek unter den eigenen Dateien liegen. Die Eigentümerschaft bleibt dadurch beim Benutzer. Dies hat Vor- und Nachteile. In bestimmten Konstellationen werden die Nachteile deutlich, wie im folgenden Szenario: Mitarbeiter M teilt eine persönliche Datei an mehrere Kollegen/Communitys. Diese arbeiten damit regelmäßig, sowohl lesend als auch schreibend – er ist jedoch alleiniger Eigentümer. Nach einiger Zeit verlässt M das Unternehmen. Zunächst bleibt dies unbemerkt. Sein Account wird deaktiviert, es kann weiterhin mit den bis dahin gesetzten Berechtigungen gearbeitet werden. Doch mit der Zeit möchte man die Rechte ändern, neue Kollegen aufnehmen, alte Entfernen und ähnliches. Teilweise gibt es jedoch bei manchen Dateien keine zweite Person mit entsprechenden Rechten, abgesehen vom inaktiven Konto M.

Übertragen von Dateien, wenn noch Zugriff auf das Quellkonto besteht

Im besten Falle steht dies auf der ToDo-Liste des Prozesses, der beim Ausscheiden eines Mitarbeiters greift: So lange der Mitarbeiter noch da ist, kann er schließlich sämtliche relevante Dinge an seinen Nachfolger übergeben. Hierzu gehören beim Einsatz von HCL Connections auch die persönlichen Dateien, sofern diese für die Kollegen Relevanz haben. Seit Connections 6.5 gibt es hierfür endlich eine integrierte Lösung, die der Nutzer selbst aufrufen kann. Ab CR1 lassen sich auch mehrere Dateien auswählen, sodass relativ praktikabel auch mehrere Dateien übertragen werden können:

Übertragen von Dateien, wenn kein Zugriff mehr auf das Quellkonto besteht

Falls diese Vorbereitung nicht getroffen wurde oder es sich um eine große Menge an Dateien handelt, enthält die HCL-Dokumentation zwar einen Artikel Transferring ownership of user files. Dieser ist jedoch in der aktuellen Form nur bedingt hilfreich: Die Funktion FilesLibraryService.transferPersonalFiles erwartet eine Textdatei mit den zu übertragenden Ids der Dateien. Woher man diese bekommen soll, wenn ein Login eben nicht mehr möglich ist, lässt der Artikel offen.

Ermitteln der Datei-Ids, die übertragen werden sollen

Connections bündelt Dateien in Bibliotheken. Diese wiederum kann persönlich sein, oder zu einer Community gehören. Leider setzt das System auf binäre Primärschlüssel – ein Konstrukt, dass ich bisher in keiner anderen Datenbank gesehen habe. Es erschwert die Arbeit in der Datenbank deutlich. Das einfache kopieren oder selektieren von Schlüsseln ist damit nicht ohne weiteres möglich. Der umständliche aber wohl einzig praktikable Workaround ist, diese in Hex umzuwandeln. Damit das Format zu den nach außen hin verwendeten Ids (z.B. in URLs) passt, müssen allerdings noch zwei weitere Modifikationen vorgenommen werden: Neben einer Umwandlung in Kleinbuchstaben fehlen trennende Bindestriche.

Für eine erste Übersicht ermittelt folgende Abfrage alle Dateien aus der Bibliothek eines Nutzers, sortiert nach dem Änderungsdatum:

SELECT LOWER(REGEXP_REPLACE(Hex(ID), '(.{8})(.{4})(.{4})(.{4})(.*)', '\1-\2-\3-\4-\5')) AS GUID, LABEL, SHARED_VIRAL, TYPE, VISIBILITY, VISIBILITY_COMPUTED, TRASHED_STATE
FROM FILES.MEDIA
WHERE LIBRARY_ID = (
	SELECT lib.ID 
	FROM FILES.LIBRARY lib, FILES."USER" u
	WHERE u.ID = lib.OWNER_USER_ID 
	AND u.DIRECTORY_ID = 'daniel'
)
AND TRASHED_STATE = 0
ORDER BY LAST_UPDATE DESC

Je nach verwendetem Verzeichnisdienst ist u.DIRECTORY_ID der Anmeldename oder die GUID des Nutzers. Für den Fall, dass man hier bestimmte Ids filtern und diese in einer SQL-Abfrage als WHERE Bedingung nutzen möchte, kann folgender SELECT genutzt werden:

SELECT LISTAGG(
	CONCAT('"', 
		CAST(LOWER(REGEXP_REPLACE(Hex(ID), '(.{8})(.{4})(.{4})(.{4})(.*)', '\1-\2-\3-\4-\5')) AS VARCHAR)
	), '",'	) AS File_IDs
...

Als Ausgabe erhalten wir eine Liste von Strings:

"24369dc9-12a6-4937-8ebb-61ff01df70d8","6e8bccc8-64c0-491a-966f-86eab6e547fc","269e3b53-7a43-4008-8279-9a8e289f4a5c"

Dies nur am Rande, für die Batchverarbeitung mit Jython brauchen wir eine Datei mit einer Id pro Zeile. Am einfachsten lässt sich dies mit dem quelloffenen und vielseitigen Verwaltungstool DBeaver erstellen. Hierzu selektieren wir ausschließlich die umgewandeleten Datei-Ids:

SELECT LOWER(REGEXP_REPLACE(Hex(ID), '(.{8})(.{4})(.{4})(.{4})(.*)', '\1-\2-\3-\4-\5'))
FROM FILES.MEDIA
WHERE LIBRARY_ID = (
	SELECT lib.ID 
	FROM FILES.LIBRARY lib, FILES."USER" u
	WHERE u.ID = lib.OWNER_USER_ID 
	AND u.DIRECTORY_ID = 'daniel'
)
AND TRASHED_STATE = 0

In den Ergebnissen ein Rechtsklick auf Ergebnis exportieren

Um das richtige Format zu erhalten, bei den Exporteinstellungen sowohl führende als auch nachgestellte Trennzeichen deaktivieren. Ansonsten beginnt und endet jede Zeile mit einer Pile (|), die wir noch händisch mit sed entfernen müssten.

Als Ergebnis erhalten wir eine Liste

1                                   
------------------------------------
24369dc9-12a6-4937-8ebb-61ff01df70d8
6e8bccc8-64c0-491a-966f-86eab6e547fc
269e3b53-7a43-4008-8279-9a8e289f4a5c

Hier genügt es, die ersten zwei Kopfzeilen zu entfernen.

Alternative: Ermitteln der Datei-Ids via API

Eine andere Möglichkeit ist die HCL Connections API: https://cnx.host/files/basic/api/userlibrary/daniel/feed?ps=500 liefert die ersten 500 Dateien des Benutzers mit der Id daniel. Auch hier kann – je nach verwendetem LDAP – eine GUID anzugeben sein. Die Benutzer-Id erhält man entweder aus der Datenbank oder über einen Profillink. Beispielsweise aus der Mitgliederliste einer Community. Allerdings liefert die API nur maximal 500 Treffer. Bei mehreren Dateien muss man die Anfragen dementsprechend splitten, sodass ich hier die DB-Variante oben definitiv bevorzugen würde.

Mit dem Kommandozeilenwerkzeug tidy (ggf. vorher mit apt-get installieren) und anderen Standardtools kann man die Ids aus dem XML-Dokument extrahieren:

tidy -xml library-feed-page-1.xml | grep “<td:uuid>”  | tr -d ”  ” | tr  ‘\>’  ‘ \>’ | tr ‘\<\/’ ‘ \<\/’ | awk ‘{print $2}’ | tee just-the-ids.txt

Weitere Informationen hierzu im (englischen) Artikel: IBM Connections change file owner. How to get the list of all the files of a user

Liste der Datei-Ids zum neuen Eigentümer übertragen

Zunächst öffnen wir eine wsadmin Konsole auf dem WAS-Server:

cd /opt/IBM/WebSphere/AppServer/profiles/Dmgr01/bin/
./wsadmin.sh -lang jython -username wasadmin -password cnx

Die Migrationsfunktion benötigt die UserId des Zielbenutzers. Wir sollten sein Profil vorab über den FilesMemberService laden. Vor allem in Anbetracht der Tatsache, dass die Groß/Kleinschreibung an dieser Stele aus unerfindlichen Gründen berücksichtigt wird. Hat der Nutzer als E-Mail Adresse Ziel@example.com angegeben, erhalten wir bei der Suche nach ziel@example.com nur eine Fehlermeldung.

wsadmin>execfile("filesAdmin.py")
wsadmin>userId=FilesMemberService.getByEmail("targetuser@posteo.de")["id"]
wsadmin>userId
'43ffe2ab-553d-4663-a290-324fa47ecacc'

Damit kennen wir seine Benutzer-Id und können diese in der Variable userId nutzen. Falls der Benutzer nicht gefunden wird, gibt das System einen Fehler aus. Erscheint keine Ausgabe, hat alles funktioniert.

Nun können wir mit der Migration selbst beginnen

wsadmin>FilesLibraryService.transferPersonalFiles("/tmp/file-ids.txt", userId, "migrated-from-old-user")

Der Pfad /tmp/file-ids.txt ist die Textdatei, welche wir vorher mithilfe der Datenbank erstellt haben. Sie enthält die Ids aller Dateien, eine Id pro Zeile. userId haben wir zuvor gesetzt, zu diesem Profil werden die Daten migriert. Optional kann als letzter Parameter ein Tag gesetzt werden. Das bietet sich an, sodass der Zielbenutzer weiß, welche Dateien ihm selbst gehören und welche er im Rahmen des Umzuges erhalten hat.

Im besten Falle sieht die Ausgabe wie folgt aus:

wsadmin>FilesLibraryService.transferPersonalFiles("/tmp/file-ids.txt", userId, "migrated-from-old-user")
The personal file with the id 24369dc9-12a6-4937-8ebb-61ff01df70d8 was transferred successfully.
The personal file with the id 6e8bccc8-64c0-491a-966f-86eab6e547fc was transferred successfully.
The personal file with the id 269e3b53-7a43-4008-8279-9a8e289f4a5c was transferred successfully.

Damit die Tags auch direkt in den Schlagwortwolken angezeigt werden, macht es Sinn, diese Aufgabe anschließend händisch zu starten. Ansonsten werden die Daten dort erst am nächsten Tag aktualisiert.

wsadmin>FilesScheduler.forceTaskExecution("TagUpdateFrequency", "true")

Nach Abschluss der Übertragung erhält der Zielbenutzer eine Benachrichtigung in seinem Aktivitätsstream:

Stolpersteine sowie Tipps und Tricks zur Fehlersuche

  • Der Zielbenutzer benötigt ein ausreichend großes Quota! Er muss mindestens so viel Platz frei haben, wie beim Quellbenutzer belegt sind. Ansonsten erhaltet ihr einen Fehler:
    [com.ibm.lconn.share.platform.exception.QuotaViolationException: EJPVJ9212E: Unable to add data to the library with ID 8d220bdc-eee5-46e2-85e0-37ffa1f8adfc., currentSize=12884886040, quota=12884901888, incrementSize=12559617]
  • Falls eine Datei bereits beim Zielbenutzer liegen sollte, erzeugt dies einen Fehler! Dies ist vor allem dann zu beachten, wenn ihr beim ersten Durchlauf einen Fehler erhaltet, diesen behebt und erneut startet. Am sinnvollsten ist daher, sich die Ausgabe abzuspeichern, grep auf „unable to transfer“ und ab Durchlauf 2 nur jene Ids aufzulisten, die noch nicht umgezogen wurden. Ansonsten geht der Überblick verloren, welche Dateien tatsächlich auf Fehler liefen und welche beim letzten Durchlauf bereits prozessiert wurden.
    Ich habe in diesem Falle folgenden Fehler erhalten:
    com.ibm.lconn.share.platform.exception.ConstraintViolationException: EJPVJ9392E: Unable to transfer media with ID dd9990d4-da79-4a39-afb9-07b83d57355d to the library with ID 8d220bdc-eee5-46e2-85e0-37ffa1f8adfc.
  • Aussagekräftige Fehlermeldungen erhaltet ihr an dieser Stelle (wsadmin-Konsole) nicht. Alle Fehler werden in das Log des Clusters geschrieben, auf dem die Anwendung läuft. Standardmäßig läuft die Files-Anwendung auf dem AppsCluster. Je nach Benennung kann der Pfad z.B. /opt/IBM/WebSphere/AppServer/profiles/CnxNode01/logs/AppsCluster_server1/SystemOut.log lauten.
  • Die Angaben zu den Dateien in IC360 sind mit Vorsicht zu genießen. Nach der Migration von mehreren hundert Dateien werden mir ein paar davon immer noch in der Bibliothek des Quellbenutzers angezeigt. Öffnet man die Datei jedoch in Connections über das Dateien-Modul, ist der neue Benutzer als Eigentümer hinterlegt. Woher dies kommt habe ich noch nicht herausgefunden, ein Neustart des AppsClusters auf dem IC360 liegt reicht jedoch nicht aus.

Leave a Reply