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

Download files

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

Source Distribution

aiognmi-0.2.0.tar.gz (26.2 kB view details)

Uploaded Source

Built Distribution

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

aiognmi-0.2.0-py3-none-any.whl (27.5 kB view details)

Uploaded Python 3

File details

Details for the file aiognmi-0.2.0.tar.gz.

File metadata

  • Download URL: aiognmi-0.2.0.tar.gz
  • Upload date:
  • Size: 26.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.13

File hashes

Hashes for aiognmi-0.2.0.tar.gz
Algorithm Hash digest
SHA256 1e20c658544f8ca69286cad9c1d781d06df98642dc689d1455dbe6d96f31099c
MD5 b7eccae8fdbd47c6ab3a7593cf932332
BLAKE2b-256 47c63dfb1daa56d0567f7286dfaf73488f713562f2a679a179758e2b51d9fc28

See more details on using hashes here.

File details

Details for the file aiognmi-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: aiognmi-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 27.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.13

File hashes

Hashes for aiognmi-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4bc78abfca09722a78c4f0b14617db592f28c0ffab8ae798e1f08640f316ef93
MD5 53bd0b9ca36de7e65131552c40930a8a
BLAKE2b-256 37fdc87ff6ce5516d24e3206efd040792090949c297640cceddbef08781738e2

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.1

2 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