<img height="1" width="1" style="display:none;" alt="" src="https://px.ads.linkedin.com/collect/?pid=1110556&amp;fmt=gif">
November 29, 2021

Employing RESTmon to Ingest Zabbix Data: Part 2

by: Saurabh Sharma

 

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Zabbix Instance

 

In the first skill builder in this series, we offered step-by-step instructions for setting up RESTmon.

In this skill builder, the second of this two-part series, we’ll offer instructions for using a deployed RESTmon instance to feed information into DX Operational Intelligence.

For a tutorial video you can refer to this course in the Broadcom Enterprise Software Academy. 

Prerequisites

1. Zabbix instance deployed

We will use the Zabbix instance (zabbix.broadcom.com) to create a schema using a live problem.

For our example, we will try to use RESTmon’s PUSH schema to pass information from Zabbix to DX Operational Intelligence.

 

Step 1: Define a Media Type

This step will allow us to create the media type that will be used for RESTmon.

Media types are the delivery channels used for sending notifications and alerts from Zabbix. For our example, we will be using webhooks.

Let us create a media type for RESTmon.

Step 1.1 Navigate to Administration > Media types

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Click “Create media type”

Step 1.1.1 Define the Name and Type

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

For name, use “Message for Restmon”. For type, use “ Webhook”.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2
Define the webhook variables as attributes key and value pairs (use the existing value as is). The macros used are from the Zabbix official documentation.

Points to Remember

restmon_endpoint

In this case, it is the endpoint URL I am using.

http://restmon.demo:30125/restmon/api/v1/logs?profileName=zabbix&schemaName=zabbix

restmon_password

The configured password

restmon_username

The username configured to access the swagger-ui

 

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2
Define the script by clicking the edit button. (You can refer to more Webhook Script examples here.)


These scripts are based on plain JavaScript.


try {
    // variables declared
    var params = JSON.parse(value), //JSONObject parse
        request = new CurlHttpRequest(),
        data,
        response;

    // Information about the event
    data = {
        event_id: params.event_id,
        event_name: params.event_name,
        event_severity: params.event_severity,
        host_name: params.host_name,
        host_ip: params.host_ip,
        event_status: params.event_status
    };

    data = JSON.stringify(data);

    Zabbix.Log(4, '[ DX-RESTmon Webhook ] Sending request: ' + params.restmon_endpoint + '\n' + data);

    request.AddHeader('Content-Type: application/json')
    request.AddHeader('Authorization: Basic ' + btoa(params.restmon_username + ':' + params.restmon_password));
    response = request.Post(params.restmon_endpoint, data);

    Zabbix.Log(4, '[ DX-RESTmon Webhook ] Received status code ' + request.Status() + '\n');

    if (request.Status() != 200) {
        throw request.Status();
    }
    return 'OK';
}
catch (error) {
    Zabbix.Log(4, '[ DX-RESTmon Webhook ] DX-RESTmon notification failed: ' + error);
    throw 'DX-RESTmon notification failed: ' + error;
}

Step 1.1.2 Define the Message Template

You can learn more about message templates in the Zabbix documentation.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2
Step 1.1.3 Message Options

Use the values as shown in the image below. The default retry attempts are 3. You can change it to whatever suits your case best.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Step 1.1.4 Test Media Type

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

If you test this Media type and if the RESTmon configuration is correct, you will see a log message in the restmon.log.

2021-10-16 09:42:24,957 [http-nio-8080-exec-8] DEBUG ProfileHandler:1611 - zabbix~~zabbix: Received payload - {
  "event_id": "{EVENT.ID}",
  "event_name": "{EVENT.NAME}",
  "event_severity": "{EVENT.SEVERITY}",
  "host_name": "{HOST.NAME}",
  "host_ip": "{HOST.IP}",
  "event_status": "{EVENT.STATUS}"
}

In a real-time scenario, you should receive a message like that below.

{
  "event_id": "346",
  "event_name": "Zabbix agent is not available (for 3m)",
  "event_severity": "Average",
  "host_name": "lvndev011524.bpc.broadcom.net",
  "host_ip": "10.74.146.11",
  "event_status": "PROBLEM"
}

Message Received at RESTmon

We will use the values from this JSON response. For example, we can refer the “event_name” from the example above using $['event_name']. Similarly, we can assign “host_name” using $[`host_name`].

Once the media type has been defined and configured, go to Administration > Users and assign the webhook media to the existing user. Ideally, the recommendation is for a dedicated user that represents the webhook.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Configuring: Alert Actions

Actions determine which notifications should be sent via the webhook (more details are available in the Zabbix documentation). They can be defined in response to events of all supported types. In our case, we will be using Trigger Actions.

Adding Action

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Navigate to Actions > Trigger actions and click “create actions.”

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Define Name

Use any meaningful name that you want to give to this action.

Define Conditions

Conditions are set when configuring an action. (For more information, refer to official Zabbix documentation.)

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Finally, the action will appear like the image below.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2
Add Operations

In this step, you can select the “Send Only to” option as well. Depending on your requirements, you can either can select a specific media type or choose all.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2


RESTmon schema guide

RESTmon has two building blocks:

  • Profile. Every product that RESTmon works on has its dedicated profile. A profile is a JSON document that has the connection information and polling details.
  • Schema. Schema is a JSON document that contains the API details and parsing logic that is written in JavaScript. It has a defined basic structure

Adding a Profile

Let’s add the profile for the Zabbix product.

Step 1: Adding Profile: Zabbix

{
  "profile": {
      "name": "zabbix",
      "active": "yes",
      "schema": "zabbix",
      "streaming": "yes",
      "inventory_topology_fullsync_interval_mins": "1440",
      "topology_ttl_mins": "2880",
      "polling_interval_secs": 1,
      "batch_size": 9000,
      "batch_wait_time_milli": 3000
    },
    "monitored_groups": {
          "Events": "yes",
          "Topology": "yes"
     }
}

 

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Step 1.1: Response

{
  "Status": "profile is added with profileName zabbix and schemaName zabbix"
}

 

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Step 1.2: Check the Profile Has Been Added by Listing

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

The response will show the profile added.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Step 2: Add/Upload a Schema

Once the profile has been, it is time add a schema. You can add a schema via the SwaggerUI or manually create a file in the config directory.

Step 2.1 Upload Schema Template

This is the foundation step, which we will keep adding to.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

If the upload is successful, it will create a file “zabbix_schema.json” in the schema folder.


Read more about definition here.


Step 2.2: Response of Upload

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Look in the mounted directory. The file contents will also confirm settings.

> cat zabbix_schema.json

{
  "zabbix": {
    "definition": {
      "resource_category": "",
      "auth": "",
      "uploadedBy": "TENANT",
      "updatedBy": "",
      "version": "2.1",
      "xml_ns": "",
      "name": "zabbix",
      "type": ""
    },
    "urls": [],
    "topology": [],
    "alarms": []
  }
}

Step 3: Topology

To create a service and use the AIOps platform’s analytics capabilities, the entities must be ingested to DX Operational Intelligence. The collection of these entities and the relationship between them is represented as a graph (TAS model) for the given monitored product.

Let’s start by adding an empty block in topology (Step 2.1).

“topology” : [{
    }
]

The contents should be similar to the following.

{
        "xml_ns": "",
        "url": "",
        "isDeltaTopology": "true",
        "group": "Topology",
        "layer": "CUSTOM",
        "attributes": {
          "oi": {          
          }
        }
}

Components
  • isDeltaTopology. Enables calculation of only delta topology.
  • group. Group name to be monitored. Please refer to the profile definition we enabled above (Topology, Events).
  • layer. Here, the association has to be applied can be CUSTOM, INFRASTRUCTURE, INFRASTRUCTURE_UIM

To correlate the ingested third-party data with the Broadcom products, you must set the normalized attributes and the correlation attributes at the tenant level in the metadata vertex for a tenant.

Next, it is time to fill in some attributes.

“oi”—DX Operational Intelligence Attributes

For topology mapping you need to define the following attributes.

ci_unique_id

Unique element being monitored

$[‘host_name’]

type

You can find more in the official documentation but to name a few:

EXTERNAL, BUSINESSTRANSACTION, EJB, EJBCLIENT, DATABASE, HOST etc

HOST

product

Indicates the product name—in our case we will use a static value: “Zabbix Broadcom”

Zabbix Broadcom

name

Name of the topology entity

$[‘host_name’]

hostname

Name of the host where the entity is deployed

$[‘host_name’]

ipAddresses

IP addreses that is linked to the entity

$[‘host_ip’]


Referring to the sample JSON response we got in the RESTMon (refer to sample message above), we will use the JSON parser reference variables to fill in the values.

  "oi": {
    "ci_unique_id": "$['host_name']",
    "type": "HOST",
    "product": "Zabbix Broadcom",
    "name": "$['host_name']",
    "hostname": "$['host_name']",
    "Display Name": "$['host_name']",
    "ipAddresses": "$['host_ip']"
  }

You can use the PUT API from Swagger to update these schemas.

POST /restmon/api/v1/schema/{schemaName}

 

{
  "zabbix": {
    "definition": {
      "resource_category": "Zabbix Product Streaming schema.",
      "auth": "",
      "uploadedBy": "TENANT",
      "updatedBy": "Saurabh Sharma",
      "version": "2.1",
      "xml_ns": "",
      "name": "zabbix",
      "type": ""
    },
    "urls": [],
    "topology": [
      {
        "xml_ns": "",
        "url": "",
        "isDeltaTopology": "true",
        "group": "Topology",
        "layer": "CUSTOM",
        "attributes": {
          "oi": {
            "ci_unique_id": "$['host_name']",
            "type": "HOST",
            "product": "Zabbix Broadcom",
            "name": "$['host_name']",
            "hostname": "$['host_name']",
            "Display Name": "$['host_name']",
            "ipAddresses": "$['host_ip']"
          }
        }
      }
    ],
    "alarms": []
  }
}

 

If you log into DX Operational Intelligence and go to Monitored Inventory you can see the entity ingested.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

In the RESTmon logs, you will notice a log entry similar to the message below.

2021-10-17 14:50:42,259 [pool-3-thread-10] DEBUG SendToTAS:755 - body:  "graph": {
    "vertices": [
      {
        "externalId": "CUSTOM:6D85F3FC-2EF8-4471-8804-BE3B74D6785C$$Zabbix Broadcom$$lvndev011524.bpc.broadcom.net",
        "attributes": {
          "ci_unique_id": " XXXXXXXXX.broadcom.net ",
          "hostname": " XXXXXXXXX.broadcom.net ",
          "hostNames": [
            "XXXXXXXXX.broadcom.net"
          ],
          "type": "HOST",
          "product": "Zabbix Broadcom",
          "name": " XXXXXXXXX.broadcom.net ",
          "Display Name": " XXXXXXXXX.broadcom.net ",
          "ipAddresses": [
            "10.74.146.11"
          ]
        },
        "startTime": 1634396921477,
        "endTime": 1634655042258
      },

The next step is to add correlation to the topology block.


You can attain a rule-based edge creation by defining the correlation metadata about the different DX OI monitored products.


There are two types of correlation that are available

  1. Compaction
  2. Association

Why do we need it?

It is useful when two different vertices from two different sources depict the same object. Refer to the original example mentioned in the TechDocs. [link needs updating]

{
        "xml_ns": "",
        "url": "",
        "isDeltaTopology": "true",
        "group": "Topology",
        "layer": "CONNECTOR_METADATA",
        "attributes": {
          "oi": {
            "ci_unique_id": "Zabbix_HOST",
            "name": "Zabbix Compaction Rule",
            "type": "SERVICE_UI_CONFIG",
            "compactionRules": [
              {
                "sourceTasVertices": {
                  "attributeFilters": [
                    {
                      "attributeName": "product",
                      "attributeValues": [
                        "Zabbix Broadcom "
                      ],
                      "operator": "IN"
                    },
                    {
                      "attributeName": "type",
                      "attributeValues": [
                        "HOST"
                      ],
                      "operator": "IN"
                    }
                  ],
                  "layer": "CUSTOM"
                },
                "matchingAttributeNames": [
                  "ipAddresses",
                  "macAddresses",
                  "hostname"
                ],
                "matchingAttributeTypes": [
                  "IP_ADDRESS",
                  "MAC_ADDRESS",
                  "ACN_HOST"
                ]
              }
            ]
          }
        }
      }

Key Points

ci_unique_id

Unique identifier for the defined rule

layer

Indicates the TAS layer to which the metadata is to be ingested – CONNECTOR_METADATA

name

Description about the rule

type

Type of the TAS vertex – SERVICE_UI_CONFIG

compactionRules

Array of rules

sourceTasVertices

Vertices on which compaction will be applied

attributeFilters

An array of possible filters. In our case we use two:

                   {
                     "attributeName": "product",
                     "attributeValues": [
                       "Zabbix Broadcom "
                     ],
                     "operator": "IN"
                   },

and

                 {
                     "attributeName": "type",
                     "attributeValues": [
                      "HOST"
                     ],
                     "operator": "IN"
                   }

attributeName: `type`, `product`

attributeValues: The possible values

operator: How to compare

layer

For RESTmon this value has to be CUSTOM

matchingAttributeTypes

Which attributes can be used for comparing with this attribute in this product.

Time to add an empty alarm section to the Schema.

Step 4: Alarms

Read more about alarms in the official documentation

{
  "xml_ns": "",
  "url": "",
  "group": "",
  "attributes": {
    "oi": {
      "status": "Alarm Status can be new, updated or closed",
      "timestamp": "Alarm timestamp",
      "host": "Hostname to attach Alarm too",
      "alarmType": "Alarm Type name",
      "product": "",
      "product_version": "",
      "summary": "",
      "severity": "",
      "severity_conversion": "",
      "metric_name": "",
      "metric_type": "",
      "configuration_item": "",
      "configuration_item_type": "",
      "ci_unique_id": "",
      "message": "",
      "alarm_unique_id": ""
    }
  }
}

 

group

Replace with a Group name to enable or disable collection using profile in RESTmon.json

alarmType

Type of alarm. It is monitoring a host so - `Infra`

alarm_unique_id

Unique value identifying the Alarm

product

Zabbix Broadcom

product_version

Version of the product – 5.0

summary

Information about the alarm - $[‘event_name’]

severity

It is used by severity conversion

severity_conversion

Mapping based on severity level

metric_name

Not used

metric_type

Not used

configuration_item

CI of the entity against which alarm is issuedNot Used

configuration_item_type

Type of CINot Used

host

Hostname = $[‘host_name’]

message

Content of alarm = $[‘event_name’]

attributes

"attributes": {
                    "oi": {
                        "alarmType": "Infra",
                        "alarm_unique_id": "$['event_id']",
                        "ci_unique_id": "$['host_name']",
                        "configuration_item": "",
                        "configuration_item_type": "",
                        "host": "$['host_name']",
                        "message": "$['event_name']",
                        "metric_name": "",
                        "metric_type": "",
                        "product": "Zabbix Broadcom",
                        "product_version": "5.0",
                        "severity": "$['event_severity']",
                        "severity_conversion":
"Disaster:Critical,High:Major,Average:Minor,Default:Information",
                        "status": "#(function() {var data=[]; if(root.event_status=='RESOLVED') { data.push('closed');} else { data.push('new');} return data;})();",
                        "summary": "$['event_name']",
                        "timestamp": "%timestamp"
                    }
                }

Status Field

The payload comes as we had defined in the script added to the media type.

response = request.Post(params.restmon_endpoint, data);

To define the status, we will employ Java Script to evaluate the payload and assign it as “new” or “closed.”

If you are new to writing this script, you can use any browser (console) to evaluate the payload and return the value as desired.

For our case, I am using a Firefox browser and will simulate the payload as a variable before using the final script.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Let’s define a function “fn()” in the console, which can be reached by using the web developer tool.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

We will refer the log as it comes in to RESTmon.

2021-10-18 07:14:37,248 [http-nio-8080-exec-10] DEBUG ProfileHandler:1611 - zabbix~~zabbix: Received payload - {"event_id":"417","event_name":"Zabbix
server: Utilization of discoverer processes over 75%","event_severity":"High","host_name":"XXXXXXX.
broadcom.net","host_ip":"10.74.146.11","event_status":"RESOLVED"}

The payload is formatted as indicated below.

{
  "event_id": "417",
  "event_name": "Zabbix server: Utilization of discoverer processes over 75%",
  "event_severity": "High",
  "host_name": "XXXXXXX. broadcom.net",
  "host_ip": "10.74.146.11",
  "event_status": "RESOLVED"
}

Based on the event_status in the data, we will define our script.

Script

Step 1: Define function.

function fn() {

Step 2: Define local data variable.

var i = ‘{
  "event_id": "417",
  "event_name": "Zabbix server: Utilization of discoverer processes over 75%",
  "event_severity": "High",
  "host_name": "XXXXXXX. broadcom.net",
  "host_ip": "10.74.146.11",
  "event_status": "RESOLVED"
}’;

Step 3: Parse into a JSON object.

var r = JSON.parse(i);

Step 4: Define a local variable to hold the result.

Var d = [];

Step 5: Do a conditional check.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

if (r.event_status == ‘RESOLVED’) {
        d.push(‘closed’);
} else {
        d.push(‘new);
}
return d;

Close the function.

};

You can call this function from the console by invoking “fn();” and it should return the variable “d” which you can check.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

You can also use console.log to check the status on the console itself while evaluating.

Change the values to see both “closed” and “new” status.

If required, you can also use JJS to do the same.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2


Refer to Parsing methods for more details.


Finally, the status field is updated as indicated below.

"status": "#(function() { var data=[]; if(root.event_status=='RESOLVED') { data.push('closed'); } else { data.push('new'); } return data; }) ();"

This completes your schema. Next,  upload and restart the pod or deactivate/activate the schema to let RESTmon start processing it.

Complete Schema

{
  "zabbix": {
    "definition": {
      "resource_category": "",
      "auth": "",
      "uploadedBy": "TENANT",
      "updatedBy": "",
      "version": "2.1",
      "xml_ns": "",
      "name": "zabbix",
      "type": ""
    },
    "urls": [],
    "topology": [
      {
        "xml_ns": "",
        "url": "",
        "isDeltaTopology": "true",
        "group": "Topology",
        "layer": "CUSTOM",
        "attributes": {
          "oi": {
            "ci_unique_id": "$['host_name']",
            "type": "HOST",
            "product": "Zabbix Broadcom",
            "name": "$['host_name']",
            "hostname": "$['host_name']",
            "Display Name": "$['host_name']",
            "ipAddresses": "$['host_ip']"
          }
        },
        "fieldId": "AB822A2CE81F4FA0BAB2AD1F802A2D57"
      },
      {
        "xml_ns": "",
        "url": "",
        "isDeltaTopology": "true",
        "group": "Topology",
        "layer": "CONNECTOR_METADATA",
        "attributes": {
          "oi": {
            "ci_unique_id": "Zabbix_HOST",
            "name": "Zabbix Compaction Rule",
            "type": "SERVICE_UI_CONFIG",
            "compactionRules": [
              {
                "sourceTasVertices": {
                  "attributeFilters": [
                    {
                      "attributeName": "product",
                      "attributeValues": [
                        "Zabbix Broadcom"
                      ],
                      "operator": "IN"
                    },
                    {
                      "attributeName": "type",
                      "attributeValues": [
                        "HOST"
                      ],
                      "operator": "IN"
                    }
                  ],
                  "layer": "CUSTOM"
                },
                "matchingAttributeNames": [
                  "ipAddresses",
                  "macAddresses",
                  "hostname"
                ],
                "matchingAttributeTypes": [
                  "IP_ADDRESS",
                  "MAC_ADDRESS",
                  "ACN_HOST"
                ]
              }
            ]
          }
        },
        "fieldId": "C92557D0FD844CB8B40D5386DA7FE4D0"
      }
    ],
    "alarms": [
      {
        "xml_ns": "",
        "url": "",
        "group": "Events",
        "attributes": {
          "oi": {
            "status": "#(function() {var data=[]; if(root.event_status=='RESOLVED') { data.push('closed');} else { data.push('new');} return data;})();",
            "timestamp": "%timestamp",
            "host": "$['host_name']",
            "alarmType": "Infra",
            "product": "Zabbix Broadcom",
            "product_version": "5.0",
            "summary": "$['event_name']",
            "severity": "$['event_severity']",
            "severity_conversion": "Disaster:Critical,High:Major,Average:Minor,Default:Information",
            "metric_name": "",
            "metric_type": "",
            "configuration_item": "",
            "configuration_item_type": "",
            "ci_unique_id": "$['host_name']",
            "message": "$['event_name']",
            "alarm_unique_id": "$['event_id']"
          }
        },
        "fieldId": "5A345F279C4E4BE68AAEED224AB4A9AE"
      }
    ],
    "inventory": [],
    "metrics": [],
    "calculated_methods": [],
    "calculated_metrics": [],
    "groups": [],
    "change_events": []
  }
}


If the alarm is processed successfully, you will see a log similar to that below.

{
  "documents" : [ {
    "header" : {
      "tenant_id" : "6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
      "product_id" : "ao",
      "doc_type_id" : "itoa_alarms_custom",
      "doc_type_version" : "1",
      "unique_id" : "$['alarm_unique_id']"
    },
    "body" : [ {
      "timestamp" : "2021-10-16T15:08:44+0000",
      "startTime" : "2021-10-16T15:08:44+0000",
      "severity" : "major",
      "host" : "XXXXXXXXXXXXXXXX.broadcom.net",
      "alarmType" : "Infra",
      "product" : "Zabbix Broadcom",
      "product_version" : "5.0",
      "summary" : "Zabbix server: Utilization of discoverer processes over 75%",
      "ci_unique_id" : "XXXXXXXXXXXXXXXXX.broadcom.net",
      "message" : "Zabbix server: Utilization of discoverer processes over 75%",
      "alarm_unique_id" : "56a73c0e2e0184c4b984e9bda701dca9",
      "status" : "new"
    } ]
  } ]
}


In DX Operational Intelligence, you can log in and see any alarms pushed.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Polling Schema

You can also build a polling schema in the same way you created the streaming schema.

There are some variations that you must be cautious about, which are covered briefly in the sections below.

Things You Must Know

  1. Zabbix API and how it works. You can use Postman, Insomnia, or any other tool to invoke these URLs and see them in action before you embed them in the schema.
  2. How HTTP POST, GET, and PUT methods work and pass payloads.
  3. Using JSON path parser to build your expressions.

Polling data from third-party applications using REST APIs.


In general, the Zabbix API allows you to retrieve and modify the configuration of Zabbix and provides access to historical data. (Read more on this  in the Zabbix documentation [v4.0])

Let’s try and define a poll schema for Zabbix. (Refer to the link

Profile: zabbixbroadcom

Attribute

Description

name

zabbixbroadcom

active

No (initial value)

schema

zabbixbroadcom

polling_interval_secs

We will use 2 minutes (120)

 

Please compare the difference between this view and the streaming profiles defined in Step 1.

Add the section “restapiconnectdetails” which is a mandatory section for a polling schema.

Attribute

Description

type

https

hostname

zabbix.broadcom.com

username

Saurabh

password

Password value for the username

 

      "restapiconnectdetails" : {
        "type" : "http",             You can use http or https here
        "hostname" : "zabbix.broadcom.com",      The machine you are trying to connect that Hosts the zabbix instance
        "port" : "80",                        The port it is listening on
        "authentication" : "none",   Refer to link
        "username" : "Saurabh",      
        "password" : "Password",
        "realmdomain" : "",
        "token" : "",
        "httptimeout" : "30000",
        "checkcert" : "no"
      }

 

In my example, the profile looks like the image below.

{
      "profile" : {
        "name" : "zabbixbroadcom",   You can choose any name
        "active" : "no",             Will activate once I define the schema and other values
        "schema" : "zabbixbroadcom",  Name of the schema
        "polling_interval_secs" : "120",    Interval for poll
        "inventory_topology_fullsync_interval_mins" : "1440",
        "topology_ttl_mins" : "2880"
      },

      "restapiconnectdetails" : {
        "type" : "http",
        "hostname" : "zabbix.broadcom.net",
        "port" : "80",
        "authentication" : "none",
        "username" : "<Admin>",
        "password" : "<Password>",
        "realmdomain" : "",
        "token" : "",
        "httptimeout" : "30000",
        "checkcert" : "no"
      },
      "monitored_groups" : {
        "Events" : "yes",
        "Topology" : "yes",
        “Items”: “yes”
      }
    }

 

With the definition in place, let’s create the schema or UPLOAD using the Swagger UI.

Schema: zaabixbroadcom_schema.json

Next, let’s work out the schema.

It has a section “urls”. While we did not need this in the streaming area, this is required to pull information from Zabbix.

Template “definition”

{
    "zabbixbroadcom": {
      "urls": [],
        "alarms": [],
        "calculated_methods": [],
        "calculated_metrics": [],
        "definition": {
            "auth": "none",
            "name": "zabbixbroadcom",
            "resource_category": null,
            "type": "https",
            "updatedBy": "Saurabh Sharma",
            "uploadedBy": "TENANT",
            "version": "21.3.1",
            "xml_ns": ""
        },
        "groups": [],
        "inventory": [],
        "metrics": [],
        "topology": []
    }
}

URLs define the REST endpoint, which you can specify to have invoked to gather information. (More details are available here

Posting Schema

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

If you are invoking via Swagger, you should see an appropriate response as follows.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

As per the Zabbix documentation, before you can access any data inside of Zabbix, you'll need to log in and obtain an authentication token. 


Refer to the Zabbix documentation here


1. You need to invoke the following URL: zabbix/api_jsonrpc.php

The Zabbix API allows you to programmatically retrieve and modify the configuration of Zabbix and provides access to historical data.

2. The payload is as defined in the following example.

{
    "jsonrpc": "2.0",
    "method": "user.login",
    "params": {
        "user": "Admin",
        "password": "<password>"
    },
    "id": 1,
    "auth": null
}

 

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

3. In my case, the output is as follows.

{
       "jsonrpc": "2.0",
        "result": "2e7f1287dc4fac1a246bd66fab47ecbe",
        "id": 1
}

The result identifies the token to be used in subsequent calls. We will use it as tokens. (See the section below.)

  • jsonrpc. The version of the JSON-RPC protocol.
  • result. The data returned by the method (`user.login`)
  • id. Identifier of the corresponding request.

4. Use the Result: $[‘result’]

Pass it to the next step for which you need a JSON path builder, such as https://jsonpath.com/

"urls": [
            {
                "id": "login",
                "body": {
                    "id": 1,
                    "jsonrpc": "2.0",
                    "method": "user.login",
                    "params": {
                        "password": "%password",
                        "user": "%username"
                    }
                },
                "httpHeaders": {
                    "Content-Type": "application/json-rpc"
                },
                "method": "post",
                "src": "",
                "tokens": {
                    "usertoken": "$['result']"
                },
                "url": "/zabbix/api_jsonrpc.php",
                "var": "",
                "xml_ns": ""
            },
            {
                "id": "hosts",
                "body": {
                    "auth": "%usertoken",
                    "id": 1,
                    "jsonrpc": "2.0",
                    "method": "host.get",
                    "params": {
                        "output": [
                            "hostid",
                            "host"
                        ],
                        "selectInterfaces": [
                            "interfaceid",
                            "ip",
                            "dns"
                        ]
                    }
                },
                "httpHeaders": {
                    "Content-Type": "application/json-rpc"
                },
                "method": "post",
                "src": "login",
                "url": "/zabbix/api_jsonrpc.php",
                "var": "",
                "xml_ns": ""
            }
]

The values defined are as follows.

Attribute

Description

id

Unique name: User Identifier that helps to identify the section. In my case the first one is called login, as I am fetching the token.

method

HTTP POST method: “post”

src

Identifies sibling URL, which for login is none so kept it as empty

url

URL to invoke: /zabbix/api_jsonrpc.php

Read more in the Zabbix documentation

tokens

Block that defines the `usertoken` that will be referenced in other blocks.

httpHeaders

Headers required for the request

"httpHeaders": {
                    "Content-Type": "application/json-rpc"
                }

body

JSON body that needs to be passed (as mentioned in the zabbix documentation)

"body": {
                    "id": 1,
                    "jsonrpc": "2.0",
                    "method": "user.login",
                    "params": {
                        "password": "%password",
                        "user": "%username"
                    }
                },

It identifies the method

"method": "user.login"

The param that are being passed

"params": {
                        "password": "%password",
                        "user": "%username"
                    }

 

5. Get Host Details

In the same way we have looked for “login” and parsed the token, you can fetch the hosts.

{
                "id": "hosts",
                "body": {
                    "auth": "%usertoken",
                    "id": 1,
                    "jsonrpc": "2.0",
                    "method": "host.get",
                    "params": {
                        "output": [
                            "hostid",
                            "host"
                        ],
                        "selectInterfaces": [
                            "interfaceid",
                            "ip",
                            "dns"
                        ]
                    }
                },
                "httpHeaders": {
                    "Content-Type": "application/json-rpc"
                },
                "method": "post",
                "src": "login",
                "url": "/zabbix/api_jsonrpc.php",
                "var": "",
                "xml_ns": ""
            }

 

Attributes

Description

body

Body has the auth and passes the %usertoken populated from login

src

Is a sibling to `login` as it uses the %usertoken

params

Based on the Zabbix documentation

"params": {
             "output": [
                            "hostid",
                            "host"
                        ],
             "selectInterfaces": [
                            "interfaceid",
                            "ip",
                            "dns"
                        ]
          }

In my case the sample response as evaluated in insomnia (API evaluator tool) is as follows.

{
  "jsonrpc": "2.0",
  "result": [
    {
      "hostid": "10084",
      "host": "lvndev011524.bpc.broadcom.net",
      "interfaces": [
        {
          "interfaceid": "1",
          "ip": "10.74.146.11",
          "dns": "lvndev011524.bpc.broadcom.net"
        }
      ]
    },
    {
      "hostid": "10432",
      "host": "ibnqa003969.bpc.broadcom.net",
      "interfaces": [
        {
          "interfaceid": "2",
          "ip": "10.80.241.78",
          "dns": "ibnqa003969.bpc.broadcom.net"
        }
      ]
    },
    {
      "hostid": "10434",
      "host": "ibnqa003970.bpc.broadcom.net",
      "interfaces": [
        {
          "interfaceid": "4",
          "ip": "10.80.241.80",
          "dns": "ibnqa003970.bpc.broadcom.net"
        }
      ]
    },
    {
      "hostid": "10435",
      "host": "node2.kubernetes.cluster",
      "interfaces": [
        {
          "interfaceid": "5",
          "ip": "10.80.120.148",
          "dns": "ibndev003277.bpc.broadcom.net"
        }
      ]
    }
  ],
  "id": 2
}

 

As in the case of streaming, the call and the result would be available in the restmon.log.

2021-11-08 10:36:06,900 [AsyncHttpClient-3-4] DEBUG ResponseHandler:217 - url: /zabbix/api_jsonrpc.php , response: {"jsonrpc":"2.0","result":[{"hostid":"10084","host":"lvndev011524.bpc.broadcom.net","interfaces":[{"interfaceid":"1","ip":"10.74.146.11","dns":"lvndev011524.bpc.broadcom.net"}]},{"hostid":"10432","host":"ibnqa003969.bpc.broadcom.net","interfaces":[{"interfaceid":"2","ip":"10.80.241.78","dns":"ibnqa003969.bpc.broadcom.net"}]},{"hostid":"10434","host":"ibnqa003970.bpc.broadcom.net","interfaces":[{"interfaceid":"4","ip":"10.80.241.80","dns":"ibnqa003970.bpc.broadcom.net"}]},{"hostid":"10435","host":"node2.kubernetes.cluster","interfaces":[{"interfaceid":"5","ip":"10.80.120.148","dns":"ibndev003277.bpc.broadcom.net"}]}],"id":1}

 

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2
6. Define Topology

Once the above details are defined, you can now move to the topology section.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

"topology": [
            {
                "xml_ns": "",
                "url": "hosts",
                "attributes": {
                    "oi": {
                        "Display Name": "$['result'][*]['host']",
                        "ci_unique_id": "$['result'][*]['hostid']",
                        "hostname": "$['result'][*]['host']",
                        "ipAddresses": "$['result'][*]['interfaces'][*]['ip']",
                        "macAddresses": "",
                        "name": "$['result'][*]['host']",
                        "product": "Zabbix Broadcom Com",
                        "product_version": "4.0",
                        "type": "HOST"
                    }
                },
                "group": "Topology",
                "layer": "CUSTOM"
            }
        ]

 

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

7. Add Other Sections

You can continue to stitch together the schema for alarms, metrics, and inventory and build the schema.

Final Schema: zabbixbroadcom

{
    "zabbixbroadcom": {
        "definition": {
            "auth": "none",
            "name": "zabbixbroadcom",
            "resource_category": null,
            "type": "https",
            "updatedBy": "Saurabh Sharma",
            "uploadedBy": "TENANT",
            "version": "21.3.1",
            "xml_ns": ""
        },
        "urls": [
            {
                "id": "login",
                "body": {
                    "id": 1,
                    "jsonrpc": "2.0",
                    "method": "user.login",
                    "params": {
                        "password": "%password",
                        "user": "%username"
                    }
                },
                "httpHeaders": {
                    "Content-Type": "application/json-rpc"
                },
                "method": "post",
                "src": "",
                "tokens": {
                    "usertoken": "$['result']"
                },
                "url": "/zabbix/api_jsonrpc.php",
                "var": "",
                "xml_ns": ""
            },
            {
                "id": "hosts",
                "body": {
                    "auth": "%usertoken",
                    "id": 1,
                    "jsonrpc": "2.0",
                    "method": "host.get",
                    "params": {
                        "output": [
                            "hostid",
                            "host"
                        ],
                        "selectInterfaces": [
                            "interfaceid",
                            "ip",
                            "dns"
                        ]
                    }
                },
                "httpHeaders": {
                    "Content-Type": "application/json-rpc"
                },
                "method": "post",
                "src": "login",
                "url": "/zabbix/api_jsonrpc.php",
                "var": "",
                "xml_ns": ""
            },
            {
                "id": "items",
                "body": {
                    "auth": "%usertoken",
                    "id": 1,
                    "jsonrpc": "2.0",
                    "method": "item.get",
                    "params": {
                        "monitored": true,
                        "output": "extend",
                        "selectHosts": "extend",
                        "sortfield": "name"
                    }
                },
                "httpHeaders": {
                    "Content-Type": "application/json-rpc"
                },
                "method": "post",
                "src": "login",
                "url": "/zabbix/api_jsonrpc.php",
                "var": "",
                "xml_ns": ""
            },
            {
                "id": "problems",
                "body": {
                    "auth": "%usertoken",
                    "id": 1,
                    "jsonrpc": "2.0",
                    "method": "problem.get",
                    "params": {
                        "output": "extend"
                    }
                },
                "httpHeaders": {
                    "Content-Type": "application/json-rpc"
                },
                "method": "post",
                "src": "login",
                "url": "/zabbix/api_jsonrpc.php",
                "var": "",
                "xml_ns": ""
            },
            {
                "id": "events",
                "body": {
                    "auth": "%usertoken",
                    "id": 1,
                    "jsonrpc": "2.0",
                    "method": "event.get",
                    "params": {
                        "eventids": "%var",
                        "output": "extend",
                        "selectHosts": "extend"
                    }
                },
                "httpHeaders": {
                    "Content-Type": "application/json-rpc"
                },
                "method": "post",
                "src": "problems",
                "url": "/zabbix/api_jsonrpc.php",
                "var": "$['result'][*]['eventid']",
                "xml_ns": ""
            }
        ],
        "topology": [
            {
                "xml_ns": "",
                "url": "hosts",
                "attributes": {
                    "oi": {
                        "Display Name": "$['result'][*]['host']",
                        "ci_unique_id": "$['result'][*]['hostid']",
                        "hostname": "$['result'][*]['host']",
                        "ipAddresses": "$['result'][*]['interfaces'][*]['ip']",
                        "macAddresses": "",
                        "name": "$['result'][*]['host']",
                        "product": "Zabbix Broadcom Com",
                        "product_version": "4.0",
                        "type": "HOST"
                    }
                },
                "group": "Topology",
                "layer": "CUSTOM"
            }
        ],
        "alarms": [
            {
                "xml_ns": "",
                "url": "events",
                "group": "Events",
                "attributes": {
                    "oi": {
                        "timestamp": "$['result'][*]['clock']",
                        "alarmType": "Infra",
                        "host": "$['result'][*]['hosts'][0]['host']",
                        "ip": "",
                        "product": "Zabbix Broadcom Com",
                        "product_version": "4.0",
                        "summary": "$['result'][*]['name']",
                        "severity": "$['result'][*]['severity']",
                        "severity_conversion": "5:critical,4:major,3:minor,Default:information",
                        "configuration_item": "$['result'][*]['hosts'][0]['host']",
                        "configuration_item_type": "Zabbix.Hosts",
                        "ci_unique_id": "$['result'][*]['hosts'][0]['hostid']",
                        "message": "$['result'][*]['name']",
                        "alarm_unique_id": "$['result'][*]['eventid']",
                        "tags": [
                            "Zabbix",
                            "Events"
                        ]
                    }
                }
            }
        ],
        "calculated_methods": [],
        "calculated_metrics": [],
        "change_events": [],
        "groups": [],
        "inventory": [
            {
                "xml_ns": "",
                "url": "hosts",
                "group": "Topology",
                "attributes": {
                    "oi": {
                        "ci_unique_id": "$['result'][*]['hostid']",
                        "host": "$['result'][*]['host']",
                        "product": "Zabbix Broadcom Com",
                        "product_version": "4.0",
                        "configuration_item_type": "Zabbix.Hosts",
                        "display_name": "$['result'][*]['host']",
                        "ip": "$['result'][*]['interfaces'][*]['ip']",
                        "tags": [
                            "Zabbix",
                            "ExcludeFromTAS"
                        ]
                    }
                }
            }
        ],
        "metrics": [
            {
                "calculation": "",
                "xml_ns": "",
                "group": "Items",
                "attributes": {
                    "oi": {
                        "metric_name": "$['result'][*][?(@.value_type == '3' || @.value_type == '0')]['name']",
                        "metric_type": "hosts",
                        "metric_unique_id": "$['result'][*][?(@.value_type == '3' || @.value_type == '0')]['hostid']%//%:%//%$['result'][*][?(@.value_type == '3' || @.value_type == '0')]['itemid']",
                        "metric_unit": "$['result'][*][?(@.value_type == '3' || @.value_type == '0')]['units']",
                        "type": "2",
                        "configuration_item_type": "Zabbix.Hosts",
                        "configuration_item": "$['result'][*][?(@.value_type == '3' || @.value_type == '0')]['hosts'][0]['host']",
                        "ci_unique_id": "$['result'][*][?(@.value_type == '3' || @.value_type == '0')]['hosts'][0]['hostid']",
                        "host": "$['result'][*][?(@.value_type == '3' || @.value_type == '0')]['hosts'][0]['host']",
                        "ip": "",
                        "mac": "",
                        "product": "Zabbix Broadcom Com",
                        "product_version": "4.0",
                        "tags": [
                            "Zabbix",
                            "$['result'][*][?(@.value_type == '3' || @.value_type == '0')]['name']"
                        ]
                    }
                },
                "value": "$['result'][*][?(@.value_type == '3' || @.value_type == '0')]['lastvalue']",
                "url": "items"
            }
        ]
    }
}

 

Validate the data in DX Operational Intelligence.

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2

Broadcom Enterprise Software Academy - Employing RESTmon to Ingest Zabbix Data: Part 2