[SNMP4J] snmpwalk fails with "No more variables left in this MIB View (It is past the end of the MIB tree)"

Maximilian Schmidt mail at d1u.de
Thu Sep 23 17:50:31 CEST 2010


Hi there,

iam using the snmp4j API to create an SNMP-agent.

When i do a

snmpwalk -0s -c public -v 2c localhost:2001 1.3.6.1.4.1.6695.1

there is this error message at the end of the result:

"No more variables left in this MIB View (It is past the end of the MIB
tree)"

A snmpnext at the very last OID in this table, jumps to a column that
doesn't exist.

Many thanks in advance,

Greetings Max Schmidt.

Here is my agent-class:
###########################
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Timer;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.rrd4j.ConsolFun;
import org.rrd4j.core.FetchData;
import org.rrd4j.core.FetchRequest;
import org.rrd4j.core.RrdDb;
import org.rrd4j.core.RrdDbPoolNew;
import org.rrd4j.core.Util;
import org.snmp4j.TransportMapping;
import org.snmp4j.agent.BaseAgent;
import org.snmp4j.agent.CommandProcessor;
import org.snmp4j.agent.DuplicateRegistrationException;
import org.snmp4j.agent.MOGroup;
import org.snmp4j.agent.ManagedObject;
import org.snmp4j.agent.mo.MOAccessImpl;
import org.snmp4j.agent.mo.MOMutableTableRow;
import org.snmp4j.agent.mo.MOTable;
import org.snmp4j.agent.mo.MOTableRow;
import org.snmp4j.agent.mo.snmp.RowStatus;
import org.snmp4j.agent.mo.snmp.SnmpCommunityMIB;
import org.snmp4j.agent.mo.snmp.SnmpNotificationMIB;
import org.snmp4j.agent.mo.snmp.SnmpTargetMIB;
import org.snmp4j.agent.mo.snmp.StorageType;
import org.snmp4j.agent.mo.snmp.VacmMIB;
import org.snmp4j.agent.security.MutableVACM;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModel;
import org.snmp4j.security.USM;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.SMIConstants;
import org.snmp4j.smi.Variable;
import org.snmp4j.transport.TransportMappings;

/**
 * This Agent contains mimimal functionality for running a version 2c snmp
 * agent.
 */
public class SNMPAgent extends BaseAgent {
	
	private Logger logger = Logger.getLogger(TTMReader.class.getName());
	private String address;
	private RrdDbPoolNew rrdPool = (RrdDbPoolNew) RrdDbPoolNew.getInstance();
	private ArrayList<String> files = null;
	private static final OID sysDescr = new OID(".1.3.6.1.2.1.1.1.0");
	private static final OID root = new OID(".1.3.6.1.4.1.6695.1");
	private ConfigCheck config = ConfigCheck.getInstance();
	private MOTable table = null;
	private Timer timer = null;
	
	public SNMPAgent(String address) throws IOException {
		// These files does not exist and are not used but has to be specified
		// Read snmp4j docs for more info
		super(new File("conf.agent"), new File("bootCounter.agent"), new
CommandProcessor(new OctetString(MPv3.createLocalEngineID())));
		this.address = address;
		// Build Table
		MOTableBuilder builder = new MOTableBuilder(root);
	
builder.addColumnType(SMIConstants.SYNTAX_OCTET_STRING,MOAccessImpl.ACCESS_READ_ONLY);
	
builder.addColumnType(SMIConstants.SYNTAX_OCTET_STRING,MOAccessImpl.ACCESS_READ_ONLY);
	
builder.addColumnType(SMIConstants.SYNTAX_INTEGER,MOAccessImpl.ACCESS_READ_ONLY);
		// Build array with rrd's that should be monitored
		Destination[] destinations = config.getDestinations();
		Source[] sources = TTMReader.getSources();
		files = new ArrayList<String>();
		for(int i = 0 ; i < sources.length ; ++i) {
			for(int j = 0 ; j < destinations.length ; ++j) {
	            if (destinations[j].getTtm().matches(sources[i].getAlias()
+ "(b|d)")) {
	                continue;
	            }
	            if (config.mergeSource(sources[i].getAlias(),
destinations[j]) == null) {
	                continue;
	            }
				files.add(config.getRRDdirectory() + sources[i].getAlias() + "_" +
destinations[j].getTtm() + "_delay.rrd");
				builder.addRowValue(new OctetString(sources[i].getAlias() + "_" +
destinations[j].getTtm()));
				builder.addRowValue(new
OctetString(config.mergeSource(sources[i].getAlias(),
destinations[j]).getSw() + "_" + destinations[j].getSw()));
				builder.addRowValue(new Integer32(-1)); // -1 = unknown = Double.NaN
			}
		}
		table = builder.build();
		// initialize timers
		timer = new Timer("snmpAgent-timer", true);
		timer.schedule( new SNMPUpdateTask(this), 300 * 1000, 300 * 1000);
	}
	
	public void shutdown() {
		if(timer != null) {
			timer.cancel();
		}
		this.stop();
	}

	/**
	 * We let clients of this agent register the MO they
	 * need so this method does nothing
	 */
	@Override
	protected void registerManagedObjects() {
	
registerManagedObject(MOScalarFactory.createReadOnly(sysDescr,"TTMreader"));
		registerManagedObject(table);
	}

	/**
	 * An Error during fetching values from the rrds is indicated with
<code>-2</code> and Double.NaN is like <code>-1</code>.
	 * Values are calculated from floating point milliseconds to integer
microseconds.
	 */
	@SuppressWarnings("unchecked")
	public void updateTable() {
		long now_N = Util.normalize(System.currentTimeMillis() / 1000, 30);
		Iterator<MOTableRow> iter = table.getModel().iterator();
		for(int i = 0 ; i < files.size() ; ++i) {
			MOMutableTableRow r = (MOMutableTableRow) iter.next();
			try {
				RrdDb db = rrdPool.requestRrdDb(files.get(i));
				FetchRequest fetchRequest = db.createFetchRequest(ConsolFun.AVERAGE,
now_N-30, now_N-30, 300); // 5min average
		        FetchData fetchData = fetchRequest.fetchData();
		        double tmp[] = fetchData.getValues(0); // Get Delay Values;
1=jitter; 2=NTPerr
		        int value = ( Double.isNaN(tmp[0]) ? -1 : (int) (tmp[0] *
1000)); // if(Double.NaN){ -1} else {ms -> ns}
			    r.setValue(2, new Integer32(value));
		        logger.log(Level.FINE, "[{0}]read: {1}", new
Object[]{r.getValue(1), tmp[0]} );
				rrdPool.release(db);
			} catch (IOException e) {
				logger.log(Level.WARNING, "[{0}]IOException during fetch values:
{1}", new Object[]{r.getValue(1), e.getMessage()});
				r.setValue(2, new Integer32(-2));
			}
		}
	}
	
	/* ######################## Wrapper and start_up functions
######################## */
	/**
	 * Start method invokes some initialization methods needed to
	 * start the agent
	 * @throws IOException
	 */
	public void start() throws IOException {

		init();
		// This method reads some old config from a file and causes
		// unexpected behavior.
		// loadConfig(ImportModes.REPLACE_CREATE);
		addShutdownHook();
		getServer().addContext(new OctetString("public"));
		finishInit();
		run();
		sendColdStartNotification();
	}
	
	/**
	 * Overrides the default MIB.
	 */
	@Override
	protected void registerSnmpMIBs() {
		registerManagedObjects();
	}
	
	/**
	 * Clients can register the MO they need
	 */
	public void registerManagedObject(ManagedObject mo) {
		try {
			server.register(mo, null);
		} catch (DuplicateRegistrationException ex) {
			throw new RuntimeException(ex);
		}
	}
	
	public void unregisterManagedObject(MOGroup moGroup) {
		moGroup.unregisterMOs(server, getContext(moGroup));
	}
	
	/**
	 * Minimal View based Access Control
	 *
	 * http://www.faqs.org/rfcs/rfc2575.html
	 */
	@Override
	protected void addViews(VacmMIB vacm) {
		vacm.addGroup(SecurityModel.SECURITY_MODEL_SNMPv2c, new
OctetString("cpublic"), new
OctetString("v1v2group"),StorageType.nonVolatile);

		vacm.addAccess(new OctetString("v1v2group"), new
OctetString("public"), SecurityModel.SECURITY_MODEL_ANY,
SecurityLevel.NOAUTH_NOPRIV,
				MutableVACM.VACM_MATCH_EXACT, new OctetString("fullReadView"), new
OctetString("fullWriteView"), new OctetString("fullNotifyView"),
StorageType.nonVolatile);

		vacm.addViewTreeFamily(new OctetString("fullReadView"), new
OID("1.3"),	new OctetString(), VacmMIB.vacmViewIncluded,
StorageType.nonVolatile);
	}

	/**
	 *
	 */
	@Override
	protected void initTransportMappings() throws IOException {
		transportMappings = new TransportMapping[1];
		Address addr = GenericAddress.parse(address);
		TransportMapping tm =
TransportMappings.getInstance().createTransportMapping(addr);
		transportMappings[0] = tm;
	}
	
	/**
	 * The table of community strings configured in the SNMP
	 * engine's Local Configuration Datastore (LCD).
	 *
	 * We only configure one, "public".
	 */
	protected void addCommunities(SnmpCommunityMIB communityMIB) {
		Variable[] com2sec = new Variable[] {
				new OctetString("public"), // community name
				new OctetString("cpublic"), // security name
				getAgent().getContextEngineID(), // local engine ID
				new OctetString("public"), // default context name
				new OctetString(), // transport tag
				new Integer32(StorageType.nonVolatile), // storage type
				new Integer32(RowStatus.active) // row status
		};
		MOTableRow row = communityMIB.getSnmpCommunityEntry().createRow(new
OctetString("public2public").toSubIndex(true), com2sec);
		communityMIB.getSnmpCommunityEntry().addRow(row);
	}
	
	/**
	 *
	 */
	protected void unregisterManagedObjects() {
		// here we should unregister those objects previously registered...
	}
	
	/**
	 * Empty implementation
	 */
	@Override
	protected void addNotificationTargets(SnmpTargetMIB targetMIB,
SnmpNotificationMIB notificationMIB) {
		/* NONE TO DO */
	}
	
	/**
	 * User based Security Model, only applicable to
	 * SNMP v.3
	 */
	protected void addUsmUser(USM usm) {
		/* NONE TO DO */
	}
}



More information about the SNMP4J mailing list