HyperV Monitor — Monitor de Clusters Hyper-V
Resumen
Servicio Python (puerto 8086) que monitoriza el espacio en disco de los Cluster Shared Volumes (CSV) de los clusters Hyper-V del equipo.
Recopila datos remotamente via PowerShell, persiste un historial de métricas, alerta via SisAlerts cuando el espacio libre cae por debajo de umbrales configurables y ofrece un panel web con estado en tiempo real.
Integrado con la plataforma SisApps (sidebar compartida, SSO via Entra ID App Proxy).
1. Acceso al sistema
| Dato | Valor |
| URL | https://hypervmonitor-idealistaa82505660.msappproxy.net |
| Autenticación | Entra ID Application Proxy (SSO con cuenta corporativa) |
| Puerto interno | 8086 |
| Acceso admin | Todos los usuarios SSO son admins (sso.auto_admin: true) |
| Servicio Windows | WinSW: hypervmonitor-service.xml |
2. Qué hace el sistema
- Polling de clusters — Cada 5 minutos (configurable) ejecuta remotamente via PowerShell
collect_cluster_data.ps1 en cada cluster habilitado. El script usa Invoke-Command para obtener el estado de nodos y CSVs sin credenciales explícitas (usa la cuenta de servicio del proceso Windows).
- Persistencia — Hace upsert del estado actual de nodos y volúmenes, y guarda un punto en la serie temporal de cada CSV para las gráficas de historial.
- Evaluación de umbrales — Para cada volumen, compara el espacio libre (en % y en GB) con los umbrales configurados (por volumen, por cluster o global). Si cualquiera de los dos umbrales se supera, activa la alerta.
- Notificación SisAlerts — POST a
/api/ingest de SisAlerts con deduplicación por external_id. Respeta un cooldown (default 4h) para no enviar spam, pero siempre reenvía si la severidad empeora.
- Auto-resolución — Cuando el espacio se recupera por encima del umbral, la alerta se cierra automáticamente.
3. Sistema de umbrales en cascada
Tanto el umbral en porcentaje de espacio libre como en GB libres se evalúan independientemente. La alerta salta si cualquiera de los dos se supera.
| Nivel | Fuente | Prioridad |
| Por volumen | csv_volumes.warning_threshold_pct / warning_threshold_gb | Máxima — si no es NULL |
| Por cluster | clusters.warning_threshold_pct / warning_threshold_gb | Media — si no está configurado por volumen |
| Global | thresholds.warning_percent en app-config.json | Mínima — fallback global (solo % ,no GB) |
Configuración por volumen
Desde Admin → Clusters → Volúmenes se puede definir un umbral independiente para cada CSV.
Los campos vacíos heredan el valor del cluster. Útil para volúmenes con comportamiento distinto al resto del cluster.
Severidades
| Nivel | Prioridad SisAlerts | Condición |
| crítico | critical | Espacio libre ≤ umbral crítico (% o GB) |
| warning | high | Espacio libre ≤ umbral warning pero > umbral crítico |
| resuelto | — | Espacio libre recuperado por encima del umbral |
4. Panel web
Dashboard (/)
- Estado global: número de clusters, nodos up/down, alertas activas.
- Por cluster: tabla de CSVs con espacio libre (%), espacio libre (GB), tamaño total, nodo propietario, estado y barra visual de uso.
- Alertas activas en color rojo/naranja con enlace a SisAlerts.
- Botón Poll ahora: fuerza un ciclo de polling inmediato.
Detalle de cluster
- Gráfica de historial de espacio libre para cada volumen (últimas 24h / 7d / 30d).
- Estado de los nodos (Up/Down, tiempo de actividad).
- Log de los últimos ciclos de polling (duración, errores).
Alertas (/alerts)
- Historial de alertas con fechas de creación, envío y resolución.
- Indicador de si la alerta fue enviada correctamente a SisAlerts.
5. Integración SisAlerts
Cuando un volumen supera el umbral, se envía un POST al endpoint /api/ingest de SisAlerts:
POST {sisalerts.url}/api/ingest
X-Api-Key: {sisalerts.api_key}
Content-Type: application/json
{
"source": "hyperv-monitor",
"sender": "hyperv-monitor",
"priority": "critical" | "high",
"external_id": "hvmon-{cluster_id}-{volume_name}",
"subject": "CSV crítico: {volume_name} — X% libre (Yz GB)",
"body_html": "...",
"rule_id": 5
}
Deduplicación y cooldown
El campo external_id garantiza que SisAlerts no duplique alertas del mismo volumen.
El cooldown (default 4h) evita spam. Se reenvía siempre si la severidad empeora (warning → critical).
El campo rule_id indica a SisAlerts qué regla de enrutamiento aplicar (canales Teams/Telegram, menciones).
6. Administración
| Sección | Descripción |
| Clusters | CRUD de clusters con nombre, dirección, estado habilitado/deshabilitado, umbrales warning/crítico (% y GB). Botón "Volúmenes" para configurar umbrales por CSV. |
| Volúmenes | Tabla editable de umbrales por cada CSV del cluster. Los campos vacíos heredan el umbral del cluster. Se muestra el espacio libre actual con color según el estado de alerta. |
| Alertas | Historial completo con lifecycle (creada, enviada, resuelta). Permite resolver manualmente alertas falsas. |
| Ajustes | Configuración de SisAlerts (URL, API key, habilitado), test de conectividad, umbrales globales, intervalo de polling. |
Test de conectividad SisAlerts
El botón Test SisAlerts en Admin → Ajustes envía una alerta de prueba con external_id: hvmon-test-connectivity.
Bypasa el flag sisalerts.enabled y devuelve errores concretos: connection refused, timeout, 401, HTTP status. Se puede indicar un rule_id para probar el enrutamiento.
7. Configuración (app-config.json)
| Parámetro | Descripción |
polling.enabled | Activa/desactiva el polling automático de clusters. |
polling.interval_seconds | Segundos entre ciclos de polling. Defecto: 300 (5 min). |
thresholds.warning_percent | % de espacio libre para alerta warning. Defecto: 20. |
thresholds.critical_percent | % de espacio libre para alerta crítico. Defecto: 10. |
thresholds.alert_cooldown_hours | Horas mínimas entre reenvíos de la misma alerta. Defecto: 4. |
sisalerts.url | URL base de SisAlerts (ej: http://localhost:8082). |
sisalerts.api_key | API key para autenticar en SisAlerts (X-Api-Key). |
sisalerts.enabled | Si false, las alertas se crean en DB pero no se envían a SisAlerts (el test de conectividad bypasa este flag). |
retention_days | Días de retención del historial de CSVs, poll_log y alertas resueltas. Defecto: 90. |
sso.auto_admin | Si true, cualquier usuario SSO tiene acceso admin. Recomendado para equipos pequeños. |
graph.tenant_id / client_id | App Registration para obtener display names y avatares de los usuarios del equipo. |
8. Arquitectura técnica
| Componente | Tecnología | Descripción |
| Backend | Python 3 + Flask + Waitress | WSGI server + scheduler en background thread. |
| Base de datos | SQLite WAL | 8 tablas. WAL permite lecturas concurrentes. Auto-migración al arrancar. |
| Recolección | PowerShell Remoting | collect_cluster_data.ps1 via Invoke-Command, salida NDJSON por stdout. |
| Umbrales | Python alert_manager.py | Evalúa % y GB, gestiona lifecycle de alertas y cooldown. |
| Notificación | SisAlerts /api/ingest | sisalerts_client.py — deduplicación por external_id. |
| Auth web | Entra ID Application Proxy | Cabecera X-MS-CLIENT-PRINCIPAL-NAME. SSO transparente. |
| UI shell | sisapps-ui package | Sidebar compartida, tema por cookie, navegación entre apps. |
| Servicio | WinSW (Windows) | hypervmonitor-service.xml. Deploy via deploy.ps1. |
Flujo completo
scheduler._run_loop() cada 300s
→ por cada cluster habilitado:
collect_cluster_data.ps1 (Invoke-Command remoto)
NDJSON: nodos + CSVs con tamaño/espacio libre
update_db(): upsert nodos, csvs, csv_history
alert_manager.evaluate_thresholds():
por cada CSV:
resolver umbral_pct y umbral_gb (volumen → cluster → global)
si free_pct ≤ umbral_pct OR free_gb ≤ umbral_gb:
crear/actualizar alerta en DB
si cooldown superado o sent_at es NULL: POST /api/ingest → SisAlerts
si espacio recuperado: auto-resolver alerta
→ purge cada hora (csv_history + poll_log + alertas resueltas antiguas)
Tablas de base de datos
| Tabla | Descripción |
clusters | Clusters con umbrales pct y GB por cluster |
cluster_nodes | Último estado de nodos (upsert) |
csv_volumes | Último estado de CSVs con umbrales pct y GB por volumen |
csv_history | Serie temporal de espacio libre (base de gráficas) |
alerts | Historial de alertas con created_at, sent_at, resolved_at |
poll_log | Log de ciclos de polling por cluster (duración, errores) |
settings | Key-value para settings persistentes |
users | Usuarios SSO con flag is_admin |
9. PowerShell Remoting
El script scripts/collect_cluster_data.ps1 usa Invoke-Command -ComputerName <ClusterName> sin credenciales explícitas. La cuenta del servicio Windows debe tener permisos de administrador Hyper-V en todos los clusters.
# Salida NDJSON por stdout (un objeto JSON por línea):
{"type":"node","name":"HV01","state":"Up","uptime_hours":720}
{"type":"csv","name":"Cluster Disk 1","size_bytes":1099511627776,"free_bytes":219902325555,"state":"Online","owner_node":"HV01"}
Cuenta de servicio
La cuenta bajo la que corre el servicio WinSW necesita permisos WinRM hacia los tres clusters.
En la configuración de clusters se puede especificar credenciales explícitas en remoting.username / remoting.secret
si la cuenta de servicio no tiene los permisos necesarios.
10. Despliegue
Requisitos
- Windows Server con Python 3.x
- SisAlerts funcionando y accesible (para las notificaciones)
- Acceso WinRM/PowerShell Remoting hacia los clusters Hyper-V
- Cuenta de servicio con permisos de administrador en los clusters
Deploy
cd C:\apps\jmfernandez\hypervmonitor
# deploy.ps1: git pull + pip install sisapps-ui + restart servicio
.\deploy.ps1
# O deploy global de todas las apps:
cd C:\apps\jmfernandez\sisapps-hub
.\sisapps_deploy.ps1
Verificación inicial
1. Abrir https://hypervmonitor-idealistaa82505660.msappproxy.net — debe mostrar el dashboard.
2. Admin → Clusters: crear los clusters con la dirección correcta (nombre NetBIOS o FQDN del cluster).
3. Admin → Ajustes: configurar SisAlerts URL + API key y probar con "Test SisAlerts".
4. Dashboard: botón Poll ahora — verificar que retorna sin error y aparecen los volúmenes.
5. Admin → Clusters → Volúmenes: revisar umbrales por volumen si hay CSVs con comportamiento especial.