Skip to main content

Netconf plugin for nornir using ncclient

Project description

Nornir NETCONF

codecov Build Status

Collection of NETCONF tasks and connection plugin for Nornir

Documentation

Documentation is generated with Sphinx and hosted with Github Pages. Documentation

To generate the latest documentation locally:

sphinx-build -vvv -b html ./docs ./docs/public
cd docs/public
python -m http.server

Installation


pip install nornir_netconf

Plugins


Connections


  • netconf - Connect to network devices using ncclient

Tasks


  • netconf_capabilities - Return server capabilities from target
  • netconf_get - Returns state data based on the supplied xpath
  • netconf_get_config - Returns configuration from specified configuration store (default="running")
  • netconf_edit_config - Edits configuration on specified datastore (default="running")
  • netconf_lock - Locks or Unlocks a specified datastore (default="lock")
  • netconf_commit - Commits a change

Response Result

The goal of the task results is to put the NETCONF RPC-reply back in your hands. An 'rpc' key will be available which can then be used to access 'data_xml' or 'xml' depending on the type of response or any other attributes available, such as 'error', 'errors'. Some of the RPC is unpacked and provided back as part of the Result by default, including the 'error', 'errors' and 'ok' if available. Anything else can be accessed directly from the rpc.

Furthermore, some tasks allow the 'xml_dict' boolean argument. This will take the response RPC XML and convert it into a python dictionary. Keep in mind, this may not be perfect as XML does't quite translate 100% into a python dictionary.

For example, an xml response can include a collapsed response with open/close as so: <ok/> If parsed into python dictionary using xml_dict argument, the key of 'ok' will have a value of none. However, if we were to be parsing <enabled>True</enabled> this would show a key of 'enabled' and a value of 'True'.

This is a simple built-in solution available, but not the only one. You have the RPC as part of the response and you are able to parse it anyway or method which works better for you.

Global Lock

The netconf_lock task will always return the Manager object, which is the established (and locked) agent used to send RPC's back and forth. The idea of retrieving the Manager is to carry this established locked session from task to task and only lock and unlock once during a run of tasks. Please review the examples below to see how to extract the manager and store it under the task.host dictionary as a variable which can be used across multiple tasks. The Manager is passed into other tasks and re-used to send RPCs to the remote server.

Examples

Head over to the Examples directory if you'd like to review the files.

Directory Structure
├── example-project
│   ├── config.yml
│   ├── inventory
│      ├── groups.yml
│      ├── hosts-local.yml
│      └── ssh_config
│   ├── logs
│      └── nornir.log
│   └── nr-get-config.py
└── README.md
Netconf Connection Plugin

Below is the snippet of a host inside the host-local.yml file and it's associated group, 'sros'.

nokia_rtr:
  hostname: "192.168.1.205"
  port: 830
  groups:
    - "sros"
sros:
  username: "netconf"
  password: "NCadmin123"
  port: 830
  platform: "sros"
  connection_options:
    netconf:
      extras:
        hostkey_verify: false
        timeout: 300
        allow_agent: false
        look_for_keys: false
Task: Get Config
"""Nornir NETCONF Example Task: 'get-config'."""
from nornir import InitNornir
from nornir_utils.plugins.functions import print_result
from nornir_netconf.plugins.tasks import netconf_get_config


__author__ = "Hugo Tinoco"
__email__ = "hugotinoco@icloud.com"

nr = InitNornir("config.yml")

# Filter the hosts by 'west-region' assignment
west_region = nr.filter(region="west-region")


def example_netconf_get_config(task):
    """Test get config."""

    task.run(
        netconf_get_config,
        source="running",
        path="""
        <configure xmlns="urn:nokia.com:sros:ns:yang:sr:conf">
            <router>
                <router-name>Base</router-name>
            </router>
        </configure>
        """,
        filter_type="subtree",
    )


def main():
    """Execute Nornir Script."""
    print_result(west_region.run(task=example_netconf_get_config))


if __name__ == "__main__":
    main()
Task: Get Capabilities
"""Nornir NETCONF Example Task: 'get-config'."""
from nornir import InitNornir
from nornir_utils.plugins.functions import print_result
from nornir_netconf.plugins.tasks import netconf_capabilities


__author__ = "Hugo Tinoco"
__email__ = "hugotinoco@icloud.com"

nr = InitNornir("config.yml")

# Filter the hosts by 'west-region' assignment
west_region = nr.filter(region="west-region")


def example_netconf_get_capabilities(task):
    """Test get capabilities."""
    task.run(netconf_capabilities)


def main():
    """Execute Nornir Script."""
    print_result(west_region.run(task=example_netconf_get_capabilities))


if __name__ == "__main__":
    main()
Task: Edit-Config with Global Lock
"""Nornir NETCONF Example Task: 'edit-config', 'netconf_lock'."""
from nornir import InitNornir
from nornir_utils.plugins.functions import print_result
from nornir_netconf.plugins.tasks import netconf_edit_config, netconf_lock, netconf_commit


__author__ = "Hugo Tinoco"
__email__ = "hugotinoco@icloud.com"

nr = InitNornir("config.yml")

# Filter the hosts by 'west-region' assignment
west_region = nr.filter(region="west-region")


def example_global_lock(task):
    """Test global lock operation of 'candidate' datastore."""
    lock = task.run(netconf_lock, datastore="candidate", operation="lock")
    # Retrieve the Manager(agent) from lock operation and store for further
    # operations.
    task.host["manager"] = lock.result["manager"]


def example_edit_config(task):
    """Test edit-config with global lock using manager agent."""

    config_payload = """
    <config>
        <configure xmlns="urn:nokia.com:sros:ns:yang:sr:conf">
            <router>
                <router-name>Base</router-name>
                <interface>
                    <interface-name>L3-OAM-eNodeB069420-X1</interface-name>
                    <admin-state>disable</admin-state>
                    <ingress-stats>false</ingress-stats>
                </interface>
            </router>
        </configure>
    </config>
    """

    result = task.run(
        netconf_edit_config, config=config_payload, target="candidate", manager=task.host["manager"], xmldict=True
    )

    # Access the RPC response object directly.
    # Or you can check the 'ok' attr from an rpc response as well, if it exists.
    if "ok" in result.result["rpc"].data_xml:
        task.run(netconf_commit, manager=task.host["manager"], xmldict=True)

    # Check OK key exists, as we passed in 'xmldict=True'
    print(result.result["xml_dict"].keys())

def example_unlock(task):
    """Unlock candidate datastore."""
    task.run(netconf_lock, datastore="candidate", operation="unlock", manager=task.host["manager"])


def main():
    """Execute Nornir Script."""
    print_result(west_region.run(task=example_global_lock))
    print_result(west_region.run(task=example_edit_config))
    print_result(west_region.run(task=example_unlock))


if __name__ == "__main__":
    main()

Additional Documentation

Contributions


No line of code shall go un tested! Any contribution will need to be accounted by the coverage report and satisfy all linting.

Linters:

  • Fake8
  • Black
  • Yamllint
  • Pylint
  • Pydocstyle
  • Bandit
  • MyPy

Testing

To test within a local docker environment

git clone https://github.com/h4ndzdatm0ld/nornir_netconf
docker-compose build && docker-compose run test

To test locally with pytest

docker-compose up netconf1
poetry install && poetry shell
pytest --cov=nornir_netconf --color=yes --disable-pytest-warnings -vvv

Integration Tests

Devices with full integration tests (ContainerLab)

  • Nokia SROS - TiMOS-B-21.2.R1
  • Cisco IOSxR - Cisco IOS XR Software, Version 6.1.3

Devices testing against Always-ON Sandboxes (Cisco DevNet)

  • Cisco IOS-XE - Cisco IOS XE Software, Version 17.03.01a

These tests are ran locally, and will soon be integrated into Github CI.

Sysrepo: netopeer2

Majority of integration tests are ran against a docker instance of netopeer2

From the Sysrepo website:

"Netopeer2 and Sysrepo provide a fully open source and standards compliant implementation of a NETCONF server and YANG configuration data stores."

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nornir_netconf-1.0.1.tar.gz (18.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nornir_netconf-1.0.1-py3-none-any.whl (20.2 kB view details)

Uploaded Python 3

File details

Details for the file nornir_netconf-1.0.1.tar.gz.

File metadata

  • Download URL: nornir_netconf-1.0.1.tar.gz
  • Upload date:
  • Size: 18.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.12 CPython/3.9.7 Linux/5.15.15-76051515-generic

File hashes

Hashes for nornir_netconf-1.0.1.tar.gz
Algorithm Hash digest
SHA256 7d39ab7a967e63db047f0767390f823140755742d2a16a5d180ebd0e9c156d21
MD5 fe204e580f992780ae9ca3825eeb93e3
BLAKE2b-256 429be34b0c24330af910f1c4bfe825777431ef2e23f1b4fea90beac75aeadbc8

See more details on using hashes here.

File details

Details for the file nornir_netconf-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: nornir_netconf-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 20.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.12 CPython/3.9.7 Linux/5.15.15-76051515-generic

File hashes

Hashes for nornir_netconf-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 092c7113738771e47f4cf50c3731cd3ba7939a2bc951d954804fef0bcc40f1b0
MD5 385bc4bb0493fc4e42362d4d99ca6234
BLAKE2b-256 35972a1a10aa05da2fb7d43935b50d4d67e3b654e926abd76421885802a6342b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page