Cómo monitorizar un servidor de actualizaciones WSUS (Windows Server Update Services) mediante el sistema de monitorización Pandora FMS. Indicamos todos los requisitos y todos los pasos a seguir. También dejamos la descarga del script Python para conexión a SQL Server de WSUS.
- Requisitos para monitorización de WSUS Windows Server Update Services mediante Pandora FMS.
- Scripts Python con código para acceso a servidor SQL Server de WSUS.
- Añadir módulos a Pandora Agent en equipo servidor WSUS.
- Añadir módulos a Pandora Agent mediante Broker en equipo externo a WSUS.
- Posibles errores y su solución.
Requisitos para monitorización de WSUS Windows Server Update Services mediante Pandora FMS
A continuación, indicamos todos los elementos necesarios para monitorizar un servidor Windows Server Update Services (WSUS) mediante Pandora FMS.
Pandora FMS Server
En primer lugar, necesitaremos disponer de un servidor de monitorización con Pandora FMS Server, en los siguientes enlaces indicamos cómo desplegarlo en Linux y en Docker:
- Instalar sistema de monitorización completo con Pandora FMS sobre Linux Ubuntu Server 22.
- Desplegar sistema de monitorización Pandora FMS en 5 minutos con Docker Compose en Linux Debian.
Habilitar base de datos Microsoft SQL Server para acceso externo
Dado que los datos de WSUS se almacenan en un servidor de base de datos SQL Server, necesitaremos acceso a este servidor y a su base de datos WSUS correspondiente. Todos los datos que se monitorizarán en Pandora FMS se obtendrán de esta base de datos.
Si la base de datos SQL Server está en el propio servidor WSUS y si vamos a realizar la monitorización dentro del propio servidor WSUS, instalando el agente de Pandora FMS en el propio servidor WSUS, no tendremos que habilitar el motor de base de datos SQL Server para acceso externo. Por lo que nos saltaremos el siguiente paso.
Si, por el contrario, vamos a realizar la monitorización de WSUS desde otro equipo externo, necesitaremos habilitar el acceso remoto a la base de datos SQL Server. Para ello, seguiremos las instrucciones del siguiente tutorial:
Scripts Python con código para acceso a servidor SQL Server de WSUS
A continuación, mostramos el código fuente completo, de los ficheros en Python, para generar el ejecutable (script) que obtendrá todos los datos a monitorizar en el servidor SQL Server de WSUS. Todos los ficheros (incluido el ejecutable wsus.exe listo para usarse) están disponibles gratuitamente en el siguiente enlace:
Fichero wsusbd.py con la clase Python WSUSBD para conexión al servidor de SQL Server y métodos de ejecución de sentencias SQL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
import pymssql # Clase para conectar con sitio web, devuelve en atributos el resultado de la conexión y el objeto conexionHTTP class WSUSBD: servidor = "" instancia = "" puerto = 1433 usuario = "" contrasena = "" bd = "" mensaje = "" conexion = None resultadoSQL = None # Constructor con los atributos def __init__(self, servidor="", puerto=1433, usuario="", contrasena="", bd="", instancia="", mensaje="", resultadoSQL=""): self.servidor = servidor self.puerto = puerto self.usuario = usuario self.contrasena = contrasena self.bd = bd self.instancia = instancia self.mensaje = mensaje self.resultadoSQL = resultadoSQL # Método para conectar con servidor de SQL Server de WSUS (devolverá True si la conexión se ha realizado) def Conectar(self): try: self.conexion = pymssql.connect( host = self.servidor, server = self.servidor + "\\" + self.instancia, user = self.usuario, password = self.contrasena, port = self.puerto, #db = self.bd, charset="UTF-8", as_dict = True ) return self.conexion except Exception as ex: # Si se produce un error, mostraremos el error en la descripción del módulo self.mensaje = "Error al conectar a servidor de BD: {0}".format( getattr(ex, 'message', str(ex))) self.conexion = None return False # Método para obtener el valor de un campo de una consulta SQL, si se le pasa el parámetro "sql" se ignoran el resto # Si se pasa el SQL completo, hay que pasar siempre el escalar en alias con nombre "valor_devuelto" def ObtenerValorTabla(self, tabla="", campoObtener="", campoFiltrar="", valorFiltrar="", sql=None): try: if sql != None: sqlSelect = sql else: sqlSelect = "SELECT {0} as valor_devuelto FROM {1} WHERE {2} = {3}".format( campoObtener, tabla, campoFiltrar, valorFiltrar) # Establecemos un cursor para la conexión con el servidor cursor = self.conexion.cursor() cursor.execute(sqlSelect) escalar = cursor.fetchone() cursor.close return escalar["valor_devuelto"] except Exception as ex: self.mensaje = "Error al ejecutar consulta SQL para obtener escalar: {0}".format( getattr(ex, 'message', str(ex))) return None # Método para obtener uno o varios registros de una consulta SQL, si se le pasa el parámetro "sql" se ignoran el resto def ObtenerRegistrosTabla(self, tabla="", campoObtener="", campoFiltrar="", valorFiltrar="", sql=None): try: if sql != None: sqlSelect = sql else: sqlSelect = "SELECT {0}} FROM {1} WHERE {2} = {3}".format( campoObtener, tabla, campoFiltrar, valorFiltrar) # Establecemos un cursor para la conexión con el servidor MySQL cursor = self.conexion.cursor() # A partir del cursor, ejecutamos la consulta SQL cursor.execute(sqlSelect) # Guardamos el resultado de la consulta en una variable self.resultadoSQL = cursor.fetchall() # Cerramos el cursor y la conexión con MySQL cursor.close() # De momento no cerramos la conexión al servidor por si se necesita en más ocasiones # self.conexionMySQL.close() return True except Exception as ex: self.mensaje = "Error al ejecutar consulta SQL para obtener registros: {0}".format( getattr(ex, 'message', str(ex))) return None def ObtenerVersion(self): return pymssql.connect.__version__ |
Fichero arg.py con la clase Python Argumentos para mostrar los argumentos que admite la aplicación y para obtener los que el usuario pase por la línea de comandos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
import argparse class Argumentos: # Mostrar y preparar los argumentos que admite el programa por la línea de comandos def MostrarArgumentos(): # Iniciamos el programa, obteniendo los argumentos pasados por la línea de comandos # Conformamos los argumentos que admitirá el programa por la línea de comandos parser = argparse.ArgumentParser() parser.add_argument("-s", "--servidor", type=str, required=True, help="IP/Nombre de servidor de SQL Server WSUS") parser.add_argument("-i", "--instancia", type=str, required=False, help="Nombre de la instancia de SQL Server") parser.add_argument("-p", "--puerto", type=int, required=True, help="Puerto de conexión al servidor de BD") parser.add_argument("-u", "--usuario", type=str, required=True, help="Usuario de conexión al servidor de BD") parser.add_argument("-c", "--contraseña", type=str, required=True, help="Contraseña del usuario de conexión al servidor de BD") parser.add_argument("-b", "--BaseDatos", type=str, required=False, help="Base de datos al que se conectará (NO incluiremos este parámetro si el usuario tiene una BD por defecto)") parser.add_argument("-one", "--ObtenerNumeroEquipos", action="store_true", required=False, help="Obtiene el número de equipos en WSUS") parser.add_argument("-oee", "--ObtenerEquiposError", action="store_true", required=False, help="Obtiene listado de equipos con error en WSUS") parser.add_argument("-onee", "--ObtenerNumeroEquiposError", action="store_true", required=False, help="Obtiene el número de equipos con error en WSUS") parser.add_argument("-onei", "--ObtenerNumeroEquiposInstalado", action="store_true", required=False, help="Obtiene el número de equipos en WSUS con estado installed (instalado)") parser.add_argument("-oneni", "--ObtenerNumeroEquiposNoInstalado", action="store_true", required=False, help="Obtiene el número de equipos en WSUS con estado not installed (no instalado)") parser.add_argument("-oned", "--ObtenerNumeroEquiposDescargado", action="store_true", required=False, help="Obtiene el número de equipos en WSUS con estado downloaded (descargado)") parser.add_argument("-onen", "--ObtenerNumeroEquiposNecesario", action="store_true", required=False, help="Obtiene el número de equipos en WSUS con estado needed (necesario)") parser.add_argument("-incinm", "--NombreModulo", type=str, required=False, help="Nombre del módulo que se asignará para Pandora FMS. Por ejemplo: WSUS_Numero_Equipos_Error") parser.add_argument("-incides", "--Descripcion", type=str, required=False, help="Descripción del módulo que se asignará para Pandora FMS. Por ejemplo: Numero de equipos con error en WSUS") return parser.parse_args() |
Fichero pandora.py con la clase Python Pandora. Esta clase será la encargada de mostrar por consola los valores pasados como argumento en formato XML Tentacle de Pandora FMS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
class Pandora: # Mostrar resultado en consola con formato tentacle de Pandora FMS def MostrarResultado(resultado, nombreModulo, descripcion, unidad=None, minWarning=None, maxWarning=None, minCritical=None, maxCritical=None, minimo=None, maximo=None): print("<module>") print("<name><![CDATA[{0}]]></name>".format(nombreModulo)) print("<type><![CDATA[generic_proc]]></type>") print("<data><![CDATA[{0}]]></data>".format(resultado)) print("<description><![CDATA[{0}]]></description>".format(descripcion)) if unidad != None: print("<unit>{0}</unit>".format(unidad)) if minWarning != None: print("<min_warning><![CDATA[{0}]]></min_warning>".format(minWarning)) if maxWarning != None: print("<max_warning><![CDATA[{0}]]></max_warning>".format(maxWarning)) if minCritical != None: print("<min_critical><![CDATA[{0}]]></min_critinal>".format(minCritical)) if maxCritical != None: print("<max_critical><![CDATA[{0}]]></max_critical>".format(maxCritical)) if minimo != None: print("<min><![CDATA[{0}]]></min>".format(minimo)) if maximo != None: print("<max><![CDATA[{0}]]></max>".format(maximo)) print("</module>") |
Fichero consultasWSUS.py con la clase Python CWSUS. Esta será la clase que ejecutará las sentencias SQL (mediante la clase WSUSBD) necesarias para obtener los distintos valores que se monitorizarán (número de equipos con estado de Failed, Needed, Installed, Not Installed o Downloaded, equipos con número de días de última sincronización, etc.). También ejecutará los métodos necesarios (de la clase Pandora) para mostrar los valores obtenidos por consola en formato XML Tentacle de Pandora FMS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
from pandora import Pandora as Pan class CWSUS: bd = None # Para instancia de la clase BD con métodos de acceso a SQL Server argumentos = None # Para el paso de los argumentos de la línea de comandos (nombre de módulos Pandora y demás) def __init__(self, bd=None, argumentos=None): self.bd = bd self.argumentos = argumentos # Obtener número total de equipos en WSUS def ObtenerNumeroEquiposTotal(self): try: valor = self.bd.ObtenerValorTabla(sql=""" SELECT COUNT(*) as valor_devuelto FROM SUSDB.dbo.tbComputerTarget;""") return valor except Exception as ex: print("Error al obtener número de equipos en WSUS: {0}".format(self.bd.getMensaje())) return 0 # Obtener número de equipos en WSUS con SummarizationState = 5 (Failed) def ObtenerNumeroEquiposError(self): try: valor = self.bd.ObtenerValorTabla(sql=""" SELECT count(distinct(u.TargetID)) AS valor_devuelto FROM SUSDB.dbo.tbUpdateStatusPerComputer u WHERE u.SummarizationState = 5;""") return valor except Exception as ex: print("Error al obtener número de equipos con Failed en WSUS: {0}".format(self.bd.getMensaje())) return 0 # Obtener número de equipos en WSUS con SummarizationState = 4 (Installed) def ObtenerNumeroEquiposInstalado(self): try: valor = self.bd.ObtenerValorTabla(sql=""" SELECT count(distinct(u.TargetID)) AS valor_devuelto FROM SUSDB.dbo.tbUpdateStatusPerComputer u WHERE u.SummarizationState = 4;""") return valor except Exception as ex: print("Error al obtener número de equipos con Installed en WSUS: {0}".format(getattr(ex, 'message', str(ex)))) return 0 # Obtener número de equipos en WSUS con SummarizationState = 3 (Downloaded) def ObtenerNumeroEquiposDescargado(self): try: valor = self.bd.ObtenerValorTabla(sql=""" SELECT count(distinct(u.TargetID)) AS valor_devuelto FROM SUSDB.dbo.tbUpdateStatusPerComputer u WHERE u.SummarizationState = 3;""") return valor except Exception as ex: print("Error al obtener número de equipos con Downloaded en WSUS: {0}".format(getattr(ex, 'message', str(ex)))) return 0 # Obtener número de equipos en WSUS con SummarizationState = 2 (Needed) def ObtenerNumeroEquiposNecesario(self): try: valor = self.bd.ObtenerValorTabla(sql=""" SELECT count(distinct(u.TargetID)) AS valor_devuelto FROM SUSDB.dbo.tbUpdateStatusPerComputer u WHERE u.SummarizationState = 2;""") return valor except Exception as ex: print("Error al obtener número de equipos con Needed en WSUS: {0}".format(getattr(ex, 'message', str(ex)))) return 0 # Obtener número de equipos en WSUS con SummarizationState = 1 (Not Installed) def ObtenerNumeroEquiposNoInstalado(self): try: valor = self.bd.ObtenerValorTabla(sql=""" SELECT count(distinct(u.TargetID)) AS valor_devuelto FROM SUSDB.dbo.tbUpdateStatusPerComputer u WHERE u.SummarizationState = 1;""") return valor except Exception as ex: print("Error al obtener número de equipos con Not Installed en WSUS: {0}".format(getattr(ex, 'message', str(ex)))) return 0 # Mostrar por consola en formato tentacle de Pandora FMS el número de equipos en WSUS def MostrarNumeroEquiposTotal(self): valor = self.ObtenerNumeroEquiposTotal() if valor == None: print(f"Error al obtener total equipos en WSUS: {self.bd.mensaje}") else: # Mostramos el resultado por consola en formato XML Tentacle de Pandora FMS Pan.MostrarResultado(resultado=valor, nombreModulo=self.argumentos.NombreModulo, descripcion=self.argumentos.Descripcion, maximo=valor, minimo=0) # Mostrar por consola en formato tentacle de Pandora FMS el número de equipos con Error en WSUS def MostrarNumeroEquiposError(self): valor = self.ObtenerNumeroEquiposError() if valor == None: print(f"Error al obtener equipos con Error en WSUS: {self.bd.mensaje}") else: # Mostramos el resultado por consola en formato XML Tentacle de Pandora FMS Pan.MostrarResultado(resultado=valor, nombreModulo="WSUS_Equipos_Error", descripcion="Numero de equipos con Error en WSUS", maximo=valor, minimo=0) # Mostrar por consola en formato tentacle de Pandora FMS el número de equipos con Installed en WSUS def MostrarNumeroEquiposInstalled(self): valor = self.ObtenerNumeroEquiposInstalado() if valor == None: print(f"Error al obtener equipos con Installed en WSUS: {self.bd.mensaje}") else: # Mostramos el resultado por consola en formato XML Tentacle de Pandora FMS Pan.MostrarResultado(resultado=valor, nombreModulo="WSUS_Equipos_Installed", descripcion="Numero de equipos con Installed en WSUS", maximo=valor, minimo=0) # Mostrar por consola en formato tentacle de Pandora FMS el número de equipos con Downloaded en WSUS def MostrarNumeroEquiposDownloaded(self): valor = self.ObtenerNumeroEquiposDescargado() if valor == None: print(f"Error al obtener equipos con Downloaded en WSUS: {self.bd.mensaje}") else: # Mostramos el resultado por consola en formato XML Tentacle de Pandora FMS Pan.MostrarResultado(resultado=valor, nombreModulo="WSUS_Equipos_Downloaded", descripcion="Numero de equipos con Downloaded en WSUS", maximo=valor, minimo=0) # Mostrar por consola en formato tentacle de Pandora FMS el número de equipos con Needed en WSUS def MostrarNumeroEquiposNeeded(self): valor = self.ObtenerNumeroEquiposNecesario() if valor == None: print(f"Error al obtener equipos con Needed en WSUS: {self.bd.mensaje}") else: # Mostramos el resultado por consola en formato XML Tentacle de Pandora FMS Pan.MostrarResultado(resultado=valor, nombreModulo="WSUS_Equipos_Needed", descripcion="Numero de equipos con Needed en WSUS", maximo=valor, minimo=0) # Mostrar por consola en formato tentacle de Pandora FMS el número de equipos con Not Installed en WSUS def MostrarNumeroEquiposNotInstalled(self): valor = self.ObtenerNumeroEquiposNoInstalado() if valor == None: print(f"Error al obtener equipos con Installed en WSUS: {self.bd.mensaje}") else: # Mostramos el resultado por consola en formato XML Tentacle de Pandora FMS Pan.MostrarResultado(resultado=valor, nombreModulo="WSUS_Equipos_NotInstalled", descripcion="Numero de equipos con Not Installed en WSUS", maximo=valor, minimo=0) |
Fichero wsus.py. Fichero principal de la aplicación, que ejecutará el programa usando las clases anteriores:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# ProyectoA.com Aplicación Python para obtener datos de un servidor de actualizaciones WSUS y devolverlos en formato Pandora FMS # Versión 1.0 from wsusbd import WSUSBD as BD from consultasWSUS import CWSUS as Con from arg import Argumentos as Arg def IniciarPrograma(): # Preparamos y mostramos los argumentos (si se indica) en la consola argum = Arg.MostrarArgumentos() if argum.servidor != None: # Instanciamos la clase WSUSBD para realizar la conexión a SQL Server bd = BD(servidor=argum.servidor, puerto=argum.puerto, usuario=argum.usuario, contrasena=argum.contraseña, bd=argum.BaseDatos, instancia=argum.instancia) # Realizamos la conexión con la base de datos if bd.Conectar(): # Instanciamos la clase CWSUS pasándole al constructor la instancia de BD anterior, para usar sus métodos # y también la instancia de la clase Argumentos para usar los datos pasados por parámetro de línea # de comandos (nombe de módulos Pandora y demás) con = Con(bd=bd, argumentos=argum) # Si se ha pasado argumento ObtenerNumeroEquipos, mostrar número total de equipos en WSUS if argum.ObtenerNumeroEquipos: con.MostrarNumeroEquiposTotal() # Si se ha pasado argumento ObtenerEquiposError, mostrar número total de equipos con Error en WSUS if argum.ObtenerNumeroEquiposError: con.MostrarNumeroEquiposError() # Si se ha pasado argumento ObtenerNumeroEquiposInstalado, mostrar número total de equipos con Installed en WSUS if argum.ObtenerNumeroEquiposInstalado: con.MostrarNumeroEquiposInstalled() # Si se ha pasado argumento ObtenerNumeroEquiposNoInstalado, mostrar número total de equipos con Not Installed en WSUS if argum.ObtenerNumeroEquiposNoInstalado: con.MostrarNumeroEquiposNotInstalled() # Si se ha pasado argumento ObtenerNumeroEquiposDescargado, mostrar número total de equipos con Downloaded en WSUS if argum.ObtenerNumeroEquiposDescargado: con.MostrarNumeroEquiposDownloaded() # Si se ha pasado argumento ObtenerNumeroEquiposDescargado, mostrar número total de equipos con Needed en WSUS if argum.ObtenerNumeroEquiposNecesario: con.MostrarNumeroEquiposNeeded() else: # Si no se ha conectado al servidor de BD mostramos error en el módulo print("Error al obtener datos: {0}".format(bd.mensaje)) # Iniciamos el programa IniciarPrograma() |
Crearemos estos ficheros en una misma carpeta y, por comodidad, generaremos el ejecutable que los empaquete todos, siguiendo estas instrucciones:
Ejecutaremos el siguiente comando desde la carpeta donde tengamos todos los ficheros anteriores:
1 |
pyinstaller.exe wsus.py -F |
Lo que nos generará el ejecutable «wsus.exe» que quedará listo para pasarlo a la carpeta «util» de Pandora Agent, como indicamos a continuación.

Añadir módulos a Pandora Agent en equipo servidor WSUS
Si optamos por instalar Pandora Agent en el propio servidor que contiene el rol de WSUS y su base de datos SQL Server, sólo tendremos que pegar el fichero wsus.exe generado anteriormente en la subcarpeta «util» de la carpeta donde hayamos instalado Pandora Agent. Por defecto suele ser:
C:\Program Files\pandora_agent\util

Editaremos el fichero pandora_agent.conf, ubicado en la carpeta de instalación de Pandora Agent:

Y añadiremos las siguientes líneas, cambiando, como es lógico, los siguientes valores por los del equipo servidor WSUS y su bd SQL Server:
- SERVERWSUS: nombre de red o dirección IP del servidor con el rol WSUS y la BD de SQL Server (si está en el mismo, si no, el nombre del equipo con la BD de SQL Server).
- WSUSDB: nombre de la instancia de SQL Server correspondiente a la BD de WSUS.
- 1433: puerto que hayamos establecido para la conexión externa a SQL Server.
- usuario_sql_server: nombre del usuario de SQL Server con permisos de lectura (SELECT) de las tablas necesarias para obtener los datos.
- Contraseña_Usuario: contraseña del usuario de SQL Server anterior.
- SUSBD: NO se indicará la base de datos si el usuario SQL Server utilizado tiene asignada la base de datos de WSUS por defecto, que es lo recomendable.
- El resto de parámetros podremos modificarlos para adaptarlos a nuestras necesiadades, son los que indican qué datos obtener y qué nombre y descripción asignar al módulo correspondiente del agente de Pandora FMS. Los posibles son:
- one: obtiene el número total de equipos en WSUS.
- onee: obtiene el número de equipos con estado «Failed».
- onei: obtiene el número de equipos con estado «Installed».
- oned: obtiene el número de equipos con estado «Downloaded».
- oneni: obtiene el número de equipos con estado «Not Installed».
- onen: obtiene el número de equipos con estado «Needed».
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Total equipos en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -one -b "SUSBD" -incinm "WSUS_Equipos_Total" -incides "Numero de equipos total en WSUS" # Equipos con error en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -onee -b "SUSBD" -incinm "WSUS_Equipos_Error" -incides "Numero de equipos con Error en WSUS" # Equipos con installed en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -onei -b "SUSBD" -incinm "WSUS_Equipos_Installed" -incides "Numero de equipos con Installed en WSUS" # Equipos con downloaded en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -oned -b "SUSBD" -incinm "WSUS_equipos_Downloaded" -incides "Numero de equipos con Downloaded en WSUS" # Equipos con Not Installed en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -oneni -b "SUSBD" -incinm "WSUS_Equipos_NotInstalled" -incides "Numero de equipos con Not Installed en WSUS" # Equipos con Needed en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -onen -b "SUSBD" -incinm "WSUS_Numero_Equipos_Needed" -incides "Numero de equipos con Needed en WSUS" |
Añadiremos todas las líneas que deseemos para generar los módulos/sondas/sensores correspondientes en Pandora FMS. Guardaremos los cambios en el fichero pandora_agent.conf.
Para aplicar los cambios, podremos reiniciar el servicio de Pandora Agent, ejecutando el script «restart_pandora_agent.bat» de la carpeta «scripts»:

Transcurridos unos segundos, accederemos a la consola web de Pandora FMS y al agente correspondiente al servidor WSUS, veremos que nos ha agregado los módulos y sus valores WSUS indicados en el fichero pandora_agent.conf:

Añadir módulos a Pandora Agent mediante Broker en equipo externo a WSUS
Si preferimos monitorizar el servidor WSUS externamente, desde otro equipo de la red, podremos hacerlo mediante un broker. Para ello, una vez instalado Pandora Agent en el equipo remoto (debe tener acceso al servidor de SQL Server de WSUS, como indicamos en este apartado), en la carpeta donde hayamos instalado Pandora Agent y donde tengamos el fichero pandora_agent.conf, añadiremos un nuevo fichero mediante un editor de texto plano, con el siguiente contenido:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
server_ip 192.168.1.150 server_path /var/spool/pandora/data_in temporal "C:\Program Files\pandora_agent\temp" agent_name SERVERWSUS address 192.168.1.160 interval 300 server_port 41121 debug 0 remote_config 0 xml_buffer 0 # Total equipos en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -one -b "SUSBD" -incinm "WSUS_Equipos_Total" -incides "Numero de equipos total en WSUS" # Equipos con error en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -onee -b "SUSBD" -incinm "WSUS_Equipos_Error" -incides "Numero de equipos con Error en WSUS" # Equipos con installed en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -onei -b "SUSBD" -incinm "WSUS_Equipos_Installed" -incides "Numero de equipos con Installed en WSUS" # Equipos con downloaded en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -oned -b "SUSBD" -incinm "WSUS_equipos_Downloaded" -incides "Numero de equipos con Downloaded en WSUS" # Equipos con Not Installed en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -oneni -b "SUSBD" -incinm "WSUS_Equipos_NotInstalled" -incides "Numero de equipos con Not Installed en WSUS" # Equipos con Needed en WSUS module_plugin "%ProgramFiles%\Pandora_Agent\util\wsus.exe" -s "SERVERWSUS" -i "WSUSDB" -p 1433 -u "usuario_sql_server" -c "Contraseña_Usuario" -onen -b "SUSBD" -incinm "WSUS_Numero_Equipos_Needed" -incides "Numero de equipos con Needed en WSUS" |
Teniendo en cuenta los siguientes valores y su significado:
- 192.168.1.150: cambiaremos esta IP por la dirección IP del servidor con Pandora FMS Server.
- SERVERWSUS: cambiaremos este valor por el nombre de red (nombre de DNS o hostname) del servidor con WSUS.
- 192.168.1.160: cambiaremos este valor por la dirección IP del servidor con WSUS.
- En el resto de líneas del fichero, las que generan los módulos en el agente SERVERWSUS (servidor de WSUS), cambiaremos, como hemos explicado el punto anterior, los valores:
- SERVERWSUS: nombre de red o dirección IP del servidor con el rol WSUS y la BD de SQL Server (si está en el mismo, si no, el nombre del equipo con la BD de SQL Server).
- WSUSDB: nombre de la instancia de SQL Server correspondiente a la BD de WSUS.
- 1433: puerto que hayamos establecido para la conexión externa a SQL Server.
- usuario_sql_server: nombre del usuario de SQL Server con permisos de lectura (SELECT) de las tablas necesarias para obtener los datos.
- Contraseña_Usuario: contraseña del usuario de SQL Server anterior.
- SUSBD: NO se indicará la base de datos si el usuario SQL Server utilizado tiene asignada la base de datos de WSUS por defecto, que es lo recomendable.
Guardaremos el contenido anterior en un fichero con el nombre wsus.conf, como hemos indicado, en la carpeta de instalación de Pandora FMS Agent.
Para ejecutar este broker y generar el agente «virtual» externo en Pandora FMS Server, en nuestro caso, con el nombre SERVERWSUS, editaremos el fichero pandora_agen.conf, ubicado en la carpeta de instalación de Pandora Agent y añadiremos la siguiente línea:
1 |
broker_agent wsus |

Guardaremos los cambios en el fichero pandora_agent.conf y reiniciaremos el servicio de Pandora Agent para que el broker cree el agente SERVEWSUS en Pandora FMS Server con los módulos indicados en el fichero wsus.conf:

Transcurridos unos segundos, en la consola de gestión web de Pandora FMS nos aparecerá el agente SERVERWSUS (el nombre del agente que hayamos establecido), si no lo teníamos ya dado de alta. Aparecerá con los nuevos módulos de monitorización de WSUS indicados en el fichero wsus.conf:

Posibles errores y su solución
20009 DB-Lib error message 20009 severity 9: Unable to connect:
Adaptive Server is unavailable or does not exist (SERVIDOR_SQL_SERVER)
Net-Lib error during Unknown error (10060)
Este error es muy genérico y puede ser debido a diversos motivos, algunos de ellos:
- En una conexión remota al servidor SQL Server desde un equipo de la red: cuando no se ha abierto el puerto de SQL Server en el cortafuegos del equipo Windows que contiene la base de datos. Este error se soluciona añadiendo una regla, como hemos indicando en este apartado y abriendo el puerto correspondiente en el cortafuegos.
- Otro motivo de este error puede ser que el servicio de SQL Server no esté activo o bien que no estemos introduciendo el nombre de la instancia de SQL Server correcta en la cadena de conexión. En este caso, revisaremos que el servicio de SQL Server esté activo en el servidor y revisaremos la cadena de conexión o el código de conexión, para asegurarnos de que estamos introduciendo el nombre de la instancia correcto. El nombre de la instancia suele ser Nombre_Servidor\Nombre_Instancia, para una instalación estándar, el nombre de la instancia por defecto es MSSQLSERVER.
- Otra posibilidad es que no estén habilitada correctamente la configuración TCP/IP de la instancia de SQL Server. Esto se puede solucionar siguiendo los pasos de este apartado del tutorial que nos ocupa.