Unterabschnitte


Pilotimplementierung

Nachdem der Entwurf des CIM-Schemas für das generische Management von Mailserver-Systemen vorlag -- siehe dazu Kapitel 7 -- diente die nun folgende Pilotimplementierung der Beantwortung der Frage, ob dieses Modell für eine praktische Umsetzung geeignet ist. Oder anders formuliert: Der Hauptaugenmerk dieser Arbeit galt zwar dem Entwurf des CIM-Schemas, um aber dessen Qualität beurteilen zu können, war es unumgänglich, mindestens eine teilweise Implementierung vorzunehmen.

Da das Modell eine generische Verwaltung ermöglichen sollte, war es nötig, diese Umsetzung für mindestens zwei konkrete Produkte vorzunehmen. Die Entscheidung zugunsten zweier spezifischer Systeme wurde bereits in Kapitel 6 begründet. Dort erfolgte auch die Vorstellung der beiden Zielsysteme, nämlich des Cyrus IMAPd (siehe Kapitel 6.1) und von Contact (siehe Kapitel 6.2). Sollten sowohl das Schema als auch dessen Implementierung gelungen sein, wäre es möglich, beide Mailserver-Systeme über eine einheitliche Konfigurationsschnittstelle zu verwalten -- was einen Mehrwert von CIM gegenüber bisherigen Ansätzen untermauern würde.

Über die Frage hinaus, wie gut CIM bzw. das entworfene Schema für die (generische) Konfigurationsverwaltung geeignet ist, welche durch die Implementierung von CIM-Providern, die das Schema instanziieren, beantwortet werden sollte, ergab sich automatisch ein weiter Aspekt: Wie gut sind die momentan verfügbaren CIM-Werkzeuge, die in Kapitel 5.5 vorgestellt wurden, für einen praktischen Einsatz geeignet?

Die gesamte Fragestellung der Implementierung lautet damit:

  1. implementierungsbezogen:
    1. Welche CIM-Softwareprodukte sind als Werkzeuge für eine Implementierung geeignet?
    2. Wie ausgereift sind diese Produkte?
  2. modellbezogen:
    1. Ist das entworfene Schema für ein generisches Konfigurationsmanagement geeignet?
    2. Ist CIM allgemein für diese Aufgabe geeignet?

Das gesamte Vorgehen für die Umsetzung des praktischen Teils dieser Arbeit wird in Abbildung 8.1 illustriert.

Abbildung 8.1: Vorgehensmodell des praktischen Teils: Entwurf, Implementierung und Bewertung
Image impl-vorgehen 

Während der Schema-Entwurf in Kapitel 7 erfolgte und die Marktübersicht über CIM-Werkzeuge und -Produkte in Kapitel 5.5 zu finden ist, wird die Auswahl der eingesetzten Tools im folgenden Kapitel 8.1 erläutert, gefolgt von einer Beschreibung der vorgenommenen Implementierung für den Cyrus IMAPd und für Contact (Kapitel 8.2). Die Bewertung schließt sich in Kapitel 8.3 an.


Auswahl von CIM-Werkzeugen

Für die Implementierung des entworfenen CIM-Schemas, also für seine Instanziierung war neben den entsprechenden Providern, die es zu entwickeln galt, eine vollständige WBEM-Infrastruktur, wie sie in Kapitel 5.4 beschrieben wird, notwendig. Produkte, die für diese Aufgabe eingesetzt werden können, wurden bereits in Kapitel 5.5 vorgestellt.

Die Manager-Seite war für die Pilotimplementierung nicht von Interesse, da hier zur Manipulation von Instanzen zunächst ein generischer CIM-Browser als ausreichend angesehen wurde. Außerdem wird der Entwurf eines CIM-basierten Mailserverkonfigurationsfrontends evtl. Thema einer späteren Diplomarbeit der Thinking Objects GmbH sein.

Somit musste eine Hauptentscheidung gefällt werden, nämlich die zugunsten eines spezifischen CIMOMs. Da die Zielplattform auf jeden Fall Linux sein musste, schieden die CIM-Umgebungen von MS Windows und Sun Solaris grundsätzlich aus. Also verblieben die vier vorhandenen Standalone-CIMOMs (siehe Kapitel 5.5.1), die alle unter Linux lauffähig sind.

Da von der Annahme ausgegangen wurde, dass ein CIMOM, der in der Programmiersprache Java geschrieben wurde, für Anwendungen des Systems Management schlecht geeignet ist, da er einen zu hohen Ressourcenbedarf besitzt und eher die Auffassung vertreten wurde, dass Programme für solche Anwendungen in Umfang und Performancebedarf schlank sein sollten, wurden die beiden Java-basierten Lösungen (SNIA CIMOM und WBEM services) ausgeschlossen.

Eine detailliertere Evaluation der verbliebenen CIMOMs OpenWBEM und OpenPegasus brachte die folgenden Ergebnisse:

Daher wurde zunächst OpenWBEM als Grundlage ausgewählt. Dieser CIMOM verfügt neben dem SNIA CIMOM und OpenPegasus über das NPI-Interface (siehe Kapitel 5.5.4.1). Dies bedeutete: Wenn für die Programmierung der Provider die NPI-API verwendet werden würde, wäre ein späterer Wechsel des CIMOMs problemlos möglich. Aus diesem Grund wurde die NPI-API als Grundlage für die Implementierung gewählt, womit als Programmiersprache C vorgegeben war.

Wegen verschiedener Fehler in OpenWBEM erfolgte gegen Ende Programmierphase ein Wechsel zum SNIA CIMOM, da sich herausstellte, dass dessen NPI-Interface als Referenzimplementierung gelten kann und somit die wenigsten Fehler aufwies. Der Einsatz von OpenPegasus scheiterte leider in Zusammhang mit dem NPI, da sich die Programmmodule für dieses Interface nicht übersetzen ließen.

Mit der Festlegung auf das NPI als Grundlage für die Implementierung der Mailserver-Provider musste nun noch festgelegt werden, wie der Zugriff auf die Mailserver-Systeme geschieht, wie also die Instrumentierung erfolgt. Grundlage dafür waren die Erkenntnisse über die Konfigurationsschnittstellen der beiden Produkte (siehe dazu Kapitel 6), das heißt:

Während die einzelnen NPI-Provider unter Linux jeweils als shared libraries vorliegen müssen, stellte es sich für die Instrumentierung heraus, dass es ,,best practice``[*] ist, diese ebenfalls als shared library auszulegen. Damit können alle Provider gegebenenfalls beliebig auf alle Routinen der Instrumentierung zugreifen.

Die Gesamtarchitektur, die sich somit auf Seiten der WBEM-Ressource ergab, geht aus Abbildung 8.2 hervor.

Abbildung 8.2: Schichtenmodell der Provider-Implementierung
Image cim-stack.gif 


Implementierung der Provider

Die Umsetzung des gesamten Mailserver-Schemas wäre aus zeitlichen Gründen nicht möglich gewesen, darüber hinaus wären der Nutzen einer vollständigen Implementierung hinsichtlich der Fragestellung (siehe Kapitel 8) nicht gegeben.

Den umgesetzten Ausschnitt des Modells zeigt Abbildung 8.3.

Abbildung 8.3: implementierte Klassen des CIM-Schemas für Mailserver-Systeme
Image mail_impl.gif 

Programmiert wurden damit für den Cyrus IMAPd sieben verschiedene Provider-Libraries:

Die selben Libraries entstanden für Contact mit der Prefix Contact_. Wie aus der Benennung hervorgeht, war für jedes der beiden Zielsysteme eine Vererbung der Klassen (ohne Änderung ihrer Struktur) mit Umbenennung der Prefix nötig. Der Grund liegt darin, dass ein CIMOM für eine Klasse immer nur einen Provider aufrufen kann.

Zusätzlich wurde für die Zielsysteme jeweils die Ressource Access Library (libcyruscimutil.so bzw. libcontactcimutil.so geschrieben. Insgesamt ergab sich damit pro Mailserver ein Codeumfang von ca. 4500 LOC.

Wie die Programmierung eines NPI-Providers erfolgt, soll anhand eines Beispiels gezeigt werden -- auf die API des NPI wurde bereits in Kapitel 5.5.4.1 eingegangen. Der folgende Ausschnitt zeigt die Verarbeitung der Operation EnumerateInstances auf die Klasse Contact_MailAccount. Dafür wird in der Provider-Library libContact_MailAccount.so die Funktion enumInstances() aufgerufen. Der um Fehlerbehandlung und Speichermanagement gekürzte Code hat die folgende Gestalt:

static Vector enumInstances(NPIHandle * nh, CIMObjectPath cop,
                            int bool_deep, CIMClass cc, int bool_localOnly)
{
   Vector                 vec;
   CIMInstance            ci;
   struct mailaccount    *al = NULL;
   int                    error = 0;

   vec = VectorNew(nh);
   /* find any mail account */
   error = listAccounts(&al);

   /* get the mail account */
   for (; al; al = al->next) {
      /* local function to convert account info into CIM instance */
      ci = makeAccountInstance(nh, cop, al);
      /* add the inctance object to the result vector */
      VectorAddTo(nh, vec, ci);
   }
   return vec;
}

Zunächst wird also mit dem Aufruf von VectorNew() eine neue Liste erzeugt, die später Zeiger auf alle gefundenen MailAccount-Instanzen enthalten wird. Anschließend wird über die Funktion listAccounts() der Ressource Access Library eine verkettete Liste aller Accounts angefordert, die dann elementweise durchlaufen wird. Jeder Struct-Zeiger vom Typ mailaccount wird dann der Funktion makeAccountInstance übergeben, der ihn in eine CIM-Instanz konvertiert (siehe unten). Schließlich wird innerhalb der Schleife der in ci zurückgegebene Zeiger auf die Instanz mit VectorAddTo() an die Rückgabeliste angehängt.

Die Funktion makeAccountInstance(), die auch von den Funktionen enumerateInstanceNames() und getInstance() verwendet wird, erzeugt aus einem Zeiger auf eine mailaccount-Struct (die in der Header-Datei zur libcontactcimutil.so definiert wird) einen Zeiger auf eine CIM-Instanz, die dem CIMOM zurückübergeben werden kann. Neben der Speicherverwaltung und Fehlerbehandlung wurde in diesem Beispiel auch die Vergabe der meisten Attribute der Klasse gekürzt.

static CIMInstance makeAccountInstance(NPIHandle *nh, CIMObjectPath op,
                                       struct mailaccount *a)
{
   CIMInstance            ci;
   CIMObjectPath          cop;
   CIMClass               cc;
   char                  *namespace = NULL;

   namespace = CIMObjectPathGetNameSpace(nh, op);
   cop = CIMObjectPathNew(nh, "Contact_MailAccount");
   CIMObjectPathSetNameSpace(nh, cop, namespace);
   cc = CIMOMGetClass(nh, cop, 0);
   ci = CIMClassNewInstance(nh, cc);

   ...
   CIMInstanceSetStringProperty(nh, ci, "Name", a->uid);
   /* - CreationClassName */
   CIMInstanceSetStringProperty(nh, ci, "CreationClassName",
                                "Contact_MailAccount");
   ...
   return ci;
}

Wie in diesem Beispiel zu erkennen ist, muss zur Erzeugung einer Klasse zunächst der Name des Namespaces mit CIMObjectPathGetNameSpace() abgefragt werden. Dann wird mit CIMObjectPathNew() ein neuer Instanzschlüssel-Zeiger (cop) erzeugt. In ihm wird der gelesene Namespace mit CIMObjectPathSetNameSpace gesetzt. Über den Zwischenschritt CIMOMGetClass(), der den Instanzschlüssel-Zeiger in eine Klasse umwandelt, kann dann per CIMClassNewInstance die Instanz selbst erzeugt werden. Auf selbige zeigt ci.

Bevor ci am Ende der Routine zurückgegeben wird, müssen nur noch die Attribute der Instanz geschrieben werden. Dies geschieht für string-Attribute über CIMInstanceSetStringProperty, für andere Datentypen über analoge Funktionen. Das Attribut Name wird hier beispielsweise mit dem Member uid der mailaccount-Struct belegt. Er enthält einen Zeiger auf die User-ID des Benutzers.

Als Beispiel für eine Ausgabe der implementierten Provider dienen die Abbildungen 8.4 und 8.5. Erstere zeigt eine Instanz der Klasse Cyrus_Mailbox im grafischen CIM-Browser des SNIA CIMOM, zweitere zeigt alle vorhandenen Instanzen dieser Klasse tabellarisch in der SRI (siehe Kapitel 5.5.4.1).

Abbildung 8.4: Ansicht der Mailserver-Provider im CIM-Browser des SNIA CIMOM
Image MailInSNIA.gif 

Abbildung 8.5: Ansicht der Mailserver-Provider in der SBLIM Reference Implementation
Image MailInSRI.gif 


Pilotimplementierung: Resümee

Welche Erfahrungen im Rahmen der Umsetzung des Schemas gewonnen wurden, soll an dieser Stelle erläutert werden. Damit verbunden ist die Beantwortung der Fragestellung, die in der Einleitung zu Kapitel 8 formuliert wurde.



Fußnoten

... practice[*]
also: guter Stil