Aktionen

ZabbixPreventDuplicateHosts Doppelte Hosts bei Installations des Agenten und Autoregistrierung verhindern

Aus znilwiki

Changelog:

  • 25.06.2018 Erste Version 0.0.0.27
  • 26.06.2018 Version 1.0.0.8: Modus für das hinzufügen eines Templates eingebaut / Fehlerbehandlung COM-Fehler eingebaut



1 Problem

Bei einem Kunden wurden die VMware-Templates von Zabbix genutzt. Dabei wird unter anderem jede VM automatisch als ein eigener Host registriert.
Die UUID der VM dient dabei als Host name, der Name der VM wird als Visible name genutzt:

ClipCapIt-180625-160707.PNG


Nun sollte zusätzlich der Zabbix-Agent auf allen VM installiert werden um mehr Möglichkeiten bei der Überwachung zu haben.
Aber natürlich sollten dafür die Hosts nicht doppelt angelegt sondern die bereits vorhandenen genutzt werden.
Dabei gab es zwei Hürden zu meistern:

  • Die Schreibweise des Hostnamen: Im vCenter wurden die Namen der VMs sowohl GROßSCHREIBUNG als auch kleinschreibung als auch GROßundklein geschrieben. Und Zabbix ist "case sensitive", beachtet also die Groß- und Kleinschreibung.
  • In der Agentkonfigurationsdatei soll der "Host name" angegeben werden - und das ist hier ja die UUID




2 Lösung

Für die Installation nutze ich eine selbst geschriebene Batchdatei: Zabbix Agent für Windows per Skript automatisch installieren Musterdatei (nur in einer aktuelleren Version).
In der Batchdatei wird der Computername ermittelt und in die Konfigurationsdatei des Agenten geschrieben.

In diese wollte ich nun nach der Ermittlung des Computernamens einen Prüfung gegen den Zabbix-Server einbauen:

  • Prüfen ob es schon einen Hosts mit dem aktuellen Computernamen gibt, dabei sowohl in Host name als auch in Visible name nachsehen
  • Falls ja den dort gesetzten Host name zurück geben

Der zurück gegebene Host name kann dann in der Konfigurationsdatei eingesetzt werden, der Visible name wird als Kommentar dazu geschrieben


3 Downloads

Version 1.0.0.8: ZabbixPreventDuplicateHosts_1.0.0.8.zip Inhalt:

  • ZabbixPreventDuplicateHosts.exe das Programm
  • ZabbixPreventDuplicateHosts.ini Beispiel-ini mit Zugansdaten
  • BatchExampleGetGostname.cmd Beispiel wie das ganze in einer Batch-Datei genutzt werden kann
  • ZabbixPreventDuplicateHosts.au3 der Quellcode


Version 0.0.0.27: ZabbixPreventDuplicateHosts.zip Inhalt:

  • ZabbixPreventDuplicateHosts.exe das Programm
  • ZabbixPreventDuplicateHosts.ini Beispiel-ini mit Zugansdaten
  • BatchExample.cmd Beispiel wie das ganze in einer Batch-Datei genutzt werden kann




4 Vorbereitung

Legt auf dem Zabbix-Server einen Benutzer an der die API nutzen darf.
Dieser braucht mindestens lesenden Zugriff (am besten auf alle Hosts) und sollte sowohl im Benutzernamen als auch im Passwort auf Sonderzeichen verzichten.
In den Beispielen ist der Benutzer apiuser mit dem Passwort userpassword



5 Anleitung

Wir die ZabbixPreventDuplicateHosts.exe ohne Parameter oder mit /? aufgerufen so erscheint die Hilfe:

+------------------------------------------------------------------------------
| ZabbixPreventDuplicateHosts.exe - Version 1.0.0.8
+------------------------------------------------------------------------------
| 2018 von Bernhard Linz für http://znil.net - Kontakt: Bernhard@znil.net
+------------------------------------------------------------------------------

ZabbixPreventDuplicateHosts.exe prüft über die Zabbix-API ob es bereits einen
Host mit dem Namen des Computers gibt. Dabei werden verschiedene Schreibweisen
toleriert (Groß und Kleinschreibung, mit und ohne Domänensuffix) und der
gefundene Hostname zurück gegeben
-------------------------------------------------------------------------------

Aufruf für Abfragen:
--------------------

ZabbixPreventDuplicateHosts.exe [Parameter] <COMPUTERNAME>

 ohne Parameter    : Testet ob es einen Host mit der folgende Schreibweisen bei
                     'Host name' oder 'Visible name' schon gibt:
                     <COMPUTERNAME>.Computerdomain
                     <COMPUTERNAME>
                     Groß- und Kleinschreibung wird dabei ignoriert

 /addVisibleName   : Erweitert die Rückgabe um den Host 'Visible name'

 /addHostID        : Erweitert die Rückgabe um die Host-ID

 Es findet eine Text-In-Text-Suche statt. Die Suche nach 'TEST8' findet also
 die Hosts 'TEST8' aber auch 'TEST81', 'TEST8.beispiel.local' oder 'MeinTEST8443'
 Es wird jeweils der kürzeste Treffer zurück gegeben (die wenigsten Zeichen).
 Gibt es mehrere Treffer mit dem gleichen Namen so wird der älteste Eintrag in
 Zabbix genommen

Rückgabe:
---------

 Wird ein Host mit dem Namen gefunden so wird dessen Eintrag aus dem Feld
  Host name
 zurück gegeben - in der exakten Schreibweise. Ggf. steht bei LLD generierten
 VMs die UUID. Der Exit-Code (%ERRORLEVEL%) ist 0
 Wurde der Parameter '/addVisibleName' mit angegeben wo wird
  Host name;Visible name
zurück gegeben.

 Wird kein Host gefunden so ist der Rückgabewert
  ZBXHOSTNOTFOUND
 Der Exit-Code (%ERRORLEVEL%) ist 1

 Gibt es einen Fehler so wird statt dessen eine passende Fehlerbeschreibung
 zurück gegeben. Der Exit-Code (%ERRORLEVEL%) ist 2


Aufruf für Zusatzfunktionen:
----------------------------

ZabbixPreventDuplicateHosts.exe [Parameter] <HostID>

 /AddTemplate=<ID> : Fügt dem Host das Template mit der angegebenen ID hinzu


Anmeldedaten des Zabbix-Servers:
--------------------------------

 Für die Abfrage der API werden die URL, der Benutzername und das Passwort
 benötigt. Diese lassen sich auf verschiedene Arten hinterlegen. Es wird in der
 angegebenen Reihenfolge gesucht:

 1. Per .ini-Datei im gleichen Verzeichnis:
    C:\_AutoIt\ZabbixAgent\ZabbixPreventDuplicateHosts\ZabbixPreventDuplicateHosts.ini
    Inhalt:
        [ZABBIXAPI]
        URL=http://IP_oder_DNSNAME/zabbix/api_jsonrpc.php
        User=Benutzername
        Password=Passwort

 2. Über das Setzen der folgenden Umgebungsvariablen:
        set ZABBIXURL="http://IP_oder_DNSNAME/zabbix/api_jsonrpc.php"
        set ZABBIXUSER="Benutzername"
        set ZABBIXPASSWORD="Passwort"
    die dann per %ZABBIXURL%, %ZABBIXUSER% und %ZABBIXPASSWORD% genutzt
    werden können. Dazu vor dem Aufruf z.B. in der gleichen CMD setzen.

 3. Über das Setzen der folgenden Registry-Schlüssel
        Schlüssel.....: HKLM\SOFTWARE\Zabbix\
        Werte (REG_SZ): URL http://IP_oder_DNSNAME/zabbix/api_jsonrpc.php
                        User Benutzername
                        Password Passwort
    zum Beispiel per Gruppenrichtlinie

Bitte Beachten:
 Die URL kann auch mit https beginnen, Zertifikatsfehler werden ignoriert.
 Je nach Installation ist der URL Pfad
 http://IP_oder_DNSNAME/zabbix/api_jsonrpc.php oder
 http://IP_oder_DNSNAME/api_jsonrpc.php
 Für den API-Benutzer reichen lesende Rechte! Der Host kann aber nur gefunden
 werden wenn für diesen auch Rechte vorhanden sind
+------------------------------------------------------------------------------
| ZabbixPreventDuplicateHosts.exe ist FREEWARE!
| Kopieren, weitergeben ausdrücklich erlaubt!
| Die jeweils aktuelleste Version, Anleitung und Quellcode findet Ihr unter:
| https://znil.net/index.php?title=ZabbixPreventDuplicateHosts
+------------------------------------------------------------------------------

Das Programm braucht natürlich die URL und die Zugangsdaten zum Zabbix-Server.
Zuerst sucht er in der .ini Datei im gleichen Verzeichnis, also passt die Daten dort an.
Alternativ geht es über Umgebungsvariablen oder Registry-Schlüssel (wie in der Hilfe beschrieben).

5.1 Host suchen

Sind die Daten in der ZabbixPreventDuplicateHosts.ini gemacht geht die Abfrage mit

ZabbixPreventDuplicateHosts.exe /AddVisibleName 9KL001dctest

In diesem Beispiel wird nach dem Host "9KL001dcte" gesucht.
Die Rückgabe ist:

423be0f8-175d-16c5-d2fa-817ed70079e3;9KL001DCTEST

Also die UUID (die Feld Host name steht) und der Name der VM.
Bei einem Host wo Visible name leer ist kommt folgendes zurück_

ZabbixPreventDuplicateHosts.exe /AddVisibleName 9KL001dc

Rückgabe:

9KL001DC;9KL001DC

Also beide mal der gleiche Wert (so macht das Zabbix)
Mit dem Parameter '/AddHostID' wird die Host-ID angehängt:

ZabbixPreventDuplicateHosts.exe /AddHostID 9KL001dctest

Rückgabe:

9KL001DCTEST;13714


Die Host-ID kann dann zum Beispiel genutzt werden um Templates mit dem Host zu verknüpfen.

In der BatchExampleGetHostname.cmd habe ich das ganze in einer Batch genutzt:
Quellcode:

@echo off
echo Ausgabe von allen 3 Werten:
echo ---------------------------
set ZABBIXHOSTNAME=
set ZABBIXVISIBLENAME=
set ZABBIXHOSTID=
for /f "tokens=1-3 delims=;" %%a in ('ZabbixPreventDuplicateHosts.exe /addVisibleName /addHostID %1') do (
    set ZABBIXHOSTNAME=%%a
    set ZABBIXVISIBLENAME=%%b
    set ZABBIXHOSTID=%%c
)
echo Host name   : %ZABBIXHOSTNAME%
echo Visible name: %ZABBIXVISIBLENAME%
echo Host ID     : %ZABBIXHOSTID%
echo.
echo.
echo Ausgabe nur Host name:
echo ---------------------------
set ZABBIXHOSTNAME=
set ZABBIXVISIBLENAME=
set ZABBIXHOSTID=
for /f "tokens=*" %%a in ('ZabbixPreventDuplicateHosts.exe %1') do set ZABBIXHOSTNAME=%%a
echo Host name   : %ZABBIXHOSTNAME%

Aufruf mit:

BatchExample.cmd 9KL001DCTEST

Rückgabe:

Ausgabe von allen 3 Werten:
---------------------------
Host name   : 423be0f8-175d-16c5-d2fa-817ed70079e3
Visible name: 9KL001DCTEST
Host ID     : 13714 
 

Ausgabe nur Host name:
---------------------------
Host name   : 423be0f8-175d-16c5-d2fa-817ed70079e3




5.2 Template zum Host hinzufügen

Wenn man die Host-ID hat kann man unter Angabe der Template-ID dieses dem Host hinzufügen:

ZabbixPreventDuplicateHosts.exe /addTemplate=10462 13714

In diesem Beispiel wird das Template mit der ID 10462 dem Host mit der ID 13714 hinzugefügt.
Woher bekommt Ihr die Template-ID? Öffnet das Template im Webbrowser auf dem Zabbix-Server, die ID steht dann in der URL:

ClipCapIt-180626-111123.PNG

Wollt Ihr mehrere Templates hinzufügen so müsst Ihr für jedes einen weiteren Aufruf des Befehls hinzufügen.
Hat der Host das Template bereits so passiert nichts, Ihr erhaltet trotzdem die Meldung das es Erfolgreich hinzugefügt wurde.



6 Quellcode

#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=zabbix.ico
#AutoIt3Wrapper_Outfile=ZabbixPreventDuplicateHosts.exe
#AutoIt3Wrapper_UseUpx=y
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_Res_Description=ZabbixPreventSuplicateHosts.exe
#AutoIt3Wrapper_Res_Fileversion=1.0.0.9
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
#AutoIt3Wrapper_Res_LegalCopyright=Apache License 2.0
#AutoIt3Wrapper_Res_SaveSource=y
#AutoIt3Wrapper_Res_Language=1031
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <Array.au3>
#include <Date.au3>
Opt("TrayIconHide", 0)
Opt("MustDeclareVars", 1)

; ###############################################################################################################################
; ###############################################################################################################################
; ****************************************************************************************
;     ##     ##    ###    ########  ####    ###    ########  ##       ########  ######
;     ##     ##   ## ##   ##     ##  ##    ## ##   ##     ## ##       ##       ##    ##
;     ##     ##  ##   ##  ##     ##  ##   ##   ##  ##     ## ##       ##       ##
;     ##     ## ##     ## ########   ##  ##     ## ########  ##       ######    ######
;      ##   ##  ######### ##   ##    ##  ######### ##     ## ##       ##             ##
;       ## ##   ##     ## ##    ##   ##  ##     ## ##     ## ##       ##       ##    ##
;        ###    ##     ## ##     ## #### ##     ## ########  ######## ########  ######
; ****************************************************************************************

Global $s_IniFile = @ScriptDir & "\" & StringTrimRight(@ScriptName, 4) & ".ini"
Global $oErrorHandler = ObjEvent("AutoIt.Error", "_COMErrFunc")

;                   	     10        20        30        40        50        60        70        80
;                 	12345678901234567890123456789012345678901234567890123456789012345678901234567890
Dim $s_Header = _
					"+------------------------------------------------------------------------------" & @CRLF & _
					"| ZabbixPreventDuplicateHosts.exe - Version " & FileGetVersion(@ScriptName) & @CRLF & _
					"+------------------------------------------------------------------------------" & @CRLF & _
					"| 2018 von Bernhard Linz für http://znil.net - Kontakt: Bernhard@znil.net" & @CRLF & _
					"+------------------------------------------------------------------------------" & @CRLF & _
					@CRLF

;                            10        20        30        40        50        60        70        80
;                 	12345678901234567890123456789012345678901234567890123456789012345678901234567890
Dim $s_HilfeText = _
					"ZabbixPreventDuplicateHosts.exe prüft über die Zabbix-API ob es bereits einen" &  @CRLF & _
					"Host mit dem Namen des Computers gibt. Dabei werden verschiedene Schreibweisen" & @CRLF & _
					"toleriert (Groß und Kleinschreibung, mit und ohne Domänensuffix) und der" & @CRLF & _
					"gefundene Hostname zurück gegeben" & @CRLF & _
					"-------------------------------------------------------------------------------" & @CRLF & _
					@CRLF & _
					"Aufruf für Abfragen: " & @CRLF & _
					"-------------------- " & @CRLF & _
					@CRLF & _
					@ScriptName & " [Parameter] <COMPUTERNAME>" & @CRLF & _
					@CRLF & _
					" ohne Parameter    : Testet ob es einen Host mit der folgende Schreibweisen bei" & @CRLF & _
					"                     'Host name' oder 'Visible name' schon gibt:" & @CRLF & _
					"                     <COMPUTERNAME>.Computerdomain" & @CRLF & _
					"                     <COMPUTERNAME>" & @CRLF & _
					"                     Groß- und Kleinschreibung wird dabei ignoriert" & @CRLF & _
					@CRLF & _
					" /addVisibleName   : Erweitert die Rückgabe um den Host 'Visible name'" & @CRLF & _
					@CRLF & _
					" /addHostID        : Erweitert die Rückgabe um die Host-ID" & @CRLF & _
					@CRLF & _
					" Es findet eine Text-In-Text-Suche statt. Die Suche nach 'TEST8' findet also" & @CRLF & _
					" die Hosts 'TEST8' aber auch 'TEST81', 'TEST8.beispiel.local' oder 'MeinTEST8443'" & @CRLF & _
					" Es wird jeweils der kürzeste Treffer zurück gegeben (die wenigsten Zeichen)." & @CRLF & _
					" Gibt es mehrere Treffer mit dem gleichen Namen so wird der älteste Eintrag in" & @CRLF & _
					" Zabbix genommen" & @CRLF & _
					@CRLF & _
					"Rückgabe: " & @CRLF & _
					"--------- " & @CRLF & _
					@CRLF & _
					" Wird ein Host mit dem Namen gefunden so wird dessen Eintrag aus dem Feld" & @CRLF & _
					"  Host name" & @CRLF & _
					" zurück gegeben - in der exakten Schreibweise. Ggf. steht bei LLD generierten" & @CRLF & _
					" VMs die UUID. Der Exit-Code (%ERRORLEVEL%) ist 0" & @CRLF & _
					" Wurde der Parameter '/addVisibleName' mit angegeben wo wird" & @CRLF & _
					"  Host name;Visible name" & @CRLF & _
					"zurück gegeben." & @CRLF & _
					@CRLF & _
					" Wird kein Host gefunden so ist der Rückgabewert" & @CRLF & _
					"  ZBXHOSTNOTFOUND" & @CRLF & _
					" Der Exit-Code (%ERRORLEVEL%) ist 1" & @CRLF & _
					@CRLF & _
					" Gibt es einen Fehler so wird statt dessen eine passende Fehlerbeschreibung" & @CRLF & _
					" zurück gegeben. Der Exit-Code (%ERRORLEVEL%) ist 2" & @CRLF & _
					@CRLF & _
					@CRLF & _
					"Aufruf für Zusatzfunktionen: " & @CRLF & _
					"---------------------------- " & @CRLF & _
					@CRLF & _
					@ScriptName & " [Parameter] <HostID>" & @CRLF & _
					@CRLF & _
					" /AddTemplate=<ID> : Fügt dem Host das Template mit der angegebenen ID hinzu" & @CRLF & _
					@CRLF & _
					@CRLF & _
					"Anmeldedaten des Zabbix-Servers:" & @CRLF & _
					"--------------------------------" & @CRLF & _
					@CRLF & _
					" Für die Abfrage der API werden die URL, der Benutzername und das Passwort" & @CRLF & _
					" benötigt. Diese lassen sich auf verschiedene Arten hinterlegen. Es wird in der" & @CRLF & _
					" angegebenen Reihenfolge gesucht:" & @CRLF & _
					@CRLF & _
					" 1. Per .ini-Datei im gleichen Verzeichnis:" & @CRLF & _
					"    " & $s_IniFile & @CRLF & _
					"    Inhalt:" & @CRLF & _
					"        [ZABBIXAPI]" & @CRLF & _
					"        URL=http://IP_oder_DNSNAME/zabbix/api_jsonrpc.php" & @CRLF & _
					"        User=Benutzername" & @CRLF & _
					"        Password=Passwort" & @CRLF & _
					@CRLF & _
					" 2. Über das Setzen der folgenden Umgebungsvariablen:" & @CRLF & _
					'        set ZABBIXURL="http://IP_oder_DNSNAME/zabbix/api_jsonrpc.php"' & @CRLF & _
					'        set ZABBIXUSER="Benutzername"' & @CRLF & _
					'        set ZABBIXPASSWORD="Passwort"' & @CRLF & _
					"    die dann per %ZABBIXURL%, %ZABBIXUSER% und %ZABBIXPASSWORD% genutzt" & @CRLF & _
					"    werden können. Dazu vor dem Aufruf z.B. in der gleichen CMD setzen." & @CRLF & _
					@CRLF & _
					" 3. Über das Setzen der folgenden Registry-Schlüssel" & @CRLF & _
					"        Schlüssel.....: HKLM\SOFTWARE\Zabbix\" & @CRLF & _
					"        Werte (REG_SZ): URL http://IP_oder_DNSNAME/zabbix/api_jsonrpc.php" & @CRLF & _
					"                        User Benutzername" & @CRLF & _
					"                        Password Passwort" & @CRLF & _
					"    zum Beispiel per Gruppenrichtlinie" & @CRLF & _
					@CRLF & _
					"Bitte Beachten:" & @CRLF & _
					" Die URL kann auch mit https beginnen, Zertifikatsfehler werden ignoriert." & @CRLF & _
					" Je nach Installation ist der URL Pfad" & @CRLF & _
					" http://IP_oder_DNSNAME/zabbix/api_jsonrpc.php oder" & @CRLF & _
					" http://IP_oder_DNSNAME/api_jsonrpc.php" & @CRLF & _
					" Für den API-Benutzer reichen lesende Rechte! Der Host kann aber nur gefunden" & @CRLF & _
					" werden wenn für diesen auch Rechte vorhanden sind" & @CRLF & _
					"+------------------------------------------------------------------------------" & @CRLF & _
					"| ZabbixPreventDuplicateHosts.exe ist FREEWARE!" & @CRLF & _
					"| Kopieren, weitergeben ausdrücklich erlaubt!" & @CRLF & _
					"| Die jeweils aktuelleste Version, Anleitung und Quellcode findet Ihr unter:" & @CRLF & _
					"| https://znil.net/index.php?title=ZabbixPreventDuplicateHosts" & @CRLF & _
					"+------------------------------------------------------------------------------" & " " & @CRLF

; Domäne aus der Registry auslesen. Ist das Feld leer so ist der Computer in keiner Domäne sondern in einer Arbeitsgruppe
Global $s_Domain = RegRead('HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters','Domain')

; Ob das Visible Name Feld mit durchsucht wird oder nicht
Global $b_AddVisibleName = False
Global $b_AddHostID = False
Global $b_AdditionalFunction = False
Global $s_OutputText = ""
Global $s_Computername = ""
Global $s_HostID = ""
Global $s_TemplateID = ""

; Die Variablen mit den Zugangsdaten zum Server:
Global $__zbxURL = ""
Global $__zbxUser = ""
Global $__zbxPassword = ""

; ###############################################################################################################################
; ###############################################################################################################################

; *************************************************************************************
;    ######## ##     ## ##    ##  ######  ######## ####  #######  ##    ##  ######
;    ##       ##     ## ###   ## ##    ##    ##     ##  ##     ## ###   ## ##    ##
;    ##       ##     ## ####  ## ##          ##     ##  ##     ## ####  ## ##
;    ######   ##     ## ## ## ## ##          ##     ##  ##     ## ## ## ##  ######
;    ##       ##     ## ##  #### ##          ##     ##  ##     ## ##  ####       ##
;    ##       ##     ## ##   ### ##    ##    ##     ##  ##     ## ##   ### ##    ##
;    ##        #######  ##    ##  ######     ##    ####  #######  ##    ##  ######
; *************************************************************************************

Func _COMErrFunc()
    ; Do nothing special, just check @error after suspect functions.
EndFunc   ;==>_COMErrFunc

;           #    #     #  #####  ###  #####  ####### ####### #     #
;          # #   ##    # #     #  #  #     # #     # #       ##   ##
;         #   #  # #   # #        #        # #     # #       # # # #
;        #     # #  #  #  #####   #   #####  #     # #####   #  #  #
;        ####### #   # #       #  #  #       #     # #       #     #
;        #     # #    ## #     #  #  #       #     # #       #     #
;        #     # #     #  #####  ### ####### ####### ####### #     #
;#######
; _ANSI2OEM löst das Problem mit dem Umlauten und anderen Sonderzeichen. Es wandelt Text so um das er korrekt in der DOS-Box dargestellt wird
; So können hier im Quellcode auch Umlaute verwendet werden (in den Textausgaben) und diese werden dann korrekt dargestellt
Func _ANSI2OEM($text)
	$text = DllCall('user32.dll', 'Int', 'CharToOem', 'str', $text, 'str', '')
	Return $text[2]
	;Return $text
EndFunc   ;==>_ANSI2OEM


;        #     #                           #
;        #     # # #      ###### ######   # #   #    #  ####   ####  ###### #####  ###### #    #
;        #     # # #      #      #       #   #  #    # #      #    # #      #    # #      ##   #
;        ####### # #      #####  #####  #     # #    #  ####  #      #####  #####  #####  # #  #
;        #     # # #      #      #      ####### #    #      # #  ### #      #    # #      #  # #
;        #     # # #      #      #      #     # #    # #    # #    # #      #    # #      #   ##
;        #     # # ###### #      ###### #     #  ####   ####   ####  ###### #####  ###### #    #
;#######
; Hilfsroutine die den Hilfetext ausgibt
Func _HilfeAusgeben()
	ConsoleWrite(_ANSI2OEM($s_Header))
	ConsoleWrite(_ANSI2OEM($s_HilfeText))
EndFunc   ;==>_HilfeAusgeben

; #############################################################################################################################################################
Func _zbx_Login( $__zbxURL, $__zbxUser, $__zbxPassword)
	Local $__zbxJSON = '{"params":{"password":"' & $__zbxPassword & '","user":"' & $__zbxUser & '","userData":true},"jsonrpc":"2.0","method":"user.login","id":42}'
	Local $__oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
	Local $__zbxSessionId = ""
	$__oHTTP.Open("POST", $__zbxURL , False)
	; ignore all SSL errors
    $__oHTTP.Option("WinHttpRequestOption_SslErrorIgnoreFlags") = 0x3300
;~ 	$__oHTTP.Option(4) = 13056 ; turns off ssl error messages and warnings
	$__oHTTP.Option(4) = 0x3300
    ; Unknown certification authority (CA) or untrusted root   0x0100
    ; Wrong usage                                              0x0200
    ; Invalid common name (CN)                                 0x1000
    ; Invalid date or certificate expired                      0x2000
	$__oHTTP.SetRequestHeader("Content-Type", "application/json-rpc")
	$__oHTTP.Send($__zbxJSON)
	Local $__oReceived = $__oHTTP.ResponseText
	Local $__oStatusCode = $__oHTTP.Status
;~ 	MsgBox(0, "_zbx_Login", StringReplace($__oReceived,",", "," & @CRLF) & @CRLF & @CRLF & "Status Code: " & $__oStatusCode)
	If $__oStatusCode = 200 Then
		Local $__atemp = StringSplit($__oReceived, ",:", 0)
		For $i = 1 To $__atemp[0] Step 1
			If StringInStr($__atemp[$i], "sessionid") > 0 Then
				$__zbxSessionId = StringRegExpReplace($__atemp[$i + 1], '[^A-Za-z0-9_().+\%\-\s]+', "")
				ExitLoop
			EndIf
		Next
	EndIf
	Return $__zbxSessionId
EndFunc

; #############################################################################################################################################################
Func _zbx_Logout( $__zbxURL, $__zbxSessionId)
	Local $__zbxJSON = '{"jsonrpc": "2.0","method": "user.logout","params": [],"id": 42,"auth": "' & $__zbxSessionId & '"}'
	Local $__oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
	Local $__zbxResult = 0
	$__oHTTP.Option(4) = 13056 ; turns off ssl error messages and warnings
	$__oHTTP.Open("POST", $__zbxURL , False)
    $__oHTTP.Option("WinHttpRequestOption_SslErrorIgnoreFlags") = 0x3300
	$__oHTTP.Option(4) = 0x3300
	$__oHTTP.SetRequestHeader("Content-Type", "application/json-rpc")
	$__oHTTP.Send($__zbxJSON)
	Local $__oReceived = $__oHTTP.ResponseText
	Local $__oStatusCode = $__oHTTP.Status
;~ 	MsgBox(0, "_zbx_Logout", StringReplace($__oReceived,",", "," & @CRLF) & @CRLF & @CRLF & "Status Code: " & $__oStatusCode)
	If $__oStatusCode = 200 Then
		Local $__atemp = StringSplit($__oReceived, ",:", 0)
		For $i = 1 To $__atemp[0] Step 1
			If StringInStr($__atemp[$i], "result") > 0 Then
				$__zbxResult = StringRegExpReplace($__atemp[$i + 1], '[^A-Za-z0-9_().+\%\-\s]+', "")
				ExitLoop
			EndIf
		Next
	EndIf
	Return $__zbxResult
EndFunc

; #############################################################################################################################################################
Func _zbx_HostGetId($__zbxURL, $__zbxSessionId, $__zbxHostname)
	Local $__zbxJSON = '{"params":{"filter":{"name":"' & $__zbxHostname & '"},"output":["hostid"]},"jsonrpc": "2.0","method": "host.get","auth": "' & $__zbxSessionId & '","id":42}'
	Local $__oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
	Local $__zbxHostId = ""
	$__oHTTP.Open("POST", $__zbxURL , False)
    $__oHTTP.Option("WinHttpRequestOption_SslErrorIgnoreFlags") = 0x3300
	$__oHTTP.Option(4) = 0x3300
	$__oHTTP.SetRequestHeader("Content-Type", "application/json-rpc")
	$__oHTTP.Send($__zbxJSON)
	Local $__oReceived = $__oHTTP.ResponseText
	Local $__oStatusCode = $__oHTTP.Status
;~ 	MsgBox(0, "_zbx_HostGetId", StringReplace($__oReceived,",", "," & @CRLF) & @CRLF & @CRLF & "Status Code: " & $__oStatusCode)
	If $__oStatusCode = 200 Then
		Local $__atemp = StringSplit($__oReceived, ",:", 0)
		For $i = 1 To $__atemp[0] Step 1
			If StringInStr($__atemp[$i], "hostid") > 0 Then
				$__zbxHostId = StringRegExpReplace($__atemp[$i + 1], '[^A-Za-z0-9_().+\%\-\s]+', "")
				ExitLoop
			EndIf
		Next
	EndIf
	Return $__zbxHostId
EndFunc

; #############################################################################################################################################################
Func _zbx_HostSearchGetId($__zbxURL, $__zbxSessionId, $__zbxHostname)
;~ 	Local $__zbxJSON = '{"params":{"search":{"name":"' & $__zbxHostname & '"},"output":["hostid"]},"jsonrpc": "2.0","method": "host.get","auth": "' & $__zbxSessionId & '","id":42}'
	Local $__zbxJSON = '{"params":{"search":{"name":"' & $__zbxHostname & '"},"output":["hostid","host","name"]},"jsonrpc": "2.0","method": "host.get","auth": "' & $__zbxSessionId & '","id":42}'
	Local $__oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
	Local $__tempHostId[1][3] 	; [0][0] = Anzahl
								; [x][0] = Host-ID
								; [x][1] = Host name
								; [x][2] = Visible name
	Local $__zbxHostId[3] = [ "", "", ""] ; 0 = Host-ID, 1 = "Host name", 2 = "Visible name"
	$__oHTTP.Open("POST", $__zbxURL , False)
    $__oHTTP.Option("WinHttpRequestOption_SslErrorIgnoreFlags") = 0x3300
	$__oHTTP.Option(4) = 0x3300
	$__oHTTP.SetRequestHeader("Content-Type", "application/json-rpc")
	$__oHTTP.Send($__zbxJSON)
	Local $__oReceived = $__oHTTP.ResponseText
	Local $__oStatusCode = $__oHTTP.Status
;~ 	MsgBox(0, "$__oReceived", $__oReceived & @CRLF & "Status Code: " & $__oStatusCode)
;~ 	MsgBox(0, "_zbx_HostGetId", StringReplace($__oReceived,",", "," & @CRLF) & @CRLF & @CRLF & "Status Code: " & $__oStatusCode)
	If $__oStatusCode = 200 Then
		Local $__atemp = StringSplit($__oReceived, ",:", 0)
		_ArrayDisplay($__oReceived)
		For $i = 1 To $__atemp[0] Step 1
			If StringInStr($__atemp[$i], "hostid") > 0 Then
				$__tempHostId[0][0] = $__tempHostId[0][0] + 1
				ReDim $__tempHostId[ $__tempHostId[0][0] + 1 ][3]

				$__tempHostId[ $__tempHostId[0][0] ][0] = StringRegExpReplace($__atemp[$i + 1], '[^A-Za-z0-9_().+\%\-\s]+', "")
			EndIf
			If StringInStr($__atemp[$i], "host") > 0 Then
				$__tempHostId[ $__tempHostId[0][0] ][1] = StringRegExpReplace($__atemp[$i + 1], '[^A-Za-z0-9_().+\%\-\s]+', "")
			EndIf
			If StringInStr($__atemp[$i], "name") > 0 Then
				$__tempHostId[ $__tempHostId[0][0] ][2] = StringRegExpReplace($__atemp[$i + 1], '[^A-Za-z0-9_().+\%\-\s]+', "")
			EndIf
		Next
	EndIf
	If $__tempHostId[0][0] > 0 Then
		$__zbxHostId[0] = $__tempHostId[1][0]
		$__zbxHostId[1] = $__tempHostId[1][1]
		$__zbxHostId[2] = $__tempHostId[1][2]
	Else
		Return $__zbxHostId ; Ist hier ein Array!
	EndIf
	; Sortieren - Statt des ersten wollen wir den kürzesten Namen - und von diesen wird es der erste und damit älteste-
	For $i = 1 To $__tempHostId[0][0] Step 1
		If StringLen($__zbxHostId[1]) < StringLen($__zbxHostId[2]) Then
			If StringLen($__zbxHostId[1]) > $__tempHostId[$i][1] Then
						$__zbxHostId[0] = $__tempHostId[$i][0]
						$__zbxHostId[1] = $__tempHostId[$i][1]
						$__zbxHostId[2] = $__tempHostId[$i][2]
			EndIf
		Else
			If StringLen($__zbxHostId[2]) > $__tempHostId[$i][2] Then
						$__zbxHostId[0] = $__tempHostId[$i][0]
						$__zbxHostId[1] = $__tempHostId[$i][1]
						$__zbxHostId[2] = $__tempHostId[$i][2]
			EndIf
		EndIf
	Next
	Return $__zbxHostId ; Ist hier ein Array!
EndFunc

; #############################################################################################################################################################
Func _zbx_AddTemplateToHost($__zbxURL, $__zbxSessionId, $__zbxHostId, $__zbxTemplateId)
	Local $__zbxJSON = '{"jsonrpc":"2.0","method":"template.massadd","params":{"templates":[{"templateid":"' & $__zbxTemplateId & '"}],"hosts":[{"hostid":"' & $__zbxHostId & '"}]},"auth": "' & $__zbxSessionId & '","id":42}'
	Local $__oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
	Local $__zbxResult = ""
	$__oHTTP.Open("POST", $__zbxURL , False)
    $__oHTTP.Option("WinHttpRequestOption_SslErrorIgnoreFlags") = 0x3300
	$__oHTTP.Option(4) = 0x3300
	$__oHTTP.SetRequestHeader("Content-Type", "application/json-rpc")
	$__oHTTP.Send($__zbxJSON)
	Local $__oReceived = $__oHTTP.ResponseText
	Local $__oStatusCode = $__oHTTP.Status
;~ 	MsgBox(0, "_zbx_HostRemoveMaintenance", StringReplace($__oReceived,",", "," & @CRLF) & @CRLF & @CRLF & "Status Code: " & $__oStatusCode)
;~ 	ConsoleWrite("$__zbxJSON:" & @CRLF & $__zbxJSON & @CRLF)
;~ 	ConsoleWrite("$__oReceived:" & @CRLF & $__oReceived & @CRLF)
	If $__oStatusCode = 200 Then
		Local $__atemp = StringSplit($__oReceived, ",:", 0)
		For $i = 1 To $__atemp[0] Step 1
			If StringInStr($__atemp[$i], "templateids") > 0 Then
				$__zbxResult = StringRegExpReplace($__atemp[$i + 1], '[^A-Za-z0-9_().+\%\-\s]+', "")
				ExitLoop
			EndIf
		Next
	EndIf
	If $__zbxResult = "" Then
		$__zbxResult = $__oReceived
	EndIf
	Return $__zbxResult
EndFunc

; ###############################################################################################################################
; ###############################################################################################################################

; ****************************************
;    ##     ##    ###    #### ##    ##
;    ###   ###   ## ##    ##  ###   ##
;    #### ####  ##   ##   ##  ####  ##
;    ## ### ## ##     ##  ##  ## ## ##
;    ##     ## #########  ##  ##  ####
;    ##     ## ##     ##  ##  ##   ###
;    ##     ## ##     ## #### ##    ##
; ****************************************

; falls keine Parameter angegeben wurden die Hilfe ausgeben
If $CmdLine[0] = 0 And @Compiled = 1 Then
	_HilfeAusgeben()
	Exit 0
EndIf
;testen ob der Parameter 1 ist auf "/?" testen und ebenfalls Hilfe ausgeben
If @Compiled = 1 Then
	If $CmdLine[1] = "/?" Then
		_HilfeAusgeben()
		Exit 0
	EndIf
EndIf

; Die übergebenen Parameter auswerten und zuordnen
For $i = 1 To $CmdLine[0]
	If $CmdLine[$i] = "/AddVisibleName" Then
		; Auch das Feld "Visible Name" mit Durchsuchen
		$b_AddVisibleName = True
	ElseIf $CmdLine[$i] = "/AddHostID" Then
		$b_AddHostID = True
	ElseIf StringLeft($CmdLine[$i], StringLen("/AddTemplate=")) = "/AddTemplate=" Then
		$s_TemplateID = StringTrimLeft($CmdLine[$i], StringLen("/AddTemplate="))
		$b_AdditionalFunction = True
		If $i < $CmdLine[0] Then
			$s_HostID = $CmdLine[$i + 1]
			ExitLoop
		EndIf
	Else
		; Da es nur einen möglichen Parameter gibt muss es ansonsten der Computername sein den wir prüfen sollen
		$s_Computername = $CmdLine[$i]
;~ 		ConsoleWrite("$s_Computername: " & $s_Computername & @CRLF)
		ExitLoop
	EndIf
Next

; Nur für Tests
If @Compiled = 0 Then
	$b_AddVisibleName = True
	$s_Computername = "9KL001DC"
EndIf

; Haben wir einen Computernamen den wir abfragen sollen?
If $s_Computername = "" And $b_AdditionalFunction = False Then
	ConsoleWrite(_ANSI2OEM("FEHLER: Es wurde kein Computername / Hostname angegeben!" & @CRLF))
	Exit 1
EndIf

; Haben wir eine HostID?
If $s_HostID = "" And $b_AdditionalFunction = True Then
	ConsoleWrite(_ANSI2OEM("FEHLER: Es wurde keine Host-ID angegeben!" & @CRLF))
	Exit 1
EndIf

; ###############################################################################################################################
; Zugangsdaten zum Zabbix-Server erhalten:
; Fall 1: Die Zugansdaten stehen in der ZabbixPreventDuplicateHosts.ini
; ConsoleWrite($s_IniFile & @CRLF)
If FileExists($s_IniFile) = 1 Then
	$__zbxURL = IniRead($s_IniFile, "ZABBIXAPI", "URL", "")
	$__zbxUser = IniRead($s_IniFile, "ZABBIXAPI", "User", "")
	$__zbxPassword = IniRead($s_IniFile, "ZABBIXAPI", "Password", "")
EndIf

;Fall 2: Die Zugangsdaten stehen in den Umgebungsvariablen
If $__zbxURL = "" Then $__zbxURL = StringReplace(EnvGet("ZABBIXURL"), '"', '')
If $__zbxUser = "" Then $__zbxUser = StringReplace(EnvGet("ZABBIXUSER"), '"', '')
If $__zbxPassword = "" Then $__zbxPassword = StringReplace(EnvGet("ZABBIXPASSWORD"), '"', '')

; Fall 3: Die Zugangsdaten wurden per Registry gesetzt. Lesen mit 2 Versuchen wegen der 32/64Bit Geschichte (ja es gibt bessere Lösungen)
If $__zbxURL = "" Then
	If $__zbxURL = "" Then $__zbxURL = RegRead("HKLM\SOFTWARE\Zabbix", "URL")
	If $__zbxURL = "" Then $__zbxURL = RegRead("HKLM64\SOFTWARE\Zabbix", "URL")
	If $__zbxUser = "" Then $__zbxUser = RegRead("HKLM\SOFTWARE\Zabbix", "User")
	If $__zbxUser = "" Then $__zbxUser = RegRead("HKLM64\SOFTWARE\Zabbix", "User")
	If $__zbxPassword = "" Then $__zbxPassword = RegRead("HKLM\SOFTWARE\Zabbix", "Password")
	If $__zbxPassword = "" Then $__zbxPassword = RegRead("HKLM64\SOFTWARE\Zabbix", "Password")
EndIf

; Nun prüfen ob wir alles haben:
If $__zbxURL = "" Or StringLeft($__zbxURL, 4) <> "http" Then
	ConsoleWrite(_ANSI2OEM("FEHLER: URL zum Zabbix-Server nicht gesetzt." & @CRLF))
	Exit 1
EndIf
If $__zbxUser = "" Then
	ConsoleWrite(_ANSI2OEM("FEHLER: Benutzer für Anmeldung am Zabbix-Server nicht gesetzt." & @CRLF))
	Exit 1
EndIf
If $__zbxPassword = "" Then
	ConsoleWrite(_ANSI2OEM("FEHLER: Passwort für Anmeldung am Zabbix-Server nicht gesetzt." & @CRLF))
	Exit 1
EndIf
;~ MsgBox(0,"","$__zbxURL: " & $__zbxURL & @CRLF & "$__zbxUser: " & $__zbxUser & @CRLF & "$__zbxPassword: " & $__zbxPassword)
;~ ConsoleWrite("$__zbxURL: " & $__zbxURL & @CRLF & "$__zbxUser: " & $__zbxUser & @CRLF & "$__zbxPassword: " & $__zbxPassword & @CRLF)

; Soweit so gut - Melden wir uns am Zabbix-Serve an:
Global $__zbxSessionId = _zbx_Login( $__zbxURL, $__zbxUser, $__zbxPassword)
;~ ConsoleWrite("$__zbxSessionId: " & $__zbxSessionId & @CRLF)

If $__zbxSessionId = "" Then
	; Leider hat die Anmeldung nicht geklappt
	ConsoleWrite(_ANSI2OEM("FEHLER: Anmeldung am Zabbix-Server fehlgeschlagen. URL, Benutzername und Passwort prüfen!" & @CRLF))
	Exit 1
EndIf

;~ $s_Computername = "9KL001dct"

If $b_AdditionalFunction = False Then
	; Nun müssen wir den Host finden:
	;~ Global $__zbxHostId = _zbx_HostGetId($__zbxURL, $__zbxSessionId, $s_Computername)
	Global $__zbxHostData = _zbx_HostSearchGetId($__zbxURL, $__zbxSessionId, $s_Computername)

	;~ ConsoleWrite("ID .........: " & $__zbxHostData[0] & @CRLF)
	;~ ConsoleWrite("Host name...: " & $__zbxHostData[1] & @CRLF)
	;~ ConsoleWrite("Visible name: " & $__zbxHostData[2] & @CRLF)

	If $__zbxHostData[0] = "" Then
		ConsoleWrite("ZBXHOSTNOTFOUND" & @CRLF)
	Else
		$s_OutputText = $__zbxHostData[1]
		If $b_AddVisibleName = True Then
			$s_OutputText = $s_OutputText & ";" & $__zbxHostData[2]
		EndIf
		If $b_AddHostID = True Then
			$s_OutputText = $s_OutputText & ";" & $__zbxHostData[0]
		EndIf
		ConsoleWrite($s_OutputText & @CRLF)
	EndIf
Else
	Consolewrite(_ANSI2OEM("Füge Template " & $s_TemplateID & " zu Host " & $s_HostID & " hinzu ... " & @CRLF))
	Local $s_Result = _zbx_AddTemplateToHost($__zbxURL, $__zbxSessionId, $s_HostID, $s_TemplateID)
	If $s_Result = $s_TemplateID Then
		ConsoleWrite(_ANSI2OEM("Template Erfolgreich hinzugefügt!"))
	Else
		ConsoleWrite(_ANSI2OEM("FEHLER beim Template hinzufügen: " & $s_Result & @CRLF))
	EndIf
EndIf

; und wieder Abmelden:
If $__zbxSessionId <> "" Then
	_zbx_Logout( $__zbxURL, $__zbxSessionId)
EndIf

Exit 0




7 Kommentare


Kommentar hinzufügen
znilwiki freut sich über alle Kommentare. Sofern du nicht anonym bleiben möchtest, trage deinen Namen oder deine Email-Adresse ein oder melde dich an. Du kannst das Feld auch einfach leer lassen.