Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to simply iterate column values? #228

Open
optimosfet opened this issue Jan 15, 2019 · 11 comments
Open

how to simply iterate column values? #228

optimosfet opened this issue Jan 15, 2019 · 11 comments

Comments

@optimosfet
Copy link

Hi Ilya,

I wonder if there is a simple way to iterate specific columns of a table as an alternative to the following implementation (based on pysnmp v4.4.4)?

    @property
    def _notification_targets(self):
        snmpNotifyEntry, = self.instrum.getMibBuilder().importSymbols('SNMP-NOTIFICATION-MIB', 'snmpNotifyEntry')

        varBinds = initialVarBinds = (
            (snmpNotifyEntry.name + (1,), None),
        )

        while varBinds:
            varBinds = self.instrum.readNextVars(varBinds)
            name, val = varBinds[0]
            if exval.endOfMibView.isSameTypeWith(val):
                break
            if name[:len(initialVarBinds[0][0])] != initialVarBinds[0][0]:
                break

            yield str(val)

A simpler and faster method would be the following:

    @property
    def _notification_targets_not_public(self):
        snmpNotifyName, = self.instrum.getMibBuilder().importSymbols('SNMP-NOTIFICATION-MIB', 'snmpNotifyName')
        for oid, val in snmpNotifyName._vars.items():
            yield str(val.syntax)

However, a protected class member is accessed here.

I would appreciate comments or alternative recommendations.

Best regards,
Andreas

@etingof
Copy link
Owner

etingof commented Jan 15, 2019

Sounds like if there was a getSubtrees() method/property alongside registerSubtrees(), that would solve this...

Meanwhile, could you walk snmpNotifyEntry subtree by calling snmpNotifyEntry.getNextNode(name) starting with name=snmpNotifyEntry.name?

@optimosfet
Copy link
Author

Good hint,
I'll take a closer look at the use of getNextNode() at getTargetNames(snmpEngine, tag)

@etingof
Copy link
Owner

etingof commented Jan 15, 2019

Just to cheer you up, in the upcoming pysnmp5 the documentation will be much better. ;-)

@optimosfet
Copy link
Author

Good to know. A well sorted collection of code snippets for the SNMP Agent implementation, for example, is certainly very helpful. In particular the iteration and traversing of managed objects is used quite often.
Also of interest is a generic approach to register callbacks for externally modified objects (MibScalarInstance and MibTableColumn).

@etingof
Copy link
Owner

etingof commented Jan 15, 2019

Thank you for the feedback and suggestions! I am planning to implement that.

Two more WIP things that are possibly relevant to agent implementation:

  • Jinja2 templates to generate pysnmp MIBs and/or MIB instances [1] stubs (possibly with some custom integration code in place)
  • General purpose SNMP responder which consumes pysnmp MIBs instances

The latter link tries to explain bits of pysnmp 5 (!) SMI model and hooks.

  1. pysmi (master) usage example:

    $ mibdump.py --no-dependencies --destination-directory /tmp/
    --destination-format pysnmp
    --destination-template pysnmp/mib-instrumentation/managed-objects-instances.j2
    SNMPv2-MIB

@optimosfet
Copy link
Author

Well, the example workflow of the SNMP responder looks promising and is similar to the implementation I've used in my MIB instrumentation. However, I am still going a bit lower and working only on a value basis (get/set), whereas the templating is focused on generating glue code for my JSON-RPC based backend.

@optimosfet
Copy link
Author

One thing I noticed about your SNMPv2-MIB::sysName.0 managed object example:
How is it possible to access the value stored in the syntax object via getNode() method?

As far as I see, getNode() does not trigger/execute a callback and the _value member of the syntax object only references a NoValue object.

@etingof
Copy link
Owner

etingof commented Jan 18, 2019

How is it possible to access the value stored in the syntax object via getNode() method?

When the OID you query comes down to the MibScalarInstance object, unless overridden, its .syntax will be called from readGet.

Should we turn syntax into a property or descriptor to get hold of this .syntax access? Would that be helpful?

As far as I see, getNode() does not trigger/execute a callback and the _value member of the syntax object only references a NoValue object.

Right, getNode is synchronous because it's expected to deal with local OID tree search.

Previously, .syntax.clone() has always been called what maintained another, alternative, entry point for value reading/setting. I am not sure if we still need two ways to tap on the value i.e.:

  • through readGet (and others) override and
  • though syntax.clone()

Because the first way should be able to cover the second. WDYT?

If you still need the syntax.clone() way (do you?), would it be a viable solution to have a template which generates necessary harness to get hold of syntax.clone() based on the readGet (and others) override?

Sorry if I misread your question.

@optimosfet
Copy link
Author

optimosfet commented Jan 18, 2019

Sorry, maybe my question was related to the wrong version. I'm still using pysnmp version 4.4.4, which has no user callbacks in the MibInstrumController. That's why in my agent implementation I developed something similar to your SNMP responder to mange custom MibScalarInstance objects. However, I use customizable and dynamically created classes instead of Jinja2 templates.

But my approach also has a flaw because in the end every request has to pass through the methods getValue()/setValue(). That's ok, but only if I access it via the instrument read/write methods. Then the defined callouts to the back-end are invoked as well. But when I try to access the syntax object internally by getting it via getNode(), then it fails of course.

This gave me the idea to move the logic regarding back-end access directly into the syntax object. But for this I would have to be able to overwrite methods of the underlying syntax class...

@etingof
Copy link
Owner

etingof commented Jan 18, 2019

This gave me the idea to move the logic regarding back-end access directly into the syntax object. But for this I would have to be able to overwrite methods of the underlying syntax class...

If you turn syntax attribute into Python property, would you be able to catch getNode().syntax access?

@optimosfet
Copy link
Author

Meanwhile...

Unfortunately, the use of the .syntax object/property is not appropriate because of the multi-phase procedure for creating/writing. For now, I will continue with the usual suspects .readGet()/.writeCommit().

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

No branches or pull requests

2 participants