python-netsnmpagent 0.6.0 released

python-netsnmpagent version 0.6.0 has just been released.

This release is the first to officially introduce Python 3 support
while staying compatible with Python 2.6 and 2.7. It was tested with
Python 3.5.

Other changes since 0.5.3:

  • Introduction of the netsnmptestenv Python module
  • Introduce test cases using nose as testing framework
  • Fix packaging of examples

Please note that by contrast to 0.5.x and earlier releases the license for python-netsnmpagent has changed to the GNU Lesser General Public License (LGPL), version 3.

As usual:

python-netsnmpagent 0.5.3 released

python-netsnmpagent version 0.5.3 has just been released.

This release contains fixes for using IpAddress objects as table indices.

As usual:

python-netsnmpagent 0.5.1 released

python-netsnmpagent version 0.5.1 has just been released.

This release has no substantial new features but a number of fixes of which the following three are important enough to warrant an update from 0.5.0:

  • netsnmpagent: Make Table’s value() method regard string lengths
  • netsnmpagent: Drop special string handling in Table’s init()/setRowCell()
  • netsnmpagent: Fix Table’s value() cutting off ASN_COUNTER64 table values

Other changes include:

  • Usage of MIB files is now completely optional
  • threading_agent got a small fix so it works on Python 2.6, too
  • __version__ got removed, use pkg_resources in your agent yourself to express version dependencies as outlined in 5715e77f’s commit message.

See the included ChangeLog for a detailed list of all changes

Ways to get the software:

  • As usual, the source is available at the GitHub repo.
  • The source distribution .tar.gz for this release can be downloaded from the PyPI page.
  • You can either build binary RPMs for your local distribution yourself (download and make rpms) or pick them up from my Open Build service project — just click on the Repositories tab and one of the Go to download repository links.

python-netsnmpagent bugfix for trailing dots in table strings

I have just pushed two fixes that should be of interest to all python-netsnmpagent users:

These changes fix the issue with trailing dots in table strings. I’ve so far only pushed them to master. I’d like to get some feedback before pushing these to the 0.5 stable branch, so please check them out :)

Moving from DataObjectManager – GridFieldRecordEditor, GridFieldRelationEditor and usability issues

Recently I’ve been working a lot with the SilverStripe CMS/framework written in PHP (as one could undoubtedly deduce from my earlier post). The context involved porting a custom application from SilverStripe 2.4 to 3.1. Naturally this also involved dealing with the formerly used DataObjectManager module and 3.x’s new ORM and GridField components.
Continue reading “Moving from DataObjectManager – GridFieldRecordEditor, GridFieldRelationEditor and usability issues”

Simplify extension for SilverStripe hides children pages in the SiteTree / TreeView

Simplify is an extension for the popular SilverStripe Content Management System (CMS). Its purpose is to simplify the use of the admin interface by allowing fine-grained permissions as to which users should be allowed to see which options.
Continue reading “Simplify extension for SilverStripe hides children pages in the SiteTree / TreeView”

python-netsnmpagent 0.5.0 released

python-netsnmpagent version 0.5.0 has just been released.

This release mainly brings new features:

  • Support for detecting connection establishment/failure in spite of net-snmp API limitations.
  • Support for custom net-snmp log handlers.
  • Export module’s version to enable version checks.

Ways to get the software:

  • As usual, the source is available at the GitHub repo.
  • The source distribution .tar.gz for this release can be downloaded from the PyPI page.
  • You can either build binary RPMs for your local (SUSE) distribution yourself (download and make rpms) or pick them up from my Open Build service project — just click on the Repositories tab and one of the Go to download repository links.

net-snmp API and connection error handling

net-snmp has a strange API that does not seem to allow us to detect errors while trying to connect to the master snmpd instance.

When playing around with python-netsnmpagent, create a copy of run_simple_agent.sh named test.sh and modify as follows:

agentXsocket tcp:localhost:9000

or similar. Do not change the python simple_agent.py line by intent.

Running test.sh will give you an output such as:

* Starting the simple example agent...
Warning: Failed to connect to the agentx master agent (/tmp/simple_agent.deBvcPS2kl/snmpd-agentx.sock): 
simple_agent.py: Registered SNMP objects in Context "": 
[...]
simple_agent.py: Serving SNMP requests, press ^C to terminate

So the only indication that our simple_agent.py could in fact not connect to the master snmpd‘s AgentX socket is the Warning: line which we only see because we currently enable logging to stderr (the comment is wrong) in python-netsnmpagent:

# FIXME: log errors to stdout for now
libnsa.snmp_enable_stderrlog()

Actual connection establishment is triggered within python-netsnmpagent’s start() method. You might be fooled to believe that I simply forgot some error handling here:

def start(self):
    """ Starts the agent. Among other things, this means connecting
        to the master agent, if configured that way. """
self._started = True
libnsa.init_snmp(self.AgentName)

But look at net-snmp itself. From include/net-snmp/library/snmp_api.h:

NETSNMP_IMPORT
void            init_snmp(const char *)

So there is no returning of error conditions. Why did they design their API like this?

Analyzing further, if you look at the implementation in snmplib/snmp_api.c (line 808 for current net-snmp 5.7.2), you will see various function calls for which no error handling whatsoever can be found. And mind you, this is C, so we have no exception system.

In our case, all we got was the error message logged to stdout. Grepping the net-snmp sources will lead you to agent/mibgroup/subagent.c line 856 (for net-snmp 5.7.2). This is from the subagent_open_master_session function:

agentx_socket = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
                                      NETSNMP_DS_AGENT_X_SOCKET);
t = netsnmp_transport_open_client("agentx", agentx_socket);
if (t == NULL) {
    /*
     * Diagnose snmp_open errors with the input
     * netsnmp_session pointer.  
     */
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
                                NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS)) {
        char buf[1024];
        snprintf(buf, sizeof(buf), "Warning: "
                 "Failed to connect to the agentx master agent (%s)",
                 agentx_socket ? agentx_socket : "[NIL]");
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
                                    NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
            netsnmp_sess_log_error(LOG_WARNING, buf, &sess);
        } else {
            snmp_sess_perror(buf, &sess);
        }
    }
    return -1;
}

So whatever we originally passed in as mastersocket ends up here as agentx_socket. If t == NULL, the connect failed (ie. invalid mastersocket or snmpd not running). Then unless the NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS flag was set, we generate the error message and either use netsnmp_sess_log_error or snmp_sess_perror to make it visible. And: we return -1. So from this perspective connection failure is detected.

However, looking further who calls subagent_open_master_session we’ll eventually end up here (line 96):

int
subagent_startup(int majorID, int minorID,
                             void *serverarg, void *clientarg)
{
    DEBUGMSGTL(("agentx/subagent", "connecting to master...\n"));
    /*
     * if a valid ping interval has been defined, call agentx_reopen_session
     * to try to connect to master or setup a ping alarm if it couldn't
     * succeed. if no ping interval was set up, just try to connect once.
     */
    if (netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
                           NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL) > 0)
        agentx_reopen_session(0, NULL);
    else {
        subagent_open_master_session();
    }
    return 0;
}

Depending on whether an AgentX ping interval was configured or not, it will either let agentx_reopen_session retry forever or just call subagent_open_master_session itself once. But as you can see: no checking of return codes, no further error handling.

What’s the context of subagent_startup itself? subagent_init, which itself does return code checking, registers it as a callback function in line 158 so that it is executed after the SNMP configs have been read:

snmp_register_callback(SNMP_CALLBACK_LIBRARY,
                       SNMP_CALLBACK_POST_READ_CONFIG,
                       subagent_startup, NULL);

Of course, if subagent_startup would returned an error code, who would be the one to take action on it? Seeing that its direct caller is merely generic callbacks code. Yet the question remains why the authors had to defer calling subagent_startup through the callback system at all, ie. why not trigger config reading and call it directly?

In either case, the way is has been implemented so far, it seems to be impossible for subagents to detect connection failures :(

python-netsnmpagent 0.4.6 released

python-netsnmpagent version 0.4.6 has just been released.

This is mainly a bugfix release with no new functional features in netsnmpagent itself:

  • With net-snmp 5.4.x, strings used to be limited in length to their initial value, an update with a longer string would truncate these. Credits for tracking down the issues behind the bug go to Max “mk23” Kalika.
  • A new subdir examples was created, example_agent renamed to simple_agent and a new second example named threading_agent was added, that demonstrates how one can use Python’s threading module to allow for asynchronous data updates.
  • All examples now use the clone’s local netsnmpagent copy instead of a possibly already installed system-wide one.
  • More explicit advertising for alternative AgentX transports, eg. TCP. We did already support these before, though.

Choices to get the software:

  • As usual, the source is available at the GitHub repo.
  • The source distribution .tar.gz for this release can be downloaded from the PyPI page.
  • You can either build binary RPMs for SuSE distributions yourself (download and make rpms) or pick them up from my Open Build service project — just click on the Repositories tab and one of the Go to download repository links.

python-netsnmpagent 0.4.5 released

python-netsnmpagent version 0.4.5 has just been released.

Just like the version released yesterday, this is only a small update with no functional changes to the Python module itself. The changes only affect packaging, trying to make package maintainers’ life easier.

  • As usual, the source is available at the GitHub repo.
  • The source distribution .tar.gz for this release can be downloaded from the PyPI page.
  • You can either build binary RPMs for SuSE distributions yourself (download and make rpms) or pick them up from my Open Build service project — just click on the Repositories tab and one of the Go to download repository links.