Event handler configuration

To configure an event handler instance, you specify the paths to monitor, the name of the MicroPython script to invoke, and object-value pairs to be used as options in the script. When a state change occurs for the monitored paths, event handler invokes the script, passing the state information and options in a JSON string as input to the script.

The following is an example configuration for an event handler instance:

--{ candidate shared default }--[  ]--
# info system event-handler instance opergrp
    system {
        event-handler {
            instance opergrp {
                admin-state enable
                upython-script oper-group.py
                paths [
                    "interface ethernet-1/55 oper-state"
                    "interface ethernet-1/56 oper-state"
                ]
                options {
                    object down-links {
                        values [
                            ethernet-1/1
                        ]
                    }
                    object required-num-up-links {
                        value 2
                    }
                }
            }
        }
    }

In this example, the event handler monitors the operational state of the uplinks defined in the paths statement, ethernet-1/55 and ethernet-1/56. If the oper-state for either uplink changes to down, then the oper-state of the downstream link in the down-links options list, ethernet-1/1, is set to down.

To do this, event handler invokes the MicroPython script defined in the upython-script statement, oper-group.py. Event handler supplies the state of the uplinks, the number of uplinks required to be up, and the associated downlinks as input to the script; this input is supplied in the form of a JSON string; for example:

{
    "paths": [
        {
            "path": "interface ethernet-1/55 oper-state", 
            "value": "down"
        },
        {
            "path": "interface ethernet-1/56 oper-state",
            "value": "down"
        }
    ],
    "options": { 
        "required-num-up-links": "2",
        "down-links": [
            "ethernet-1/1",
        ]
    }
}

The logic for counting the number of operationally up uplinks and setting downlinks to operationally down is kept within the oper-group.py script. After processing the input, the script returns a list of actions to event handler for execution on the SR Linux device. See Event handler scripts for more information.

Specifying paths to monitor

The paths statement specifies the objects for the event handler instance to monitor. Paths are configured in CLI notation and specify any leaf or leaf-list available in the state datastore. You can use ranges and wildcards in the path.

The following examples show possible paths configurations in an event handler instance:

  • "interface ethernet-1/1 oper-state"

    Monitors changes in the oper-state for interface ethernet-1/1

  • "interface ethernet-1/{1..12} oper-state"

    Monitors changes in the oper-state for interface ethernet-1/1 through ethernet-1/12

  • "interface ethernet-1/* oper-state"

    Monitors changes in the oper-state for all interfaces on a line card

  • "interface * oper-state"

    Monitors changes in the oper-state for all interfaces on the SR Linux device

Specifying options

The options statement contains a set of user-defined objects and associates either a single value or list of values to them. The object-value pairs are carried as input to the MicroPython script, allowing you to potentially pass configuration. Event handler passes the options to the script as JSON strings; the objects do not need to follow any particular schema.

The following example defines object-value pairs in the options statement of an event handler instance:

--{ candidate shared default }--[  ]--
# info system event-handler instance opergrp options
    system {
        event-handler {
            instance opergrp {
                options {
                    object down-links {
                        values [
                            ethernet-1/1
                            ethernet-1/2
                        ]
                    }
                    object required-num-up-links {
                        value 1
                    }
                }
            }
        }
    }

In the example, the interfaces in the down-links object are specified as a list of values, and the number in the required-num-up-links object is specified as a single value.

Specifying a MicroPython script

To specify the MicroPython script, use the upython-script statement. This statement refers to a MicroPython script in one of the following locations:

  • /etc/opt/srlinux/eventmgr for user-provided scripts
  • /opt/srlinux/eventmgr for Nokia-provided scripts

No other directories can be used for event handler scripts. See Event handler scripts for information about how event handler supplies input to a script and how the script processes the input and returns a list of actions to the event handler for execution.

Configuring the user for event handler operations

By default, event handler configuration operations executed via the set-cfg-path and delete-cfg-path actions, scripts executed via the run-script action, and tools commands executed via the set-tools-path action are all performed by the SR Linux admin user. You can change the user that performs these operations.

The user must be a local user; that is, a user configured within the SR Linux CLI. Linux users and remote users cannot be configured to execute event handler operations. See "User types" in the SR Linux Configuration Basics Guide for information about each user type.

The user's role must have the appropriate privileges to perform the set-cfg-path, delete-cfg-path, and set-tools-path actions required for the event handler operations. See "Authorization using role-based access control" in the SR Linux Configuration Basics Guide for information about configuring roles.

The configured user executes operations for all event handler instances. If a user is not configured to execute event handler operations, they are executed by local SR Linux user admin.

Configure an SR Linux local user to execute event handler operations

The following example creates a local SR Linux user and configures the user to execute operations for event handler instances.

--{ * candidate shared default }--[ ]--
# system aaa authentication user EHexec password sr1l234
--{ * candidate shared default }--[ ]--
# info system event-handler
    system {
        event-handler {
            run-as-user EHexec
        }
    }

Configure the user's role to allow execution of event handler operations

The following example configures a role that gives write privileges to all paths (/) and assigns that role to the user configured to execute event handler operations.

--{ candidate shared default }--[  ]--
# info system aaa authorization
    system {
        aaa {
            authorization {
                role EHexecRole {
                }
            }
        }
    }
--{ * candidate shared default }--[  ]--
# info system configuration role EHexecRole
    system {
        configuration {
            role EHexecRole {
                rule / {
                    action write
                }
            }
        }
    }
--{ * candidate shared default }--[  ]--
# info system aaa authentication
    system {
        aaa {
            authentication {
                authentication-method [
                    local
                ]
                user EHexec {
                    password $ar2$kYDzvtHbUuc=$VINLYMbZ8f8u4gMtuPnSVQ==
                    role [
                        EHexecRole
                    ]
                }
            }
        }
    }

Displaying event handler information

Use the info from state command to display information about an event handler instance, including any errors.

--{ running }--[  ]--
# info from state system event-handler instance opergrp
    system {
        event-handler {
            instance opergrp {
                admin-state enable
                upython-script oper-group.py
                oper-state up
                paths [
                    "interface ethernet-1/1 oper-state"
                    "interface ethernet-1/4 oper-state"
                ]
                options {
                    object down-links {
                        values [
                            ethernet-1/3
                            ethernet-1/8
                        ]
                    }
                    object required-num-up-links {
                        value 2
                    }
                }
                last-execution {
                    start-time now
                    end-time now
                    upython-duration 1
                    input "{\"paths\":[{\"path\":\"interface ethernet-1/1 oper-state\",\"value\":\"up\"},{\"path\":\"interface ethernet-1/4 oper-state\",\"value\":\"up\"}],\"options\":{\"down-links\":[\"ethernet-1/3\",\"ethernet-1/8\"],\"required-num-up-links\":\"2\"},\"persistent-data\":{\"last-state\":\"up\"}}"
                    output "{\"actions\": [{\"set-ephemeral-path\": {\"path\": \"interface ethernet-1/3 oper-state\", \"value\": \"up\"}}, {\"set-ephemeral-path\": {\"path\": \"interface ethernet-1/8 oper-state\", \"value\": \"up\"}}], \"persistent-data\": {\"last-state\": \"up\"}}"
                    stdout-stderr ""
                }
                last-errored-execution {
                    oper-down-reason admin-disabled
                    oper-down-reason-detail ""
                    start-time "26 seconds ago"
                    end-time "25 seconds ago"
                    upython-duration 0
                    input "{\"paths\":[{\"path\":\"interface ethernet-1/1 oper-state\",\"value\":\"up\"},{\"path\":\"interface ethernet-1/4 oper-state\",\"value\":\"down\"}],\"options\":{\"down-links\":[\"ethernet-1/3\",\"ethernet-1/8\"],\"required-num-up-links\":\"2\"},\"persistent-data\":{\"last-state\":\"down\"}}"
                    output "{\"actions\": [{\"set-ephemeral-path\": {\"path\": \"interface ethernet-1/3 oper-state\", \"value\": \"up\"}}, {\"set-ephemeral-path\": {\"path\": \"interface ethernet-1/8 oper-state\", \"value\": \"up\"}}], \"persistent-data\": {\"last-state\": \"up\"}}"
                    stdout-stderr ""
                }
                statistics {
                    upython-duration 516
                    execution-count 1643
                    execution-successes 1642
                    execution-errors 1
                }
            }
        }
    }

You can clear the statistics for the event handler instance using a tools command. For example:

--{ running }--[  ]--
# tools system event-handler instance opergrp statistics clear

Error handling for event handler

Whenever calling the event_handler_main() function for a script results in an error, the event handler instance oper-state is set to down, and the oper-down-reason under last-errored-execution indicates the reason for the failure. The oper-down-reason-detail is populated from stderr and displays any additional details. The relevant error counters execution-timeouts and execution-errors are incremented.

Whenever a script exceeds the 10-second execution timer (the amount of time it takes for a call to event_handler_main() to return a list of actions, and for event_mgr to execute the actions) the function call is terminated, and the execution-timeouts error counter is incremented.

Any time an instance experiences a failure, any pre-existing set-ephemeral-path actions are cleared, resulting in the modified objects reverting back to their original state.

If a script fails, it is automatically retried after a 10-second delay. During the 10-second delay, the oper-reason reflects the most recent oper-state down transition. After the 10-second delay, the instance moves to oper-state starting, before moving to oper-state down or oper-state up depending on the execution of the event_handler_main() function.

The 10-second delay and retry continues until the script execution is successful. For the following oper-reason errors, the instance stays at oper-state down until a user intervenes, with no retry:

  • failed-to-compile
  • script-unavailable
  • system-error
  • missing-function