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