Skip to content

Make the recorders work again - #18

Open
stupalov wants to merge 1 commit into
lextudio:masterfrom
observium:upstream-recorders
Open

Make the recorders work again#18
stupalov wants to merge 1 commit into
lextudio:masterfrom
observium:upstream-recorders

Conversation

@stupalov

@stupalov stupalov commented Aug 20, 2026

Copy link
Copy Markdown

snmpsim-record-commands

It sends its first GETNEXT, writes an empty file and then hangs forever — no error, no traceback.

Three things have to change for a walk to complete:

  1. The response format. pysnmp used to hand the callback a table of rows; it now passes a flat list of var-binds, so for row in table: for oid, value in row: unpacks an OID into two names and the record is never written.
  2. Nobody continues the walk. NextCommandGenerator.process_response_varbinds() now ends right after calling the callback — there is no follow-up request. This is deliberate on the pysnmp side: asked about it in lextudio/pysnmp#251, the maintainer confirmed "This change is intentional." So the recorder has to issue each step itself; the three copies of the "send a request" block that were already in the file are replaced by one place that does it.
  3. Nothing ends the run. AsyncioDispatcher.run_dispatcher() runs its loop until the loop is stopped; it does not return when the last job finishes. So the command stops the dispatcher itself once the agent is walked, the stop OID is reached, or an error is final.

Two more things surfaced once it ran at all: the IPv6 transport class no longer exists under the name used (udp6.Udp6SocketTransport), and the summary line counted every OID twice. It also needs an event loop of its own — pysnmp builds transports around the loop of the calling thread, and Python no longer hands out one that was never created.

$ snmpsim-record-commands --agent-udpv4-endpoint=127.0.0.1:1655 \
    --community=public --output-file=recorded.snmprec
OIDs dumped: 7, elapsed: 0.01 sec, rate: 623.00 OIDs/sec, errors: 0

snmpsim-record-traffic

This one cannot start at all: it requires pylibpcap 0.6.4, a SourceForge release from 2011 which does not build on any current Python. Behind that check sit three more breakages — packet headers parsed with Python 2 byte semantics (ord() over bytes), the argument namespace overwritten by a packet tuple inside the read loop (args = pcap_obj.next()), and an output directory that is never created because os.mkdir() cannot create a missing parent.

A capture file is a global header followed by a length in front of every packet, so reading one needs no extension module: CaptureFile does it in 40 lines, handling both byte orders and both timestamp resolutions, and pointing at editcap when handed a pcapng file. pylibpcap is now needed only for live capture off an interface, which needs root anyway — tcpdump -w plus --capture-file is the usual path and now works out of the box.

Tests

tests/test_cmd2rec.py records a live agent through both GETNEXT and GETBULK and compares the result with what the agent serves. tests/test_pcap2rec.py builds a capture file in the test out of real SNMP responses and checks the recording produced from it. The stub in tests/test_issue_224.py is updated to the attribute name pysnmp 7 uses.

Both recording commands are dead on pysnmp 7, and both fail quietly rather
than with an error.

snmpsim-record-commands sends its first GETNEXT, writes nothing and hangs
forever. It reads the response as the old table of rows, which pysnmp now
delivers as a flat list of var-binds; and pysnmp no longer continues a walk
by itself, nor does the asyncio dispatcher return from run_dispatcher() when
the last job is done. So the walk is now driven from the command: one place
issues each request, and the run ends by stopping the dispatcher once the
agent is walked, the stop OID is reached, or an error is final. Two side
effects of it never having run: the IPv6 transport class no longer exists
under the name it used, and the summary counted every OID twice. It also
needs an event loop of its own, since Python no longer hands out one which
was never created.

snmpsim-record-traffic cannot even start: it wants pylibpcap 0.6.4, which
has not been installable for years, and behind that it parses packet headers
with Python 2 byte semantics, overwrites its own argument namespace with a
packet tuple mid-loop, and cannot create its output directory. Capture files
are now read directly - the format is a global header and a length in front
of every packet, which needs no extension module - and pylibpcap is required
only for live capture off an interface.

Also fix --debug in the recorder, which died on a pysnmp function renamed
years ago.

Tests record a live agent through both GETNEXT and GETBULK, and turn a
capture file built in the test into a recording.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant