Posts Tagged: ‘Quick-Tipp’

Quick-Tipp: Neues Feature “Dedicated View Thread” in IBM Domino 9.0.1 FP 3

13. Juli 2015 Posted by Thomas Bahn

Quick-TippIBM Domino
Ganz still und heimlich hat IBM im Fix Pack 3 zum IBM Domino-Server in der Version 9.0.1 ein kleines Juwel versteckt.

Okay, das ist jetzt nichts für jeden, aber wer einige riesige Datenbanken auf seinem Server hat, kann seinen Benutzern jetzt vielleicht etwas weniger Wartezeiten bescheren.

Worum geht es? Wenn in einer Datenbank neue Dokumente erstellt oder vorhandene geändert werden, müssen die Ansichten-Indexe aktualisiert werden - das sind interne Datenstrukturen zu den Ansichten, die im Wesentlichen alle Informationen enthalten, die der Notes-Client dem Benutzer anzeigt.

Diese Aufgabe übernimmt der View Indexer ziemlich verlässlich und normalerweise im Hintergrund. Nur wenn er nicht "rechtzeitig" fertig wird, bekommt der Benutzer, der eine noch-nicht-aktuelle Ansicht in der Datenbank öffnet, die Mitteilung, dass die Ansicht gerade noch aktualisiert werden muss und er derweil ja woanders weiter arbeiten könne (sic!).

Ein Randproblem dabei ist, dass nur ein View Indexer gleichzeitig auf einer Datenbank arbeiten darf und er diese blockiert. Also auch wenn der Benutzer eine kleine Ansicht öffnet, während der View Indexer noch für einen anderen Benutzer eine große Ansicht aktualisiert, muss der Benutzer ziemlich lange warten.

Die Neuerung ist der "Dedicated View Thread".

Damit kann man besonders wichtige und große Ansichten in einer Datenbank markieren, die dann von einem eigenen Thread des View Indexers aktualisiert werden. Damit blockiert nicht mehr die ganze Datenbank, sondern Benutzer der "kleinen" Ansicht können schnell wieder weiter arbeiten.

Noch wichtiger aber ist, dass Benutzer auch die große Ansicht schnell öffnen können - und zwar im Zustand vor den letzten Änderungen, also dem Zustand, als der Ansichten-Index das letzte Mal aktualisiert wurde. Sie sehen dann zwar nicht die allerneuesten Informationen (aus den letzen x Sekunden), können dafür aber sofort und ohne zu warten weiter arbeiten.

Jeder Administrator bzw. Datenbankverantwortlich muss natürlich betrachten, ob das für die jeweilige Datenbank möglich ist oder immer und auf jeden Fall die aktuellsten Informationen dargestellt werden müssen.

Das wichtigste "Bekannte Problem" ist, dass bis zur Installation des Fix Pack 4 sich die Funktion nicht mehr dauerhaft deaktivieren lässt.

Nach meiner Beobachtung wird das übrigens im "$Index"-Item der View gespeichert.

Quellen:
What is the "Dedicated View Thread" feature in IBM Domino?
Known issues with the "Dedicated View Thread" feature in IBM Domino

Quick Tipp: Schnelladressierung zuerst auf dem Server suchen lassen

20. März 2015 Posted by Manuel Nientit

Quick-TippIBM Notes
Kürzlich kam bei einem Kunden die Frage auf, warum denn die "privaten" E-Mail-Adressen eines Kontaktes in der Vorschlagsliste bei der Schnelladressierung höher angezeigt werden, als die beruflichen.
Das liegt natürlich zunächst einmal mit daran, dass Notes natürlich nicht von sich aus zwischen beruflich und privat unterscheiden könnte - wie sollte auch das gehen? Aber hängt auch damit zusammen, dass Vorschläge nach Häufigkeit der Korrespondenz gewichtet angezeigt werden.

In diesem Fall war es jedoch so, dass das Workspace-Verzeichnis, in dem die Datenbank für die Gewichtung (DIP) abgelegt ist, zurückgesetzt worden war. Somit waren private und die berufliche Adressen erst einmal theoretisch gleichwertig. Allerdings fließt hier außerdem die Standardsuchreihenfolge ein, die bei der Schnelladressierung immer erst lokale Adressbücher und dann erst Serveradressbücher berücksichtigt.

Aber genau das ist einer der Punkte, an denen man einhaken kann, indem man die Schnelladressierung die Adressen vom Server stärker gewichten lässt als die lokalen. Zu diesem Zweck muss, beginnend mit Notes 8.5.3, die Variable:
TypeAheadShowServerFirstDefault=1
in die notes.ini eingetragen werden.
Details dazu können auch hier nachgelesen werden: "New Type-ahead Feature in Notes v9"

Das Ergebnis sieht aus, wie in folgendem Screenshot:
Schnelladressierung_mit_ServerFirst.png
Die Treffer von Server-Adressbüchern inklusive Verzeichnisunterstützung werden oben gelistet und erst dann unter "Local Directory" die Treffer aus allen lokalen Adressbüchern.

Dieses Ergebnis mag auch nicht für alle Nutzer und alle Situationen nützlich sein. Das ist sehr stark abhängig von der Gesamtkonfiguration der Adressbücher und der persönlichen Nutzung. Daher gibt es hier keinen goldenen Weg.

Die Schnelladressierung in Notes ist ein sehr hilfreiches und wertvolles Feature. Aber auch das Feature das vermutlich alleine mit am meisten Supportfälle verursacht. Nicht zuletzt, weil es nahezu untrennbar mit dem nicht minder wertvollen Feature "Letzte Kontakte", das seinerseits für einige Fragen gut ist, verheiratet ist. An dieser Stelle sind Administratoren herausgefordert, ihre Nutzer zu kennen und sinnvolle Vorgaben zu machen und gleichzeitig den First-Level-Support zu schulen, bestimmte Fragen diesbezüglich beantworten bzw. die Konfiguration wie oben kurzfristig ändern zu können.

Quick-Tipp: E-Mails mit POP3 abholen – E-Mail-Server mag nur TLS

21. November 2014 Posted by Thomas Bahn

Quick-TippIBM Notes
Seit früher in diesem Jahr erlauben viele E-Mail-Provider nur noch das verschlüsselte Abholen und Senden von E-Mails über POP3, IMAP und SMTP. Wegen eines Sicherheitsproblems mit SSL v3 (POODLE) schalten einige Server-Betreiber dieses Protokoll jetzt ab und erlauben nur noch TLS. Dazu gehören auch die E-Mail-Provider GMX und web.de.


Wenn man mit dem Notes-Client E-Mails per POP3 von E-Mail-Servern abholen will, die nur TLS erlauben, muss man den Notes-Client aktualisieren - und zwar (mindestens) auf die Version 9.0.1 Fix Pack 2 Interims Fix 2, den es im Moment nur relativ versteckt und nur für Windows gibt. Danke, Daniel, für den Tipp: Some Additonal TLS 1.0 Information).

Danach funktionierte es bei mir leider immer noch nicht, aber das lag einfach an einer falschen Einstellung.
Im Benutzerkonto (Account)-Dokument gibt es unter Erweitert die Einstellung "SSL-Sitezertifikate annehmen", die bei mir auf "Nein" stand - auf "Ja" korrigiert, läuft die E-Mail-Abfrage sofort.
Danke an Wollgraeser für den Tipp in die richtige Richtung: Re: Domino Client mit GMX Mail und SSL - TLS

Quick-Tipp: Nach Umbenennung eines Sametime-Servers startet DB2 nicht mehr

21. Oktober 2014 Posted by Thomas Bahn

Quick-TippIBM Sametime
Kürzlich habe ich den Namen eines Sametime-Servers geändert, genauer den Hostnamen der (virtuellen) Maschine. Auf der gleichen Box läuft auch der IBM DB2-Server, der für den System Console-Server und den Proxy-Server benötigt wird. Alles läuft unter Microsoft Windows 2008 R2.

Nach dem für die Umbenennung notwendigen Neustart begrüßte mich der DB2-Dienst mit "SQL1042C Ein Systemfehler ist aufgetreten" ("SQL1042C An unexpected system error occurred") und weigerte sich fortan zu starten - weder als Dienst, noch manuell. Sogar das DB2-Befehlsfenster beendete sich immer sofort wieder.

In den Details der Protokolldateien fand ich die - mehr oder wendiger - informative Meldung: "SQL1022C There is not enogh memory available to process the command".
Zu diesem Zeitpunkt waren aber mehr als 6 GB physischer und sogar ungefähr 20 GB logischer Arbeitsspeicher noch frei!?!

Nach langer, ausgiebiger Recherche kam ich zu dem Schluss, dass mich die Fehlermeldung erfolgreich komplett auf die falsche Fährte gelockt hatte.

DB2 speichert unter Windows einige Informationen, u.a. über lokale Benutzer (in der Form ServerName\Benutzername) und den Hostnamen des Server in der Windows-Registrierung unter dem Schlüssel HKEY_LOCAL_MACHINE\SOFTWARE\IBM\DB2\InstalledCopies\DB2COPY1\GLOBAL_PROFILE. (ändere "DB2COPY1", wenn deine Instanz anders heißt).

Wenn ich es vorher gekannt hätte, wäre ich einfach den Anweisungen in diesem Dokument gefolgt: Changing hostname of the DB2 server. Aber ich wollte jetzt nicht erst die Umbenennung rückgängig machen, um alles jetzt einmal "richtig" zu wiederholen.

In diesem Blog-Eintrag How do you rename the Windows machine name for a DB2 v9.1.x database? und vor allem in den zugehörigen Kommentaren fand ich doch noch einen schnellere, einfacheren und direkteren Weg, um das DB2-System zu wieder zum Laufen zu bringen.

Da ich einen Workgroup-Server (WSE = Workgroup Server Edition) habe, entfällt das Anpassen der db2nodes.cfg.

In einer als Administrator gestarteten Eingabeaufforderung habe ich folgende Befehle ausgeführt:
  •  db2extsec -r
  •  db2extsec /a DB2ADMNS /u DB2USERS
  •  db2set -g DB2SYSTEM={NewHostName}
danach die Maschine noch einmal durch gestartet und DB2 lief wieder wie gewohnt!  

Quick Tip: Benutzervalidierung durch erneute Passwort-Eingabe

30. September 2014 Posted by Thomas Bahn

Quick-TippIBM Notes
Ich hatte letzte Woche eine "kleine" Anforderung von einem Kunden: Er ist interessiert an der erweiterten kommerziellen Version unseres assono Password-Safes. Aber seine interne Revisionsabteilung hatte noch eine neue Anforderung: Der aktuelle Benutzer sollte vor dem Öffnen eines Dokuments oder beim Kopieren eines Passworts in die Zwischenablage direkt aus einer Ansicht vorher noch einmal sein Notes-Passwort eingeben müssen.

Dafür gibt es ein @Command: ToolsUserLogoff. Wenn es ausgeführt wird, logt es den Benutzer aus. Wenn man dieses Kommando mit etwas Code kombiniert, mit dem man auf den Server zugreift, erscheint der Passworteingabe-Dialog, wie es zum Bespiel hier beschrieben wurde: Forcing user re-entry of passwords for electronic signatures in script.

Dieser Ansatz hat aber für mich drei Nachteile:
1. Er funktioniert nicht offline, also z. B. bei einer lokalen Replik, weil der Serverzugriff notwendig ist, um den Passworteingabe-Dialog zu öffnen.
2. Ich möchte es nutzen, um das Öffnen von existierenden Dokumenten abzusichern. Wenn der Benutzer den Dialog abbricht, wird das Dokument trotzdem geöffnet.
3. Der Formel-Code muss im QueryOpen-Ereignis der Maske eingetragen werden. Dort brauche ich aber zwangsläufig LotusScript.

Also musste ich weiter suchen nach einer Lösung in LotusScript. Und ich wurde fündig bei Eknori, der in 2004 diesen Blog-Eintrag verfasst hat: @Command(ToolsUserLogoff) in Lotus Script.
Diese Lösung muss für die aktuellen Versionen von Notes angepasst werden, weil man sich jetzt nicht mehr mit F5, sondern mit Strg-F5 auslogt.

Ich war immer noch nicht überzeugt, dass dies die bestmögliche Lösung für mein Problem sein sollte. Es ist wegen der Verwendung von Windows-DLLs nicht auf andere Plattformen übertragbar, der Benutzer bleibt ausgeloggt, wenn er den Passworteingabe-Dialog abbricht, es würde wohl auch nicht lokal funktionieren usw.

Ich suchte weiter und fand diese großartige Idee: Mittels Notes C-API auf den privaten Teil der Benutzer-ID-Datei zugreifen, genauer mit der  REGGetIDInfoString-Function mit REGIDGetPrivateKey als infoType.
  • Dies würde den Passworteingabe-Dialog erzwingen, aber gleichzeitig den Benutzer nicht abmelden.
  • Es würde auch lokal ohne jeden Server-Kontakt funktionieren.
  • Und ich könnte sogar feststellen, wenn der Benutzer den Dialog abgebrochen hätte und darauf falls nötig reagieren.

Vielen Dank an Davy Vanherbergen für seinen OpenNTF Code Bin-Beitrag (von 2003!): Call notes password prompt from lotusscript 

Ich habe seine Idee genommen und auf "meine Art" neu implementiert. Dabei habe ich unsere C-API-Hilfsfunktionen genutzt, und ich lasse den Benutzer eine andere ID-Datei auswählen, wenn die in der notes.ini eingestellte nicht die seine ist.

Function ValidateCurrentUser As Boolean
        '/**
        ' * validates current user by letting him enter his password
        ' *
        ' * @return  True, if user has successfully entered his password
        ' *
        ' * @author  Thomas Bahn/assono <tbahn@assono.de>
        ' * @version 2014-09-30
        ' */

        Const MAXOUTBUFRLEN% = 4096
       
        Dim idFileName As String
        Dim returnCode As Integer
        Dim userNameBuffer As String*MAXUSERNAME
        Dim actualLen As Long
        Dim currentUserName As String                
        Dim outBufrLen As String*MAXOUTBUFRLEN
       
        If Not IsDebugMode() Then On Error GoTo errorHandler
       
        ValidateCurrentUser = False
       
        idFileName = session.GetEnvironmentString("KeyFileName", True)
        returnCode = REGGetIDInfoString(idFileName, REGIDGetName, _
                userNameBuffer, MAXUSERNAME, actualLen)
        Call ShowCAPIErrorIfAnyAndEnd(returnCode, "REGGetIDInfo", _
                NULLHANDLE)
       
        currentUserName = Left(userNameBuffer, actualLen - 1)        
        Do While session.UserName <> currentUserName
                ' ID file configured in notes.ini is not the ID file of the
                ' current user
                idFileName = uiws.OpenFileDialog(False, _
                        "Wählen Sie Ihre ID-Datei:", "*.ID|", _
                        GetNotesDataDirectory(), idFileName)(0)

                returnCode = REGGetIDInfoString(idFileName, REGIDGetName, _
                        userNameBuffer, MAXUSERNAME, actualLen)
                Call ShowCAPIErrorIfAnyAndEnd(returnCode, "REGGetIDInfo", _
                        NULLHANDLE)
               
                currentUserName = Left(userNameBuffer, actualLen - 1)
        Loop
       
        returnCode = REGGetIDInfoString(idFileName, REGIDGetPrivateKey, _
                        outBufrLen, MAXOUTBUFRLEN, actualLen)
        If returnCode = -32355 Then
                Exit Function ' user cancelled dialog
        Else
                Call ShowCAPIErrorIfAnyAndEnd(returnCode, "REGGetIDInfo", _
                        NULLHANDLE)
        End If

        ' when we get here, the user must have entered his password
        ' successfully
        ValidateCurrentUser = True
        Exit Function
       
errorHandler:
        If HandleError() = RESUME_NEXT_LINE Then Resume Next
        Exit Function
End Function

GetNotesDataDirectory() ist eine Hilfsfunktion, die das Notes-Datenverzeichnis zurück gibt. Ersetze diese Funktion durch deine eigene oder einfach eine String-Konstante.
Und passe den Fehlerbehandlungscode (IsDebugMode() and HandleError()) entsprechend deinen Standards an.

Ich benötige noch einige Deklarationen (Declarations):

Private Const LIBRARY = "Eintrag utils"

' WORD LNPUBLIC OSLoadString(HMODULE hModule, STATUS StringCode, char far *retBuffer, WORD BufferLength);
Declare Function OSLoadString Lib "nnotes" Alias "OSLoadString" (ByVal hModule As Long, ByVal stringCode As Integer, ByVal retBuffer As LMBCS String, ByVal bufferLength As Integer) As Integer

' STATUS LNPUBLIC REGGetIDInfo(char far *IDFileName, WORD InfoType, void far *OutBufr, WORD OutBufrLen, WORD far *ActualLen);
Declare Function REGGetIDInfoString  Lib "nnotes" Alias "REGGetIDInfo" (ByVal idFileName As String, ByVal infoType As Integer, ByVal outBufr As String, ByVal outBufrLen As Integer, actualLen As Long) As Integer
Declare Function REGGetIDInfoBoolean Lib "nnotes" Alias "REGGetIDInfo" (ByVal idFileName As String, ByVal infoType As Integer, ByVal outBufr As Long,   ByVal outBufrLen As Integer, actualLen As Long) As Integer

Const REGIDGetName = 7 ' Data structure returned Is char xx[MAXUSERNAME]
Const REGIDGetPrivateKey = 9 ' Data structure returned Is char xx[xx]


' STATUS LNPUBLIC NSFDbClose(DBHANDLE hDB);
Declare Function NSFDbClose Lib "nnotes.dll" (ByVal hDB As Long) As Integer


Const NOERROR = 0

Const NULLHANDLE = 0&

Const MAXUSERNAME = 256


And two support functions for the C API error handling:

Sub ShowCAPIErrorIfAnyAndEnd(errorCode As Integer, functionName As String, hDB As Long)
        '/**
        ' * shows user the C API error and aborts execution.
        ' *
        ' * @param   errorCode return code of the function's execution
        ' * @param   functionName name of the C API function called
        ' * @param   hDB handle to the open database
        ' *
        ' * @author  Thomas Bahn/assono <tbahn@assono.de>
        ' * @version 2014-07-17
        ' */                
       
        If errorCode = NOERROR Then Exit Sub ' exit if no error occured
       
        If hDB <> 0 Then
                ' if there is a valid handle, try to close database
                Call NSFDbClose(hDB)
        End If
       
        Error Err, "Fehler in Bibliothek '" & LIBRARY & "'" & Chr$(10) & _
        "Ein Fehler ist aufgetreten in der C-API-Funktion'" & _
        functionName & "': "  & Chr$(10) &_
        "Fehler-Code: " & Trim$(Str$(errorCode)) & Chr$(10) & _
        "Fehler-Text: " & Chr$(10) & GetCAPIErrorMsg(errorCode)
End Sub

Function GetCAPIErrorMsg(errorCode As Integer) As String
        '/**
        ' * gets error message for the C API error.
        ' *
        ' * @param   errorCode return code of the function's execution
        ' * @return  error message for the C API error
        ' *
        ' * @author  Thomas Bahn/assono <tbahn@assono.de>
        ' * @version 2014-07-17
        ' */        
       
        Dim length As Integer
        Dim buffer As String
       
        ' initialize a buffer of adequate length to accept the error string
        buffer = String$(256, 0)
       
        ' get the API error message from the internal Notes/Domino string
        ' tables
        length = OSLoadString(NULLHANDLE, errorCode, buffer, Len(buffer))
        If length > 0 Then
                ' remove any trailing characters from the string and
                ' return it to the caller
                GetCAPIErrorMsg = Left$(buffer, InStr(1,buffer,Chr$(0))-1)
        Else
                ' couldn’t locate the error message in the string tables
                GetCAPIErrorMsg = "Unbekannter Fehler"
        End If
End Function

Schließlich platziere Code ähnlich dem folgenden in das QueryOpen-Ereignis deiner Maske:

If continue Then
        continue = ValidateCurrentUser()
       
        If continue Then
                ' do some stuff if necessary
        End If
End If

Da der Code ausschließlich Notes C-API-Aufrufe benutzt, kann er leicht auf weitere Plattformen erweitert werden. Momentan ist er auf Windows beschränkt.

Quick-Tipp: Script-Bibliothek verhindert Ausführung eines Agenten

21. August 2014 Posted by Thomas Bahn

Quick-TippIBM Notes
Heute konnte ich ein Problem eines meiner Kunden lösen: Ein geplanter Server-Agent lief einfach nicht!

Eigentlich lief er doch, nur tat er einfach nichts. Wenn man ihn z. B. per Agent Manager aufgerufen hat (z. B. mit tell amgr run "some-db.nsf" 'Test'), erschienen folgende zwei Zeilen im Server-Protokoll:
AMgr: Start executing agent 'Test' in 'some-db.nsf'
AMgr: Agent 'Test' in 'some-db.nsf' completed execution
Aber selbst ein einfaches Print "TEST" in der ersten Zeile der Initialize-Prozedur gab nichts aus - gar nicht erst zu sprechen von der eigentlichen Aufgabe des Agenten.

Wir haben (wirklich!) alles geprüft, was irgendwie Einfluss haben könnte - u.a. die Einstellungen zur Server-Sicherheit, die Anwendungseigenschaften ("Hintergrundagenten in dieser Datenbank nicht ausführen"), Zugriffskontrollliste (ACL), die Eigenschaften des Agenten...

Dann habe ich Schritt für Schritt den Agenten nachgebaut. Erst die Use-Befehle, dann Stück für Stück den restlichen Code, und alles getestet, wieder und wieder: Es lief so wie es sollte.

Schließlich habe ich den vermeintlich "korrupten" Agenten gelöscht und den neue Agenten umbenannt, so dass er hieß, wie der alte. Und in dem Moment hörte er auf zu funktionieren!

Okay, wieder zurück umbennant - läuft. Noch einmal auf den Namen des ursprünglichen Agenten geändert - läuft nicht.

Weiter im Domino Administrator den "Gottmodus" (Full-access administration) aktiviert und die Datenbank neu im Designer inspiziert. Gibt es vielleicht einen bisher unsichtbaren Agenten mit dem gleichen Namen? Nöps, auch nichts.

Aber ich fand eine Script-Bibliothek mit exakt demselben Namen wie der Agent. Naja, vielleicht... Umbenannt ... und ... der ... Agent ... LÄUFT!

Was habe ich daraus gelernt: Eine Script-Bibliothek verhindert die Ausführung eines Agenten, wenn beide gleich heißen!

Auch mit Firefox 31 nun keine selbstsignierten SSL Zertifikate mehr unterstützt

1. August 2014 Posted by Manuel Nientit

Quick-Tipp Lotus Notes Traveler IBM Domino
Die Luft für Nutzer selbstsignierter SSL Zertifikate wird immer dünner.
Schon vor einiger Zeit berichteten wir darüber, dass Windows Phone keine selbst signierten Zertifikate unterstützt. Diese Problem ist nun bei einem anderen Kunden wieder aufgetaucht, der nun auch mit einem Nokia Lumia experimentieren wollte. Erschwerend war hier nun aber, dass auch der Zugriff auf die Traveler-Weboberfläche mit Firefox plötzlich nicht mehr möglich war. Statt der erwarteten Anmeldemaske erschien eine Fehlermeldung, die einem mitteilte, dass das Zertifikat ungültig sei. Keine Möglichkeit mehr, die Meldung zu ignorieren bzw. eine Ausnahme hinzuzufügen.

Dazu gibt es seit gestern eine Technote bei IBM.
Es gibt offenbar mit Firefox 31 einen neuen Validierungsalgorithmus für SSL-Zertifikate, der das neue Verhalten zeigt. Diesen kann man über die Konfiguration (about:config) deaktivieren, um das alte Verhalten zurück zu bekommen. Das ist natürlich aus mehreren Gründen keine langfristige Lösung:
  • Der alte Algorithmus wird mit der Zeit aus Firefox ausgebaut werden (laut Mozilla Wiki), so dass man sich dem Problem mittelfristig wieder wird stellen müssen.
  • Es ist zu viel Aufwand, wenn man das nicht zentral steuern kann - was vermutlich nicht bei allen Unternehmen der Fall ist
  • Es bedeutet einen vermutlich sichereren Algorithmus mutwillig zu deaktivieren, weil man...
  • ...nicht das ohnehin sicherere, aber kostenpflichtige/-günstige, vertrauenswürdige Zertifikat kaufen möchte.
-> Also besser gleich ein Zertifikat einer vertrauenswürdigen CA ausstellen lassen.

BTW: Die von IBM vorgeschlagene "Lösung" funktioniert .

Quick-Tipp: ‘Verbergen-Formeln von Aktionen bei jedem Dok’wechsel prüfen’ funktioniert nicht

24. Juli 2014 Posted by Thomas Bahn

Quick-TippIBM Notes
Es gibt immer mal wieder Tage, wo einem das Offensichtliche nicht ins Gesicht springt und man sucht und sucht und sucht...

Man kann bei einer Ansicht eine Eigenschaft einstellen, dass die Verbergen-Wenn-Formeln (hide when) jedes mal neu berechnet werden, wenn man auf ein anderes Dokument in der Ansicht geht bzw. darauf klickt.
A picture named M2

Das braucht man, wenn man z. B. Ansicht-Aktionen abhängig von Status des Dokuments anzeigen möchte, also die Aktion "Antrag genehmigen" in der Ansicht nur anzeigen möchte, wenn der aktuell ausgewählte Antrag auf "zu genehmigen" steht.

Ich wollte eine Aktion zum Kopieren des Feldinhalts in die Zwischenablage nur dann anzeigen, wenn das Feld "Passwort" ausgefüllt ist:
A picture named M3

So einfach funktioniert das - normalerweise. Und die gleiche Aktion in der Maske funktionierte auch, nur eben nicht in der Ansicht.

Nach längerer Suche und viel Ausprobieren bin ich dann auf die Lösung gekommen. Kern des Problems war, dass das Feld "Passwort" verschlüsselt gespeichert wird:
A picture named M4

Verschlüsselte Felder werden nicht "normal" im Dokument gespeichert, sondern in $SealData-Items.
A picture named M5

Sie können dann weder in Spalten angezeigt, noch in Spalten- oder Aktionsformeln benutzt werden.

Als Lösung habe ich ein neues Feld "PasswortEingegeben" in der Maske hinzugefügt, dass nur die Information speichert, ob das Passwort-Feld gefüllt ist. Im geöffneten Dokument kann man ja noch einfach auf die verschlüsselten Felder zugreifen.
A picture named M6

Danach habe ich das neue Feld in der Verbergen-Wenn-Formel der Aktion benutzt:
A picture named M7

Und es funktioniert!

Quick-Tipp: Wie du die lästigen Fehlermeldungen des Schedulers beim Domino-Server-Start los wirst

18. Juli 2014 Posted by Thomas Bahn

Quick-TippIBM Domino
Chris Miller ist sicherlich einer der besten Domino-Administratoren der Welt. Er schreibt auch regelmäßig für die SocialBiz user group und beantwortet dort schwierige Fragen rund um die IBM Notes und Domino-Administration.

Letzte Woche hat er darüber geschrieben, wie man gezielt Datenbanken vom Scheduler und Rooms and Resources Manager ausnimmt: From the SocialBiz Mailbox: Excluding Calendars from Mail-in Databases  


Du kennst wahrscheinlich auch diese "Fehlermeldungen" des Schedulers und des RnRMgr, die jedesmal kommen, wenn einer der beiden Prozess auf eine Datenbank stößt, zu der er den Eigentümer nicht (mehr) im Domino-Verzeichnis findet:
SchedMgr: Error processing calendar profile document (NoteID: NT....) in database...:
Can't find $BusyName field on profile

SchedMgr: Error processing calendar profile document (NoteID: NT...) in database ...:
Cannot find user in Domino Directory


Dass passiert zum Beispiel wenn das Personen-Dokument gelöscht wurde (Mitarbeiter arbeitet nicht mehr für das Unternehmen) und bei Mail-In-Datenbanken.

Die beiden Prozesse sind wichtig, um die Freie-Zeit-Datenbank (busytime.nsf bzw. clubusy.nsf) immer auf dem aktuellen Stand zu halten. Aber bei bestimmten Datenbanken ist das einfach nicht (mehr) relevant. Und da wäre es doch toll, wenn man den beiden Prozessen einfach sagen könnten: "Diese Datenbank bitte ignorieren."

Und Chris kennt eine Lösung: In kleines Programm namens "NoCal".

Leider hat es ein paar Nachteile
  • Es ist wirklich, wirklich alt: Release: R5, Platform: Windows 95/98/NT, Date Posted: 04.05.2001,
  • es muss von der Kommandozeile aus gestartet werden und
  • es kann die "Has Calendar"-Datenbank-Option nur ausschalten, nicht wieder anschalten, wenn man aus Versehen die falsche Datenbank erwischt hat.
Es juckte mich in den Fingern: Das kann ich doch besser, oder?  
  • Meine Lösung sollte klein und transportabel sein, wie z. B. ein Agent, den man einfach in die Schablone oder jede Datenbank packen kann,
  • sie sollte in der Lage sein, die Option an- und auszuschalten und
  • sie sollte einfach aus dem Notes-Client heraus aufgerufen werden können.
Nach ausgiebiger Recherche, vielen (erfolglosen) Versuchen und einigen C-API-Aufrufen habe ich es geschafft.

Im Kern sieht der Agent so aus:

Sub Initialize
        '/**
        ' * gets current database's options, prints "Has Calendar" option,
        ' * toggles it and prints new status
        ' *
        ' * @author        Thomas Bahn/assono <tbahn@assono.de>
        ' * @version        2014-07-17
        ' */                

        Dim session As NotesSession
        Dim returnCode As Integer
        Dim hDB As Long
        Dim retDbOptions As Long
       
        On Error GoTo miniErrorHandler

        Set session = New NotesSession
       
        ' open the current database
        returnCode = NSFDbOpen(session.CurrentDatabase.FilePath, hDB)
        Call ShowCAPIErrorIfAnyAndEnd(returnCode, "NSFDbOpen", hDB)

        ' get current options
        returnCode = NSFDbGetOptions(hDB, retDbOptions)
        Call ShowCAPIErrorIfAnyAndEnd(returnCode, "NSFDbGetOptions", hDB)
       
        ' print current status
        If retDbOptions And  DBOPTION_HAS_CALENDAR Then
                Print "Database has calendar"
        Else
                Print "Database doesn't have calendar"
        End If
       
        ' toggle option
        returnCode = NSFDbSetOptions(hDB, _
                        retDbOptions Xor DBOPTION_HAS_CALENDAR, _
                        DBOPTION_HAS_CALENDAR)
        Call ShowCAPIErrorIfAnyAndEnd(returnCode, "NSFDbSetOptions", hDB)
       
        ' get current options
        returnCode = NSFDbGetOptions(hDB, retDbOptions)
        Call ShowCAPIErrorIfAnyAndEnd(returnCode, "NSFDbGetOptions", hDB)
       
        ' print new status
        If retDbOptions And  DBOPTION_HAS_CALENDAR Then
                Print "Database now has calendar"
        Else
                Print "Database now doesn't have calendar"
        End If
       
        ' close the database
        returnCode = NSFDbClose(hDB)
        Exit Sub
       
miniErrorHandler:
        MessageBox "Error #" & Err & " occurred in line " & Erl & Chr$(10) &_
                "Error message: " & Chr$(10) & Error$, 48, "Error"
       
        If hDB <> 0 Then ' if there is a valid handle, try to close database
                returnCode = NSFDbClose(hDB)
        End If
End Sub

Er braucht noch einige Deklarationen (Declarations):

' STATUS LNPUBLIC NSFDbOpen(char far *PathName, DBHANDLE far *rethDB);
Declare Function NSFDbOpen Lib "nnotes.dll" (ByVal pathName As LMBCS String, rethDB As Long) As Integer

' WORD LNPUBLIC OSLoadString(HMODULE hModule, STATUS StringCode, char far *retBuffer, WORD BufferLength);
Declare Function OSLoadString Lib "nnotes" Alias "OSLoadString" (ByVal hModule As Long, ByVal stringCode As Integer, ByVal retBuffer As LMBCS String, ByVal bufferLength As Integer) As Integer

' STATUS LNPUBLIC NSFDbGetOptions(DBHANDLE  hDB, DWORD far *retDbOptions);
Declare Function NSFDbGetOptions Lib "nnotes.dll" (ByVal hDB As Long, retDbOptions As Long) As Integer

' STATUS LNPUBLIC NSFDbSetOptions(DBHANDLE hDB, DWORD DbOptions, DWORD Mask);
Declare Function NSFDbSetOptions Lib "nnotes.dll" (ByVal hDB As Long, ByVal dbOptions As Long, ByVal mask As Long) As Integer

' STATUS LNPUBLIC NSFDbClose(DBHANDLE hDB);
Declare Function NSFDbClose Lib "nnotes.dll" (ByVal hDB As Long) As Integer

' DBOPTION_HAS_CALENDAR          -  TRUE if database stores calendar events.
Const DBOPTION_HAS_CALENDAR& = &H00002000

Const NOERROR = 0

Const NULLHANDLE = 0&


Und zwei unterstützende Funktionen für die C-API-Fehlerbehandlung:

Sub ShowCAPIErrorIfAnyAndEnd(errorCode As Integer, functionName As String, hDB As Long)
        '/**
        ' * shows user the C API error and aborts execution.
        ' *
        ' * @param        errorCode return code of the function's execution
        ' * @param        functionName name of the C API function called
        ' * @param        hDB handle to the open database
        ' *
        ' * @author        Thomas Bahn/assono <tbahn@assono.de>
        ' * @version        2014-07-17
        ' */                
       
        If errorCode = NOERROR Then Exit Sub ' exit if no error occured
       
        MessageBox _
        "An error occurred in C API function '" & functionName & "'"  & Chr$(10) &_
        "Error code: " & Trim$(Str$(errorCode)) & Chr$(10) & _
        "Error message:" & Chr$(10) & GetCAPIErrorMsg(errorCode), _
        48, "Error calling C API"
       
        If hDB <> 0 Then ' if there is a valid handle, try to close database
                Call NSFDbClose(hDB)
        End If
        End
End Sub

Function GetCAPIErrorMsg(errorCode As Integer) As String
        '/**
        ' * gets error message for the C API error.
        ' *
        ' * @param        errorCode return code of the function's execution
        ' * @return        error message for the C API error
        ' *
        ' * @author        Thomas Bahn/assono <tbahn@assono.de>
        ' * @version        2014-07-17
        ' */                
       
        Dim length As Integer
        Dim buffer As String
       
        ' initialize a buffer of adequate length to accept the error string
        buffer = String$(256, 0)
       
        ' get the API error message from the internal Notes/Domino string tables
        length = OSLoadString(NULLHANDLE, errorCode, buffer, Len(buffer))
        If length > 0 Then
                ' remove any trailing characters from the string
                GetCAPIErrorMsg = Left$(buffer, InStr(1, buffer, Chr$(0)) - 1)
        Else
                ' couldn’t locate the error message in the string tables
                GetCAPIErrorMsg = "Unknown error"
        End If
End Function

Erstelle einfachen einen LotusScript-Agenten, der manuell gestartet wird mit dem Ziel "Keine".

Hier ist eine kleine Datenbank mit dem Agenten - fertig zum Kopieren:


Die Datenbank enthält auch eine erweiterte Version des Agenten, mit dem man andere Datenbanken umstellen kann.
Der Benutzer wählt als erstes die Datenbank aus, bekommt den aktuellen Status angezeigt und kann dann entscheiden, ob er die Einstellung ändern möchte.
A picture named M2


Wichtig: Soweit meine Versuche ergeben haben, wird die Änderungen der Datenbank-Option nicht repliziert. Du musst also jede Replik auf jedem Server einzeln umstellen.

Quick-Tipp: Domino Console verbindet sich nicht mit lokalem Server

6. Juli 2014 Posted by Thomas Bahn

Quick-TippIBM Domino
Seit einigen Versionen des Windows-Servers kann man nicht mehr direkt die Konsole des Domino-Servers sehen - aus Sicherheitsgründen.

Als Ersatz kann man die Domino Console (jconsole.exe) auf dem Server starten, die auch deutlich vielseitiger und leistungsfähiger als die "alte" Serverkonsole ist.

Normalerweise (soll heißen: in meiner Erfahrung bisher immer) findet die Domino Console nach dem Start den lokal laufenden Domino-Server und verbindet sich ohne weitere Authentifizierung mit diesem. Letzten Donnerstag habe ich das erste Mal erlebt, dass es nicht funktioniert hat.

Der Server wurde migriert von Hardware auf VM, die Version von 8.5.3 FP6 auf 9.0.1 FP1 IF1 angehoben. Er ist ein Cluster-Server mit einer zweiten Netzwerkkarte und IP-Adresse für den Cluster-internen Verkehr. Der "Hauptserver" des Clusters wurde vorher schon umgestellt und alles lief auf Anhieb wie erwartet. Bei diesem, zweiten Server jedoch hat sich die Domino Console nicht mit dem laufenden Domino-Server verbunden - weder automatisch beim Start der Console, noch auf "Aufforderung".

Man konnte sich mit der Domino Console auf andere Server über Netzwerk verbinden, indem man Server-Adresse, Name und Passwort angab.

netstat -a -n zeigte, dass der Dienst auf tcp/2050 lauschte und zwar auf der Hauptadresse des Servers. Die Domino Console versucht beim Start sich mit dem lokalen Server zu verbinden und benutzt dazu den Namen des Windows-Servers (der abweicht vom Namen des Domino-Servers).

Ein ping auf den Windows-Namen nutzte IPv6, ein ping -4 zeigte, dass der Windows-Name auf die IP-Adresse des Cluster-Netzwerks aufgelöst wurde. Das ließ sich erstaunlicherweise aber weder über den DNS-Eintrag noch über einen entsprechenden Eintrag in der lokalen hosts-Datei ändern. Windows halt.

Die Lösung fand ich in einer Technote, die sich eigentlich mit etwas anderem beschäftigt: Domino running on Windows 2008, Is there way to set the Lotus Domino Console starts, it would connect to the local Domino server ?

Dort stand in der dconsole.ini im ersten Abschnitt:
LocalHost=Name:2050

Flugs habe ich eine solche Zeile auf dem problembehafteten Server eingetragen - mit dem Domino-Server-Namen, der per DNS-Eintrag auf die "richtige" IP-Adresse übersetzt wird, und nach einem Server-Neustart und dem Aufruf der Domino Console verbindet sich diese automatisch mit dem lokalen Domino-Server! Ich habe fertig!

Quick-Tipp: Fehler beim Signieren von Datenbanken mit der Server-ID

5. Juli 2014 Posted by Thomas Bahn

Quick-TippIBM NotesIBM Domino
Das war mal wieder ein ganz mysteriöser Fehler: Im Domino Administrator unter dem Reiter Dateien eine Datenbank ausgewählt, im Rechtsklick-Kontextmenü "Signieren..." und im folgenden Dialog "ID des aktiven Servers" gewählt. Sofort kommt eine Dialogbox mit der Fehlermeldung "Sie sind zur Durchführung dieser Operation nicht berechtigt." (You are not authorized to perform that operation).

Kurze Recherche und viel Überprüfen der aktuellen Einstellungen:
  • Aktueller Benutzer muss Administrator auf dem Server sein (Server-Dokument, Sicherheit-Reiter): gecheckt.
    Er hat sogar das Recht für Administration mit voller Berechtigung - und selbst wenn diese aktiviert ist, kommt der Fehler.
  • Er muss mindestens Autor sein auf der Datenbank admin4.nsf (Administrationsanforderungen) und Dokumente erstellen können: gecheckt, sogar Manager mit allen Rechten.
  • Er ist Manager auf der zu signierenden Datenbank
  • Er kann die Gestaltung der Datenbank mit seiner ID problemlos signieren.
Als Entwickler im Herzen probiere ich es über einen Agenten, den ich in der zu signierenden Datenbank erstelle:

Option Public
Option Declare

Sub Initialize
        '/**
        ' * signs this database by manually creating a request with NotesAdministrationProcess.
        ' *
        ' * @author                Thomas Bahn <tbahn@assono.de>
        ' * @version        2014-07-03
        ' */
       
        Dim uiws As New NotesUIWorkspace
        Dim session As NotesSession
        Dim currentDB As NotesDatabase
        Dim adminDB As NotesDatabase
        Dim adminP As NotesAdministrationProcess
        Dim noteID As String
       
        Set uiws = New NotesUIWorkspace
        Set session = New NotesSession
        Set currentDB = session.CurrentDatabase
        Set adminDB = New NotesDatabase(currentDB.Server, "admin4.nsf")
        Set adminP = session.CreateAdministrationProcess(currentDB.Server)

        noteID = adminP.SignDatabaseWithServerID(currentDB.Server, currentDB.FilePath, False)
        If noteID <> "" Then
                Call uiws.EditDocument(False, adminDB.GetDocumentByID(noteID))
        End If
End Sub

Ich nenne ihn "Datenbank per Administration Request signieren lassen via AdminP-Objekt" (SignDatabaseAdminPViaAdminPObject),
  • Auslöser: Durch Ereignis - Auswahl im Menü 'Aktionen'
  • Ziel: Keine
  • Sicherheitsstufe zur Laufzeit: 2. Beschränkte Operationen zulassen

Es kommt in der Zeile mit "adminP.SignDatabaseWithServerID" der gleiche Fehler wie im Admin-Client.

Noch gebe ich mich nicht geschlagen, ein anderer Weg, ein anderer Agent:

Option Public
Option Declare

Sub Initialize
        '/**
        ' * signs this database by manually creating a request document in the admin4.nsf.
        ' *
        ' * @author                Thomas Bahn <tbahn@assono.de>
        ' * @version        2014-07-03
        ' */
       
        Dim session As NotesSession
        Dim currentDB As NotesDatabase
        Dim adminDB As NotesDatabase
        Dim requestDoc As NotesDocument

       
        Set session = New NotesSession
        Set currentDB = session.CurrentDatabase
        Set adminDB = New NotesDatabase(currentDB.Server, "admin4.nsf")
       
        Set requestDoc = adminDB.CreateDocument
       
        Call CreateItem(requestDoc, "Form", 0, "AdminRequest", False, True)
        Call CreateItem(requestDoc, "Type", 0, "AdminRequest", False, True)
       
        Call CreateItem(requestDoc, "ProxyProcess", 0, "Adminp", True, True)
        Call CreateItem(requestDoc, "ProxyAction", 0, "101", True, True)
        Call CreateItem(requestDoc, "ProxyTextItem1", 0, "0", True, True)
        Call CreateItem(requestDoc, "ProxyOriginatingTimeDate", 0, Now, True, False)
       
        Call CreateItem(requestDoc, "ProxyServer", 0, currentDB.Server, True, True)
        Call CreateItem(requestDoc, "ProxyDatabasePath", 0, currentDB.FilePath, True, True)
        Call CreateItem(requestDoc, "ProxyNameList", 0, currentDB.Title, True, True)
               
        Call CreateItem(requestDoc, "ProxyAuthor", 0, session.UserName, True, True)
        Call CreateItem(requestDoc, "FullName", AUTHORS, session.UserName, True, False)
        Call CreateItem(requestDoc, "$OnBehalfOf", AUTHORS, session.UserName, True, False)
        Call CreateItem(requestDoc, "ProxyOriginatingAuthor", AUTHORS, session.UserName, True, False)
        Call CreateItem(requestDoc, "ProxyOriginatingOrganization", AUTHORS, StrRightBack(session.UserName, "/O="), True, False)

        Call CreateItem(requestDoc, "ProxyOriginatingRequestUNID", 0, requestDoc.UniversalID, False, False)
        Call requestDoc.Sign()
        Call requestDoc.Save(True, True)

End Sub

Sub CreateItem(doc As NotesDocument, itemName As String, itemType As Integer, itemValue As Variant, signItem As Boolean, protectItem As Boolean)
        '/**
        ' * creates a item in the document.
        ' *
        ' * @param                doc NotesDocument to create item in.
        ' * @param                itemName name of the item to create.
        ' * @param                itemType type of the item to create.
        ' * @param                itemValue value to assign to item.
        ' * @param                signItem should item be signed?
        ' * @param                protectItem should item be protected?
        ' *
        ' * @author                Thomas Bahn <tbahn@assono.de>
        ' * @version        2014-07-03
        ' */
       
        Dim item As NotesItem
       
        If doc.HasItem(itemName) Then
                Call doc.RemoveItem(itemName)
        End If
       
        If itemType <> 0 Then
                Set item = New NotesItem(doc, itemName, itemValue, itemType)
        Else
                Set item = New NotesItem(doc, itemName, itemValue)
        End If
        item.IsSummary = True
        item.IsSigned = signItem
        item.IsProtected = protectItem
End Sub

Ich speichere diesen Agenten in der gleichen Datenbank unter den Namen "Datenbank per Administration Request signieren lassen via admin4.nsf-Dokument" (SignDatabaseAdminPViaAdmin4.nsfDoc).
  • Auslöser: Durch Zeiplan - Nie
  • Ziel: Keine
  • Sicherheitsstufe zur Laufzeit: 2. Beschränkte Operationen zulassen

Dann starte ich ihn auf der Serverkonsole mit
tell amgr run "datenbank.nsf" 'SignDatabaseAdminPViaAdmin4.nsfDoc'
Er läuft fehlerfrei durch und die Datenbank wird tatsächlich mit der Server-ID signiert (Juhu!).

Eigentlich machen beide Agenten doch das gleiche: Ein Dokument in der admin4.nsf anlegen, das dann vom Administrationsprozess abgearbeitet wird. Trotzdem geht der eine Weg, der andere nicht.

Weitere, ausgiebige Recherchen bringen weitere Ideen:
  • cache.ndk löschen - bringt nichts
  • eine neue Arbeitsumgebung anlegen und zu dieser wechseln - bringt nichts
  • im persönlichen Adressbuch die Letzten Kontakte (Recent Contacts) löschen - bringt nichts
  • im persönlichen Adressbuch einen vorhandenen Eintrag für den aktuellen Benutzer löschen - bringt nichts
  • im persönlichen Adressbuch alle Gruppen löschen - bringt nichts

Jetzt komme ich irgendwie auf die Idee, einige Gruppen aus dem öffentlichen Adressbuch in das persönliche kopieren: LocalDomainAdmins und LocalDomainServers.

ERFOLG!

Das war's.

Offenbar prüft der (Admin-)Client die Berechtigung des Benutzers und verwendet dabei ggf. vorhandene lokale Gruppen?!

Egal, Problem gelöst, Kunde glücklich. Und das ist das Wichtigste.

Quick-Tipp: Unter CentOS 6 zusätzliche Repositories benutzen

1. Juli 2014 Posted by Thomas Bahn

Quick-Tipp
CentOS 6 ist für mich eine rundherum gelungene Distribution. In Zusammenhang mit IBM-Software, wie z. B. IBM Domino, gefällt mir besonders die Kombination aus "fast" offiziell vom Hersteller unterstützter Plattform und kostenloser Benutzung für beliebig viele Server. Gerade wenn man ständig neue VMs erstellt zum Testen, für Demos usw., die man aber auch nach Monaten und Jahren noch nutzen können möchte, müsste man sonst für andere Betriebssystemlizenzen sehr viel Geld ausgeben. Nur "fast" weil es (binär-)kompatibel zum RedHat Enterprise Linux (RHEL) ist, das IBM offiziell als Betriebssystem für IBM Notes, IBM Sametime, IBM Connections usw. unterstützt.

Eine kleine Einschränkung ist aber, dass die Paketbibliotheken (Repositories), die direkt zu CentOS gehören, relativ klein sind zu anderen Linux-Distributionen. Kürzlich hatte ich auf einem Gentoo-Linux ein kleines Hilfsprogramm gesehen (htop), das mir auf Anhieb gefiel. Heute wollte ich auf eine mit NTFS formatierte, externe Festplatte zugreifen. Beides geht nicht mit den Paketen aus den Standard-Repositories. Aber glücklicherweise gibt es da was von Ratio... RepoForge (vormals RPMForge), einem weiteren Repository, das sich leicht einbinden lässt.

Bei zusätzlichen Repositories gibt es ein prinzipielles Problem: Was ist, wenn die Pakete und/oder Versionen enthalten, die mit denen aus den Standard-Repositories konkurrieren? Bei RepoForge sollte das kaum auftreten, aber wenn man sich trotzdem etwas absichern möchte, kann man das mit dem yum-priorities-Plug-in tun. Hier die notwendigen Schritte in aller Kürze für CentOS 6:
  • im Terminalfenster
    yum install yum-plugin-priorities
  • prüfen von /etc/yum/pluginconf.d/priorities.conf: enthält die Datei enabled=1 im Abschnitt ain/font>?
  • in allen Dateien in /etc/yum.repos.d/ Prioritäten eintragen, also priority=n in allen Abschnitten eintragen, wobei ich für die Basis-Pakete in CentOS-Base.repo 1 bzw. 2 vergebe, in CentOS-Vault.repo 3 bis 7 (aufsteigend zu den älteren Versionen hin), in CentOS-Media.repo die 8 und in CentOS-Debuginfo.repo die 9.

Jetzt kann man das RepoForge-Repository hinzufügen:
  • Je nach Plattform: 32-bit (i686):
    wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.i686.rpm
    bzw. 64-bit (x86_64):
    wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
    oder einfach:
    wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.`uname -m`.rpm
  • Signatur-Schlüssel holen:
    rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt
  • Paket überprüfen:
    rpm -K rpmforge-release-0.5.3-1.el6.rf.*.rpm

    Ergebnis sollte etwa so aussehen:
    rpmforge-release-0.5.3-1.el6.rf.i686.rpm: (sha1) dsa sha1 md5 gpg OK
  • und installieren:
    rpm -i rpmforge-release-0.5.3-1.el6.rf.*.rpm
  • in /etc/yum.repos.d/rpmforge.repo Prioritäten eintragen, also priority=n in allen Abschnitten eintragen (ich verwende 10 bis 12 von oben nach unten)

Und zum Test kann man jetzt htop installieren:
  • einmalig die Yum-Caches säubern:
    yum clean all
  • htop installieren:
    yum install htop
  • und schließlich ausführen:
    htop
  • für die NTFS-Unterstützung installiere ich ntfs-3g:
    yum install ntfs-3g

Quick-Tipp: Unter CentOS 6 zusätzliche Repositories benutzen

1. Juli 2014 Posted by Thomas Bahn

Quick-Tipp
CentOS 6 ist für mich eine rundherum gelungene Distribution. In Zusammenhang mit IBM-Software, wie z. B. IBM Domino, gefällt mir besonders die Kombination aus "fast" offiziell vom Hersteller unterstützter Plattform und kostenloser Benutzung für beliebig viele Server. Gerade wenn man ständig neue VMs erstellt zum Testen, für Demos usw., die man aber auch nach Monaten und Jahren noch nutzen können möchte, müsste man sonst für andere Betriebssystemlizenzen sehr viel Geld ausgeben. Nur "fast" weil es (binär-)kompatibel zum RedHat Enterprise Linux (RHEL) ist, das IBM offiziell als Betriebssystem für IBM Notes, IBM Sametime, IBM Connections usw. unterstützt.

Eine kleine Einschränkung ist aber, dass die Paketbibliotheken (Repositories), die direkt zu CentOS gehören, relativ klein sind zu anderen Linux-Distributionen. Kürzlich hatte ich auf einem Gentoo-Linux ein kleines Hilfsprogramm gesehen (htop), das mir auf Anhieb gefiel. Heute wollte ich auf eine mit NTFS formatierte, externe Festplatte zugreifen. Beides geht nicht mit den Paketen aus den Standard-Repositories. Aber glücklicherweise gibt es da was von Ratio... RepoForge (vormals RPMForge), einem weiteren Repository, das sich leicht einbinden lässt.

Bei zusätzlichen Repositories gibt es ein prinzipielles Problem: Was ist, wenn die Pakete und/oder Versionen enthalten, die mit denen aus den Standard-Repositories konkurrieren? Bei RepoForge sollte das kaum auftreten, aber wenn man sich trotzdem etwas absichern möchte, kann man das mit dem yum-priorities-Plug-in tun. Hier die notwendigen Schritte in aller Kürze für CentOS 6:
  • im Terminalfenster
    yum install yum-plugin-priorities
  • prüfen von /etc/yum/pluginconf.d/priorities.conf: enthält die Datei enabled=1 im Abschnitt ain/font>?
  • in allen Dateien in /etc/yum.repos.d/ Prioritäten eintragen, also priority=n in allen Abschnitten eintragen, wobei ich für die Basis-Pakete in CentOS-Base.repo 1 bzw. 2 vergebe, in CentOS-Vault.repo 3 bis 7 (aufsteigend zu den älteren Versionen hin), in CentOS-Media.repo die 8 und in CentOS-Debuginfo.repo die 9.

Jetzt kann man das RepoForge-Repository hinzufügen:
  • Je nach Plattform: 32-bit (i686):
    wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.i686.rpm
    bzw. 64-bit (x86_64):
    wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
    oder einfach:
    wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.`uname -m`.rpm
  • Signatur-Schlüssel holen:
    rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt
  • Paket überprüfen:
    rpm -K rpmforge-release-0.5.3-1.el6.rf.*.rpm

    Ergebnis sollte etwa so aussehen:
    rpmforge-release-0.5.3-1.el6.rf.i686.rpm: (sha1) dsa sha1 md5 gpg OK
  • und installieren:
    rpm -i rpmforge-release-0.5.3-1.el6.rf.*.rpm
  • in /etc/yum.repos.d/rpmforge.repo Prioritäten eintragen, also priority=n in allen Abschnitten eintragen (ich verwende 10 bis 12 von oben nach unten)

Und zum Test kann man jetzt htop installieren:
  • einmalig die Yum-Caches säubern:
    yum clean all
  • htop installieren:
    yum install htop
  • und schließlich ausführen:
    htop
  • für die NTFS-Unterstützung installiere ich ntfs-3g:
    yum install ntfs-3g

Quick-Tipp: Optionale berechnete Teilmaske

30. Mai 2014 Posted by Thomas Bahn

Quick-TippIBM Notes
Manchmal möchte man eine Teilmaske in eine Maske nur einfügen, wenn eine Bedingung erfüllt ist, z. B. wenn ein bestimmter Status im Workflow erreicht wurde. Gegenüber dem Verstecken mit "Hide-When"-Formeln hat das den Vorteil, dass der Notes-Client entsprechend weniger berechnen muss (Hide-When-Formeln selbst, aber ggf.auch viele @DbLookups, Werte-Formeln, usw.) und das Dokument von unnötigen Items verschont bleibt. Dafür gibt es bei Notes die Möglichkeit der Berechneten Teilmaske.

Für eine Anpassung der Mail-Datenbank hatte ich kürzlich wieder mal diesen Fall. Nur wenn in den Mail-Vorgaben die Funktion "Zentrale Ablage" aktiviert wurde, sollte die Teilmaske zur Auswahl der zentralen Ablage und zur Verschlagwortung des Dokuments angezeigt werden. Die Formel der Berechneten Teilmaske in der Memo- und den beiden Reply-Masken sah dann (vereinfacht) so aus:
@If(
        @GetProfileField("CalendarProfile"; "CentralFilingStatus") = "1";
        "CentralFiling";
        ""
)

Das funktioniert auch wunderbar.

Einige Tage später kam dann ein Kollege auf mich zu und machte mich darauf aufmerksam, dass in der Statuszeile immer wieder die Meldung "Element des Dokuments nicht gefunden" erschien. Nach kurzer Analyse konnte ich die Meldung mit der Berechneten Teilmaske in Verbindung bringen.

Meine erste Lösung:
Eine leere Teilmaske z. B. "EmptySubform" - erstellen und deren Name (oder Alias) in die Formel einfügen:
@If(
        @GetProfileField("CalendarProfile"; "CentralFilingStatus") = "1";
        "CentralFiling";
        "EmptySubform"
)

Die zweite, etwas elegantere Lösung:
Statt des leeren Strings @Nothing zurück geben:
@If(
        @GetProfileField("CalendarProfile"; "CentralFilingStatus") = "1";
        "CentralFiling";
        @Nothing
)

Quick-Tipp: FTP-Server auf VMware vSphere Hypervisor (ESXi) einrichten

30. Mai 2014 Posted by Thomas Bahn

Quick-Tipp
Wenn man große Dateien kopiert, dauert es eigentlich immer zu lange...
Aber besonders langsam ist das Kopieren in meiner Erfahrung mit dem Datastore Explorer beim VMware vSphere Client. Und da die VMDK-Dateien normalerweise auch ziemlich groß sind - zwei- bis dreistellige Werte in GB - nervt das zumindest mich ganz erheblich.

Wenn man die SSH-Funktion aktiviert hat, dann man mit FTPs und SCP schon deutlich schneller kopieren. Auf Windows benutze ich dann entweder WinSCP oder FileZilla. Je nach Ausstattung des VMware vSphere Hypervisors (ESXi-Servers), macht es auch noch einen Unterschied, welchen Verschlüsselungsalgorithmus man auswählt (Blowfish ist normalerweise schneller als AES ist schneller als 3DES) und ob man die Datenkompression aktiviert.

Wenn man es aber noch schneller haben möchte und sich innerhalb einer sicheren, vertrauenswürdigen Umgebung befindet, könnte man auch das unverschlüsselte FTP nutzen.

Der VMware vSphere Hypervisor bringt auch einen FTP-Client mit, aber leider nur einen ziemlich einfachen, konsolen-basierten. In der ESXi- oder einer SSH-Shell kann man mit ftp zielhost eine FTP-Sitzung starten. help gibt die möglichen Befehle aus.

Komfortabler wäre es, wenn man einen "richtigen", grafischen FTP-Client unter Windows oder Linux nutzen könnte und ein FTP-Server auf dem ESXi-Server liefe. Leider hat VMware dieses Feature bisher nicht vorgesehen, so dass man sich anders behelfen muss.

Zum Glück hat Andreas Peetz sich die Arbeit gemacht, den kostenlosen Open-Source-FTP-Server ProFTPd für den ESXi-Server zu paketieren und teilt mit uns das Ergebnis seiner Arbeit.
Jetzt sind es praktisch nur noch wenige Zeilen in der ESXi- oder einer SSH-Shell:
  •  mkdir Zielverzeichnis
  •  cd Zielverzeichnis
  •  wget http://esxi-customizer.googlecode.com/files/ProFTPD-1.3.3-8-offline_bundle.zip
  •  esxcli software vib install --no-sig-check -d /vmfs/volumes/1TB/ftp/ProFTPD-1.3.3-8-offline_bundle.zip
Das Zielverzeichnis solte dabei keine Leerzeichen enthalten...
Die Deinstallation geht dann einfach mit
esxcli software vib remove -n ProFTPD

Man kann den FTP-Server dann mit /etc/init.d/proftpd stop beenden und mit /etc/init.d/proftpd start wieder starten.

Quellen:
Howto add FTP server in ESXi 5.x to support Fast Download/Upload of VM / Images
elease ProFTPD (FTP server) for VMware ESXi 5.x

Unter A Daemon's VIB: Building a software package for VMware beschreibt Andreas Peetz in drei Artikeln, wie der das ProFTPd-Paket erstellt hat.