Un plug-in dynamique est un plug-in personnalisé que vous pouvez créer pour tous les nœuds de transport pris en charge, comme un hôte ESXi, pour vérifier la santé du nœud.
Un plug-in dynamique peut être installé au moment de l'exécution. Il exécute les fonctions suivantes :
- Rédiger un journal système pour le nœud de transport affecté.
- Exécuter une commande ou une interface de ligne de commande via la fonction
run_command()
. - Lire les mesures existantes.
- Exporter les données vers Wavefront (uniquement dans un environnement VMware Cloud).
Vous pouvez créer un plug-in dynamique si vous disposez d'une expertise dans la gestion de NSX. Un plug-in dynamique peut également être créé par le support VMware. Un plug-in créé doit être envoyé à un référentiel GIT pour validation. Avant l'envoi, le plug-in doit être examiné et testé.
Gestion de la sécurité
Après l'examen et les tests, le plug-in, ses résultats de test et les modifications de code sont envoyés pour validation dans un référentiel GIT. Utilisez les détails du référentiel GIT suivant :
- GitLab : https://gitlab.eng.vmware.com/core-build/nsbu-sha-plugin
- Produit : nsx-sha-plugins
- Prise en charge de Gitreview : effectuée par l'équipe VMware
Une fois le plug-in validé et approuvé, il est transmis dans le référentiel GIT. Tous les plug-ins dynamiques sont générés et signés lors de la création d'un nouveau build. Chaque plug-in est empaqueté et signé séparément. Vous pouvez obtenir le plug-in requis dans les fichiers publiés du build.
Lorsqu'un plug-in signé est téléchargé dans le plan de gestion, ce dernier utilise une clé publique pour vérifier la signature et confirmer que ce plug-in est valide. Une fois le plug-in validé, les fichiers du plug-in sont envoyés aux hôtes de destination via les canaux sécurisés entre le plan de gestion et le plan de contrôle central (CCP) et entre le CCP et les hôtes.
Si une instance de l'agent de santé système (SHA) est redémarrée, elle récupère les fichiers de plug-in à partir du plan de gestion. Comme tous les fichiers sont publiés via des canaux sécurisés et qu'aucun fichier temporaire n'est utilisé, le risque de modification des scripts par des pirates est évité.
De plus, pour éviter les risques de code nuisible, SHA utilise RestrictedPython pour vérifier le script Python du plug-in avant d'exécuter le script.
Gestion des versions
Un plug-in peut être basé sur une commande ou un outil qui n'est pas pris en charge dans les versions ultérieures de NSX. Par conséquent, chaque plug-in personnalisé doit définir la version de NSX prise en charge dans le fichier manifest.yml. La version doit être une chaîne REGEX pour toutes les versions prises en charge. SHA sur le côté hôte vérifie la version du plug-in personnalisé et exécute uniquement les correspondances REGEX.
-
Définissez la version de NSX prise en charge d'une version majeure.
Comme la plupart des commandes et des outils ne changent pas entre les versions mineures d'une même version majeure, la méthode suivante est suggérée pour définir la version de toutes les versions mineures.
Par exemple,
version: ^2\.5\.[0-9.]+ <== The custom plugin supporting all NSX 2.5 releases
- Lorsqu'une nouvelle version majeure est publiée, tous les plug-ins dynamiques envoyés doivent être examinés.
- L'auteur du plug-in doit mettre à jour le script lorsque les commandes ou les outils associés sont modifiés.
Installer un plug-in dynamique
Le nœud de transport ou le nœud Edge sur lequel le plug-in est installé doit disposer d'un minimum de 30 Mo d'espace de mémoire. De plus, notez que vous ne pouvez installer que 10 plug-ins maximum. Lorsque le nombre de plug-ins atteint 10, toute installation ultérieure d'un plug-in échouera.
- Créez les fichiers de plug-in dynamique dans le référentiel GIT. Pour plus d'informations sur les fichiers de plug-in, reportez-vous à la section Fichiers de plug-in dynamique.
- Déclenchez le build du produit dans le référentiel GIT pour générer le module zippé des fichiers de plug-in dynamique et téléchargez le module.
- Créez le plug-in dynamique à l'aide de l'API suivante avec la méthode POST.
https://<manager_ip>/api/v1/systemhealth/plugins
- Chargez le module zippé du plug-in dans le plan de gestion à l'aide de l'API suivante avec la méthode POST. Le plan de gestion extrait le fichier chargé et effectue la validation requise.
/systemhealth/plugins/<plugin-id>/files/<file-name>/data
Note : La taille maximale du fichier zippé de plug-in est de 500 Ko. - Créez un groupe de nœuds avec les nœuds de transport requis en tant que membres à l'aide de l'API suivante avec la méthode POST.
/<manager_ip>/api/v1/ns-groups
- Appliquez le profil de plug-in au groupe de nœuds en créant une nouvelle configuration de service à l'aide de l'API suivante. La structure de configuration de service envoie le contenu du plug-in au groupe de nœuds.
https://<manager_ip>/api/v1/service-configs
Pour plus d'informations sur les API, reportez-vous à la documentation Guide des API de NSX.
Obtenir l'état du plug-in
Une fois que le plug-in dynamique est en cours d'exécution, il télécharge automatiquement l'état sur le plan de gestion via le canal de message existant. Le plan de gestion agrège les informations d'état du plug-in et les stocke dans la base de données. Pour obtenir l'état de tous les plug-ins sur chaque nœud, utilisez l'API suivante avec la méthode GET.
https://<manager_ip>/api/v1/systemhealth/plugins/status/<transport_node_id>
Exemple de demande :
GET https://<manager_ip>/api/v1/systemhealth/plugins/status/a257b981-1a1c-4b95-b16c-8646
{ "result_count":1, "results": [ { "id": "72e1bd4b-6df6-42d0-9c59-a1c31312c9f1", "name": "health-check-compute", "status": "NORMAL", "detail": "" } ] }
Désinstaller un plug-in dynamique
Pour désinstaller un plug-in, supprimez la configuration du service à l'aide de l'API suivante.
https://<manager_ip>/api/v1/service-configs/<service_config_id>
Autres API pour la gestion des plug-ins
Le tableau suivant répertorie les API pour gérer les plug-ins dynamiques. Pour plus d'informations sur les API, reportez-vous à la documentation Guide des API de NSX.
Tâche | Méthode | API |
---|---|---|
Supprimer un plug-in | SUPPRIMER | /systemhealth/plugins/<plugin-id> |
Créer un profil de santé du système | POST | /systemhealth/profiles |
Surveiller l'état du plug-in |
GET | /systemhealth/plugins/status/<node-id> |
Activer le plug-in | Pour activer un plug-in, les deux étapes suivantes sont requises :
|
|
Modifier l'intervalle du plug-in | POST | Pour modifier l'intervalle du plug-in, les deux étapes suivantes sont requises :
|
Fichiers de plug-in dynamique
Un plug-in dynamique comprend les fichiers suivants :
- Fichier de spécification d'installation
Le fichier de spécification d'installation, manifest.yml, contient les informations suivantes pour l'agent de santé du système :
- Structure du plug-in
- Contraintes, le cas échéant
- Comment installer et utiliser le plug-in
- Restrictions de sécurité pour le script de contrôle de santé. Par exemple, les autorisations dont dispose le script et les fichiers auxquels il peut accéder.
Le tableau suivant répertorie les champs qui sont spécifiés dans un fichier manifest.yml.Nom Description Requis/facultatif Exemple classes Spécifie les classes nécessaires dans le script de plug-in. Les classes doivent être spécifiées au format suivant. '<module_name>.<class_name>'
Facultatif classes: ['datetime.datetime','datetime.date']
modules Spécifie les modules nécessaires dans le script de plug-in. Facultatif modules: ['random', 'math'] plugin Spécifie la structure du plug-in comme suit :
config :nom du fichier de configuration
script : nom du fichier de script
Requis plugin:
config: plugin.cfg.yml
script: plugin.py
version Spécifie les versions de NSX sur lesquelles ce plug-in peut être installé. Requis version: '^3\.1\.[0-9.]+'
node_type Spécifie les types de nœuds NSX sur lesquels ce plug-in peut être installé. Les types de nœuds disponibles sont les suivants :
- nsx-esx
- nsx-bms
- nsx-edge
Requis node_type: ['nsx-esx']
metrics Spécifie les mesures qui peuvent être utilisées dans le script de plug-in. Facultatif metrics: ['nsx.host.host-metrics']
precondition Spécifie la condition préalable pour le plug-in. La condition préalable disponible est Wavefront.
Note : Ce champ s'applique uniquement dans un environnement VMware Cloud (VMC).Facultatif precondition: ['wavefront']
N'utilisez pas les modules intégrés suivants :-
os
-
subprocess
-
sys
-
multiprocessing
-
importlib
Le tableau suivant répertorie les interfaces que vous devez utiliser à la place des fonctions intégrées des modules respectifs. Ces interfaces sont fournies par le système. Vous pouvez les utiliser directement sans spécifier leur module/classe dans le fichier manifest.yml.Exemple de fichier manifest.yml.Module Fonction intégrée Interface de remplacement 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 # 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']
- Fichier de profil par défaut
Le fichier de profil par défaut, plugin.cfg.yml, est utilisé pour configurer le comportement du plug-in, tel que la fréquence d'exécution du script de contrôle de santé. Pour modifier les configurations par défaut, vous pouvez créer un profil SHA pour un plug-in dynamique spécifique et l'appliquer au nœud de transport via le groupe NS à l'aide du plan de gestion vers le CCP vers le canal NestDB.
Le tableau suivant répertorie les champs spécifiés dans un fichier plugin.cfg.yml.Nom Description Requis/facultatif Exemple CHECK_INTERVAL Spécifie l'intervalle par défaut en secondes pour l'exécution du script de plug-in. Requis CHECK_INTERVAL: 20 ACTIVER Spécifie si le plug-in est activé par défaut. Requis ENABLE: true Exemple de fichier plugin.cfg.yml.# 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
- Script de contrôle de santé
Un fichier de script de contrôle de santé, plugin.py, contient un script Python pour vérifier l'état de santé d'un nœud de transport.
Le tableau suivant répertorie les variables et fonctions définies par le système qui peuvent être utilisées et les données pouvant être lues dans un fichier plugin.py.Variable/Données/Fonction Description Type Exemple logger Écrit les informations de journal dans Syslog. La variable existante définie par le système, logger, peut être utilisée directement dans le script de plug-in. Le nom du journal de sortie est précédé du nom et de l'ID du plug-in, comme indiqué dans l'exemple de sortie suivant.
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 Dictionnaire existant défini par le système qui est utilisé pour extraire les données transmises par le système. Par exemple, profile, metric et host_id.
Variable profile = data_store['profile']
profile Les données de profil sont un dictionnaire analysé à partir du profil par défaut (plugin.cfg.yml) ou du profil SHA effectif (appliqué via l'API Manager) qui est lu depuis data_store. Son format est le suivant :
{'ENABLE': True, 'CHECK_INTERVAL': 20, 'EXPORT_DATA': True}
Données profile = data_store['profile']
metric La mesure est un dictionnaire avec « value » et « timestamp » qui est lu depuis data_store. Son format est le suivant :
data_store['metrics'][<metric_name>]
Où,
La première clé doit être « metrics ».
La deuxième clé est un nom de mesure existant.
Données 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
}
Remarque : la première exécution du plug-in peut ne pas renvoyer de mesure, car actuellement une mesure est collectée de manière asynchrone avec le plug-in en cours d'exécution. Par conséquent, il se peut que la mesure n'ait pas été collectée lors de la première exécution du plug-in.
host_id Host_id est une instance de classe uuid.UUID lue depuis data_store. Données host_id = data_store['host_id']
run_command Cette fonction exécute les commandes sous forme de liste. Son format est le suivant. run_command(cmd, timeout=4)
Où,
- cmd : commandes à exécuter. Doit être sous forme de liste comme dans l'exemple.
- timeout : délai d'expiration de l'attente du résultat de la commande. Le délai d'expiration par défaut est de 4 s. Le délai d'expiration ne doit pas être supérieur à 20 s.
Cette fonction renvoie le résultat de l'exécution de la commande.
Fonction cmd = ['nsxdp-cli', 'ipfix', 'settings', 'granular', 'get', '--dvs-alias', 'nsxvswitch', '--dvport=dafa09ca-33ed-4e04-ae3d-1c53305d5fe6']
res = run_command(cmd)
Exportdata Cette fonction exporte les données vers Wavefront. Actuellement, un plug-in dynamique prend en charge l'exportation vers Wavefront uniquement. Note : Cette fonction s'applique uniquement dans un environnement VMware Cloud (VMC).Exportdata: ExportData(data={}, exports=[], source=host_uuid)
Où :
data : données à exporter ; les données doivent être au format de dictionnaire, par exemple.
exports : liste de destination pour l'exportation. En HL, ne prend en charge que Wavefront dans la destination. Il est obligatoire.
source : chaîne source pour l'exportation. Elle est utile uniquement pour la destination Wavefront. Elle est facultative, la valeur par défaut est NSX host_uuid.
La fonction ne renvoie aucune valeur.
Fonction Exportdata(data={'esx.plugin.stats': {'stats': {'gc-esx-001': data}}}, exports=['wavefront'])
Exemple de fichier plugin.py.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()