Den Import von Fremddaten mit dem HttpPostAdapter hatten wir uns für die Version 5.x von vRealize Operations Manger am Beispiel von Wetter Daten angesehen. Wie in einigen der letzten Artikeln erwähnt, existiert seit der Version 6 eine REST API. Heute wollen wir uns die REST API nochmals ansehen und hierbei zeigen, wie aus Python die REST API mit dem von der API mitgelieferten Python Client genutzt werden kann.
Wie erwähnt ist der Einstieg für die REST API in vRealize Operations die URL
https://VROPS/suite-api VROPS mit der IP Adresse oder dem Host Namen der vROps Instanz ersetzten.
Nach der Eingabe der URL erscheint die folgende Seite. Am Ende findet sich der Verweis auf den Python Client.
Diesen können wir nun aus dem Web Browser durch anwählen des mit “Click” hervorgehobenen Links herunterladen. Via Kommandozeile und Tools wie wget/curl etc. einfach die URL https://VROPS/suite-api/docs/bindings/python/vcops-python.zip verwenden.
Das Archiv im zip Format am besten in ein eigenes Verzeichnis verschieben und entpacken. Z.B. vrops-python
Aktuell unterstützt der Python Client die Python Version 2.6 & 2.7.
Zur Installation einfach wie angegeben python setup.py install aufrufen.
Die Installation erfolgt automatisch an die richtigen Stellen und sollte bei Erfolg mit den obigen Zeilen enden.
Soweit haben wir nun die Voraussetzungen geschaffen mit dem Python Client in Python zu arbeiten. Hier schonmal erwähnt, der Python Client wird mit dem Namen nagini in die Scripte eingebunden und referenziert.
Weitere Voraussetzungen:
- Wetter Daten – Diese beziehen wir wie in unserem HttpPost Beispiel von openweathermap.org und nutzen die API.
Via api.openweathermap.org/data/2.5/find?q=London&units=metric erhalten wir die Daten im JSON Format
für die Stadt London mit metrischen Daten (also Celsius …). Also für andere Städte einfach den Stadtnamen austauschen. - Argument parsing – Alles wird innerhalb einer vROps TestVM durchgeführt. Python 2.6 ist hier nur vorhanden und um keine weitere Software zu installieren für das parsen von Argumenten wird das Python Script simple_argparse.py verwendet. Ab Python 2.7 ist sicher argparse als Standardbibliothek vorzuziehen, soll aber für unsere Zwecke erstmal ausreichen.
Im folgenden einige Erklärungen zu den wichtigsten Teilen des Scripts, im speziellen zu der Verwendung des Python Clients nagini für die Nutzung der REST API wie eingangs erwähnt.
- Zeile 12 – Import des Python Clients für die Verwendung in unserem Skript
- Zeile 16 – Import des oben erwähnten Scripts simple_argparse.py für das Parsing der Kommandozeilen Argumente
- die anderen Imports sind für weitere Funktionen die genutzt werden notwendig
- Zeile 129 – In der Variablen cities findet sich die Liste der Städte, deren Wetterdaten ausgelesen werden. Weitere/andere einfach einfügen/ersetzen.
- Zeile 132 – Hier findet der Verbindungsaufbau zu dem vRealize Operations Manager System statt. Der vorher installierte Python Client “nagini” wird hierbei genutzt. URL, Benutzername & Passwort für die Authentifizierung werden als Argument im Aufruf an das Skript übergeben und entsprechend verwendet. Der Handler n aus dem Verbindungsaufbau wird für spätere Aufrufe verwendet. Die Aufrufe erfolgen dann in der Form n.Funktion()
- Zeile 138 – Kleine eigene Funktion zwecks besserer Lesbarkeit. In dieser wird nachgesehen, ob die Stadt schon in vROps vorhanden ist und wenn nicht entsprechend angelegt.
- Zeile 139 – Wetter Daten für die entsprechende Stadt werden ermittelt
- Zeile 141 – Die Wetter Daten werden dem entsprechenden Stadt Objekt (resID aus 138) angehängt
Die in Zeile 138 verwendete Funktion findCreateResource hier noch etwas mehr beleuchtet.
- Zeile 80 – Zuerst suchen wir nach der Stadt ob diese schon im vROps vorhanden ist. Der resourceKind spezifiziert hierbei die Art der Resource mit diese angelegt wurde. Als in unserem Fall “City”.
- Zeile 83 – Falls die Stadt (die Resource vom Typ “City” und dem entsprechenden Namen resource) nicht gefunden wurde, dann legen wir hier die Resource an. Der Aufbau des Arguments zur Resource Beschreibung (resDto) entspricht hierbei dem, der in der REST API für createResourceUsingAdapterKind zu finden ist.
Hier noch ein Auszug aus der REST API zu dem createResourceUsingAdapterKind Aufruf.
Die Funktion addStats aus Zeile 140 hier im Detail:
- Zeile 90 – Als Aufrufargument wird die Resource ID (resID) und alle anzuhängenden Daten übergeben
- Zeile 92-98 – Hier wird die Struktur für den Aufruf zusammengestellt. Der Aufbau der Struktur kann entsprechend der REST API Dokumentation für addStats nachgelesen werden.
- Zeile 100 – Hiermit wird jeweils eine Metrik und deren Wert(e) – in unserem Fall nur Wert – übertragen
Bleibt noch die Frage: Welche der REST API Funktion sind über der Python Client nagini nutzbar?
Dazu nutzen wir Informationen aus dem extrahierten zip Verzeichnis der Python Clients vom Anfang des Beitrages. Hier findet sich ein Unterverzeichnis nagini mit den beiden Dateien nagini.py und methods.json. Die Funktion für den Verbindungsaufbau nagini() ist in nagini.py enthalten und dort findet sich auch die Information zu den Parametern des Aufrufs. Alle unterstützten/abgebildeten Funktionen der REST API lassen sich in methods.json finden. Bleibt anzumerken das die Namen der Funktionsaufrufe in Python nicht 1:1 dem Namen der REST API entsprechen. Durch eine Suche mit dem REST API Namen in methods.json lässt sich das aber leicht lösen.
Viel Spaß beim Testen
Wie wir ein eigenes Dashboard mit den Daten bauen beim nächsten Mal.
Und hier das komplette Script. simple_arparse.py aus den Voraussetzung nicht vergessen.
Hi Frank
Dies ist echt ein genialer und hilfreicher Blogeintrag. Habe dein Skript minimal angepasst und zusätzlich auch versucht mittels Firefox (HTTP Resource Test) entsprechende POST Requests abzusetzen.
Leider erhalte ich jedoch immer folgende Antwort:
httpStatusCode=”500″ apiErrorCode=”500″>Internal Server error, cause unknown.
Hättest du mir einen Tipp bezüglich der Fehlersuche?
Gruss und Dank,
Andy
Hallo Andy,
500 als Return Code tritt meistens bei fehlerhafter Übergabe von Parametern auf.
Für Debugging gebe ich die Übergabewerte aus. Hierzu kannst Du beim Aufruf des Scripts –debug=1 die Ausgabe aktivieren.
Für von mir vorgesehen Stellen erfolgt die Ausgabe. Falls Du eigene Werte ausgeben möchtest einfach pp(variable) einsetzen.
Die API ist hier und da noch etwas spröde was den Informationsgehalt bei Fehlern betrifft und erfordert manchmal noch etwas trial&error.
Falls es weiterhin nicht funktioniert einfach das Script anhängen und ich schau mal drüber.
Ciao, Frank
Hey Frank
Danke für dein promptes Feedback! Ich vermute, dass ich mit dem Übergeben der Daten selbst ein Problem habe, da ich den identischen Fehler auch mittels Firefox (HTTP Resource Test) erhalte.
Request = POST
Content-Type = application/json
URL = https://vrops.bl.ch/suite-api/api/resources/aa125428-5786-4a8d-ad78-0ec396d58663/stats
Data = {“stat-content”:[{“timestamps”: [1430381971048],”statKey”: “ALL”,”data”: [1835]}]}
Die Ressouce ID aa125428-5786-4a8d-ad78-0ec396d58663 existiert und kann auch mittels GET Request aufgerufen werden.
Hast du ebenfall die neuste vROps Versio im Einsatz?
Version 6.0.1.2523163
Build 2523163
Gruss und Dank,
Andy
Andy,
die Daten die übergeben werden sehen soweit OK aus.
Habe das bei mir mit POSTMAN für Chrome versucht und funktionierte mit folgenden Daten die identisch zu Deinen sind.
{
“stat-content”: [ {
“timestamps”: [ 1430414499362 ],
“statKey”: “ALL”,
“data”: [ 3957 ]
} ]
}
Vermutung ist das evtl. der API Collector down ist.
Habe ich bei mir mal gestoppt und erhalte auch 500 für den Fall.
Versuche mal folgendes:
Gehe nach
Administration -> Environment Overview
In der Liste auf der rechten Seite findet sich ein Eingabefeld mit “Filter” als Angabe. Hier mgrapi eingeben und jetzt
sollte nur noch eine Zeile mit dem Namen ‘vRealizeOpsMgrAPI’ erscheinen.
Einfach selektieren und danach das STOP und nach 2-3 Sekunden das Start Icon in der Leiste darüber betätigen.
Hoi Frank
Entschuldige meine verspätete Antwort (war im Urlaub). Es scheint irgendwie am Adapter und dem dazugehörigen Aufruf zu liegen.
// Gemässe deinem Skript (funktioniert bei mir leider nicht)
n.add_stats(stats, id = resID , disableAnalyticsProcessing = False)
// Angepasster Aufruf mit dem HTTP Post Adapter, welcher bei mir funktioniert
n.add_stats_using_push_adapter_kind(stats, id = resID , adapterKind=”Http%20Post”)
Gruss,
Andy