Ein dynamisches Plug-in ist ein benutzerdefiniertes Plug-in, das Sie für jeden unterstützten Transportknoten (z. B. ESXi-Host) erstellen können, um den Systemstatus des Knotens zu überprüfen.

Ein dynamisches Plug-in kann zur Laufzeit installiert werden. Es führt die folgenden Funktionen aus:

  • Ein Systemprotokoll für den betroffenen Transportknoten schreiben.
  • Einen Befehl oder einen CLI-Befehl über die run_command()-Funktion ausführen.
  • Vorhandene Metriken lesen.
  • Daten in Wavefront exportieren (nur in einer VMware Cloud-Umgebung).

Sie können ein dynamisches Plug-in erstellen, wenn Sie über Kenntnisse in der Verwaltung von NSX verfügen. Ein dynamisches Plug-in kann auch vom VMware Support erstellt werden. Ein erstelltes Plug-in muss zur Validierung an ein GIT-Repository übermittelt werden. Vor der Übermittlung muss das Plug-in überprüft und getestet werden.

Sicherheitsverwaltung

Nachdem das Plug-in überprüft und getestet wurde, werden das Plug-in, das Testergebnis und die Codeänderungen zur Validierung an ein GIT-Repository übermittelt. Verwenden Sie die folgenden Details für das GIT-Repository:

  • GitLab: https://gitlab.eng.vmware.com/core-build/nsbu-sha-plugin
  • Produkt: nsx-sha-plugins
  • Gitreview-Unterstützung: Wird von VMware-Team ausgeführt

Nachdem das Plug-in validiert und genehmigt wurde, wird es an das GIT-Repository übergeben. Alle dynamischen Plug-ins werden erstellt und signiert, wenn ein neuer Build erstellt wird. Jedes Plug-in wird separat verpackt und signiert. Sie können das erforderliche Plug-in aus den veröffentlichten Dateien des Build abrufen.

Wenn ein signiertes Plug-in auf die Management Plane hochgeladen wird, verwendet die Management Plane einen öffentlichen Schlüssel, um die Signatur zu überprüfen und zu bestätigen, dass dieses Plug-in gültig ist. Nach der Validierung des Plug-ins werden die Dateien des Plug-ins über die gesicherten Kanäle zwischen der Management Plane und der zentralen Control Plane (CCP) und zwischen CCP und Hosts an die Zielhosts übertragen.

Wenn eine Instanz des Systemintegritäts-Agents (SHA) neu gestartet wird, werden die Plug-ins erneut von der Management Plane abgerufen. Da alle Dateien über gesicherte Kanäle veröffentlicht werden und keine temporären Dateien verwendet werden, besteht kein Risiko, dass Hacker die Skripte verändern könnten.

Um Risiken durch schädlichen Code zu verhindern, verwendet SHA außerdem RestrictedPython, um das Python-Skript des Plug-ins vor der Ausführung des Skripts zu überprüfen.

Versionsverwaltung

Ein Plug-in basiert unter Umständen auf einem Befehl oder einem Tool, das in späteren Versionen von NSX nicht mehr unterstützt wird. Daher muss jedes benutzerdefinierte Plug-in die unterstützte NSX-Version in der Datei manifest.yml definieren. Bei der Version sollte es sich um eine REGEX-Zeichenfolge für alle unterstützten Versionen handeln. Der SHA auf der Hostseite prüft die Version des benutzerdefinierten Plug-ins und führt nur die mit der REGEX übereinstimmenden aus.

Die Richtlinien für die empfohlene Versionsverwaltung lauten:
  • Definieren Sie die unterstützte NSX-Version einer Hauptversion.

    In Anbetracht der Tatsache, dass die meisten Befehle und Tools bei Nebenversionen derselben Hauptversion nicht geändert werden, wird die folgende Methode empfohlen, um die Version für alle Nebenversionen zu definieren.

    Beispiel:

    version: ^2\.5\.[0-9.]+ <== The custom plugin supporting all NSX 2.5 releases

  • Wenn eine neue Hauptversion veröffentlicht wird, sollten alle übermittelten dynamischen Plug-ins überprüft werden.
  • Der Verfasser des Plug-ins muss das Skript aktualisieren, wenn sich die zugehörigen Befehle oder Tools ändern.

Installieren eines dynamischen Plug-ins

Der Transportknoten bzw. der Edge-Knoten, auf dem das Plug-in installiert ist, muss über mindestens 30 MB Speicherplatz verfügen. Beachten Sie außerdem, dass nur bis zu 10 Plug-ins installiert werden können. Sobald die Anzahl der Plug-ins 10 erreicht hat, schlägt die weitere Installation eines Plug-ins fehl.

Um das Plug-in zu installieren, führen Sie die folgenden Aufgaben durch:
  1. Erstellen Sie die Dateien für das dynamische Plug-in im GIT-Repository. Weitere Informationen zu den Plug-in-Dateien finden Sie im Abschnitt Dateien für dynamische Plug-ins.
  2. Lösen Sie den Produkt-Build im GIT-Repository aus, um das komprimierte Paket der Dateien für das dynamische Plug-in zu generieren und das Paket herunterzuladen.
  3. Erstellen Sie das dynamische Plug-in mithilfe der folgenden API mit der POST-Methode.

    https://<manager_ip>/api/v1/systemhealth/plugins

  4. Laden Sie das komprimierte Plug-in-Paket mit der folgenden API mit der POST-Methode auf die Management Plane hoch. Die Management Plane extrahiert die hochgeladene Datei und führt die erforderliche Validierung durch.

    /systemhealth/plugins/<plugin-id>/files/<file-name>/data

    Hinweis: Die maximale Größe der komprimierten Plug-in-Datei beträgt 500 K.
  5. Erstellen Sie eine Knotengruppe mit den erforderlichen Transportknoten als Mitglieder, indem Sie die folgende API mit der POST-Methode verwenden.

    /<manager_ip>/api/v1/ns-groups

  6. Wenden Sie das Plug-in-Profil auf die Knotengruppe an, indem Sie eine neue Dienstkonfiguration mithilfe der folgenden API erstellen. Das Dienstkonfigurations-Framework sendet den Plug-in-Inhalt an die Knotengruppe.

    https://<manager_ip>/api/v1/service-configs

Weitere Informationen zu APIs finden Sie im NSX-API-Handbuch.

Abrufen des Plug-in-Status

Sobald das dynamische Plug-in ausgeführt wird, wird der Status automatisch über den vorhandenen Nachrichtenkanal auf die Management Plane hochgeladen. Die Management Plane aggregiert die Statusinformationen des Plug-ins und speichert Sie in der Datenbank. Um den Status aller Plug-ins auf jedem Knoten abzurufen, verwenden Sie die folgende API mit der GET-Methode.

https://<manager_ip>/api/v1/systemhealth/plugins/status/<transport_node_id>

Anforderungsbeispiel:

GET https://<manager_ip>/api/v1/systemhealth/plugins/status/a257b981-1a1c-4b95-b16c-8646

Antwortbeispiel:
{
 "result_count":1,
 "results": [
 {
 "id": "72e1bd4b-6df6-42d0-9c59-a1c31312c9f1",
 "name": "health-check-compute",
 "status": "NORMAL",
 "detail": ""
 }
 ]
 }

Deinstallieren eines dynamischen Plug-ins

Um ein Plug-in zu deinstallieren, entfernen Sie die Dienstkonfiguration mithilfe der folgenden API.

https://<manager_ip>/api/v1/service-configs/<service_config_id>

Andere APIs für die Verwaltung der Plug-ins

In der folgenden Tabelle sind die APIs für die Verwaltung von dynamischen Plug-ins aufgelistet. Weitere Informationen zu APIs finden Sie im NSX-API-Handbuch.

Aufgabe Methode API
Löschen eines Plug-ins LÖSCHEN /systemhealth/plugins/<plugin-id>
Erstellen eines Systemzustandprofils POST /systemhealth/profiles

Einsehen des Plug-in-Status

GET /systemhealth/plugins/status/<node-id>
Aktivieren des Plug-ins Die Aktivierung eines Plug-ins ist ein zweistufiger Prozess:
  1. Verwenden Sie die folgende API, um die enabled-Eigenschaft auf true oder false festzulegen.

    https://<manager_ip>/api/v1/systemhealth/profiles/

  2. Verwenden Sie die folgende API, um das SHA-Profil auf die NS-Gruppe anzuwenden.

    https://<manager_ip>/api/v1/service-configs

Ändern des Plug-in-Intervalls POST

Die Änderung des Plug-in-Intervalls ist ein zweistufiger Prozess:

  1. Verwenden Sie die folgende API, um die config-Eigenschaft festzulegen.

    https://<manager_ip>/api/v1/systemhealth/profiles/

  2. Verwenden Sie die folgende API, um das SHA-Profil auf die NS-Gruppe anzuwenden.

    https://<manager_ip>/api/v1/service-configs

Dateien für dynamische Plug-ins

Ein dynamisches Plug-in besteht aus den folgenden Dateien:

  • Datei mit den Installationsspezifikationen
    Die Datei mit den Installationsspezifikationen manifest.yml enthält die folgenden Informationen für den System Health Agent:
    • Plug-in-Struktur
    • Einschränkungen, falls vorhanden
    • Installieren und Verwenden des Plug-ins
    • Sicherheitseinschränkungen für das Skript für die Integritätsprüfung. Zum Beispiel Berechtigungen, die das Skript hat, und Dateien, auf die das Skript zugreifen kann.
    In der folgenden Tabelle sind Felder aufgelistet, die in einer manifest.yml-Datei angegeben sind.
    Name Beschreibung Erforderlich/Optional Beispiel
    classes Gibt Klassen an, die im Skript des Plug-ins benötigt werden.

    Die Klassen müssen im folgenden Format angegeben werden. '<module_name>.<class_name>'

    Optional classes: ['datetime.datetime','datetime.date']
    modules Gibt Module an, die im Skript des Plug-ins benötigt werden. Optional Module: ['random', 'math']
    plugin

    Gibt die Plug-in-Struktur wie folgt an:

    Konfiguration: Name der Konfigurationsdatei

    Skript: Name der Skriptdatei

    Erforderlich

    plugin:

    config: plugin.cfg.yml

    script: plugin.py

    version Gibt die NSX-Versionen an, auf denen dieses Plug-in installiert werden kann. Erforderlich version: '^3\.1\.[0-9.]+'
    node_type

    Gibt die NSX-Knotentypen an, auf denen dieses Plug-in installiert werden kann. Die verfügbaren Knotentypen sind:

    • nsx-esx
    • nsx-bms
    • nsx-edge
    Erforderlich node_type: ['nsx-esx']
    metrics Gibt Metriken an, die im Skript des Plug-ins verbraucht werden können. Optional metrics: ['nsx.host.host-metrics']
    precondition

    Gibt die Vorbedingung für das Plug-in an. Die verfügbare Vorbedingung ist Wavefront.

    Hinweis: Dieses Feld bezieht sich nur auf eine VMware Cloud (VMC)-Umgebung.
    Optional precondition: ['wavefront']
    Verwenden Sie nicht die folgenden integrierten Module:
    • os

    • subprocess

    • sys

    • multiprocessing

    • importlib

    In der folgenden Tabelle sind die Schnittstellen aufgelistet, die Sie anstelle der integrierten Funktionen der jeweiligen Module verwenden müssen. Diese Schnittstellen werden vom System bereitgestellt. Sie können sie direkt verwenden, ohne deren Modul/Klasse in der Datei manifest.yml-Datei anzugeben.
    Modul Integrierte Funktion Ersatzschnittstelle
    datetime datetime.date.strftime(self, fmt)

    datetime_date_strftime(dt, fmt)

    :param dt: date instance

    :param fmt: format string

    datetime datetime.date.today() datetime_date_today()
    sys sys.getrecursionlimit() sys_getrecursionlimit()
    sys sys.getrefcount(object) sys_getrefcount(object)
    sys sys.getsizeof(object, default) sys_getsizeof(object, default)
    sys sys.maxsize sys_maxsize
    sys sys.path sys_path
    Beispiel einer manifest.yml-Datei.
    # specify classes needed in plugin script 
    classes: ['datetime.datetime','datetime.date']
    # specify modules needed in plugin script 
    modules: ['random', 'math']
    # plugin structure
    plugin:
     config: plugin.cfg.yml
     script: plugin.py
    # specify nsx versions on which this plugin can be installed
    version: '^3\.1\.[0-9.]+'
    # specify nsx node type where this plugin can be installed
    node_type: ['nsx-esx']
    # specify metrics which can be consumed in plugin script
    metrics: ['nsx.host.host-metrics']
    # specify precondition for plugin 
    precondition: ['wavefront']
  • Standardprofildatei

    Die Standardprofildatei plugin.cfg.yml wird verwendet, um das Plug-in-Verhalten zu konfigurieren, wie z. B. die Ausführungshäufigkeit des Skripts für die Integritätsprüfung. Um die Standardkonfigurationen zu ändern, können Sie ein SHA-Profil für ein bestimmtes dynamisches Plug-in erstellen und es auf den Transportknoten über die NS-Gruppe anwenden, indem Sie den Kanal von der Management Plane zu CCP zu NestDB verwenden.

    In der folgenden Tabelle sind Felder aufgelistet, die in einer plugin.cfg.yml-Datei angegeben sind.
    Name Beschreibung Erforderlich/Optional Beispiel
    CHECK_INTERVAL Gibt das Standardintervall für die Ausführung des Plug-in-Skripts in Sekunden an. Erforderlich CHECK_INTERVAL: 20
    AKTIVIEREN Gibt an, ob das Plug-in standardmäßig aktiviert ist. Erforderlich ENABLE: true
    Beispiel einer plugin.cfg.yml-Datei.
    # Required field - default interval (unit: second) between plugin script executions.
    CHECK_INTERVAL: 20
    
    # Required field - whether plugin is enabled by default
    ENABLE: true
    
    # Plugin user can add other fields as below if needed to control plugin script logic.
    EXPORT_DATA: true
  • Skript für die Integritätsprüfung

    Die Datei mit dem Skript für die Integritätsprüfung plugin.py enthält ein Python-Skript zur Überprüfung des Integritätsstatus eines Transportknotens.

    In der folgenden Tabelle sind die systemdefinierten Variablen und Funktionen, die verwendet werden können, und Daten, die in einer plugin.py-Datei gelesen werden können, aufgelistet.
    Variable/Daten/Funktion Beschreibung Typ Beispiel
    logger Schreibt Protokollinformationen in syslog. Die vorhandene systemdefinierte Variable „logger“ kann direkt im Skript des Plug-ins verwendet werden.

    Das Ausgabeprotokoll wird mit dem Namen und der ID des Plug-ins wie in der folgenden Beispielausgabe dargestellt.

    2020-10-28T10:47:43Z nsx-sha: NSX 2101378 - [nsx@6876 comp="nsx-esx" subcomp="nsx-sha" username="root" level="INFO"] [name:hl-esx-002-04][id:a3eb14f1-d185-4bc7-bfaa-6cf888bbeb22] dynamic plugin - not export data

    Variable logger.info("this is a demo log")
    data_store

    Das vorhandene systemdefinierte Wörterbuch, das zum Abrufen von vom System bereitgestellten Daten verwendet wird. Beispielsweise „profile“, „metric“, und „host_id“.

    Variable profile = data_store['profile']
    profile

    Bei „profile“ handelt es sich um ein aus dem Standardprofil (plugin.cfg.yml) oder dem effektiven SHA-Profil (vom Benutzer über die Manager-API angewendet) analysiertes Wörterbuch, das aus „data_store“ gelesen wird. Es weist folgendes Format auf:

    {'ENABLE': True, 'CHECK_INTERVAL': 20, 'EXPORT_DATA': True}

    Daten profile = data_store['profile']
    metric

    Bei „metric“ handelt es sich um ein Wörterbuch mit 'value' und 'timestamp', das aus „data_store“ gelesen wird. Es weist folgendes Format auf:

    data_store['metrics'][<metric_name>]

    Dabei gilt Folgendes:

    Der erste Schlüssel muss 'metrics' lauten.

    Der zweite Schlüssel ist der Name einer vorhandenen Metrik.

    Daten

    metric = data_store['metrics']['nsx.host.host-metrics']

    metric is: {

    ‘value’:XXX, <== the collected data of the metric

    ‘timestamp’: XXX <== timestamp of the data collected

    }

    Hinweis: Bei der ersten Ausführung des Plug-ins wird möglicherweise keine Metrik zurückgegeben, da derzeit eine Metrik asynchron mit dem ausgeführten Plug-in erfasst wird, sodass die Metrik bei der ersten Ausführung des Plug-ins unter Umständen nicht erfasst wurde.

    host_id „host_id“ ist eine Instanz der Klassen-uuid.UUID, die von „data_store“ gelesen wird. Daten host_id = data_store['host_id']
    run_command Diese Funktion führt Befehle in einem Listenformat aus. Sie weist folgendes Format auf.

    run_command(cmd, timeout=4)

    Dabei gilt Folgendes:

    • cmd: Befehle, die ausgeführt werden sollen. Muss im Listenformat wie im Beispiel angegeben werden.
    • timeout: Zeitüberschreitung beim Warten auf das Befehlsergebnis. Die standardmäßige Zeitüberschreitung beträgt 4 s. Die Zeitüberschreitung darf nicht auf mehr als 20 s festgelegt werden.

    Diese Funktion gibt das Ergebnis der Befehlsausführung zurück.

    Funktion

    cmd = ['nsxdp-cli', 'ipfix', 'settings', 'granular', 'get', '--dvs-alias', 'nsxvswitch', '--dvport=dafa09ca-33ed-4e04-ae3d-1c53305d5fe6']

    res = run_command(cmd)

    Exportdata Mit dieser Funktion werden Daten in Wavefront exportiert. Derzeit unterstützt ein dynamisches Plug-in nur den Export in Wavefront.
    Hinweis: Dieses Funktion bezieht sich nur auf eine VMware Cloud (VMC)-Umgebung.
    Es weist folgendes Format auf:

    Exportdata: ExportData(data={}, exports=[], source=host_uuid)

    Dabei gilt Folgendes:

    data: Daten, die exportiert werden sollen; die Daten müssen im Wörterbuchformat wie im Beispiel angegeben werden.

    exports: Zielliste für den Export. In HL wird nur Wavefront im Ziel unterstützt. Dies ist erforderlich.

    source: Quellzeichenfolge für den Export. Dies ist nur für das Wavefront-Ziel nützlich. Dies ist optional, der Standardwert ist die „host_uuid“ von NSX.

    Die Funktion gibt keinen Wert zurück.

    Funktion Exportdata(data={'esx.plugin.stats': {'stats': {'gc-esx-001': data}}}, exports=['wavefront'])
    Beispiel einer plugin.py-Datei.
    def report_test_data(edge_service_status):
        if edge_service_status == 'running':
            data = 2
        else:
            data = 3
        
        # examples on how to report data to wavefront.
        Exportdata(data={'esx.plugin.stats': {'stats': {'esx-dynamic-plugin-001': data}}}, exports=['wavefront'])
    
    
    def run():
        # examples on how to write log.
        logger.debug("this is a debug message!")
        logger.info("this is a demo message!")
        
        # examples on how to use specified module in manifest. Take 'random' as an example.
        s_res = random.randint(1,10)
        logger.warn("random.randint(1,10)=%s", s_res)
        
        # examples on how to use specified class in manifest. Take 'datetime' and 'date' as an example.
        logger.info('date.ctime(datetime.now()):{}'.format(date.ctime(datetime.now())))
        
        # examples on how to run cmd via interface run_command
        cmd = ['nsxdp-cli', 'ipfix', 'settings', 'granular', 'get', '--dvs-alias', 'nsxvswitch', '--dvport=dafa09ca-33ed-4e04-ae3d-1c53305d5fe6']
        c_res = run_command(cmd)
        logger.error("run_command(cmd) res:%s", c_res)
        
        # examples on how to read existing metrics from data_store
        m_res = data_store['metrics']['nsx.host.host-metrics']
        # examples on how to read effective profile from data_store
        profile = data_store['profile']
        logger.error("data_store['metrics']['nsx.host.host-metrics']:%s, profile:%s", m_res, profile)
        
        # examples on how to read host_id from data_store
        host_id = data_store['host_id']
        logger.info('host_id:{}'.format(host_id))
    
        if profile['EXPORT_DATA']:
            report_test_data('running')
            logger.info("dynamic plugin - exported data to wavefront")
        else:
            logger.info("dynamic plugin - not export data ")
        
        # examples on how to use substitute interfaces for sys. 
        logger.info("sys_path:{}".format(sys_path))
        logger.info("sys_getsizeof(1):{}".format(sys_getsizeof(1)))
        logger.info("sys_getrefcount(cmd):{}".format(sys_getrefcount(cmd)))
        logger.info("sys_maxsize:{}".format(sys_maxsize))
        logger.info("sys_getrecursionlimit():{}".format(sys_getrecursionlimit()))
        
        # examples on how to use substitute interfaces for datetime.
        today = datetime_date_today()
        logger.info("datetime today:{}".format(today))
        logger.info("datetime_date_strftime now:{}".format(datetime_date_strftime(datetime.now(), '%H:%M')))
        logger.info('date.ctime(today):{}'.format(date.ctime(today)))
    
    
    run()