Skip to main content

sysrepo-python-plugind

A Python reimplementation of sysrepo-plugind — the sysrepo plugin daemon.

The C daemon loads compiled .so plugins via dlopen. This daemon loads Python plugins discovered via entry points (importlib.metadata), giving plugin authors a pure-Python development experience against the existing sysrepo-python CFFI bindings.

The two daemons can run simultaneously: the Python daemon manages its own YANG subtree (python-plugin-order, python-loaded-plugins) and never touches the C daemon’s nodes.

Requirements

  • Python ≥ 3.10

  • sysrepo-python (and the underlying libsysrepo.so)

  • sysrepo core 4.2.10 (ships sysrepo-plugind@2022-08-26.yang)

Installation

pip install sysrepo-python-plugind

Then register the YANG augmentation module with sysrepo (requires write access to the sysrepo repository, typically run as root):

sysrepo-python-plugind-setup

This is idempotent — safe to run on every deployment or system boot. Pass --force to upgrade the module after a package update.

Writing a plugin

Subclass SysrepoPlugin and implement init(). Register the class via an entry point in your package’s pyproject.toml:

[project.entry-points."sysrepo_python.plugins"]
my-plugin = "my_package.plugin:MyPlugin"

Installing your package makes the plugin visible to the daemon immediately — no copying of files or environment variables required.

Minimal example:

import logging
import sysrepo
from sysrepo_python_plugind import SysrepoPlugin

LOG = logging.getLogger(__name__)

class MyPlugin(SysrepoPlugin):

    def init(self, session: sysrepo.SysrepoSession) -> None:
        self._counter = 0
        session.subscribe_module_change(
            "my-module", None, self._on_change, done_only=True
        )
        session.subscribe_oper_data_request(
            "my-module", "/my-module:stats", self._on_oper
        )
        LOG.info("MyPlugin ready")

    def cleanup(self, session: sysrepo.SysrepoSession) -> None:
        LOG.info("MyPlugin stopping (counter=%d)", self._counter)

    def _on_change(self, event, req_id, changes, priv):
        self._counter += 1

    def _on_oper(self, xpath, priv):
        return {"my-module": {"stats": {"change-count": self._counter}}}

State that the C daemon stored in void *private_data is stored as instance attributes (self._counter above).

Each plugin is given its own dedicated SysrepoSession. The same session object is passed to init() and later to cleanup(), and the daemon stops it only after cleanup() returns — so cleanup() can still unsubscribe and access the datastore through it. (The C sysrepo-plugind shares a single session across every plugin; this daemon does not.)

Async callbacks

The daemon starts an asyncio event loop in a background thread before calling any init(), so plugins can use asyncio_register=True subscriptions without managing a loop themselves:

class AsyncMyPlugin(SysrepoPlugin):

    def init(self, session: sysrepo.SysrepoSession) -> None:
        session.subscribe_module_change(
            "my-module", None, self._on_change,
            done_only=True, asyncio_register=True,
        )

    async def _on_change(self, event, req_id, changes, priv):
        ...

Running the daemon

# Foreground, INFO-level logging to stderr:
sysrepo-python-plugind -d -v 2

# Background (daemonize), write PID file:
sysrepo-python-plugind -p /run/sysrepo-python-plugind.pid

CLI flags mirror those of the C sysrepo-plugind:

-d

Stay in foreground; log to stderr instead of syslog

-v LEVEL

Verbosity: 0=ERROR 1=WARNING 2=INFO 3=DEBUG (default: 2)

-p PATH

Write PID file at PATH

-f

Exit if any plugin fails to initialise (default: skip and continue)

Plugin ordering

By default plugins are initialised in entry-point discovery order. To override this, set the python-plugin-order leaf-list in sysrepo’s running datastore:

sysrepocfg -d running --edit

Add under /sysrepo-plugind:sysrepo-plugind:

<python-plugin-order xmlns="urn:sysrepo:python-plugind">
  <plugin>my-plugin</plugin>
  <plugin>other-plugin</plugin>
</python-plugin-order>

Plugins absent from the list are appended after the ordered set, preserving their discovery order. A trailing file extension in a configured name (e.g. my-plugin.so) is stripped before comparison, so operator configs written for the C daemon can be reused unchanged.

The list of successfully initialised plugins is published to the operational datastore at /sysrepo-plugind:sysrepo-plugind/sysrepo-python-plugind:python-loaded-plugins/plugin.

Systemd deployment

A service file is provided in the systemd/ directory of the source distribution:

cp systemd/sysrepo-python-plugind.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now sysrepo-python-plugind

The service runs sysrepo-python-plugind-setup as ExecStartPre=, ensuring the YANG module is present before the daemon starts.

If the daemon binary is not at /usr/bin/sysrepo-python-plugind (e.g. when installed into a virtual environment), update the ExecStartPre= and ExecStart= paths in the service file accordingly.

License

BSD-3-Clause — same as sysrepo-python.

Metadata

Release files for sysrepo-python-plugind 1.1.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 sysrepo-python-plugind 1.1.0
File Size Uploaded
sysrepo_python_plugind-1.1.0.tar.gz 19.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sysrepo-python-plugind 1.1.0
File Interpreter ABI Platform
sysrepo_python_plugind-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 39.3 kB

Release files / sysrepo_python_plugind-1.1.0.tar.gz

Download URL sysrepo_python_plugind-1.1.0.tar.gz
Size 19.9 kB
Tags Source
SHA-256 checksum
How to use checksums
01c2ad39d83eaa6868ee6a31f6ba7f00df4ad6456d87d24698aa5976205e90bf
BLAKE2b-256 checksum
How to use checksums
0c088b39702151133eda6b27c343023ea06850d4e1a1a30bfcef2fa4a3dc61f8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.

Transparency log

Release files / sysrepo_python_plugind-1.1.0-py3-none-any.whl

Download URL sysrepo_python_plugind-1.1.0-py3-none-any.whl
Size 19.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
76c81d50ae78990c122485dc548a0ca2326bc7c1f1e86e050f91bdd99b169b54
BLAKE2b-256 checksum
How to use checksums
4f5b640fc547e693a9fddb26525d096b9d1ad19bee64cd116906fbd526bf14d2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.1

2 release files

1.0.0

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