mirror of
https://github.com/taylanbakircioglu/haproxy-openmanager.git
synced 2026-09-16 15:45:11 +00:00
a1192e602d
Manage highly-available virtual IPs backed by Keepalived (VRRP) directly from the OpenManager
UI — no more SSHing into nodes to install/configure Keepalived by hand. Builds on the agent
pull-architecture: define the VIP centrally, click Apply, and the agents converge.
Highlights:
- New "HA / VIP" tab: create a virtual IP, pick a per-node interface, select which pool nodes
participate (MASTER/BACKUP roles + priorities); live MASTER/BACKUP/FAULT per node.
- On Apply, agents install & configure Keepalived (unicast VRRP, cloud-safe default) across the
major distros (Debian/Ubuntu, RHEL/CentOS/Alma/Rocky, Fedora, SUSE/openSUSE, Alpine) with a
HAProxy health-check, so the VIP fails over automatically when HAProxy drops.
- Single-node (a managed floating IP without failover) and multi-node VRRP failover both work.
- VIP changes ride the standard Apply Management flow with the standard "View Change" diff.
- Approval-gated deletion (safety): deleting a running VIP is staged for approval and the VIP
keeps running, untouched, until you approve it — an agent never tears a VIP down without an
explicit human approval. Per-VIP Diagnostics view; opt-in package uninstall (only on nodes
where OpenManager installed it). A node already running a hand-managed Keepalived is detected
and never overwritten ("externally managed").
- Fully opt-in and backward compatible: nodes/clusters without a VIP are unaffected. Adds
vip_instances + vip_members tables (idempotent SCHEMA_VERSION bump; existing data and
passwords unaffected) and a `vip` RBAC permission group.
- Also includes a HAProxy config-generator robustness fix: auto-inject a stick-table when a
frontend uses a stick counter (track-sc / sc_*_rate) but declares none.
On-prem / L2 (VRRP) scope; the UI notes the cloud caveat.
64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
from pydantic import BaseModel
|
|
from typing import Optional, List
|
|
|
|
class HAProxyClusterCreate(BaseModel):
|
|
name: str
|
|
description: Optional[str] = None
|
|
connection_type: str = "agent" # Only "agent" supported now
|
|
stats_socket_path: str = "/run/haproxy/admin.sock"
|
|
haproxy_config_path: str = "/etc/haproxy/haproxy.cfg"
|
|
haproxy_bin_path: str = "/usr/sbin/haproxy" # HAProxy binary path
|
|
keepalived_config_path: str = "/etc/keepalived/keepalived.conf" # HA/VIP: keepalived.conf path (Issue #27)
|
|
pool_id: Optional[int] = None # Which pool this cluster belongs to
|
|
|
|
class HAProxyClusterUpdate(BaseModel):
|
|
name: Optional[str] = None
|
|
description: Optional[str] = None
|
|
connection_type: Optional[str] = None
|
|
stats_socket_path: Optional[str] = None
|
|
haproxy_config_path: Optional[str] = None
|
|
haproxy_bin_path: Optional[str] = None
|
|
keepalived_config_path: Optional[str] = None
|
|
pool_id: Optional[int] = None
|
|
is_active: Optional[bool] = None
|
|
acme_enabled: Optional[bool] = None
|
|
acme_backend_url: Optional[str] = None
|
|
|
|
class HAProxyClusterResponse(BaseModel):
|
|
id: int
|
|
name: str
|
|
description: Optional[str] = None
|
|
|
|
# Installation options
|
|
installation_type: str
|
|
deployment_type: str
|
|
|
|
# Connection details
|
|
host: str
|
|
port: int
|
|
connection_type: str
|
|
|
|
# Status info
|
|
is_active: bool
|
|
is_default: bool
|
|
last_connected_at: Optional[str] = None
|
|
connection_status: str
|
|
connection_error: Optional[str] = None
|
|
haproxy_version: Optional[str] = None
|
|
created_at: str
|
|
|
|
class HAProxyGlobalConfig(BaseModel):
|
|
max_connections: int = 4096
|
|
timeout_connect: int = 10000
|
|
timeout_client: int = 60000
|
|
timeout_server: int = 60000
|
|
log_level: str = "info"
|
|
stats_enabled: bool = True
|
|
stats_uri: str = "/stats"
|
|
stats_port: int = 8404
|
|
|
|
class ConfigVersion(BaseModel):
|
|
version_name: str
|
|
description: Optional[str] = None
|
|
config_content: Optional[str] = None
|
|
cluster_id: Optional[int] = None |