Skip to content

Latest commit

 

History

History
592 lines (457 loc) · 11.4 KB

examples.adoc

File metadata and controls

592 lines (457 loc) · 11.4 KB

Some real life examples.

Small utility scripts

UNIX timestamp to human readable

return strftime("%d.%m.%Y %H:%M:%S", $1);

Table DCI manipulation script

Get table item. Is used to make DCI from Table DCI.

// Warning: this script works only on the same node
//
// $1 - Description
// $2 - column name
table = GetDCIValueByDescription($node, $1);
if (table != NULL) {
	col = table->getColumnIndex($2);
	if (col >= 0) {
		return table->get(0, col);
	}
}
return 0;

Primary mac address

Script to print primary MAC address.

for(i : $node->interfaces)
{
   for(a : i->ipAddressList)
   {
      if (a->address == $node->ipAddr)
         println(i->macAddr);
   }
}

Check if node is under cluster or container

Script that returns TRUE if current node is under at least one container or cluster.

for (p : $node->parents) {
    if (p->type == 5 or p->type == 14) { //5 is container and 14 is cluster
        return true;
    }
}
return false;

Change expected state for all interfaces

Set ignore expected state for all interfaces of all nodes.

for (n : GetAllNodes()) {
    println(n->name .. "(" .. n->id .. ")");
    for (i : n->interfaces) {
        println("\t" .. i->name);
        i->setExpectedState("IGNORE");
    }
}

Instance filtering script for "Net.InterfaceNames"

Requirements

Instance filtering script for "Net.InterfaceNames" list, that will filter only "eth*" and "bond*" interfaces, that can be used in Net.Interface.BytesIn64 or Net.Interface.BytesOut64 DCIs.

Solution

Select "Agent List" as instance discovery method. Set "Net.InterfaceNames" as list name and add script to instance discovery filter script section:

name=$1;
if (name ~= "eth|bond")
{
    return %(name);
}
return false;

Filter out some interfaces from creation

Requirements

Filter interfaces that should not be monitored by NetXMS. In this case "isatap*" interfaces.

Solution

Update "Hook:CreateInterface" script in script library.

if ( $1->name ~= "^isatap" )
    return false;

return true;

Additional Information About Connected Node

Requirements

Add information about name, IP address, and MAC address about connected node to notification about switch port being down and up.

Solution

Script that is being called from Event Processing Policy that adds named event parameter to the event. Parameter is named additionalInfo, correspondingly %<additionalInfo> macro can be used to add value of that parameter to notification text.

// only for interface up and down events
if (($event->name != "SYS_IF_DOWN") && ($event->name != "SYS_IF_UP"))
	return true;

// get interface object from interface index
iface = $node->getInterface($5);
if (iface == null)
	return true;

// get peer node (node connected to this interface) object
peer = iface->peerNode;
if (peer == null)
	return true;

// get peer interface object (needed to obtain MAC address)
peerIface = iface->peerInterface;
if (peerIface != null)
{
	macAddr = peerIface->macAddr;
}
else
{
	macAddr = "<MAC unknown>";
}

// set event's named parameter
SetEventParameter($event, "additionalInfo",
	"Peer: " .. peer->name .. " " .. peer->ipAddr .. " " .. macAddr);

return true;

Enumerate All Nodes

Requirements

Enumerate all nodes in NetXMS database.

Solution 1

Create script in script library which will find "Entire Networks" object and walk down the tree. This script can be executes as an action from event processing policy, or directly from server debug console via exec command or on any node.

In order to be able to access info about all nodes, the CheckTrustedNodes server configuration variable needs to be set to 0.

// This function walks object tree recursively starting from given root
sub EnumerateNodes(obj, level)
{
    foreach(o : obj->children) {
        for (i = 0; i < level; i++) { print("  "); }
        println("[" .. o->type .. " / " .. classof(o) .. "] " .. o->name);

        EnumerateNodes(o, level + 1);
    }
}
// Find "Entire Network" object and start enumeration from it
EnumerateNodes(FindObject("Entire Network"), 0);

Solutions 2

When only nodes are required, not walk down the tree then this script can be used:

for (n : GetAllNodes()) {
  println(n->name);
}

Enumerate All Custom Attributes for Node

Requirements

Enumerate all custom attributes on a node.

Solution

attributes = $node->customAttributes;
foreach(a : attributes->keys)
{
        println(a .. "=" .. attributes[a]);
}

Bubble sort with alphabetical sorting

sub BubbleSort(a)
{
   n = a->maxIndex + 1;
   do
   {
      newn = 0;
      for(i = 1; i < n; i++)
      {
         if (a[i - 1]->compareTo(a[i]) > 0)
         {
            t = a[i - 1];
            a[i - 1] = a[i];
            a[i] = t;
            newn = i;
         }
      }
      n = newn;
   }
   while(n > 1);
   return a;
}

Bubble sort with numeric sorting

sub BubbleSort(a)
{
   n = a->maxIndex + 1;
   do
   {
      newn = 0;
      for(i = 1; i < n; i++)
      {
         if (a[i - 1] > a[i])
	     {
            t = a[i - 1];
            a[i - 1] = a[i];
            a[i] = t;
            newn = i;
         }
      }
      n = newn;
   }
   while(n > 1);
   return a;
}

Aggregation of DCI values and applying the 95% percentile average

The example is based around a template which configures ICMP Packet Loss probes. This script will loop around the nodes, collect the required DCI values. The values are then ordered and the top 5 percent discarded, the remaining entries are averaged to give the required value;

sub main()
{

trace(1, "Global Ping Loss 95");
array pValue;
arrayI  = 0;

foreach(parent : $node->parents)
{
	trace(3, "Parent object: name='" .. parent->name ."' id=" .. parent->id);
	if (parent->name == "all voice")
	{
		foreach(vNode : parent->children)
		{
			dciName = "ICMP: Packet loss to ".vNode->name;
			dciId = FindDCIByDescription(vNode, dciName);
			if (dciId > 0)
			{
				tmpValue = GetDCIValue(vNode,dciId);
				if (tmpValue != null)
				{
					pValue[arrayI++] = tmpValue;
				}
			}
		}
	}
}

// Sort the Array
bubbleSort(pValue);

// Apply the 95 percent rule
upTo = arrayI * 0.95;
pLoss = 0;
pCount = 0;
for(ia = 0; ia < upTo; ia++)
{
	pLoss += pValue[ia];
	pCount = ia;
}
p95AvgLoss = pLoss / pCount;

trace(1, "Global Ping Loss 95 Summary: arrayI=".arrayI." upTo=".upTo." p95AvgLoss=".p95AvgLoss );

return p95AvgLoss;
}

sub bubbleSort(arr)
{
	swapped = true;
	while (swapped == true){
		swapped = false;
		for(ia = 1; arr[ia] != null; ia++)
		{
			ib = ia - 1;

			if (arr[ib] > arr[ia]){
				trace(3,"swap: ".ib.":".arr[ib]." with ".ia.":".arr[ia]);
				swapped=true;
				t = arr[ib];
				arr[ib] = arr[ia];
				arr[ia] = t;
				swapped = true;
			}
		}
	}
}

sub printArray(arr)
{
	for(ia = 0; arr[ia] != null; ia++)
	{
		trace(1,"printArray: ".ia.":".arr[ia]);
	}
}

Read SNMP Value From Node

This script can be put into Script Library and run from server’s debug console. It accepts node object name or ID as parameter and prints value of SNMP sysDescription to console.

if ($1 == null)
{
   println("Please specify node name as parameter");
   return 3;
}

transport = FindObject($1)->createSNMPTransport();    // Create SNMP transport for node
if (transport == null)
{
    println("Failed to create SNMP transport, exit");
    return 1;
}

value = transport->getValue(".1.3.6.1.2.1.1.1.0");
if (value == null)
{
    println("Failed to issue SNMP GET request");
    return 2;
}
else
{
    println("System description: " .. value);
    return 0;
}

Read SNMP octet string as byte

transport = $node->createSNMPTransport();
if (transport == null) exit;

varbind = transport->get(".1.3.6.1.2.1.25.3.5.1.2.1");
if (varbind == null) exit;

bytestream = varbind->getValueAsByteStream();

println(bytestream->pos); // after bytestream is created, it's position is set to 0
println("0x" .. d2x(bytestream->readByte(), 2)); // prints the hex value of 0-th byte

Read Table From Agent

This script can be put into Script Library and run from server’s debug console. It accepts node object name or ID as first parameter, table name as second parameter, and prints content of given table to console.

// Find node object
node = FindObject($1);
if (node == null)
{
	println("ERROR: Node not found");
	return;
}

// REad table data from agent
table = AgentReadTable(node, $2);
if (table == null)
{
	println("ERROR: Cannot read table from agent");
	return;
}

// Print column names
for(i = 0; i < table->columnCount; i++)
	print("| " .. left(table->getColumnName(i), 20));
println("|");
for(i = 0; i < table->columnCount; i++)
	print("+" .. left("-", 21, "-"));
println("+");

// Print data
for(i = 0; i < table->rowCount; i++)
{
	for(j = 0; j < table->columnCount; j++)
	{
		print("| " .. left(table->get(i, j), 20));
	}
	println("|");
}

Recursively Collect Values from Custom Attributes

This script recursively collects values of custom attribute contacts from all node parents. Collected values concatenated into single string and separated by semicolons. Duplicate values added only once.

global contacts = "";  // concatenated values will be stored here
global presence = %{ };  // value presence indicator (hash map)

// walk through each parent object for current node
foreach(o : $node->parents)
{
	add_contacts(o);
}

// Concatenated result is in "contacts" global variable
println("Contacts: " .. contacts);

/**
 * Recursively add contacts from object and it's parents
 */
sub add_contacts(curr)
{
	c = curr->getCustomAttribute("contacts");
	if ((c != null) && (presence[c] == null))
	{
		if (length(contacts) > 0)
			contacts = contacts .. ";" .. c;
		else
			contacts = c;
		presence[c] = true;
	}

	foreach(o : curr->parents)
	{
		add_contacts(o);
	}
}

Setting node geolocation from SNMP

Adjust the OIDs in SNMPGetValue as required.

transport = $node->createSNMPTransport();
if (transport == null) {
  return null;
}

lat = transport->get(".1.2.3.4.1");
lon = transport->get(".1.2.3.4.2");

if (lat == null || lon == null) {
  return null;
}

geoLoc = new GeoLocation(lat, lon);
$node->setGeoLocation(geoLoc);

return 0;

Object query to list asset values

Saved object query script to list all nodes linked to asset and list values for serial, vendor, model asset properties.

with
	objName (order = "asc", name = "Object name") = {
    	return $node->name;
	},

	serial (name = "Serial") = {
		return $node->assetProperties->serial;
	},

	vendorVar (name = "Vendor") = {
		return $node->assetProperties->vendor;
	},

	model (name = "Model") = {
		return $node->assetProperties->model;
	}

(type == NODE) && $node->asset != null //show all nodes linked to asset

Exactly the same script, but without "with" syntax:

if (($object->type == NODE) && $node->asset != null)
{
    global objName (order = "asc", name = "Object name") = $node->name;
    global serial (name = "Serial") = $node->assetProperties->serial;
    global vendorVar (name = "Vendor") = $node->assetProperties->vendor;
    global model (name = "Model") = $node->assetProperties->model;
}
return ($object->type == NODE) && $node->asset != null; //show all nodes linked to asset