Skip to main content

Supported Versions PyPI version Ruff License: MIT CI

aiogNMI

About

This Python library provides an efficient and lightweight gNMI client implementation that leverages asynchronous approach.

Supported RPCs:

  • Capabilities
  • Get
  • Set
  • Subscribe (under development)

Tested on:

  • Arista EOS
  • Nokia SR OS

Repository contains protobuf files from the gNMI repo, vendored from OpenConfig gNMI release v0.14.1. The upstream core gnmi_service proto option remains 0.10.0. Earlier gNMI versions should work too; 0.7.0 has been tested successfully.

NOTE: At this moment supporting of the secure connections (with encryption or certificate) is in alpha version. You can use them, but I don't guarantee stable work.

Install

Install with uv:

uv add aiognmi

Or install into the current environment:

uv pip install aiognmi

Examples

Capabilities RPC

import asyncio

from aiognmi import AsyncgNMIClient


async def main():
    async with AsyncgNMIClient(host="test-1", port=6030, username="admin", password="admin", insecure=True) as client:
        resp = await client.get_capabilities()

    print(resp.result)


if __name__ == "__main__":
    asyncio.run(main())

Get RPC

import asyncio

from aiognmi import AsyncgNMIClient


async def main():
    async with AsyncgNMIClient(host="test-1", port=6030, username="admin", password="admin", insecure=True) as client:
        resp = await client.get(
            paths=[
                "/interfaces/interface[name=Management0]",
            ]
        )

    print(resp.result)


if __name__ == "__main__":
    asyncio.run(main())

Limit the returned subtree with the depth extension convenience option:

resp = await client.get(
    paths=[
        "/interfaces/interface[name=Management0]",
    ],
    depth=2,
)

The depth applies to every path in the Get request, matching the gNMI depth extension semantics. A depth of 0 means no depth limit.

Set RPC

import asyncio

from aiognmi import AsyncgNMIClient


async def main():
    async with AsyncgNMIClient(host="test-1", port=6030, username="admin", password="admin", insecure=True) as client:
        resp = await client.set(
            update=[
                {"path": "/interfaces/interface[name=Management0]/config", "data": {"description": "gnmi update test"}}
            ]
        )

    print(resp.result)


if __name__ == "__main__":
    asyncio.run(main())

Commit-confirmed Set operations

Pass a client-generated commit_id and a positive rollback duration (in seconds) to start a commit-confirmed Set. Use the same ID to confirm, cancel, or change the rollback duration of the active commit:

# Start a commit that rolls back after 60 seconds unless it is confirmed.
await client.set(
    update=[{"path": "/system/config", "data": {"hostname": "router-1"}}],
    commit_id="change-1",
    commit_rollback_duration=60,
)

# Confirm the active commit.
await client.set(commit_id="change-1", commit_confirm=True)

# Or cancel the active commit before it is confirmed.
await client.set(commit_id="change-1", commit_cancel=True)

# Or extend its rollback window to 120 seconds.
await client.set(commit_id="change-1", commit_set_rollback_duration=120)

Only one commit action can be sent in each Set request. Commit-confirmed support varies by target; unsupported or invalid operations are returned by the target through the usual gRPC/gNMI error handling.

Prebuilt gNMI extensions can be passed to get() and set() with the extensions argument. Commit-confirmed operations are supported through the set() arguments shown above, and get(depth=...) builds the depth extension automatically. Other feature-specific extensions can still be passed as prebuilt Extension messages.

import asyncio

from aiognmi import AsyncgNMIClient, Extension, ExtensionID, RegisteredExtension


async def main():
    extension = Extension(
        registered_ext=RegisteredExtension(id=ExtensionID.Value("EID_EXPERIMENTAL"), msg=b"custom-payload")
    )

    async with AsyncgNMIClient(host="test-1", port=6030, username="admin", password="admin", insecure=True) as client:
        resp = await client.get(
            paths=[
                "/interfaces/interface[name=Management0]",
            ],
            extensions=[extension],
        )

    print(resp.result)


if __name__ == "__main__":
    asyncio.run(main())

TLS

NOTE: At this moment supporting of the secure connections (with encryption or certificate) is in alpha version. You can use them, but I don't guarantee stable work.

Secure connections are controlled by the verify argument on AsyncgNMIClient (insecure=True bypasses TLS entirely and verify has no effect in that case):

  • verify=True (default) — the server certificate is actually verified. If path_root_cert is provided, it is used as the trust anchor; otherwise the system trust store is used.
  • verify=False — the client fetches the target's certificate over the network and trusts it (trust-on-first-use), overriding gRPC's hostname check to match the fetched certificate. A warning is logged whenever verification is disabled. In this mode path_root_cert is ignored, while path_private_key and path_cert_chain continue to provide client credentials for mTLS. The target certificate must contain at least a SAN or a subject CN; gRPC always verifies the certificate identity, so connect() raises ValueError if no identity can be extracted from the fetched certificate.

Behavior change: earlier versions silently auto-fetched and trusted the server certificate even with the default settings. If you relied on that behavior, pass verify=False explicitly — with the current default (verify=True) an untrusted certificate will now cause the connection to fail.

import asyncio

from aiognmi import AsyncgNMIClient


async def main():
    async with AsyncgNMIClient(
        host="test-1", port=6030, username="admin", password="admin", verify=False
    ) as client:
        resp = await client.get_capabilities()

    print(resp.result)


if __name__ == "__main__":
    asyncio.run(main())

Credits

My work is inspired by these people:

  1. Anton Karneliuk and his pyGNMI library
  2. Carl Montanari and his scrapli library

Release files for aiognmi 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aiognmi 0.2.0
File Size Uploaded
aiognmi-0.2.0.tar.gz 26.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aiognmi 0.2.0
File Interpreter ABI Platform
aiognmi-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 53.7 kB

Release files / aiognmi-0.2.0.tar.gz

Download URL aiognmi-0.2.0.tar.gz
Size 26.2 kB
Tags Source
SHA-256 checksum
How to use checksums
1e20c658544f8ca69286cad9c1d781d06df98642dc689d1455dbe6d96f31099c
BLAKE2b-256 checksum
How to use checksums
47c63dfb1daa56d0567f7286dfaf73488f713562f2a679a179758e2b51d9fc28
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.13

Release files / aiognmi-0.2.0-py3-none-any.whl

Download URL aiognmi-0.2.0-py3-none-any.whl
Size 27.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4bc78abfca09722a78c4f0b14617db592f28c0ffab8ae798e1f08640f316ef93
BLAKE2b-256 checksum
How to use checksums
37fdc87ff6ce5516d24e3206efd040792090949c297640cceddbef08781738e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page