Rearm table threshold / Clear alarm from NXSL script

Started by mk, November 07, 2014, 12:00:33 PM

Previous topic - Next topic

mk

I have a table data collection item configured which pulls the alert messages from our printers. It consists of two columns: SNMP parameter .1.3.6.1.2.1.43.18.1.1.7 is the integer alert code (and I've set that as instance column), and .1.3.6.1.2.1.43.18.1.1.8 is the textual description of the alert.
I have a threshold set on that table which raises the SYS_TABLE_THRESHOLD_ACTIVATED event when the description is neither "Sleep" nor "Sleep mode on". The alarm gets raised properly when the printer has an alert message, but the SYS_TABLE_THRESHOLD_DEACTIVATED event is never raised. The reason for this is that the alert just gets removed from the table because it is no longer reported via SNMP and this does not trigger any events.

Is there any way to raise an SYS_TABLE_THRESHOLD_DEACTIVATED event when the line that triggered the SYS_TABLE_THRESHOLD_ACTIVATED event is removed from a table DCI?

One thing I've thought about is writing a transformation script that does something like this:

idxCode = $1->getColumnIndex("Code");
nodeId = d2x($node->id, 8);
tableId = d2x(FindDCIByName($node, "printerAlert"), 8);
prefix = "DCTTHR_" . nodeId . "_" . tableId . "_"; // the keys look like DCTTHR_<node ID in hex>_<DCI ID in hex>_<instance ID>

alarms = GetAlarmWithKeyStartingWith(prefix);
foreach(alarm : alarms)
{
    removeAlarm = true;
    for (i = 0; i < $1->rowCount; i++)
    {
        if ($1->get(i, idxCode) == substr(alarm->key, length(prefix)) // instance part of the alarm key matches the code in the current row
        {
            removeAlarm = false;
        }
    }
    if (removeAlarm)
    {
        alarm->terminate();
    }
}

Of course, this doesn't work for the simple reason that NXSL does not offer any way to access the  alarm list (i.e. the list which is shown in the Alarm Browser in the GUI), at least I couldn't find one.
There would need to be some way to get an alarm object associated with a specific node and DCI (e.g. GetAlarmWithKeyStartingWith as used above), and the NXSL alarm class would need to have at least a key attribute and a terminate() method.

mk

Using ExternalParametersProvider also does not help: according to Executing Powershell with Tabel result.:
Quote from: Victor KirhenshteinThere are no external table support in agent.

Victor Kirhenshtein

Hi,

you can create a script which will compare current table rows with rows from previous poll (you can get previous value using GetDCIValue function - when transformation script runs previous value still available) and generate events as needed using PostEvent function.

Best regards,
Victor

mk

Thanks, I'll try that. I've come up with the following code, I'll let you know how that goes.
idxCode = $1->getColumnIndex("Code");
idxDescr = $1->getColumnIndex("Description");
dciName = "prtAlert";
dciId = FindDCIByDescription($node, dciName);
dciObj = GetDCIObject($node, dciId);

tableOld = GetDCIValue($node, dciId);

if (tableOld != null)
{
for (j = 0; j < tableOld->rowCount; j++)
{
keepAlarm = false;
for (i = 0; i < $1->rowCount; i++)
{
if ($1->get(i, idxCode) == tableOld->get(j, idxCode))
{
keepAlarm = true;
}
   }
   if (!keepAlarm)
   {
    PostEvent($node, 70, null, dciObj->name, dciObj->description, dciId, j, tableOld->get(j, idxCode), tableOld->get(j, idxDescr));
   }
}
}

mk

So far, it looks like it almost works.
One remaining issue is that while the event gets triggered and I get the appropriate notification email, the "Terminate alarm" action on the event does not do anything. The threshold violation remains in the alarm list until cleared manually.
Another (minor) issue is that if a row gets inserted into the table above an existing row is that a deactivation and a violation event are both triggered. That could probably be resolved by not using thresholds and also sending the violation events from the transformation script as well.