Skip to content

Commit

Permalink
Add a "silly" example
Browse files Browse the repository at this point in the history
  • Loading branch information
karimra committed Nov 17, 2024
1 parent 67a5b4a commit 79509c6
Showing 1 changed file with 174 additions and 0 deletions.
174 changes: 174 additions & 0 deletions docs/snmp/snmp_framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -673,3 +673,177 @@ Debug files are generated in `/tmp/snmp_debug/$NETWORK_INSTANCE`:
* Input/Output Logs: Check `.json_input`, `.json_output`, `.console` and `.error` files for debugging script execution.
The `.console` files contain anything printed by the scripts and the `.error` files contain mapping and scripts errors.
* Path Data: Inspect debug outputs for issues in path retrieval.

## Example: gRPCServer MIB

Let's add a custom SNMP MIB to SR Linux at **runtime**, no feature requests, no software upgrades,
let it be a gRPC server SNMP MIB 🤪.

1. Add a new table definition under `/etc/opt/srlinux/snmp/scripts/grpc_mib.yaml`

This MIB has a single index `gRPCServerName` and 6 columns; the gRPC server network instance, its admin and operational states, the number of accepted and rejected RPCs as well as the last time an RPC was accepted.

All these fields can be mapped from leaves that can be found under the xpath `/system/grpc-server/...`

```yaml
###########################################################################
# Description:
#
# Copyright (c) 2024 Nokia
###########################################################################
# yaml-language-server: $schema=../table_definition_schema.json
paths:
- /system/grpc-server/...
python-script: grpc_mib.py
enabled: true
debug: true
tables:
- name: gRPCServerTable
enabled: true
oid: 1.3.6.1.4.1.6527.115.114.108.105.110.117.120
indexes:
- name: gRPCServerName
oid: 1.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.1
syntax: octet string
columns:
- name: grpcServerNetworkInstance
oid: 1.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.2
syntax: octet string
- name: grpcServerAdminState
oid: 1.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.3
syntax: integer
- name: grpcServerOperState
oid: 1.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.4
syntax: integer
- name: grpcServerAccessRejects
oid: 1.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.5
syntax: integer
- name: grpcServerAccessAccepts
oid: 1.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.6
syntax: integer
- name: grpcServerLastAccessAccept
oid: 1.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.7
syntax: timeticks
```

2. The YAML file points to a python script called `grpc_mib.py`. It must be placed in the same directory as the `grpc_mib.yaml` file.

The script is fairly simple; grabs the JSON input, set some global SNMP information such as the box boot time (useful for calculating time ticks values).
After that, it iterates over the list of gRPC servers in the input JSON and set each server's columns values (with the correct format) in the prepared output dict.
Finally it returns the output dict as a JSON blob.

```python
#!/usr/bin/python
###########################################################################
# Description:
#
# Copyright (c) 2024 Nokia
###########################################################################
import json
import utilities
SERVERADMINSTATUS_UP = 1
SERVERADMINSTATUS_DOWN = 2
IFOPERSTATUS_UP = 1
IFOPERSTATUS_DOWN = 2
# maps the gNMI admin status value to its corresponding SNMP value
def convertAdminStatus(value: str):
if value is not None:
if value == 'enable':
return SERVERADMINSTATUS_UP
elif value == 'disable':
return SERVERADMINSTATUS_DOWN
# maps the gNMI oper status value to its corresponding SNMP value
def convertOperStatus(value: str):
if value is not None:
if value == 'up':
return IFOPERSTATUS_UP
elif value == 'down':
return IFOPERSTATUS_DOWN
#
# main routine
#
def snmp_main(in_json_str: str) -> str:
in_json = json.loads(in_json_str)
del in_json_str
# read in general info from the snmp server
snmp_info = in_json.get('_snmp_info_')
utilities.process_snmp_info(snmp_info)
# prepare the output dict
output = {"tables": {"gRPCServerTable": []}}
# Iterate over all grpc-server instances
grpc_servers = in_json.get("system", {}).get("grpc-server", [])
for server in grpc_servers:
# Extract required fields
name = server.get("name", "")
statistics = server.get("statistics", {})
access_rejects = statistics.get("access-rejects", 0)
access_accepts = statistics.get("access-accepts", 0)
# Grab the last-access-accept timestamp
ts = utilities.parse_rfc3339_date(statistics.get("last-access-accept", 0))
# Convert it to timeTicks from boottime
last_access_accept = utilities.convertUnixTimeStampInTimeticks(ts)
# Append the object to the output
output["tables"]["gRPCServerTable"].append({
"objects": {
"gRPCServerName": name,
"grpcServerNetworkInstance": server.get("network-instance", ""),
"grpcServerAdminState": convertAdminStatus(server.get("admin-state", "")),
"grpcServerOperState": convertOperStatus(server.get("oper-state")),
"grpcServerAccessRejects": access_rejects,
"grpcServerAccessAccepts": access_accepts,
"grpcServerLastAccessAccept": last_access_accept
}
})
return json.dumps(output)
```

3. Reference the YAML mapping file in the user's `snmp_files_config.yaml` so that the SNMP server picks it up

```shell
cat /etc/opt/srlinux/snmp/snmp_files_config.yaml
table-definitions:
- scripts/grpc_mib.yaml
```

4. Restart the SNMP server process

```
--{ + running }--[ ]--
A:srl1# /tools system app-management application snmp_server-mgmt restart
/system/app-management/application[name=snmp_server-mgmt]:
Application 'snmp_server-mgmt' was killed with signal 9

/system/app-management/application[name=snmp_server-mgmt]:
Application 'snmp_server-mgmt' was restarted
```
5. Test your new MIB
```shell
$ snmpwalk -v2c -c public clab-snmp-srl1 1.3.6.1.4.1.6527.115
iso.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.2.4.109.103.109.116 = STRING: "mgmt" # <-- grpcServerNetworkInstance
iso.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.3.4.109.103.109.116 = INTEGER: 1 # <-- gRPCServerAdminState
iso.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.4.4.109.103.109.116 = INTEGER: 1 # <-- grpcServerOperState
iso.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.5.4.109.103.109.116 = INTEGER: 0 # <-- grpcServerAccessRejects
iso.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.6.4.109.103.109.116 = INTEGER: 3 # <-- grpcServerAccessAccepts
iso.3.6.1.4.1.6527.115.114.108.105.110.117.120.1.7.4.109.103.109.116 = Timeticks: (44659000) 5 days, 4:03:10.00 # <-- grpcServerLastAccessAccept
```

Have a look at `/tmp/snmp_debug` to see the input and output JSON blobs.

There you have it: A user-defined SNMP MIB added to SR Linux at **runtime**, no feature request, no software upgrade needed.

0 comments on commit 79509c6

Please sign in to comment.