Sei sulla pagina 1di 14

Monitoraggio risorse di un sistema con snmp

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).

Ad esempio la notazione SNMP .1.3.6.1.4.1.2000 è un’alberatura che indica:

iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 2000(Tibco)

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.

Ovviamente è consigliabile aggiungere delle


properties per leggere dei valori configurabili
oltre a dei log con log4j.

Lascio al lettore il gusto di ricostruirsi il progetto,


è da tener conto che è necessario scaricare SNMP4J.jar da Internet ed includerlo ai due progetti come jar
esterno.

Seguono i sorgenti di esempio.

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

*/

public class TestSender {

public static void main(String[] args) {

SNMPTrapSenderVersion2 snmpobj = new SNMPTrapSenderVersion2(10,20,30,40);

snmpobj.start();

SNMPTrapSenderVersion2.java

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

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.*;

public class SNMPTrapSenderVersion2 {

private static String curDir;

private static String path;

private static Logger log;

private static String SnmpV;

private static String ipAddress;

private static String portAgent;

private static String localIpAddress;

private static String udpAddress;

private static int version;

// Qua vanno tutti gli OID

private static String Oid1;

private static String Oid2;

private static String Oid3;

private static String Oid4;

private static int ValOid1;

4
private static int ValOid2;

private static int ValOid3;

private static int ValOid4;

public static final String community = "public";

//Ideally Port 162 should be used to send receive Trap, any other available Port can be used

public SNMPTrapSenderVersion2(){

public SNMPTrapSenderVersion2(int Valid1, int Valid2, int Valid3, int Valid4){

ValOid1=Valid1;

ValOid2=Valid2;

ValOid3=Valid3;

ValOid4=Valid4;

public void start() {

SNMPTrapSenderVersion2 trapV2 = new SNMPTrapSenderVersion2();

System.out.println("Start Java TrapSender SNMP");

// Lettura configurazione

log=Logger.getLogger("SNMPS"); ;

curDir = System.getProperty("user.dir");

path=curDir + "/log4jSen.properties";

PropertyConfigurator.configure(path);

System.out.println("Directory di configurazione "+curDir);

log.info("SNMP Trap Sender Configuration log ok (v. SNMP 0, 1 o 3)");

trapV2.sendTrap_Version2();

/**

* This methods sends the V1 trap to the Localhost in port 162

*/

public void sendTrap_Version2() {

ReadProperties snmpV = new ReadProperties();

SnmpV = snmpV.UTReadPropertiesString("SNMP_VERSION", curDir, "SNMPS.properties");

if(SnmpV==null){

SnmpV="1"; // default => valori possibili di snmp sono 0, 1 , 3

5
log.warn("SNMP version default 1");

version = Integer.parseInt(SnmpV);

ReadProperties ipLV = new ReadProperties();

localIpAddress = ipLV.UTReadPropertiesString("LOCAL_IP", curDir, "SNMPS.properties");

if(localIpAddress==null){

log.error("Non è segnato il LocalIP. Shutdown");

System.exit(0);

// Ancora configurazione

ReadProperties ipV = new ReadProperties();

ipAddress = ipV.UTReadPropertiesString("IP", curDir, "SNMPS.properties");

if(ipAddress==null){

log.error("Non è segnato l'IP remoto o del server. Shutdown");

System.exit(0);

ReadProperties pV = new ReadProperties();

portAgent = pV.UTReadPropertiesString("PORT", curDir, "SNMPS.properties");

if(portAgent==null){

portAgent="162";

log.warn("Assunto port=162 per l'agent TrapReceiver SNMP");

udpAddress = ipAddress+"/"+portAgent;

ReadProperties oV = new ReadProperties();

Oid1 = oV.UTReadPropertiesString("OID1", curDir, "SNMPS.properties");

if(Oid1==null){

log.error("Non è segnato l'OID1 su cui chiedere le info. Shutdown");

System.exit(0);

ReadProperties o2V = new ReadProperties();

Oid2 = o2V.UTReadPropertiesString("OID2", curDir, "SNMPS.properties");

if(Oid2==null){

6
log.error("Non è segnato l'OID2 su cui chiedere le info. Shutdown");

System.exit(0);

ReadProperties o3V = new ReadProperties();

Oid3 = o3V.UTReadPropertiesString("OID3", curDir, "SNMPS.properties");

if(Oid3==null){

log.error("Non è segnato l'OID3 su cui chiedere le info. Shutdown");

System.exit(0);

ReadProperties o4V = new ReadProperties();

Oid4 = o4V.UTReadPropertiesString("OID4", curDir, "SNMPS.properties");

if(Oid4==null){

log.error("Non è segnato l'OID4 su cui chiedere le info. Shutdown");

System.exit(0);

try {

// Create Transport Mapping

TransportMapping transport = new DefaultUdpTransportMapping();

transport.listen();

// Create Target

CommunityTarget cTarget = new CommunityTarget();

cTarget.setCommunity(new OctetString(community));

cTarget.setVersion(version);

cTarget.setAddress(new UdpAddress(udpAddress));

cTarget.setRetries(3);

cTarget.setTimeout(5000);

// Create PDU for V2

PDU pdu = new PDU();

// need to specify the system up time

pdu.add(new VariableBinding(SnmpConstants.snmpTrapAddress, new IpAddress(localIpAddress)));

pdu.add(new VariableBinding(new OID(Oid1), new Integer32(ValOid1)));

pdu.add(new VariableBinding(new OID(Oid2), new Integer32(ValOid2)));

pdu.add(new VariableBinding(new OID(Oid3), new Integer32(ValOid3)));

7
pdu.add(new VariableBinding(new OID(Oid4), new Integer32(ValOid4)));

pdu.setType(PDU.NOTIFICATION);

// Send the PDU

Snmp snmp = new Snmp(transport);

System.out.println("Sending V2 Trap... Check Wheather NMS is Listening or not? ");

snmp.send(pdu, cTarget);

snmp.close();

} catch (Exception e) {

System.out.println(e);

ReadProperties.java

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package utility;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.util.Properties;

import java.io.FileInputStream;

public class ReadProperties

public String UTReadPropertiesString(String pKey, String path_properties, String fileProperties)

Properties props = new Properties();

String myReturn = "1";

try {

//CARICO IL FILE DI CONFIGURAZIONE

8
props.load(new FileInputStream(fileProperties));

//LEGGO IL VALORE DI RITORNO

myReturn = props.getProperty(pKey);

} catch (FileNotFoundException ex) {

ex.printStackTrace();

} catch (IOException ex) {

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

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

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.*;

public class TrapReceiver implements CommandResponder {

private static String ipAddress;

private static String portAgent;

private static String udpAddress;

private static String curDir;

private static String path;

private static String path2;

private static Logger log;

private static Logger logSnmp;

private static String sPool;

private static int iPool;

public static void main(String[] args) {

TrapReceiver snmp4jTrapReceiver = new TrapReceiver();

System.out.println("Start Java TrapReceiver SNMP");

10
// Lettura configurazione

log=Logger.getLogger("SNMPR");

curDir = System.getProperty("user.dir");

path=curDir + "/log4jRec.properties";

PropertyConfigurator.configure(path);

System.out.println("Directory di configurazione "+curDir);

log.info("SNMP Trap Receiver Configuration ok");

ReadProperties ipV = new ReadProperties();

ipAddress = ipV.UTReadPropertiesString("IP", curDir, "SNMPR.properties");

if(ipAddress==null){

ipAddress="localhost";

log.warn("Assunto localhost per il TrapReceiver SNMP");

ReadProperties pV = new ReadProperties();

portAgent = pV.UTReadPropertiesString("PORT", curDir, "SNMPR.properties");

if(portAgent==null){

portAgent="162";

log.warn("Assunto port=162 per il TrapReceiver SNMP");

udpAddress = ipAddress+"/"+portAgent;

ReadProperties poV = new ReadProperties();

sPool = poV.UTReadPropertiesString("POOL", curDir, "SNMPR.properties");

if(sPool==null){

sPool="10";

log.warn("Assunto pool=10 per il TrapReceiver SNMP");

iPool=Integer.parseInt(sPool);

try {

snmp4jTrapReceiver.listen(new UdpAddress(udpAddress));

} catch (IOException e) {

log.error(e);

11
System.out.println(e);

/**

* Trap Listner

*/

public synchronized void listen(TransportIpAddress address) throws IOException {

AbstractTransportMapping transport;

if (address instanceof TcpAddress) {

transport = new DefaultTcpTransportMapping((TcpAddress) address);

} else {

transport = new DefaultUdpTransportMapping((UdpAddress) address);

ThreadPool threadPool = ThreadPool.create("DispatcherPool", iPool);

MessageDispatcher mDispathcher = new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl());

// add message processing models

mDispathcher.addMessageProcessingModel(new MPv1());

mDispathcher.addMessageProcessingModel(new MPv2c());

// add all security protocols

SecurityProtocols.getInstance().addDefaultProtocols();

SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES());

// Create Target

CommunityTarget target = new CommunityTarget();

target.setCommunity(new OctetString("public"));

Snmp snmp = new Snmp(mDispathcher, transport);

snmp.addCommandResponder(this);

transport.listen();

System.out.println("Listening on " + address);

try {

this.wait();

} catch (InterruptedException ex) {

Thread.currentThread().interrupt();

12
}

/**

* This method will be called whenever a pdu is received on the given port

* specified in the listen() method

*/

public synchronized void processPdu(CommandResponderEvent cmdRespEvent) {

logSnmp=Logger.getLogger("SNMPEND");

path2=curDir + "/log4jsnmp.properties";

PropertyConfigurator.configure(path2);

System.out.println("Received PDU...");

PDU pdu = cmdRespEvent.getPDU();

if (pdu != null) {

String appo = "" + pdu.getType();

System.out.println("Trap Type = " + pdu.getType());

logSnmp.info(appo);

appo = "" + pdu.getVariableBindings();

System.out.println("Variables = " + pdu.getVariableBindings());

logSnmp.info(appo);

SNMPR.properties

IP=localhost

PORT=162

POOL=10

Un esempio di Log4J è il seguente

## see PatternLayout

## %d{ISO8601} = yyyy-MM-dd HH:mm:ss,SSS

## %d{ABSOLUTE} = HH:mm:ss,SSS

## %-5p = level, left aligned, minimum 5 characters

## %c{1} = last part of the name of the logger

13
## %m = message

## %n = newline (platform dependend)

## example

#LOGGER

log4j.rootCategory=DEBUG, APPENDER_OUT, APPENDER_FILE

#APPENDER_OUT

log4j.appender.APPENDER_OUT=org.apache.log4j.ConsoleAppender

log4j.appender.APPENDER_OUT.layout=org.apache.log4j.PatternLayout

# Print the date in ISO 8601 format

log4j.appender.APPENDER_OUT.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

#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

log4j.appender.APPENDER_FILE.layout.ConversionPattern=%d [%t] %-5p %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

Potrebbero piacerti anche