Integración de Webhooks de OpenStack Monasca
2016-03-25
Machine-translated from English. Read the English original
### La historia de dos segundos de Graham sobre los Webhooks [no técnico]
Bueno, estoy seguro de que todos saben qué son los webhooks, pero yo solo lo descubrí el mes pasado, en preparación para otra integración de Helion OpenStack.
Aquí está mi comprensión simplificada de ellos: son “Notificaciones Push”.
Con la llegada de la red de redes (intertubes) nos volvimos muy listos muy rápido y comenzamos a utilizar todos estos locos protocolos UDP y TCP para la comunicación M2M. Dado que el ancho de banda nunca fue un problema (estoy bromeando), la eficiencia nunca fue el primer requisito.
Muchas soluciones de monitoreo se decantaron por HTTP como el protocolo de elección y simplemente realizaban sondeos (polling) a los recursos que les interesaban y esperaban una respuesta. Monasca proporciona una API RESTful si desea utilizar este enfoque.
Sin embargo, con la nube llegan los desafíos de la escala. Y cuando estás intentando sondear cientos de miles de servicios en segundos, la eficiencia es muy importante. Entonces aparecen los webhooks para salvar el día.
A diferencia del sondeo (polling) ‘antiguo’ e ineficiente, que requiere una HTTP GET seguida de una HTTP POST incluso cuando no hay nada que reportar, los webhooks requieren una única HTTP POST y solo se activan cuando hay algo digno de reportar a casa!!!
Así que, para resumir: se trata de frecuentes HTTP GET/POST frente a infrecuentes HTTP POST. Existe un mito urbano que circula por la red que dice que cuando Github introdujo los Webhooks, redujo la carga en sus servidores de los usuarios que monitoreaban cambios de código nuevo en un factor de 66X. [No tengo ningún dato]
¿Cómo los configuramos? Sencillo, especialmente si leíste mi blog anterior sobre la integración SMTP. Hagamos primero la parte de la GUI: todo esto podría hacerse desde la CLI, pero eso requeriría que leyera más.
Nota: La GUI de la Consola de Operaciones es específica de la distribución Helion OpenStack. Si no estás utilizando Helion, necesitarás usar la CLI de Monasca.
Configuración de Webhooks en HOS Monasca
-
Inicia sesión en la Consola de Ops de Helion como un usuario administrador de la nube

-
Selecciona la opción Métodos de Notificación desde el menú ‘hamburguesa’ en la parte superior izquierda de la pantalla.

-
Crea un nuevo método de notificación, seleccionando Webhook e ingresa los detalles de la URL a la que deseas enviar las notificaciones por HTTP POST.

Y eso es todo lo que hay que hacer con los webhooks. Pero espera, ‘¿cómo probamos y verificamos esto?’ creo que me oyes pensar… bueno, sigue leyendo.
Crear una Alarma de Prueba
Volvamos a nuestro menú ‘hamburguesa’ y esta vez selecciona Creación de Alarmas y crea una nueva alarma como sigue: queremos alertas falsas aquí, así que usaré cpu.idle como métrica y estableceré valores absurdos –

Crear Nueva Definición de Alarma
Inicialmente pueden aparecer 2 Alarmas Desconocidas ya que es la primera vez que esta alarma se ejecuta y no tiene un estado anterior. Sin embargo, ten paciencia, en unos minutos más deberías ver cómo el tablero se ilumina como se muestra a continuación.

Espera unos minutos (5)
Ahora puedes seleccionar las alarmas para obtener más detalles.

Observa las Alarmas

Ver Detalles de la Alarma
Y por supuesto, lo que todos hemos estado esperando: ¡alertas de webhook!!!
¡Doh! ¿Cómo probamos las Alertas de Webhook…?
Muchas soluciones de monitoreo de grado empresarial aún no admiten webhooks hoy en día: estos chicos simplemente no entienden la agilidad y se preguntan por qué los peces más pequeños los superan.
Una vez más, no recomiendo hacer nada de lo que estás a punto de ver en sistemas de producción: esto es puramente para probar y verificar webhooks. Además, ten en cuenta que he abierto un puerto en el firewall del plano de control de HOS para permitirme usar mi nodo de implementación como el servidor de webhook ejecutándose en el puerto 3001. [Consulta la publicación anterior sobre SMTP si deseas probar esto EN TU LABORATORIO]
Nota: A todos los programadores ahí fuera, me disculpo ahora por todas las reglas que estoy rompiendo, mala codificación, etc. Sean amables, hackeé estos ejemplos juntos gracias a todas sus publicaciones 🙂
He proporcionado dos scripts de ejemplo a continuación: uno para NodeJS y otro para Python. Python porque muchos usuarios de OpenStack estarán familiarizados con él. NodeJS porque quería una excusa para jugar con él: ¡es genial! No estoy cubriendo cómo configurar tus entornos de python o node aquí, hay toneladas de blogs sobre estos temas. El Entorno Virtual (virtualenv) es tu amigo si usas python: úsalo.
Ejemplo de Python
Copia el siguiente script de python a un archivo y guárdalo como webhook.py. Este script espera notificaciones de webhook y cuando las recibe, las escribe en un archivo de registro. Esto podría ser utilizado por soluciones de monitoreo heredadas para analizar las alertas, aunque no es de grado empresarial, solo es un ejemplo.
webhook.py
# Author: Graham Joseph Land
# Blog: allthingscloud.eu
# Twitter: @allthingsclowd
# Email: graham@ the above domain
# Date: 24/03/2016
#
# Name: webhook.py
# Version: 0.1
# Purpose: This script listens for webhook notifications and then writes them to a logfile
#
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import json
import logging
import logging.handlers
# log file for this script
log_file = '/home/stack/monitoring/venv/webhook/webhook.log'
log_max_size = 25165824 # 24 MB
log_level = logging.INFO
#log_level = logging.DEBUG # DEBUG is quite verbose
log = logging.getLogger('log')
log.setLevel(log_level)
log_handler = logging.handlers.RotatingFileHandler(log_file,
maxBytes=log_max_size,
backupCount=4)
f = logging.Formatter("%(asctime)s %(filename)s %(levelname)s %(message)s",
"%B %d %H:%M:%S")
log_handler.setFormatter(f)
log.addHandler(log_handler)
class webhookReceiver(BaseHTTPRequestHandler):
def do_POST(self):
"""
receives post, handles it
"""
log.info('<<<<<<<<< Alert Start >>>>>>>>')
message = 'OK'
self.rfile._sock.settimeout(5)
data_string = self.rfile.read(int(self.headers['Content-Length']))
self.send_response(200)
self.send_header("Content-type", "text")
self.send_header("Content-length", str(len(message)))
self.end_headers()
self.wfile.write(message)
# parse data
text = json.loads(data_string)
text = json.dumps(text, indent=2)
log.info(text)
log.info('<<<<<<<<< Alert End >>>>>>>>')
def log_message(self, formate, *args):
"""
disable printing to stdout/stderr for every post
"""
return
def main():
"""
the main event.
"""
try:
server = HTTPServer(('', 3001), webhookReceiver)
log.info('started web server...')
server.serve_forever()
except KeyboardInterrupt:
log.info('ctrl-c pressed, shutting down.')
server.socket.close()
if __name__ == '__main__':
Ejecuta el script y sigue el archivo de registro (tail) – ahora vuelve y genera las alertas de nuevo y observa qué sucede..

Y ahí lo tienes – webhooks – ¡“sencillo”!
Para descartar problemas de Monasca, también podrías probar este script utilizando una declaración curl como sigue:
curl -H "Content-Type: application/json" -X POST -d '{"alarm_id": "1234","alarm_definition_id": "freddef","alarm_name": "fire alarm","alarm_description": "alarmDescription","alarm_timestamp": "timestamp","state": "Critical","old_state": "oldState","message": "this is the message","tenant_id": "tenant1234","metrics": "1234"}' --trace-ascii debugdump.txt http://172.16.60.9:3000/openstack/alerts
Ejemplo de NodeJS
Ten en cuenta que estoy utilizando un punto final (endpoint) de webhook diferente al utilizado en el ejemplo de python.

Se requiere una estructura de archivos ligeramente más compleja para la aplicación de ejemplo de NodeJS.
Utilizamos el principal app server.js que luego llama a la aplicación de ‘ruta’ webhook.js la cual procesará el webhook al recibirlo.
(venv)stack@helion-cp1-c0-m1-mgmt:~/monitoring/nodejs$ tree -I node_modules
.
|-- routers
| `-- webhook.js
`-- server.js
Copia las dos aplicaciones a continuación en archivos coincidentes nombrados utilizando la misma estructura de directorio mostrada arriba.
server.js
var bodyParser = require( 'body-parser' ),
express = require( 'express' ),
app = express();
var webhook = require( './routers/webhook' );
app.use( bodyParser.json() );
app.use( bodyParser.urlencoded({
extended: true
}) );
app.get( '/', function ( req, res, next ) {
res.send( 'Hooks listener running' );
});
app.use( '/openstack/alerts', webhook );
app.listen( 3001 );
y en el subdirectorio routers
webhook.js
var express = require( 'express' ),
bodyParser = require('body-parser'),
router = express.Router();
router.use(bodyParser.json());
router.post( '/', function ( req, res, next ) {
console.log(req.body);
res.status(200).json({message: 'Monasca Hook received!'})
});
module.exports = router;
Lanza la aplicación y pruébala con curl primero –
stack@helion-cp1-c0-m1-mgmt:~$ curl -H "Content-Type: application/json" -X POST -d '{"alarm_id": "1234","alarm_definition_id": "freddef","alarm_name": "fire alarm","alarm_description": "alarmDescription","alarm_timestamp": "timestamp","state": "Critical","old_state": "oldState","message": "this is the message","tenant_id": "tenant1234","metrics": "1234"}' --trace-ascii debugdump.txt http://172.16.60.9:3001/openstack/alerts
{"message":"Monasca Hook received!"}stack@helion-cp1-c0-m1-mgmt:~$
El resultado debería verse así
(venv)stack@helion-cp1-c0-m1-mgmt:~/monitoring/nodejs$ nodejs server.js
{ alarm_id: '1234',
alarm_definition_id: 'freddef',
alarm_name: 'fire alarm',
alarm_description: 'alarmDescription',
alarm_timestamp: 'timestamp',
state: 'Critical',
old_state: 'oldState',
message: 'this is the message',
tenant_id: 'tenant1234',
metrics: '1234' }
Y finalmente, envía una alerta desde Monasca como se detalló anteriormente para ver cómo llegan las notificaciones de webhook y son procesadas por la aplicación.

[Notas: Solución de problemas de entrega de notificaciones]
- Si aún no ves ningún tráfico AHORA Y tu archivo
/var/log/monasca/notification/notification.logestá vacío, intenta reconfigurar monasca
cd ~/scratch/ansible/next/hos/ansible
ansible-playbook -i hosts/verb_hosts monasca-reconfigure.yml
-
Al reconfigurar definiciones de alarma existentes, asegúrate de seleccionar AMBOS la casilla de verificación de notificaciones Y los métodos de notificación individuales requeridos.

-
Utiliza TCPDUMP para verificar si el tráfico de webhook está saliendo de las interfaces de cualquiera de los tres nodos controladores [busca en el número de puerto del webhook].
Originally published on allthingscloud.eu (2016-03-25).