R. Turco
Uno dei problemi non funzionali, classici dell’informatica di tipologia infrastrutturale, è la necessità di
monitorare le risorse di un sistema ed avere un unico punto di monitoraggio centralizzato per tutti i sistemi.
Le risorse di un sistema da monitorare possono essere di vario tipo: hardware, filesystem cluster,
alimentazione supplementare, prodotti software (BEA, Tibco etc) etc.
In questi casi sono assolutamente da scartare tutte le soluzioni di overload del sistema, che potrebbero
portare a pensare di dover scrivere le informazioni su file o su DB durante il funzionamento normale del
business, con un agent locale che legge le informazioni. Si otterrebbe un degrado di prestazioni in taluni
casi. In ambito monitoraggio di prodotti software la soluzione intelligente è di progettare il tutto con SNMP
(Simple Network Manager Protocol) e la relativa specifica RFC. Spesso poggiando anche sulle possibilità
offerte dai prodotti stessi da monitorare.
La soluzione più efficiente è quella “PUSH”, cioè dell’invio dell’evento di superamento soglia, direttamente
via rete con protocollo snmp, ad un receiver snmp preposto al monitoraggio di molti sistemi.
Una seconda soluzione snmp è quella di avere un client snmp sottoscrittore (pattern Publish-Subscribe) che
inoltra le informazioni ad un agent locale che le registra in memoria; mentre un client remoto chiede le
informazioni all’agent periodicamente.
Nel caso PUSH si effettua il Trap degli eventi eccezionali solo quando si verificano (ad esempio di
raggiungimento di valori di soglia) e si inoltrano, tramite un TrapSender, che fa da Agent locale sul proprio
hardware, ad un server remoto che riconosce i messaggi SNMP.
L’agent interviene solo nei casi eccezionali per trasmettere al receiver. E’ chiaro che una soluzione del
genere NON impatta sul business, né sulle prestazioni del sistema ed evita il polling del client remoto.
1
In SNMP esiste una alberatura con rami e foglie (MIB Tree) con cui individuare gli oggetti di interesse, i rami
sono standard, mentre le foglie si possono concordare con chi riceve le informazioni su come interpretarle
(vedi [1][2] ed altri).
Supponiamo di esserci messo d’accordo con chi riceve le info snmp (un prodotto come HP OpenView
oppure make) di voler monitorare ad esempio un EMS server Tibco se supera delle soglie corrispondenti a:
.1.3.6.1.4.1.2000.1 $sys.monitor.limits.connection
.1.3.6.1.4.1.2000.2 $sys.monitor.limits.queue
.1.3.6.1.4.1.2000.3 $sys.monitor.limits.server
.1.3.6.1.4.1.2000.4 $sys.monitor.limits.topic
Mentre con la variabile ipAddress SNMP daremo l’IP della risorsa monitorata.
A questo punto possiamo adottare una soluzione push, dove una prima parte è un Agent Tibco che è in
ascolto sulle Topic Monitor dell’EMS server (in pratica interessa qualsiasi $sys.monitor.limits.*), quando
riceve un messaggio inoltra il tutto tramite un TrapSender che si basa sulla libreria Java SNMP4J.
2
Per comodità io ho usato Netbeans 6.1.9 e ho
diviso il progetto in due progetti
(SnmpTrapSender e SnmpTrapReceiver). Dal
primo progettino TrapSender otteniamo il jar che
servirà a TIBCO per l’agent. Mentre il secondo
progettino può servire a testare innanzitutto il
sender; ma anchead essere un receiver di
esempio se si deve implementare in proprio se
non si ha una console ad hoc, ma occorre
implementarla in Java.
Per richiamare il TrapSender basta un po’ di codice, passando i valori tramite il costruttore, come segue:
TestSender.java
package com.G2.SNMP.Trap.Sender;
/**
* @author R. Turco
*/
snmpobj.start();
SNMPTrapSenderVersion2.java
/*
3
*/
package com.G2.SNMP.Trap.Sender;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.IpAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import utility.*;
4
private static int ValOid2;
//Ideally Port 162 should be used to send receive Trap, any other available Port can be used
public SNMPTrapSenderVersion2(){
ValOid1=Valid1;
ValOid2=Valid2;
ValOid3=Valid3;
ValOid4=Valid4;
// Lettura configurazione
log=Logger.getLogger("SNMPS"); ;
curDir = System.getProperty("user.dir");
path=curDir + "/log4jSen.properties";
PropertyConfigurator.configure(path);
trapV2.sendTrap_Version2();
/**
*/
if(SnmpV==null){
5
log.warn("SNMP version default 1");
version = Integer.parseInt(SnmpV);
if(localIpAddress==null){
System.exit(0);
// Ancora configurazione
if(ipAddress==null){
System.exit(0);
if(portAgent==null){
portAgent="162";
udpAddress = ipAddress+"/"+portAgent;
if(Oid1==null){
System.exit(0);
if(Oid2==null){
6
log.error("Non è segnato l'OID2 su cui chiedere le info. Shutdown");
System.exit(0);
if(Oid3==null){
System.exit(0);
if(Oid4==null){
System.exit(0);
try {
transport.listen();
// Create Target
cTarget.setCommunity(new OctetString(community));
cTarget.setVersion(version);
cTarget.setAddress(new UdpAddress(udpAddress));
cTarget.setRetries(3);
cTarget.setTimeout(5000);
7
pdu.add(new VariableBinding(new OID(Oid4), new Integer32(ValOid4)));
pdu.setType(PDU.NOTIFICATION);
snmp.send(pdu, cTarget);
snmp.close();
} catch (Exception e) {
System.out.println(e);
ReadProperties.java
/*
*/
package utility;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.io.FileInputStream;
try {
8
props.load(new FileInputStream(fileProperties));
myReturn = props.getProperty(pKey);
ex.printStackTrace();
ex.printStackTrace();
return(myReturn);
SNMPS.properties
SNMP_VERSION=1
LOCAL_IP=127.0.0.1
IP=127.0.0.1
PORT=162
OID1=.1.3.6.1.2.1.1.8.1
OID2=.1.3.6.1.2.1.1.8.2
OID3=.1.3.6.1.2.1.1.8.3
OID4=.1.3.6.1.2.1.1.8.4
TrapReceiver.java
/*
*/
package com.G2.SNMP.Trap.receiver;
import java.io.IOException;
import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.CommunityTarget;
import org.snmp4j.MessageDispatcher;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.PDU;
9
import org.snmp4j.Snmp;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.security.Priv3DES;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TcpAddress;
import org.snmp4j.smi.TransportIpAddress;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.AbstractTransportMapping;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import utility.*;
10
// Lettura configurazione
log=Logger.getLogger("SNMPR");
curDir = System.getProperty("user.dir");
path=curDir + "/log4jRec.properties";
PropertyConfigurator.configure(path);
if(ipAddress==null){
ipAddress="localhost";
if(portAgent==null){
portAgent="162";
udpAddress = ipAddress+"/"+portAgent;
if(sPool==null){
sPool="10";
iPool=Integer.parseInt(sPool);
try {
snmp4jTrapReceiver.listen(new UdpAddress(udpAddress));
} catch (IOException e) {
log.error(e);
11
System.out.println(e);
/**
* Trap Listner
*/
AbstractTransportMapping transport;
} else {
mDispathcher.addMessageProcessingModel(new MPv1());
mDispathcher.addMessageProcessingModel(new MPv2c());
SecurityProtocols.getInstance().addDefaultProtocols();
SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES());
// Create Target
target.setCommunity(new OctetString("public"));
snmp.addCommandResponder(this);
transport.listen();
try {
this.wait();
Thread.currentThread().interrupt();
12
}
/**
* This method will be called whenever a pdu is received on the given port
*/
logSnmp=Logger.getLogger("SNMPEND");
path2=curDir + "/log4jsnmp.properties";
PropertyConfigurator.configure(path2);
System.out.println("Received PDU...");
if (pdu != null) {
logSnmp.info(appo);
logSnmp.info(appo);
SNMPR.properties
IP=localhost
PORT=162
POOL=10
## see PatternLayout
## %d{ABSOLUTE} = HH:mm:ss,SSS
13
## %m = message
## example
#LOGGER
#APPENDER_OUT
log4j.appender.APPENDER_OUT=org.apache.log4j.ConsoleAppender
log4j.appender.APPENDER_OUT.layout=org.apache.log4j.PatternLayout
#APPENDER_FILE
log4j.appender.APPENDER_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.APPENDER_FILE.File=C:/Users/SNMPREC.log
log4j.appender.APPENDER_FILE.Append=true
log4j.appender.APPENDER_FILE.MaxFileSize=100KB
log4j.appender.APPENDER_FILE.MaxBackupIndex=1
log4j.appender.APPENDER_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.APPENDER_FILE.layout.ConversionPattern=%p %t %c - %m%n
Riferimenti
[1] http://www.javvin.com/protocolSNMP.html
[2]http://www.loriotpro.com/Products/On-line_Documentation_V5/LoriotProDoc_EN/C3-
Introduction_to_Network_Supervision/C3-F6_Main_%20SNMP_Objects_EN.htm
14