Hook Scripts

Hook scripts are NXSL scripts stored in the Script Library with names prefixed by Hook::. The NetXMS server calls them automatically at specific points during its operation. They allow you to customize server behavior without modifying the core product.

Hook scripts are pre-created in the Script Library during server initialization. To customize a hook, edit the corresponding script in Configuration → Script Library. An empty hook script is ignored by the server.

Polling Hooks

These hooks execute during their respective polling cycles (most of them at the end of the poll). They receive the polled object as $object; $node is additionally set when the polled object is a node, $isCluster is always set (true when the object is a cluster), and $map is additionally set when the object is a network map. Status and configuration polls also run for clusters, sensors, and other pollable objects — in those cases $node is not defined. Access points and wireless domains run only Hook::ConfigurationPoll, not Hook::StatusPoll. These hooks are useful for custom post-poll processing, logging, or side effects.

Use PollerTrace() to send diagnostic messages to the polling trace output.

Hook::StatusPoll

Executes at the end of each status poll cycle.

Item Details

Fires

After status poll completes for a pollable object (Node, Cluster, Sensor, etc.). Does not fire for access points and wireless domains — those run only Hook::ConfigurationPoll

Object context

The polled object ($object; $node when it is a node)

Return value

Not used

// Log status changes to persistent storage
if ($node.status != ReadPersistentStorage("lastStatus:" .. $node.name))
{
    WritePersistentStorage("lastStatus:" .. $node.name, $node.status);
    PollerTrace("Status changed to " .. $node.status);
}

Hook::ConfigurationPoll

Executes during each configuration poll, after capability and interface discovery but before automatic template and container binding. For access points the hook runs at the start of the poll.

Item Details

Fires

During configuration poll for Node, AccessPoint, WirelessDomain, Cluster, Sensor, cloud domain, or traffic observer objects — after capability and interface discovery but before automatic template and container binding (for access points, at the start of the poll)

Object context

The polled object ($object; $node when it is a node)

Return value

Not used

// Set custom attribute based on discovered platform
if ($node.platformName ~= "^linux")
    $node.setCustomAttribute("os_family", "Linux");

Hook::InstancePoll

Executes at the end of each instance discovery poll cycle.

Item Details

Fires

After instance discovery poll completes for a data collection target. Runs only when the target is reachable — the poll is aborted (and the hook skipped) when the target is unreachable

Object context

The polled object ($object; $node when it is a node)

Return value

Not used

Hook::TopologyPoll

Executes at the end of each topology poll cycle.

Item Details

Fires

After topology poll completes for a Node

Object context

The polled Node ($object, $node)

Return value

Not used

Hook::DiscoveryPoll

Executes at the end of each discovery poll cycle.

Item Details

Fires

After network discovery poll completes for a Node

Object context

The polled Node ($object, $node)

Return value

Not used

Hook::DiscoveryFilter

Evaluates whether a discovered node should be created, after the host has been contacted and its capabilities determined. This hook runs in Stage 2 of the discovery flow (see Network Discovery) — after reachability checks, capability probing, and protocol filtering.

Unlike Hook::AcceptNewNode which only has IP/MAC information, this hook receives a DiscoveredNode object with full details about the discovered device.

Item Details

Fires

During network discovery Stage 2, after capabilities are gathered

Object context

None

Script arguments

$1 — DiscoveredNode object (also available as $node)

Additional variables

$snmp — SNMPTransport object (if SNMP is available, null otherwise)

Return value

true to accept the node, false to reject

Default

return true;

The DiscoveredNode object provides the following attributes:

Attribute Description

ipAddr

IP address as string

ipAddress

IP address as InetAddress object

netMask

Network mask (prefix length)

subnet

Subnet address as string

zoneUIN

Zone UIN

zone

Zone object (or null)

isAgent

true if NetXMS agent detected

isSNMP

true if SNMP detected

isSSH

true if SSH detected

isRouter

true if device is a router

isBridge

true if device is a bridge

isCDP

true if CDP supported

isLLDP

true if LLDP supported

isSONMP

true if SONMP/NDP supported

isPrinter

true if device is a printer

agentVersion

Agent version string (empty if no agent)

platformName

Platform name as reported by agent (empty if no agent)

snmpOID

SNMP sysObjectID as string

snmpVersion

SNMP version (0=v1, 1=v2c, 3=v3)

dnsName

DNS name resolved from IP address (or null)

interfaces

Array of DiscoveredInterface objects

Each DiscoveredInterface object has:

Attribute Description

name

Interface name

alias

Interface alias

description

Interface description

index

Interface SNMP index

type

Interface type

macAddr

MAC address as string

ipAddressList

Array of InetAddress objects

speed

Interface speed

mtu

Interface MTU

isPhysicalPort

true if this is a physical port

chassis, module, pic, port

Physical location identifiers

// Accept only SNMP devices that are routers or bridges
if ($node.isSNMP && ($node.isRouter || $node.isBridge))
    return true;
return false;

Object Lifecycle Hooks

These hooks fire when objects are created, modified, or deleted.

Hook::AcceptNewNode

Evaluates whether a newly discovered IP address should become a Node object. This is one of the most commonly used hooks for controlling automatic network discovery.

Item Details

Fires

During network discovery, before creating a new Node from a discovered address

Object context

None (no $object or $node)

Predefined variables

$ipAddress (InetAddress), $ipAddr (String), $ipNetMask (Integer — mask bits), $macAddress (MacAddress or null), $macAddr (String or null), $zoneUIN (Integer)

Return value

Only an explicit false rejects the node; returning null or nothing accepts it. A script runtime error also rejects the node

Default

return true;

// Only accept nodes from specific subnets
if ($ipAddr ~= "^10\.1\." || $ipAddr ~= "^192\.168\.5\.")
    return true;
return false;

Hook::PostObjectCreate

Executes immediately after a new object is created and inserted into the server’s in-memory object index. The database write happens later, asynchronously.

Item Details

Fires

After a new object of any type is created (manually or automatically)

Object context

The newly created object ($object, $node if applicable)

Return value

Not used

// Send notification when new node is created
if (classof($object) == "Node")
    SendNotification("SMTP-Text", "[email protected]", "New node created", "New node created: " .. $object.name);

The first argument of SendNotification() must name an existing notification channel (SMTP-Text exists on default installations); notifications sent to unknown channel names are silently dropped.

Hook::ObjectDelete

Executes when an object is about to be deleted, before the deletion occurs.

Item Details

Fires

Before an object of any type is deleted

Object context

The object being deleted ($object, $node if applicable)

Return value

Not used

// Log object deletion
trace(1, "Object deleted: " .. $object.name .. " (ID: " .. $object.id .. ")");

Hook::CreateInterface

Evaluates whether an automatically discovered interface should be created as an object. Only called for interfaces discovered during polling, not for manually created interfaces.

Item Details

Fires

During configuration poll, when a new interface is discovered on a Node

Object context

The parent Node ($object, $node)

Script arguments

$1 — the Interface object being created

Return value

true to accept, false to reject. Script errors also block creation.

Default

return true;

// Skip virtual and loopback interfaces
if ($1.name ~= "^(lo|veth|docker|br-|virbr)")
    return false;
return true;

Hook::UpdateInterface

Executes when an existing interface is updated during configuration polling (properties changed, port location updated, etc.).

Item Details

Fires

During configuration poll, when an existing interface’s properties change

Object context

The parent Node ($object, $node)

Predefined variables

$interface (Interface)

Script arguments

$1 — the Interface object

Return value

Not used

Hook::CreateSubnet

Evaluates whether an automatically discovered subnet should be created as an object.

Item Details

Fires

During configuration poll, when a new subnet is derived from node interface addresses

Object context

The parent Node ($object, $node)

Script arguments

$1 — the Subnet object being created

Return value

true to accept, false to reject. Script errors also block creation.

Default

return true;

// Do not create /32 or /128 subnets
if ($1.ipAddress.mask == 32 || $1.ipAddress.mask == 128)
    return false;
return true;

Event and Alarm Hooks

Hook::EventProcessor

Executes for every event before it enters Event Processing Policy (EPP) rule evaluation. Can be used to modify events, add tags, or perform pre-processing logic.

Item Details

Fires

After event creation and correlation, before EPP rules process the event

Object context

The event source object ($object, $node), or null if no source

Predefined variables

$event (Event)

Return value

Not used

// Add a tag to all events from a specific zone
if ($node != null && $node.zoneUIN == 5)
    $event.addTag("remote-site");

Hook::AlarmStateChange

Executes when an existing alarm changes state (updated, acknowledged, resolved, or terminated). It does not fire on alarm creation. Runs asynchronously in a background thread.

Item Details

Fires

When an existing alarm transitions between states (not on alarm creation)

Object context

None (runs asynchronously without object context)

Predefined variables

$alarm (Alarm)

Return value

Not used

// Log alarm state changes to persistent storage
WritePersistentStorage(
    "alarm_log:" .. $alarm.id,
    $alarm.state .. ":" .. GetCurrentTime()
);

Tunnel Hooks

Hook::OpenBoundTunnel

Executes when an agent tunnel is established and the agent is bound to a known Node.

Item Details

Fires

When a bound agent tunnel connects

Object context

The Node the tunnel is bound to ($object, $node)

Predefined variables

$tunnel (Tunnel)

Return value

Not used

Hook::OpenUnboundTunnel

Executes when an agent tunnel is established but the agent is not bound to any Node.

Item Details

Fires

When an unbound agent tunnel connects

Object context

None (no $object or $node)

Predefined variables

$tunnel (Tunnel)

Return value

Not used

// Log unbound tunnel connections for review
trace(1, "Unbound tunnel from " .. $tunnel.systemName ..
    " (" .. $tunnel.address .. ")");

Authentication and User Hooks

Hook::Login

Evaluates whether a user login attempt should be allowed. Runs after standard authentication succeeds but before the session is fully established.

Item Details

Fires

After successful authentication, before session creation

Object context

None (no $object or $node)

Predefined variables

$session (ClientSession), $user (User)

Return value

false to deny login, true or null to allow

// Block login outside business hours (8:00-18:00)
t = DateTime(time());
if (t.hour < 8 || t.hour >= 18)
{
    if ($user.name != "admin")
        return false;
}
return true;

Hook::LDAPSynchronization

Evaluates each LDAP object during user/group synchronization. Can filter which LDAP users and groups are synchronized into NetXMS.

Item Details

Fires

For each LDAP user or group found during LDAP synchronization

Object context

None (no $object or $node)

Predefined variables

$ldapObject (LDAPObject)

Return value

false to reject the object, true or null to accept

// Only sync users whose login name starts with "it_"
if ($ldapObject.isUser)
{
    if (not ($ldapObject.loginName ~= "^it_"))
        return false;
}
return true;

Configuration Backup Hook

Hook::RegisterForConfigurationBackup

Determines whether a node should be registered for device configuration backup via the external backup API. Evaluated during configuration polls.

Item Details

Fires

During configuration poll, when evaluating node for backup registration

Object context

The polled Node ($object, $node)

Return value

true to register for backup, false to skip

Default

return $node.isSNMP;

// Register only SNMP routers for configuration backup
return $node.isSNMP && $node.isRouter;

Common Patterns

Using PollerTrace in Poll Hooks

Poll hooks can send diagnostic messages to the poller trace output visible in the management console:

// In Hook::ConfigurationPoll
PollerTrace("Custom hook: checking compliance...");
if ($node.customAttributes["compliance_status"] == null)
{
    $node.setCustomAttribute("compliance_status", "unchecked");
    PollerTrace("Custom hook: set initial compliance status");
}

See PollerTrace() for details.

Error Handling

If a hook script that returns a boolean encounters a runtime error:

  • For filter hooks (CreateInterface, CreateSubnet, AcceptNewNode, DiscoveryFilter, RegisterForConfigurationBackup): the object creation is blocked (treated as rejection)

  • For Hook::Login and Hook::LDAPSynchronization: only an explicit false return blocks the operation — a runtime error (like a null return) does not block

  • For informational hooks (StatusPoll, ConfigurationPoll, etc.): the error is logged and the poll continues normally

See Also