netdiff


Namenetdiff JSON
Version 1.1 PyPI version JSON
download
home_pagehttps://github.com/ninuxorg/netdiff
SummaryPython library for parsing network topology data (eg: dynamic routing protocols, NetJSON, CNML) and detect changes.
upload_time2024-08-14 18:43:18
maintainerNone
docs_urlNone
authorFederico Capoano
requires_pythonNone
licenseMIT
keywords networking mesh-network netjson olsr batman bmx
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            netdiff
=======

.. image:: https://github.com/openwisp/netdiff/workflows/OpenWISP%20CI%20Build/badge.svg?branch=master
    :target: https://github.com/openwisp/netdiff/actions?query=workflow%3A%22OpenWISP+CI+Build%22
    :alt: CI build status

.. image:: https://coveralls.io/repos/openwisp/netdiff/badge.svg
    :target: https://coveralls.io/r/openwisp/netdiff

.. image:: https://img.shields.io/librariesio/release/github/openwisp/netdiff
    :target: https://libraries.io/github/openwisp/netdiff#repository_dependencies
    :alt: Dependency monitoring

.. image:: https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square
    :target: https://gitter.im/openwisp/general

.. image:: https://badge.fury.io/py/netdiff.svg
    :target: http://badge.fury.io/py/netdiff

.. image:: https://pepy.tech/badge/netdiff
    :target: https://pepy.tech/project/netdiff
    :alt: downloads

.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
    :target: https://pypi.org/project/black/
    :alt: code style: black

----

Netdiff is a simple abstraction layer for parsing network topology data of
open source dynamic routing protocols or any other networking software
which has knowledge about the topology of a network.

Its goal is to allow applications like `openwisp-network-topology
<https://github.com/openwisp/openwisp-network-topology>`_ to collect,
visualize and monitor network topology data without having to deal with
the details of each networking software from which the data is retrieved.

**Features**:

- `parse different formats <https://github.com/openwisp/netdiff#parsers>`_
- `detect changes in two topologies
  <https://github.com/openwisp/netdiff#basic-usage-example>`_
- `return consistent NetJSON output
  <https://github.com/openwisp/netdiff#netjson-output>`_
- uses the popular `networkx <https://networkx.github.io/>`_ library under
  the hood

.. image:: https://raw.githubusercontent.com/openwisp/openwisp2-docs/master/assets/design/openwisp-logo-black.svg
    :target: http://openwisp.org

----

.. contents:: **Table of Contents**:
    :backlinks: none
    :depth: 3

----

Install stable version from pypi
--------------------------------

Install from pypi:

.. code-block:: shell

    pip install netdiff

Install development version
---------------------------

Install tarball:

.. code-block:: shell

    pip install https://github.com/openwisp/netdiff/tarball/master

Alternatively you can install via pip using git:

.. code-block:: shell

    pip install -e git+git://github.com/openwisp/netdiff#egg=netdiff

If you want to contribute, install your cloned fork:

.. code-block:: shell

    git clone git@github.com:<your_fork>/netdiff.git
    cd netdiff
    python setup.py develop

Basic Usage Example
-------------------

Calculate diff of an OLSR 0.6.x topology:

.. code-block:: python

    from netdiff import OlsrParser
    from netdiff import diff

    old = OlsrParser(file="./stored-olsr.json")
    new = OlsrParser(url="http://127.0.0.1:9090")
    diff(old, new)

In alternative, you may also use the subtraction operator:

.. code-block:: python

    from netdiff import OlsrParser
    from netdiff import diff

    old = OlsrParser(file="./stored-olsr.json")
    new = OlsrParser(url="http://127.0.0.1:9090")
    old - new

The output will be an ordered dictionary with three keys:

- added
- removed
- changed

Each key will contain a dict compatible with the `NetJSON NetworkGraph`_
format representing respectively:

- the nodes and links that have been added to the topology
- the nodes and links that have been removed from the topology
- the nodes and links that are present in both topologies but their
  attributes have changed

If no changes are present, keys will contain ``None``.

So if between ``old`` and ``new`` there are no changes, the result will
be:

.. code-block:: python

    {"added": None, "removed": None, "changed": None}

While if there are changes, the result will look like:

.. code-block:: python

    {
        "added": {
            "type": "NetworkGraph",
            "protocol": "OLSR",
            "version": "0.6.6",
            "revision": "5031a799fcbe17f61d57e387bc3806de",
            "metric": "ETX",
            "nodes": [
                {
                    "id": "10.150.0.7",
                    "label": "Node A",
                    "local_addresses": [],
                    "properties": {},
                },
                {
                    "id": "10.150.0.6",
                    "label": "Node B",
                    "local_addresses": ["10.56.2.1"],
                    "properties": {"hostname": "nodeb.lan"},
                },
            ],
            "links": [
                {
                    "source": "10.150.0.3",
                    "target": "10.150.0.7",
                    "cost": 1.50390625,
                    "cost_text": "",
                    "properties": {},
                },
                {
                    "source": "10.150.0.3",
                    "target": "10.150.0.6",
                    "cost": 1.0,
                    "cost_text": "",
                    "properties": {},
                },
            ],
        },
        "removed": {
            "type": "NetworkGraph",
            "protocol": "OLSR",
            "version": "0.6.6",
            "revision": "5031a799fcbe17f61d57e387bc3806de",
            "metric": "ETX",
            "nodes": [
                {
                    "id": "10.150.0.8",
                    "label": "Node C",
                    "local_addresses": [],
                    "properties": {},
                }
            ],
            "links": [
                {
                    "source": "10.150.0.7",
                    "target": "10.150.0.8",
                    "cost": 1.0,
                    "cost_text": "",
                    "properties": {},
                }
            ],
        },
        "changed": {
            "type": "NetworkGraph",
            "protocol": "OLSR",
            "version": "0.6.6",
            "revision": "5031a799fcbe17f61d57e387bc3806de",
            "metric": "ETX",
            "nodes": [],
            "links": [
                {
                    "source": "10.150.0.3",
                    "target": "10.150.0.2",
                    "cost": 1.0,
                    "cost_text": "",
                    "properties": {},
                }
            ],
        },
    }

Parsers
-------

Parsers are classes that extend ``netdiff.base.BaseParser`` and implement
a ``parse`` method which is in charge of converting a python data
structure into ``networkx.Graph`` object and return the result.

Parsers also have a ``json`` method which returns valid `NetJSON output
<https://github.com/openwisp/netdiff#netjson-output>`_.

The available parsers are:

- ``netdiff.OlsrParser``: parser for the `olsrd jsoninfo plugin
  <http://www.olsr.org/?q=jsoninfo_plugin>`_ or the older `txtinfo plugin
  <http://www.olsr.org/?q=txtinfo_plugin>`_
- ``netdiff.BatmanParser``: parser for the `batman-advanced alfred tool
  <http://www.open-mesh.org/projects/open-mesh/wiki/Alfred>`_ (supports
  also the legacy txtinfo format inherited from olsrd)
- ``netdiff.Bmx6Parser``: parser for the BMX6 `b6m tool
  <http://dev.qmp.cat/projects/b6m>`_
- ``netdiff.CnmlParser``: parser for `CNML 0.1
  <http://en.wiki.guifi.net/wiki/CNML>`_
- ``netdiff.NetJsonParser``: parser for the `NetJSON NetworkGraph`_ format
- ``netdiff.OpenvpnParser``: parser for the `OpenVPN status file
  <https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage>`_
- ``netdiff.WireguardParser``: parser for the Wireguard VPN (the command
  to use is ``wg show all dump``)
- ``netdiff.ZeroTierParser``: parser for ZeroTier VPN (the command to use
  is ``zerotier-cli peers -j`` or access the peers information through the
  `ZeroTier Service API
  <https://docs.zerotier.com/service/v1/#operation/getPeers>`_)

Initialization arguments
~~~~~~~~~~~~~~~~~~~~~~~~

Data can be supplied in 3 different ways, in the following order of
precedence:

- ``data``: ``dict`` or ``str`` representing the topology/graph
- ``url``: URL to fetch data from
- ``file``: file path to retrieve data from

Other available arguments:

- **timeout**: integer representing timeout in seconds for HTTP or telnet
  requests, defaults to ``None``
- **verify**: boolean indicating to the `request library whether to do SSL
  certificate verification or not
  <http://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification>`_
- **directed**: boolean that enables the use of a directed graph
  (``networkx.DiGraph``), defaults to ``False``

Initialization examples
~~~~~~~~~~~~~~~~~~~~~~~

Local file example:

.. code-block:: python

    from netdiff import BatmanParser

    BatmanParser(file="./my-stored-topology.json")

HTTP example:

.. code-block:: python

    from netdiff import NetJsonParser

    url = "https://raw.githubusercontent.com/interop-dev/netjson/master/examples/network-graph.json"
    NetJsonParser(url=url)

Telnet example with ``timeout``:

.. code-block:: python

    from netdiff import OlsrParser

    OlsrParser(url="telnet://127.0.1", timeout=5)

HTTPS example with self-signed SSL certificate using ``verify=False``:

.. code-block:: python

    from netdiff import NetJsonParser

    OlsrParser(
        url="https://myserver.mydomain.com/topology.json", verify=False
    )

NetJSON output
--------------

Netdiff parsers can return a valid `NetJSON NetworkGraph`_ object:

.. code-block:: python

    from netdiff import OlsrParser

    olsr = OlsrParser(url="telnet://127.0.0.1:9090")

    # will return a dict
    olsr.json(dict=True)

    # will return a JSON formatted string
    print(olsr.json(indent=4))

Output:

.. code-block:: javascript

    {
        "type": "NetworkGraph",
        "protocol": "OLSR",
        "version": "0.6.6",
        "revision": "5031a799fcbe17f61d57e387bc3806de",
        "metric": "ETX",
        "nodes": [
            {
                "id": "10.150.0.3"
            },
            {
                "id": "10.150.0.2"
            },
            {
                "id": "10.150.0.4"
            }
        ],
        "links": [
            {
                "source": "10.150.0.3",
                "target": "10.150.0.2",
                "cost": 2.4
            },
            {
                "source": "10.150.0.3",
                "target": "10.150.0.4",
                "cost": 1.0
            }
        ]
    }

Exceptions
----------

All the exceptions are subclasses of
``netdiff.exceptions.NetdiffException``.

ConversionException
~~~~~~~~~~~~~~~~~~~

``netdiff.exceptions.ConversionException``

Raised when netdiff can't recognize the format passed to the parser.

Not necessarily an error, should be caught and managed in order to support
additional formats.

The data which was retrieved from network/storage can be accessed via the
"data" attribute, eg:

.. code-block:: python

    def to_python(self, data):
        try:
            return super().to_python(data)
        except ConversionException as e:
            return self._txtinfo_to_jsoninfo(e.data)

ParserError
~~~~~~~~~~~

``netdiff.exceptions.ParserError``

Raised when the format is recognized but the data is invalid.

NetJsonError
~~~~~~~~~~~~

``netdiff.exceptions.NetJsonError``

Raised when the ``json`` method of ``netdiff.parsers.BaseParser`` does not
have enough data to be compliant with the `NetJSON NetworkGraph`_
specification.

TopologyRetrievalError
~~~~~~~~~~~~~~~~~~~~~~

``netdiff.exceptions.TopologyRetrievalError``

Raised when it is not possible to retrieve the topology data (eg: the URL
might be temporary unreachable).

Specialized features
--------------------

OpenVPN
~~~~~~~

By default, the OpenVPN parser uses the common name to identify a client,
this was chosen because if the public IP address is used, the same client
will not be recognized if it connects with a different IP address (very
probable since many ISPs use dynamic public IP addresses).

This does not work when the vpn server configuration allows different
clients to use the same common name (which is generally not recommended
anyway).

If you need to support legacy systems which are configured with the
OpenVPN ``duplicate-cn`` feature enabled, you can pass
``duplicate_cn=True`` during the initialization of ``OpenvpnParser``. This
will change the behavior of the parser so that each client is identified
by their common name and IP address (and additionally the port used if
there are multiple clients with same common name and IP).

Known Issues
------------

ConnectionError: BadStatusLine
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you get a similar error when performing a request to the `jsoninfo
plugin <http://www.olsr.org/?q=jsoninfo_plugin>`_ of `olsrd
<http://www.olsr.org/>`_ (version 0.6 to 0.9) chances are high that http
headers are disabled.

To fix it turn on http headers in your olsrd configuration file, eg:

::

    LoadPlugin "olsrd_jsoninfo.so.0.0"
    {
        PlParam "httpheaders" "yes"   # add this line
        PlParam "Port" "9090"
        PlParam "accept" "0.0.0.0"
    }

Running tests
-------------

Install your forked repo:

.. code-block:: shell

    git clone git://github.com/<your_fork>/netdiff
    cd netdiff/
    python setup.py develop

Install test requirements:

.. code-block:: shell

    pip install -r requirements-test.txt

Run tests with:

.. code-block:: shell

    ./runtests.py
    ./run-qa-checks

Alternatively, you can use the ``nose2`` command (which has a ton of
available options):

.. code-block:: shell

    nose2
    nose2 tests.test_olsr  # run only olsr related tests
    nose2 tests/test_olsr.py  # variant form of the previous command
    nose2 tests.test_olsr:TestOlsrParser  # variant form of the previous command
    nose2 tests.test_olsr:TestOlsrParser.test_parse  # run specific test

See test coverage with:

.. code-block:: shell

    coverage run --source=netdiff runtests.py && coverage report

Contributing
------------

Please refer to the `OpenWISP contributing guidelines
<http://openwisp.io/docs/developer/contributing.html>`_.

Support
-------

See `OpenWISP Support Channels <http://openwisp.org/support.html>`_.

Changelog
---------

See `CHANGES
<https://github.com/openwisp/netdiff/blob/master/CHANGES.rst>`_.

License
-------

See `LICENSE <https://github.com/openwisp/netdiff/blob/master/LICENSE>`_.

.. _netjson networkgraph: http://netjson.org/rfc.html#rfc.section.4

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/ninuxorg/netdiff",
    "name": "netdiff",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "networking, mesh-network, netjson, olsr, batman, bmx",
    "author": "Federico Capoano",
    "author_email": "federico.capoano@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/09/ea/11dcb049598c8bd991fb66bc8573bd398bc314d51a27ff309668dbb71379/netdiff-1.1.tar.gz",
    "platform": "Platform Independent",
    "description": "netdiff\n=======\n\n.. image:: https://github.com/openwisp/netdiff/workflows/OpenWISP%20CI%20Build/badge.svg?branch=master\n    :target: https://github.com/openwisp/netdiff/actions?query=workflow%3A%22OpenWISP+CI+Build%22\n    :alt: CI build status\n\n.. image:: https://coveralls.io/repos/openwisp/netdiff/badge.svg\n    :target: https://coveralls.io/r/openwisp/netdiff\n\n.. image:: https://img.shields.io/librariesio/release/github/openwisp/netdiff\n    :target: https://libraries.io/github/openwisp/netdiff#repository_dependencies\n    :alt: Dependency monitoring\n\n.. image:: https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square\n    :target: https://gitter.im/openwisp/general\n\n.. image:: https://badge.fury.io/py/netdiff.svg\n    :target: http://badge.fury.io/py/netdiff\n\n.. image:: https://pepy.tech/badge/netdiff\n    :target: https://pepy.tech/project/netdiff\n    :alt: downloads\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n    :target: https://pypi.org/project/black/\n    :alt: code style: black\n\n----\n\nNetdiff is a simple abstraction layer for parsing network topology data of\nopen source dynamic routing protocols or any other networking software\nwhich has knowledge about the topology of a network.\n\nIts goal is to allow applications like `openwisp-network-topology\n<https://github.com/openwisp/openwisp-network-topology>`_ to collect,\nvisualize and monitor network topology data without having to deal with\nthe details of each networking software from which the data is retrieved.\n\n**Features**:\n\n- `parse different formats <https://github.com/openwisp/netdiff#parsers>`_\n- `detect changes in two topologies\n  <https://github.com/openwisp/netdiff#basic-usage-example>`_\n- `return consistent NetJSON output\n  <https://github.com/openwisp/netdiff#netjson-output>`_\n- uses the popular `networkx <https://networkx.github.io/>`_ library under\n  the hood\n\n.. image:: https://raw.githubusercontent.com/openwisp/openwisp2-docs/master/assets/design/openwisp-logo-black.svg\n    :target: http://openwisp.org\n\n----\n\n.. contents:: **Table of Contents**:\n    :backlinks: none\n    :depth: 3\n\n----\n\nInstall stable version from pypi\n--------------------------------\n\nInstall from pypi:\n\n.. code-block:: shell\n\n    pip install netdiff\n\nInstall development version\n---------------------------\n\nInstall tarball:\n\n.. code-block:: shell\n\n    pip install https://github.com/openwisp/netdiff/tarball/master\n\nAlternatively you can install via pip using git:\n\n.. code-block:: shell\n\n    pip install -e git+git://github.com/openwisp/netdiff#egg=netdiff\n\nIf you want to contribute, install your cloned fork:\n\n.. code-block:: shell\n\n    git clone git@github.com:<your_fork>/netdiff.git\n    cd netdiff\n    python setup.py develop\n\nBasic Usage Example\n-------------------\n\nCalculate diff of an OLSR 0.6.x topology:\n\n.. code-block:: python\n\n    from netdiff import OlsrParser\n    from netdiff import diff\n\n    old = OlsrParser(file=\"./stored-olsr.json\")\n    new = OlsrParser(url=\"http://127.0.0.1:9090\")\n    diff(old, new)\n\nIn alternative, you may also use the subtraction operator:\n\n.. code-block:: python\n\n    from netdiff import OlsrParser\n    from netdiff import diff\n\n    old = OlsrParser(file=\"./stored-olsr.json\")\n    new = OlsrParser(url=\"http://127.0.0.1:9090\")\n    old - new\n\nThe output will be an ordered dictionary with three keys:\n\n- added\n- removed\n- changed\n\nEach key will contain a dict compatible with the `NetJSON NetworkGraph`_\nformat representing respectively:\n\n- the nodes and links that have been added to the topology\n- the nodes and links that have been removed from the topology\n- the nodes and links that are present in both topologies but their\n  attributes have changed\n\nIf no changes are present, keys will contain ``None``.\n\nSo if between ``old`` and ``new`` there are no changes, the result will\nbe:\n\n.. code-block:: python\n\n    {\"added\": None, \"removed\": None, \"changed\": None}\n\nWhile if there are changes, the result will look like:\n\n.. code-block:: python\n\n    {\n        \"added\": {\n            \"type\": \"NetworkGraph\",\n            \"protocol\": \"OLSR\",\n            \"version\": \"0.6.6\",\n            \"revision\": \"5031a799fcbe17f61d57e387bc3806de\",\n            \"metric\": \"ETX\",\n            \"nodes\": [\n                {\n                    \"id\": \"10.150.0.7\",\n                    \"label\": \"Node A\",\n                    \"local_addresses\": [],\n                    \"properties\": {},\n                },\n                {\n                    \"id\": \"10.150.0.6\",\n                    \"label\": \"Node B\",\n                    \"local_addresses\": [\"10.56.2.1\"],\n                    \"properties\": {\"hostname\": \"nodeb.lan\"},\n                },\n            ],\n            \"links\": [\n                {\n                    \"source\": \"10.150.0.3\",\n                    \"target\": \"10.150.0.7\",\n                    \"cost\": 1.50390625,\n                    \"cost_text\": \"\",\n                    \"properties\": {},\n                },\n                {\n                    \"source\": \"10.150.0.3\",\n                    \"target\": \"10.150.0.6\",\n                    \"cost\": 1.0,\n                    \"cost_text\": \"\",\n                    \"properties\": {},\n                },\n            ],\n        },\n        \"removed\": {\n            \"type\": \"NetworkGraph\",\n            \"protocol\": \"OLSR\",\n            \"version\": \"0.6.6\",\n            \"revision\": \"5031a799fcbe17f61d57e387bc3806de\",\n            \"metric\": \"ETX\",\n            \"nodes\": [\n                {\n                    \"id\": \"10.150.0.8\",\n                    \"label\": \"Node C\",\n                    \"local_addresses\": [],\n                    \"properties\": {},\n                }\n            ],\n            \"links\": [\n                {\n                    \"source\": \"10.150.0.7\",\n                    \"target\": \"10.150.0.8\",\n                    \"cost\": 1.0,\n                    \"cost_text\": \"\",\n                    \"properties\": {},\n                }\n            ],\n        },\n        \"changed\": {\n            \"type\": \"NetworkGraph\",\n            \"protocol\": \"OLSR\",\n            \"version\": \"0.6.6\",\n            \"revision\": \"5031a799fcbe17f61d57e387bc3806de\",\n            \"metric\": \"ETX\",\n            \"nodes\": [],\n            \"links\": [\n                {\n                    \"source\": \"10.150.0.3\",\n                    \"target\": \"10.150.0.2\",\n                    \"cost\": 1.0,\n                    \"cost_text\": \"\",\n                    \"properties\": {},\n                }\n            ],\n        },\n    }\n\nParsers\n-------\n\nParsers are classes that extend ``netdiff.base.BaseParser`` and implement\na ``parse`` method which is in charge of converting a python data\nstructure into ``networkx.Graph`` object and return the result.\n\nParsers also have a ``json`` method which returns valid `NetJSON output\n<https://github.com/openwisp/netdiff#netjson-output>`_.\n\nThe available parsers are:\n\n- ``netdiff.OlsrParser``: parser for the `olsrd jsoninfo plugin\n  <http://www.olsr.org/?q=jsoninfo_plugin>`_ or the older `txtinfo plugin\n  <http://www.olsr.org/?q=txtinfo_plugin>`_\n- ``netdiff.BatmanParser``: parser for the `batman-advanced alfred tool\n  <http://www.open-mesh.org/projects/open-mesh/wiki/Alfred>`_ (supports\n  also the legacy txtinfo format inherited from olsrd)\n- ``netdiff.Bmx6Parser``: parser for the BMX6 `b6m tool\n  <http://dev.qmp.cat/projects/b6m>`_\n- ``netdiff.CnmlParser``: parser for `CNML 0.1\n  <http://en.wiki.guifi.net/wiki/CNML>`_\n- ``netdiff.NetJsonParser``: parser for the `NetJSON NetworkGraph`_ format\n- ``netdiff.OpenvpnParser``: parser for the `OpenVPN status file\n  <https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage>`_\n- ``netdiff.WireguardParser``: parser for the Wireguard VPN (the command\n  to use is ``wg show all dump``)\n- ``netdiff.ZeroTierParser``: parser for ZeroTier VPN (the command to use\n  is ``zerotier-cli peers -j`` or access the peers information through the\n  `ZeroTier Service API\n  <https://docs.zerotier.com/service/v1/#operation/getPeers>`_)\n\nInitialization arguments\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nData can be supplied in 3 different ways, in the following order of\nprecedence:\n\n- ``data``: ``dict`` or ``str`` representing the topology/graph\n- ``url``: URL to fetch data from\n- ``file``: file path to retrieve data from\n\nOther available arguments:\n\n- **timeout**: integer representing timeout in seconds for HTTP or telnet\n  requests, defaults to ``None``\n- **verify**: boolean indicating to the `request library whether to do SSL\n  certificate verification or not\n  <http://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification>`_\n- **directed**: boolean that enables the use of a directed graph\n  (``networkx.DiGraph``), defaults to ``False``\n\nInitialization examples\n~~~~~~~~~~~~~~~~~~~~~~~\n\nLocal file example:\n\n.. code-block:: python\n\n    from netdiff import BatmanParser\n\n    BatmanParser(file=\"./my-stored-topology.json\")\n\nHTTP example:\n\n.. code-block:: python\n\n    from netdiff import NetJsonParser\n\n    url = \"https://raw.githubusercontent.com/interop-dev/netjson/master/examples/network-graph.json\"\n    NetJsonParser(url=url)\n\nTelnet example with ``timeout``:\n\n.. code-block:: python\n\n    from netdiff import OlsrParser\n\n    OlsrParser(url=\"telnet://127.0.1\", timeout=5)\n\nHTTPS example with self-signed SSL certificate using ``verify=False``:\n\n.. code-block:: python\n\n    from netdiff import NetJsonParser\n\n    OlsrParser(\n        url=\"https://myserver.mydomain.com/topology.json\", verify=False\n    )\n\nNetJSON output\n--------------\n\nNetdiff parsers can return a valid `NetJSON NetworkGraph`_ object:\n\n.. code-block:: python\n\n    from netdiff import OlsrParser\n\n    olsr = OlsrParser(url=\"telnet://127.0.0.1:9090\")\n\n    # will return a dict\n    olsr.json(dict=True)\n\n    # will return a JSON formatted string\n    print(olsr.json(indent=4))\n\nOutput:\n\n.. code-block:: javascript\n\n    {\n        \"type\": \"NetworkGraph\",\n        \"protocol\": \"OLSR\",\n        \"version\": \"0.6.6\",\n        \"revision\": \"5031a799fcbe17f61d57e387bc3806de\",\n        \"metric\": \"ETX\",\n        \"nodes\": [\n            {\n                \"id\": \"10.150.0.3\"\n            },\n            {\n                \"id\": \"10.150.0.2\"\n            },\n            {\n                \"id\": \"10.150.0.4\"\n            }\n        ],\n        \"links\": [\n            {\n                \"source\": \"10.150.0.3\",\n                \"target\": \"10.150.0.2\",\n                \"cost\": 2.4\n            },\n            {\n                \"source\": \"10.150.0.3\",\n                \"target\": \"10.150.0.4\",\n                \"cost\": 1.0\n            }\n        ]\n    }\n\nExceptions\n----------\n\nAll the exceptions are subclasses of\n``netdiff.exceptions.NetdiffException``.\n\nConversionException\n~~~~~~~~~~~~~~~~~~~\n\n``netdiff.exceptions.ConversionException``\n\nRaised when netdiff can't recognize the format passed to the parser.\n\nNot necessarily an error, should be caught and managed in order to support\nadditional formats.\n\nThe data which was retrieved from network/storage can be accessed via the\n\"data\" attribute, eg:\n\n.. code-block:: python\n\n    def to_python(self, data):\n        try:\n            return super().to_python(data)\n        except ConversionException as e:\n            return self._txtinfo_to_jsoninfo(e.data)\n\nParserError\n~~~~~~~~~~~\n\n``netdiff.exceptions.ParserError``\n\nRaised when the format is recognized but the data is invalid.\n\nNetJsonError\n~~~~~~~~~~~~\n\n``netdiff.exceptions.NetJsonError``\n\nRaised when the ``json`` method of ``netdiff.parsers.BaseParser`` does not\nhave enough data to be compliant with the `NetJSON NetworkGraph`_\nspecification.\n\nTopologyRetrievalError\n~~~~~~~~~~~~~~~~~~~~~~\n\n``netdiff.exceptions.TopologyRetrievalError``\n\nRaised when it is not possible to retrieve the topology data (eg: the URL\nmight be temporary unreachable).\n\nSpecialized features\n--------------------\n\nOpenVPN\n~~~~~~~\n\nBy default, the OpenVPN parser uses the common name to identify a client,\nthis was chosen because if the public IP address is used, the same client\nwill not be recognized if it connects with a different IP address (very\nprobable since many ISPs use dynamic public IP addresses).\n\nThis does not work when the vpn server configuration allows different\nclients to use the same common name (which is generally not recommended\nanyway).\n\nIf you need to support legacy systems which are configured with the\nOpenVPN ``duplicate-cn`` feature enabled, you can pass\n``duplicate_cn=True`` during the initialization of ``OpenvpnParser``. This\nwill change the behavior of the parser so that each client is identified\nby their common name and IP address (and additionally the port used if\nthere are multiple clients with same common name and IP).\n\nKnown Issues\n------------\n\nConnectionError: BadStatusLine\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIf you get a similar error when performing a request to the `jsoninfo\nplugin <http://www.olsr.org/?q=jsoninfo_plugin>`_ of `olsrd\n<http://www.olsr.org/>`_ (version 0.6 to 0.9) chances are high that http\nheaders are disabled.\n\nTo fix it turn on http headers in your olsrd configuration file, eg:\n\n::\n\n    LoadPlugin \"olsrd_jsoninfo.so.0.0\"\n    {\n        PlParam \"httpheaders\" \"yes\"   # add this line\n        PlParam \"Port\" \"9090\"\n        PlParam \"accept\" \"0.0.0.0\"\n    }\n\nRunning tests\n-------------\n\nInstall your forked repo:\n\n.. code-block:: shell\n\n    git clone git://github.com/<your_fork>/netdiff\n    cd netdiff/\n    python setup.py develop\n\nInstall test requirements:\n\n.. code-block:: shell\n\n    pip install -r requirements-test.txt\n\nRun tests with:\n\n.. code-block:: shell\n\n    ./runtests.py\n    ./run-qa-checks\n\nAlternatively, you can use the ``nose2`` command (which has a ton of\navailable options):\n\n.. code-block:: shell\n\n    nose2\n    nose2 tests.test_olsr  # run only olsr related tests\n    nose2 tests/test_olsr.py  # variant form of the previous command\n    nose2 tests.test_olsr:TestOlsrParser  # variant form of the previous command\n    nose2 tests.test_olsr:TestOlsrParser.test_parse  # run specific test\n\nSee test coverage with:\n\n.. code-block:: shell\n\n    coverage run --source=netdiff runtests.py && coverage report\n\nContributing\n------------\n\nPlease refer to the `OpenWISP contributing guidelines\n<http://openwisp.io/docs/developer/contributing.html>`_.\n\nSupport\n-------\n\nSee `OpenWISP Support Channels <http://openwisp.org/support.html>`_.\n\nChangelog\n---------\n\nSee `CHANGES\n<https://github.com/openwisp/netdiff/blob/master/CHANGES.rst>`_.\n\nLicense\n-------\n\nSee `LICENSE <https://github.com/openwisp/netdiff/blob/master/LICENSE>`_.\n\n.. _netjson networkgraph: http://netjson.org/rfc.html#rfc.section.4\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python library for parsing network topology data (eg: dynamic routing protocols, NetJSON, CNML) and detect changes.",
    "version": "1.1",
    "project_urls": {
        "Download": "https://github.com/ninuxorg/netdiff/releases",
        "Homepage": "https://github.com/ninuxorg/netdiff"
    },
    "split_keywords": [
        "networking",
        " mesh-network",
        " netjson",
        " olsr",
        " batman",
        " bmx"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "52a1334ad0185cda212caece42929443461f91c27efda9fdfa522b883c02a1de",
                "md5": "2e42566ed7626706005b28d82aebf915",
                "sha256": "967ec2f292c0c628f9e6ab0131e17e579e81af9f35ae1e66c2e3f5d97b376e69"
            },
            "downloads": -1,
            "filename": "netdiff-1.1-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "2e42566ed7626706005b28d82aebf915",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": null,
            "size": 21417,
            "upload_time": "2024-08-14T18:43:17",
            "upload_time_iso_8601": "2024-08-14T18:43:17.046659Z",
            "url": "https://files.pythonhosted.org/packages/52/a1/334ad0185cda212caece42929443461f91c27efda9fdfa522b883c02a1de/netdiff-1.1-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "09ea11dcb049598c8bd991fb66bc8573bd398bc314d51a27ff309668dbb71379",
                "md5": "61cf7bec32002db71ef1faf1a9ef4020",
                "sha256": "aef337e7c628762699baa18cb5fdf04b2db05ac83142d5fa4b0b290dfd8391c6"
            },
            "downloads": -1,
            "filename": "netdiff-1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "61cf7bec32002db71ef1faf1a9ef4020",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 33779,
            "upload_time": "2024-08-14T18:43:18",
            "upload_time_iso_8601": "2024-08-14T18:43:18.292638Z",
            "url": "https://files.pythonhosted.org/packages/09/ea/11dcb049598c8bd991fb66bc8573bd398bc314d51a27ff309668dbb71379/netdiff-1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-08-14 18:43:18",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "ninuxorg",
    "github_project": "netdiff",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "netdiff"
}
        
Elapsed time: 0.37359s