http://qs321.pair.com?node_id=296312

Rhys has asked for the wisdom of the Perl Monks concerning the following question:

Okay, we talked about this in CB yesterday, but I think I've got it figured out in the Best Way (since there doesn't really seem to be a Right Way...). Opinions are welcome.

Some background: I've written a Perl app that includes several scripts, several mods, and more than a few vendors' MIB files, which are critical. The app depends upon the Net-SNMP (see Net-SNMP for details) libraries AND the SNMP.pm module that comes with it. UCD SNMP (which is just the earlier version of Net-SNMP) will usually work as well.

NOTE: Do not confuse the Net-SNMP package with the "Net::SNMP" module available from CPAN. They are different. The "SNMP" module on CPAN is closer, but it's a really old version of UCD SNMP (egad! 4.2.0!).

Anyway, the SNMP Perl module has three functions that are useful in this context:

&SNMP::addMibDirs('dir'...); # Add a new SEARCH directory for findin +g MIBs. &SNMP::addMibFiles('file'...); # Load a file's contents into the MIB. &SNMP::loadModule('NAME'...); # Look in all search dirs for a file co +ntaining the NAME MIB. First one found is loaded.
Okay, you can kind of see where some of this is going. Adding hard-coded directories and/or filenames is a bad idea, in general, because I don't want to have to care where the user stores the MIB files once installation is complete. They need to be found automatically if at all possible. Therefore, I'm going to stick with SNMP::loadModule() for finding the MIBs I need.

Okay, so now I have to figure out where to put my included MIBs. In the package itself, the files are laid out in a tree like this:

mibs/[vendor]/[files]

For ease of maintenance (and uninstallation, which is still a manual process for the poor sysadmin), I'd like to keep all these MIB files under some similar structure once installed. However, I don't want to have to add every directory in the tree to the search list.

So here's what I propose. First, the Net-SNMP installation, by default, installs it's own MIB files in $PREFIX/share/snmp/mibs. The files are named MIB-NAME.txt. So I'll have my included post-install script (called automatically when the user does 'make install') stat() the common places - where $PREFIX = /usr or /usr/local - and ask the user if I can install my MIB files there. If that fails, I could also look for $ENV{MIBDIRS} and prompt to install in the first one in the list.

Anyway, the idea is that I'm going to install the dir subtree underneath someplace that SNMP.pm is already going to look for MIB files, then I'm going to create symlinks such that $MIBDIR/RAPID-CITY.txt -> $MIBDIR/mypackage/Passport/rapid_city.mib. So the user can just remove $MIBDIR/mypackage and all related symlinks when it comes time to uninstall, and the symlinks in the actual searchdir will follow the same naming convention as used by Net-SNMP without having to rename the original vendor MIB files. (Sometimes the only place you can find the revision number of the MIB file is the filename, so I don't want to lose the original name.) This has the additional advantage that if a newer version of my package is installed over the old one and there are two files in $MIBDIR/mypackage/BayStack named s5roo115.mib and s5roo116.mib, only the one with the S5-ROOT-MIB.txt symlink in $MIBDIR will get loaded.

SO... What I'm thinking ./post-install should do is look for $ENV{MIBDIRS} and prompt the user for the first entry in the list. If there's no $ENV{MIBDIRS}, look for /usr/share/snmp/mibs or /usr/local/share/snmp/mibs and prompy the user for one of those. If neither is found, simply prompt the user for a dirname and not accept a NULL input. If the directory doesn't exist, print something that says I'm creating it.

Once the MIB directory has been copied, test for duplicate MIBs for each file that gets symlinked and prompt for how to handle each one.

Lastly, test that either $MIBDIR is the default searchdir for Net-SNMP or that it's listed in $ENV{MIBDIRS}. If not, print a warning. Either way, print a notice that $MIBDIR should be in $ENV{MIBDIRS} for things to work properly. I could also run a test that the installed MIBs are, in fact, found by SNMP::loadModule().

So what am I forgetting, and does any of this go against the grain of known good practices? Advice is welcome. I've been struggling with this for a couple of years, now, and I've tried several different ways of dealing with this, only to wind up back here trying to solve this problem again. I want to get it done and move on to something else. :-)

Thanks in advance!

--Rhys

janitored by ybiC: replaced [ and ] chars with [ and ] to avoid inadvertant PM linking

Replies are listed 'Best First'.
Re: SNMP MIB files...
by freddo411 (Chaplain) on Oct 03, 2003 at 18:01 UTC
    Sounds like you have a reasonable approach:

    * Look for a value in an ENV var
    * Look for existing dirs that make sense
    * Prompt to create things if the above doesn't workout

    When you prompt to create the needed dir, you might want to display a reasonable default and wait for the user to hit return. This is an often seen pattern that is great because it:

    * demonstrates to the user what is happening
    * Allows things to be stop/changed by the user
    * And "does the right thing" if the user just accepts the defaults

    Cheers

    -------------------------------------
    Nothing is too wonderful to be true
    -- Michael Faraday

Re: SNMP MIB files...
by zengargoyle (Deacon) on Oct 03, 2003 at 19:30 UTC

    i would just keep my MIB files installed with the package and add the directory to the (front or end... i forget which) of the $ENV[MIBDIRS] variable. if you craft your own .index file in the directory you don't have to worry about the filenames.

    be warned, there used to be a bug in the .index code that would ignore the freshness of the .index file and re-create it every time.

      I thought about modifying the $ENV{MIBDIRS}, but I wouldn't be able to make it either global or permanent without (probably) a lot of extra work *and* making mor eintrusive changes to the system.

      Besides, adding eight or nine directories with names like '/usr/local/share/snmp/mibs/JScan/BayStack' to that variable would make it gigantic. Enormous variables have always annoyed me, and I kind of figured it annoyed others as well.

      I'm not married to the opinion, though. If I should be modifying $ENV{MIBDIRS}, what's the best way to do it? Add a script to /etc/profile.d?

      --Rhys

        (Rhys -- I see you've fleshed it out quite a bit since we chatted in the CB.)

        How 'bout having your perl app read the dir list from a config file? This not only lets you change you mind about the MIBDIR layout, but keeps the changes confined to the app's process tree and lets your end users choose different MIBs than yours, should they wish to extend your app.

        In fact, with that, you could even keep your MIBs completely out of the common hierarchy.


        Remember, when you stare long into the abyss, you could have been home eating ice cream.
Re: SNMP MIB files...
by Rhys (Pilgrim) on Oct 03, 2003 at 16:31 UTC
    Hrm... Just saw the warning about PRE tags on the submission page. To the editors: Please feel free to edit the code-y section of my post as appropriate to get rid of the long lines.

    Sorry 'bout that...

    --Rhys