Cálculo de memoria a través de SNMP



  • Hola buenas,

    Estoy intentando hacer el cálculo de memoria del pfSense utilizando python y SNMP, pero no consigo que coincida la memoria usada del script con la que muestra el Dashboard.

    #!/usr/bin/env python
    
    import argparse
    import sys
    from pysnmp.entity.rfc3413.oneliner import cmdgen
    
    snmp_ois = {
    	'total': '1.3.6.1.4.1.2021.4.5.0',
    	'free': '1.3.6.1.4.1.2021.4.6.0',
    	'buffer': '1.3.6.1.4.1.2021.4.14.0',
    	'cache': '1.3.6.1.4.1.2021.4.15.0',
    }
    
    parser = argparse.ArgumentParser(description='Check free memory of a host using snmp.')
    parser.add_argument('-H', '--host', dest='host', help='Hostname or IP')
    parser.add_argument('-P', '--port', dest='port', default=161, help='SNMP port')
    parser.add_argument('-C', '--community', dest='community', default='public', help='Community')
    parser.add_argument('-w', '--warning', default='80', dest='warning', help='Warning threshold')
    parser.add_argument('-c', '--critical', default='90', dest='critical', help='Critical threshold')
    
    args = parser.parse_args()
    
    if not args.host or not args.community:
    	parser.print_help()
            sys.exit(2)
    
    def get_value(list, value):
    	for name, val in list:
    		if str(name) == value:
    			return float(val)
    	return None
    
    cmdGen = cmdgen.CommandGenerator()
    
    errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
    	cmdgen.CommunityData(args.community),
    	cmdgen.UdpTransportTarget((args.host, args.port)),
    	snmp_ois.get('total'),
    	snmp_ois.get('free'),
    	snmp_ois.get('buffer'),
    	snmp_ois.get('cache')
    )
    
    if errorIndication:
    	print("ERROR: %s" % errorIndication)
    	sys.exit(2)
    else:
    	if errorStatus:
    		print('ERROR: %s at %s' % (
    			errorStatus.prettyPrint(),
    			errorIndex and varBinds[int(errorIndex)-1] or '?'
    			)
    		)
    		sys.exit(2)
    	else:
    		Used = get_value(varBinds, snmp_ois.get('total')) - get_value(varBinds, snmp_ois.get('free'))
    		Used_Real = Used - get_value(varBinds, snmp_ois.get('cache'))
    		Percent = (Used_Real / get_value(varBinds, snmp_ois.get('total'))) * 100
    
    		print('OK: Total: %dkb - Free: %dkb - Cache: %dkb - Percent: %0.2f%%' % (
    			get_value(varBinds, snmp_ois.get('total')),
    			get_value(varBinds, snmp_ois.get('free')),
    			get_value(varBinds, snmp_ois.get('cache')),
    			Percent
    			)
    		);
    		sys.exit(0)
    
    print('WARNING: Unknown error');
    sys.exit(1)
    

    Este script me devuelve:

    OK: Total: 8317720kb - Free: 112096kb - Cache: 6636552kb - Percent: 18.86%
    

    mientras que el dashboard muestra un uso del 17%

    Rebuscando en los OID he hecho este loop simple para sacar todos los datos que podrían ser de memoria:

    for i in `seq 1 15`; do snmpget -v 2c -c public 192.168.xx.xxx 1.3.6.1.4.1.2021.4.$i.0|grep -iv "No Such"; doneiso.3.6.1.4.1.2021.4.1.0 = INTEGER: 0
    iso.3.6.1.4.1.2021.4.2.0 = STRING: "swap"
    iso.3.6.1.4.1.2021.4.3.0 = INTEGER: 16777088
    iso.3.6.1.4.1.2021.4.4.0 = INTEGER: 16777064
    iso.3.6.1.4.1.2021.4.5.0 = INTEGER: 8317720
    iso.3.6.1.4.1.2021.4.6.0 = INTEGER: 116768
    iso.3.6.1.4.1.2021.4.11.0 = INTEGER: 183064
    iso.3.6.1.4.1.2021.4.12.0 = INTEGER: 16000
    iso.3.6.1.4.1.2021.4.13.0 = INTEGER: 207528
    iso.3.6.1.4.1.2021.4.14.0 = INTEGER: 841840
    iso.3.6.1.4.1.2021.4.15.0 = INTEGER: 6635400
    

    Con esto deduzco que las entradas son:

    • 3: Total SWAP

    • 4: Swap libre

    • 5: RAM total

    • 6: Free?

    • 15: Buffer?

    Las que tienen interrogación las saqué de una WEB y no estoy seguro y las que no pongo no sé seguro qué son.

    ¿Alguien sabe qué medidas tengo que usar para calcularlo?

    Gracias!!



  • Hola

    Desde la shell de un Debian con cliente snmp instalado:

    Para el total de memoria RAM:

    snmpget -v1 -c public 10.168.0.254 .1.3.6.1.4.1.2021.4.5.0
    

    Para la RAM en uso:

    snmpget -v1 -c public 192.168.0.254 .1.3.6.1.4.1.2021.4.6.0
    

    operador@debian0:~$ snmpget -v1 -c public 192.168.0.254 .1.3.6.1.4.1.2021.4.6.0
    iso.3.6.1.4.1.2021.4.6.0 = INTEGER: 882296
    operador@debian0:~$ snmpget -v1 -c public 192.168.0.254 .1.3.6.1.4.1.2021.4.5.0
    iso.3.6.1.4.1.2021.4.5.0 = INTEGER: 3036060

    Salu2



  • Sigue sin cuadrarme, ya que el que pones como memoria en uso da un número muy bajo. Haciendo cálculos sería como un 1% en lugar del que muestra el dashboard, además de que se acerca más a lo que da como libre el comando top.

    Un saludo.



  • Hola

    Sí, acabo de hacer pruebas con otro pfSense y no me cuadra a mi tampoco el snmpget… para la ram total y en uso.

    Habrá que documentarse algo más con snmp :)

    Salu2



  • Es raro porque he encontrado un script para sacar la información de la memoria en FreeBSD y la información que muestra se acerca más a la que saco yo por snmp que a la que muestra el dashboard:

    SYSTEM MEMORY INFORMATION:
    mem_wire:        1022111744 (    974MB) [ 12%] Wired: disabled for paging out
    mem_active:  +    343109632 (    327MB) [  4%] Active: recently referenced
    mem_inactive:+   6808539136 (   6493MB) [ 82%] Inactive: recently not referenced
    mem_cache:   +     38961152 (     37MB) [  0%] Cached: almost avail. for allocation
    mem_free:    +     80510976 (     76MB) [  0%] Free: fully available for allocation
    mem_gap_vm:  +            0 (      0MB) [  0%] Memory gap: UNKNOWN
    -------------- ------------ ----------- ------
    mem_all:     =   8293232640 (   7909MB) [100%] Total real memory managed
    mem_gap_sys: +    224112640 (    213MB)        Memory gap: Kernel?!
    -------------- ------------ -----------
    mem_phys:    =   8517345280 (   8122MB)        Total real memory available
    mem_gap_hw:  +     72589312 (     69MB)        Memory gap: Segment Mappings?!
    -------------- ------------ -----------
    mem_hw:      =   8589934592 (   8192MB)        Total real memory installed
    
    SYSTEM MEMORY SUMMARY:
    mem_used:        1661923328 (   1584MB) [ 19%] Logically used memory
    mem_avail:   +   6928011264 (   6607MB) [ 80%] Logically available memory
    -------------- ------------ ----------- ------
    mem_total:   =   8589934592 (   8192MB) [100%] Logically total memory
    

    mientras que mi script dice:

    OK: Total: 8317720kb - Free: 93708kb - Cache: 6674860kb - Percent: 18.62%
    

    Ambos coinciden, porque 18.62% redondeado es el 19% que da el script local para la memoria lógica utilizada.

    A lo mejor el dashboard no muestra la memoria libre real o tiene en cuenta algún dato extra…

    Un saludo.

    EDIT: Miento, viéndolos juntos he visto que tampoco cuadra al 100%... aún así se acerca más que el 17% que dice el dashboard.

    EDIT2:
    Rebuscando he visto:
    iso.3.6.1.4.1.2021.4.5.0: muestra la memoria real disponible (un poco menos que la instalada)
    iso.3.6.1.4.1.2021.4.15.0: muestra la memoria lógica disponible

    Si hacemos la relación sale:
    (8317720 - 6674860) / 8317720 * 100 = 19,75%, que si redondea hacia abajo sería un 19% mientras que la libre (100-19.75=80.25) sería un 80%. Esto ya si coincidiría con los datos que da el script interno.



  • Hola.

    He leido un hilo (del 2013)

    http://serverfault.com/questions/495835/how-can-i-get-freenas-and-pfsense-to-report-more-using-snmp

    After much research on this I discovered what the problem was. Both pfSense and FreeNAS provide SNMP support through the FreeBSD begemot SNMP daemon (bsnmpd). In order to provide memory usage, CPU usage, and Load Average information, the begemot SNMP daemon needs to have an additional module, snmp_ucd.so loaded.

    I found the following forum thread explaining to load snmp_ucd.so, however it was not present on my two systems.

    To resolve this, I created a virtual machine and installed FreeBSD 8.3 on it. Inside this virtual machine, I used the FreeBSD Ports system to download and build the required snmp_ucd.so library using:

    cd /usr/ports/net-mgmt/bsnmp-ucd
    make all install clean
    cd /usr/ports/net-mgmt/bsnmptools
    make all install clean

    After that, I used scp to copy /usr/local/lib/snmp_ucd.so from the FreeBSD virtual machine to both my pfSense server as well as my FreeNAS server.

    Resumiendo: Que el begemot SNMP daemon de pfSense (al menos en el 2013) para cáculo de cpu y ram necesita el módulo snmp_ucd.

    ¿Y cómo carga el módulo? Construyendolo en otra máquina FreeBSD (que se corresponda a la versión de pfSense), compilandolo y despues copiandolo donde corresponda en el pfSense …

    Por ahora no tengo tiempo para probar esto, ya comentaré si lo hago o veo otra solución

    Salu2



  • Pufff, eso se sale por mucho del nivel de modificación al que quiero llegar en este box. Si hago modificaciones de este tipo no creo que sean capaces de reconstruirlo algún día sin mi ayuda (hasta un simple script es mucho ya  ;D).

    De todas formas es interesante saberlo…

    ¡¡Un saludo!!



  • Hola

    No todo es SNMP. Se puede vía NRPE (Nagios: ejecución remota de plugin ) obtener esos datos: RAM en uso, etc.

    Hay un paquete en pfSense 2.3.2_1: nrpe ( https://github.com/pfsense/FreeBSD-ports/commits/devel/net-mgmt/pfSense-pkg-nrpe )

    Pero, claro, ya necesitas tener NSclient o NRPE/Nagios core fuera de pfsense …

    Más trabajo, ... sobre esto ando documentandome, Nagios es un mundo, parece ser el estandar de facto para monitorizar redes y dispositivos de redes, aunque pfSense en su doc ( https://doc.pfsense.org/index.php/SNMP_Daemon ), recomienda http://www.cacti.net/ open y free.

    Salu2



  • Hola,

    El nagios es un referente en cuanto a monitorización, porque tiene bastantes plugins hechos por la comunidad y es fácil de configurar (además de versátil). Además, añadir monitorizaciones nuevas es tan fácil como hacerse un script y ejecutarlo a través de NRPE.
    Llevo tiempo usándolo y en este caso también lo estoy usando, lo que pasa es que el plugin de checkeo de memoria no está incluido en el paquete de plugins, por lo que ya hay que andar descargándolo y copiándolo. Antes de que se me dañara el pfSense ya lo tenía puesto, pero por lo que te comento de que quiero modificar lo menos posible el Box, no quiero volver a añadirlo y estoy intentándolo por otras formas.

    Otro que también me gustó mucho es el Zabbix. Como pro tenía que instalabas el agente y muchísimas métricas se autoconfiguraban, por lo que la puesta en marcha era fácil. La contra es que tiene muchos menos plugins que el nagios.

    Un saludo.



  • Hola.

    Desde un Debian, una forma de obtener la memoria total y usada de un pfSense

    root@debian0:/home/user2# sshpass -p unaclave  ssh -t root@192.168.0.254 grep memory /var/run/dmesg.boot
    real memory  = 8589934592 (8192 MB)
    avail memory = 8172339200 (7793 MB)
    Connection to 192.168.0.254 closed.

    Salu2



  • Lo miraré, porque crear un usuario si se puede y mantenerlo al recuperar con un fichero de configuración.

    Gracias!!



  • Hola

    Otra forma de obtener el % de memoria ram usada, que he implementado mirando el código de:

    https://github.com/pfsense/pfsense/blob/master/src/usr/local/www/includes/functions.inc.php#L36

    [2.3.2-RELEASE][root@pfsense.localdomain]/scripts: echo php -r "require('/etc/inc/functions.inc');echo '% Memoria usada = '.round(get_single_sysctl('vm.stats.vm.v_page_count')-get_single_sysctl('vm.stats.vm.v_inactive_count')-get_single_sysctl('vm.stats.vm.v_cache_count')-get_single_sysctl('vm.stats.vm.v_free_count'))*100/get_single_sysctl('vm.stats.vm.v_page_count').' ';"
    % Memoria usada = 8.2853002576452

    El comando vía shell

    echo `php -r "require('/etc/inc/functions.inc');echo '% Memoria usada = '.round(get_single_sysctl('vm.stats.vm.v_page_count')-get_single_sysctl('vm.stats.vm.v_inactive_count')-get_single_sysctl('vm.stats.vm.v_cache_count')-get_single_sysctl('vm.stats.vm.v_free_count'))*100/get_single_sysctl('vm.stats.vm.v_page_count').' ';"`
    
    

    Y me coincide el 8% con el valos del widget del dashboard.

    Salu2



  • Hola

    La forma anterior de obtener la memoria ram usada, de forma más simplificada:

    echo `php -r "require('/usr/local/www/includes/functions.inc.php');echo mem_usage();"`
    

    [2.3.2-RELEASE][root@pfsense.localdomain]/scripts: echo php -r "require('/usr/local/www/includes/functions.inc.php');echo mem_usage();"
    8

    Redondeando sin decimales ;)

    Salu2