📜 ⬆️ ⬇️

Discovery + Zabbix API for Java

As the project develops, the infrastructure serving this project grows. Over time, there are many elements of the network, the parameters of which it is important to track online. To solve this problem, network elements must be added to the monitoring system.
You can add a new node to Zabbix in several ways:


Manually adding many new nodes is a routine task that takes a lot of time to solve. Well, if the new nodes will be 5 - 10. And if 50 - 100 and more? In this case, you will help the "Detection". After configuring the detection rules and actions for the detected nodes, Zabbix itself will create new detected nodes, connect the necessary templates, move the created node to the desired group. This method has a disadvantage.



This is what the detected and created node looks like. We see that the names of new nodes are put in accordance with the IP of the node, as well as the connection method - by default over IP. Detection allows you to get rid of the routine and long work to add new nodes, but the names of the nodes do not carry any semantic load. Also, the method of connecting via IP is inconvenient because when changing IP servers you have to change IP again on all nodes. The DNS connection method will solve the problem with changing IP. What can be done about it? You can write a data update script directly in the Zabbix database, which is not very correct.
')
And what if you rename the name of the nodes and change the connection settings through the API? To work with Zabbix API, libraries have been written for different languages, which can be viewed here . I chose a library for Java, created a project in IDEA, connected the library and started studying the documentation from the official site for Zabbix v.2.0.8 .
What objects is the node?



As shown in the figure, the fields of interest to us belong to two objects: Host and Host interface. To solve the problem you need:


The library for working with Zabbix API for Java is described as an example of work, using it, we try to solve our problem.

The first thing that needs to be done is to establish a connection to the Zabbix server.

String url = "http://ZabbixServer/zabbix/api_jsonrpc.php"; zabbixApi = new DefaultZabbixApi(url); zabbixApi.init(); 

Then log in to the Zabbix server as a user.

 boolean login = zabbixApi.login("login", "password"); 

Now you need to find the node ID, rename and reconfigure the agent connection. The documentation for the node search method provides an example query. Let us see what it means.

 { "jsonrpc": "2.0", "method": "host.get", //  API "params": { //   "output": "extend", //  ,     //            "filter": { //  ,    "host": [ //   Host:    "Zabbix server", //    "Linux server" ] } }, "auth": "038e1d7b1735c6a5436ee9eae095879e", "id": 1 } 

The result of this example will be the receiving of Host objects with the technical names “Zabbix server” and “Linux server” and the full sets of properties of these nodes.

Using this example, we form the request. In the downloaded library there is a query designer to which you need to pass the method name and query parameters. In the example above, we see that the method needs to pass the "host" parameter with the current node name as the value of the "filter" parameter.

 JSONObject filter = new JSONObject(); filter.put("host", “127.0.0.1”); Request request = RequestBuilder.newBuilder() .method("host.get") .paramEntry("filter", filter) .build(); 

To call the generated method and get an answer, call the call () method.

 JSONObject response = zabbixApi.call(request); 

The resulting answer will look like this:

 { "id":2, "jsonrpc":"2.0", "result":[ { "hostid":"10503" } ] } 

To display the received answer on the screen, it is enough to transfer the received answer to the println () method ;

 System.out.println(response); 

We get the node ID from the response received:

 String hostid = response.getJSONArray("result").getJSONObject(0).getString("hostid"); 

Node ID found. Using it, we can rename the node. To do this, call the method "host.update" with the parameters "hostid", "host", "name".

 request = RequestBuilder.newBuilder() .method("host.update") .paramEntry("hostid", hostid) .paramEntry("host", "localhost") .paramEntry("name", "localhost") .build(); response = zabbixApi.call(request); 

What happened?



Half of the task is completed. It remains to find the object Host interface and change its properties. To search for the Host interface object, use the found node identifier.

 request = RequestBuilder.newBuilder() .method("hostinterface.get") .paramEntry("hostids", new String [] {hostid}) .build(); response = zabbixApi.call(request); interfaceid = response.getJSONArray("result") .getJSONObject(0).getString("interfaceid"); 

To the found object we change the properties “dns”, “useip”.

 request = RequestBuilder.newBuilder() .method("hostinterface.update") .paramEntry("interfaceid", interfaceid) .paramEntry("dns", "localhost") .paramEntry("useip", 0) .build(); response = zabbixApi.call(request); 



The task is performed for one node, but there are many more. To solve this problem, I wrote a small utility that reads a text file of the form:

 HOSTNAME localhost 

Receives IP and changes node properties according to the algorithm described above. Below is a listing.

 import com.alibaba.fastjson.JSONObject; import io.github.hengyunabc.zabbix.api.DefaultZabbixApi; import io.github.hengyunabc.zabbix.api.Request; import io.github.hengyunabc.zabbix.api.RequestBuilder; import java.io.File; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class Main { public static String EXECUTION_DIR = new File("").getAbsolutePath(); public static String fileHostParams = EXECUTION_DIR + "/HostName.txt"; public static DefaultZabbixApi zabbixApi; /*     */ public static void main(String[] args) throws Exception { String url = "http://ZabbixServer/zabbix/api_jsonrpc.php"; try { zabbixApi = new DefaultZabbixApi(url); zabbixApi.init(); } catch (Exception e) { e.printStackTrace(); } boolean login = zabbixApi.login("login", "password"); Map<String, String> params = readhostNameFromFile(); String hostid = ""; String interfaceid = ""; for (Map.Entry hostParam : params.entrySet()) { String hostName = hostParam.getKey().toString(); String ip = hostParam.getValue().toString(); //   Request request = RequestBuilder.newBuilder() .method("host.exists") .paramEntry("host", ip) .build(); JSONObject response = zabbixApi.call(request); boolean hostexist = response.getBooleanValue("result"); if (hostexist) { //   JSONObject filter = new JSONObject(); filter.put("host", ip); request = RequestBuilder.newBuilder() .method("host.get") .paramEntry("filter", filter) .build(); System.out.println(request); response = zabbixApi.call(request); hostid = response.getJSONArray("result").getJSONObject(0).getString("hostid"); //  request = RequestBuilder.newBuilder() .method("host.update") .paramEntry("hostid", hostid) .paramEntry("host", hostName) .paramEntry("name", hostName) .build(); zabbixApi.call(request); //   request = RequestBuilder.newBuilder() .method("hostinterface.get") .paramEntry("output", new String[]{"interfaceid"}) .paramEntry("hostids", hostid) .build(); response = zabbixApi.call(request); interfaceid = response.getJSONArray("result").getJSONObject(0).getString("interfaceid"); //   request = RequestBuilder.newBuilder() .method("hostinterface.update") .paramEntry("interfaceid", interfaceid) .paramEntry("dns", hostName.toLowerCase()) .paramEntry("useip", 0) .build(); zabbixApi.call(request); } else { System.out.println("Host with name - " + ip + " not found;"); } } } /** *    DNS  * @return maping <hostName, IP> */ public static Map<String, String> readhostNameFromFile() throws Exception { Map<String, String> hostParams = new HashMap<>(); File file = new File(fileHostParams); Scanner sc = new Scanner(file); //Ignor header from file sc.nextLine(); while (sc.hasNext()) { String[] line = sc.nextLine(); hostParams.put(line[0], getIPbyHostName(line[0])); } return hostParams; } /** * Return IP address by dns host name * @param hostName * @return IP */ public static String getIPbyHostName(String hostName) { String ipAddr = ""; try { InetAddress inetAddr = InetAddress.getByName(hostName); byte[] addr = inetAddr.getAddress(); for (int i = 0; i < addr.length; i++) { if (i > 0) { ipAddr += "."; } ipAddr += addr[i] & 0xFF; } } catch (UnknownHostException e) { System.out.println("Host not found: " + e.getMessage()); } return ipAddr; } } 

I removed most of the error handlers and conditions from the listing to show the implementation of the task. The described method can help solve an existing problem with the name of the detected nodes.

Someone can say that it would be easier, using the API, to immediately create nodes with all the necessary parameters. And I agree. By slightly modifying the listing, you can rewrite the code not to change the properties, but to create nodes with the necessary parameters without using Zabbix “detection”. So I will do in the future.

Source: https://habr.com/ru/post/277027/


All Articles