Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d46b568
[change] NetJSON DeviceMonitoring compliance #2
purhan Jun 5, 2021
9168a27
[change] Add monitoring info to OpenWRT backend
purhan Jun 10, 2021
cfa6650
[chores] Fix failing tests
purhan Jun 11, 2021
c9962e2
[chores/qa] Improvements to tests
purhan Jun 13, 2021
8cd7089
[change] Add monitoring info to AirOS backend
purhan Jun 15, 2021
da39965
[chores] Some requested changes
purhan Jun 18, 2021
1800332
[chores] Fix neighbor information when mac address is not found
purhan Jun 25, 2021
cda0295
[change] Add IP to neighbor information
purhan Jul 5, 2021
0edc93a
[chores] Add comment
purhan Jul 6, 2021
acafe93
[change] Add more interfaces, Add RAM_used
purhan Jul 6, 2021
34f05c9
[change] Use one query for neighbors and their states
purhan Jul 7, 2021
034475c
[chores] Fix failing build
purhan Jul 12, 2021
995b703
[change] Implement SNMPDUMP
purhan Jul 16, 2021
83a25de
[change] Add device name, ip to interfaces
purhan Jul 22, 2021
0f37717
[change] Make interface types NetJSON compliant
purhan Jul 22, 2021
5dc3cc6
[change] Change RAM OIDs, add load info, add wireless interfaces
purhan Jul 26, 2021
d746f2d
[change] Use Trie instead of Dict in walk function
purhan Jul 29, 2021
56ea551
[docs] Update docs for AirOS and OpenWRT backends
purhan Aug 19, 2021
4e6f1f1
[chores] Move OpenWRT interface type to match AirOS
purhan Aug 19, 2021
5424532
[change] Add CPU_count to airOS
purhan Aug 23, 2021
621f725
[qa] Reformatted code and docs
nemesifier Jul 31, 2026
9b99213
Merge branch 'master' into netjson-compliance
nemesifier Jul 31, 2026
8f9254a
[fix] Added back jsonschema
nemesifier Jul 31, 2026
7bb97e3
[chores] Added device model, OS
nemesifier Jul 31, 2026
a32bb7c
[chores] Fixed bugs uncovered by Kilobot
nemesifier Jul 31, 2026
e50844e
[fix] Addressed @coderabbitai reviews
nemesifier Jul 31, 2026
4690657
[fix] Fixed more nasty bugs
nemesifier Jul 31, 2026
25db8fb
[fix] Renamed memory "cached" (bogus) to "cache" (correct)
nemesifier Aug 1, 2026
a89c8fe
[chores] Follow up with coderabbit
nemesifier Aug 1, 2026
436b1e3
[chores] Addressed @coderabbitai review comments
nemesifier Aug 1, 2026
c19ceff
Merge remote-tracking branch 'origin/master' into netjson-compliance
nemesifier Aug 1, 2026
6f0e676
[chores] Addressed @coderabbitai review comments
nemesifier Aug 1, 2026
ec706d0
[chores] Addressed @coderabbitai review comments
nemesifier Aug 1, 2026
78c93e1
[chores] Addressed @coderabbitai review comments
nemesifier Aug 1, 2026
f32abd8
[chores] Further cleanup
nemesifier Aug 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ jobs:
permissions:
id-token: write
steps:
- uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: '3.10'
- name: Install dependencies
run: |
pip install -U pip
pip install build
- name: Build package
run: python -m build
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@v1.14.2
- uses: actions/checkout@v7
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.10"
- name: Install dependencies
run: |
pip install -U pip
pip install build
- name: Build package
run: python -m build
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ build
test-settings.json
*.#
python
docs/_build
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ Contents:
.. toctree::
:maxdepth: 2

/topics/backends/snmp
/topics/usage
/topics/snmp

Indices and tables
------------------
Expand Down
105 changes: 105 additions & 0 deletions docs/source/topics/backends/snmp.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
SNMP backend
============

SNMP
----

SNMP (Simple Network Management Protocol) retrieves information from a
device through a tree of object identifiers (OIDs) defined by management
information bases (MIBs).

The base SNMP backend contains the following methods (some internal
methods are not documented and are subject to change in the future):

============ =============================================================
**to_dict** Returns a dict containing monitoring information depending on
the type of the device. It follows the `NetJSON
Devicemonitoring
<https://netjson.org/rfc.html#name-devicemonitoring>`_ spec
**to_json** Calls the `to_dict` method and returns a JSON string of the
dict
**validate** Checks if connection with the device is working and raises
`NetEngineError` in case something is wrong
============ =============================================================

``to_dict`` and ``to_json`` enable ``autowalk`` by default, collecting the
required OIDs before serializing the result. To serialize an existing SNMP
dump without querying the device, call ``to_dict(snmpdump=dump,
autowalk=False)``.

Initializing an SNMP backend class requires a host. The optional arguments
are:

============= ==========================================================
**host** Management ip or hostname of the device
**community** Community string for the SNMP connection. Default value is
'public'
**agent** Agent string for the SNMP connection. Default value is
'my-agent'
**port** Port for the SNMP connection. Default value is `161`
============= ==========================================================

The SNMP backend provides support for 2 firmwares:
- AirOS
- OpenWRT

.. note::

The data collected by Netengine is dependant on the OIDs available on
your device. Some proprietary manufacturers may not provide the same
information as others.

AirOS
=====

With AirOS, Netengine is able to collect the following information which
is returned in the `NetJSON Devicemonitoring
<https://netjson.org/rfc.html#name-devicemonitoring>`_ format:

Comment thread
coderabbitai[bot] marked this conversation as resolved.
- ``general``: uptime, local time, and hostname.
- ``hardware``: device model.
- ``operating_system``: name, description, and firmware version.
- ``resources``: CPU load, memory, and swap usage.
- ``interfaces``: name, MAC address, type, received bytes, and transmitted
bytes.

AirOS example
-------------

::

from netengine.backends.snmp import AirOS
device = AirOS("10.40.0.130")
device.name()
'RM5PomeziaSNode'
device.uptime()
104405

We have just called two simple methods on **device**, but we can ask **device** for more specific values or portions of the SNMP tree not included in the API, just type::
device.next("1.3.6")

Otherwise, if you want simply a value of the tree just type::
device.get_value("oid_you_want_to_ask_for")

To collect the whole json::
device.to_json()
Comment thread
coderabbitai[bot] marked this conversation as resolved.

OpenWRT
=======

With OpenWRT, Netengine is able to collect the following information which
is returned in the `NetJSON Devicemonitoring
<https://netjson.org/rfc.html#name-devicemonitoring>`_ format:

- ``general``: uptime, local time, and hostname.
- ``resources``: CPU count, memory, and swap usage.
- ``interfaces``: name, type, MAC address, state, traffic counters, MTU,
and addresses.
- ``neighbors``: MAC address, state, interface, and IP address.

OpenWRT example
---------------

The same instructions typed above can be applied to OpenWRT itself. Import
it with ``from netengine.backends.snmp import OpenWRT`` and use the same
methods described for AirOS.
44 changes: 0 additions & 44 deletions docs/source/topics/snmp.rst

This file was deleted.

8 changes: 4 additions & 4 deletions netengine/backends/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ def __repr__(self):
"""returns unicode string represantation"""
return self.__str__()

def validate(self):
def validate(self, *args, **kwargs):
raise NotImplementedError("Not implemented")

def to_dict(self):
def to_dict(self, autowalk=True):
raise NotImplementedError("Not implemented")

def to_json(self, **kwargs):
dictionary = self.to_dict()
def to_json(self, autowalk=True, **kwargs):
dictionary = self.to_dict(autowalk=autowalk)
return json.dumps(dictionary, **kwargs)

@property
Expand Down
2 changes: 1 addition & 1 deletion netengine/backends/dummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def get_interfaces(self):
},
]

def to_dict(self):
def to_dict(self, *args, **kwargs):
return self._dict(
{
"name": "dummy",
Expand Down
154 changes: 154 additions & 0 deletions netengine/backends/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# NetJSON DeviceMonitoring schema,
# https://github.com/netjson/netjson/blob/master/schema/device-monitoring.json
schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://raw.githubusercontent.com/netjson/netjson/master/schema/device-monitoring.json",
"title": "NetJSON Device Monitoring",
"description": "Monitoring information sent by a device.",
"type": "object",
"additionalProperties": True,
"required": ["type"],
"properties": {
"type": {"type": "string", "enum": ["DeviceMonitoring"]},
"general": {
"type": "object",
"title": "General",
"additionalProperties": True,
"properties": {
"local_time": {"type": "integer"},
"uptime": {"type": "integer"},
},
},
"resources": {
"type": "object",
"title": "Resources",
"additionalProperties": True,
"properties": {
"load": {
"type": "array",
"minItems": 3,
"maxItems": 3,
"items": {"type": "number"},
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"memory": {
"id": "memory",
"type": "object",
"properties": {
"total": {"type": "integer"},
"free": {"type": "integer"},
"buffered": {"type": "integer"},
"cache": {"type": "integer"},
},
},
"swap": {
"type": "object",
"properties": {
"total": {"type": "integer"},
"free": {"type": "integer"},
},
},
"connections": {
"type": "object",
"properties": {
"ipv4": {
"type": "object",
"properties": {
"tcp": {"type": "integer"},
"udp": {"type": "integer"},
},
},
"ipv6": {
"type": "object",
"properties": {
"tcp": {"type": "integer"},
"udp": {"type": "integer"},
},
},
},
},
"processes": {
"type": "object",
"properties": {
"running": {"type": "integer"},
"sleeping": {"type": "integer"},
"blocked": {"type": "integer"},
"zombie": {"type": "integer"},
"stopped": {"type": "integer"},
"paging": {"type": "integer"},
},
},
"cpu": {
"type": "object",
"properties": {
"frequency": {"type": "integer"},
"user": {"type": "integer"},
"system": {"type": "integer"},
"nice": {"type": "integer"},
"idle": {"type": "integer"},
"iowait": {"type": "integer"},
"irq": {"type": "integer"},
"softirq": {"type": "integer"},
},
},
"flash": {
"type": "object",
"properties": {
"total": {"type": "integer"},
"free": {"type": "integer"},
},
},
"storage": {
"type": "object",
"properties": {
"total": {"type": "integer"},
"free": {"type": "integer"},
},
},
},
},
"interfaces": {
"type": "array",
"title": "Interfaces",
"uniqueItems": True,
"additionalItems": True,
"items": {
"type": "object",
"title": "Interface",
"additionalProperties": True,
"required": ["name"],
"properties": {
"name": {"type": "string"},
"uptime": {"type": "integer"},
"statistics": {
"type": "object",
"properties": {
"collisions": {"type": "integer"},
"rx_frame_errors": {"type": "integer"},
"tx_compressed": {"type": "integer"},
"multicast": {"type": "integer"},
"rx_length_errors": {"type": "integer"},
"tx_dropped": {"type": "integer"},
"rx_bytes": {"type": "integer"},
"rx_missed_errors": {"type": "integer"},
"tx_errors": {"type": "integer"},
"rx_compressed": {"type": "integer"},
"rx_over_errors": {"type": "integer"},
"tx_fifo_errors": {"type": "integer"},
"rx_crc_errors": {"type": "integer"},
"rx_packets": {"type": "integer"},
"tx_heartbeat_errors": {"type": "integer"},
"rx_dropped": {"type": "integer"},
"tx_aborted_errors": {"type": "integer"},
"tx_packets": {"type": "integer"},
"rx_errors": {"type": "integer"},
"tx_bytes": {"type": "integer"},
"tx_window_errors": {"type": "integer"},
"rx_fifo_errors": {"type": "integer"},
"tx_carrier_errors": {"type": "integer"},
},
},
},
},
},
},
}
Loading