Merge pull request #401 from gyptazy/feature/391_improve_native_ha_rules_pve8

fix: HA affinity/anti-affinity rules can only be evaluated on PVE9+ nodes
This commit is contained in:
gyptazy
2025-12-14 09:37:47 +01:00
committed by GitHub
3 changed files with 48 additions and 5 deletions

View File

@@ -74,8 +74,9 @@ def main():
# Get all required objects from the Proxmox cluster
meta = {"meta": proxlb_config}
nodes = Nodes.get_nodes(proxmox_api, proxlb_config)
meta = Features.validate_any_non_pve9_node(meta, nodes)
pools = Pools.get_pools(proxmox_api)
ha_rules = HaRules.get_ha_rules(proxmox_api)
ha_rules = HaRules.get_ha_rules(proxmox_api, meta)
guests = Guests.get_guests(proxmox_api, pools, ha_rules, nodes, meta, proxlb_config)
groups = Groups.get_groups(guests, nodes)

View File

@@ -88,3 +88,37 @@ class Features:
proxlb_data["meta"]["balancing"]["enable"] = False
logger.debug("Finished: validate_available_features.")
@staticmethod
def validate_any_non_pve9_node(meta: any, nodes: any) -> dict:
"""
Validate if any node in the cluster is running Proxmox VE < 9.0.0 and update meta accordingly.
This function inspects the cluster node versions and sets a flag in meta indicating whether
any node is running a Proxmox VE version older than 9.0.0.
Args:
meta (dict): Metadata structure that will be updated with cluster version information.
nodes (dict): Cluster nodes mapping whose values contain 'pve_version' strings.
Returns:
dict: The updated meta dictionary with 'cluster_non_pve9' flag set to True or False.
Side effects:
- Mutates meta["meta"]["cluster_non_pve9"] based on node versions.
- Emits debug log messages.
Notes:
- Version comparison uses semantic version parsing; defaults to "0.0.0" if pve_version is missing.
"""
logger.debug("Starting: validate_any_non_pve9_node.")
any_non_pve9_node = any(version.parse(node.get("pve_version", "0.0.0")) < version.parse("9.0.0") for node in nodes.get("nodes", {}).values())
if any_non_pve9_node:
meta["meta"]["cluster_non_pve9"] = True
logger.debug("Finished: validate_any_non_pve9_node. Result: True")
else:
meta["meta"]["cluster_non_pve9"] = False
logger.debug("Finished: validate_any_non_pve9_node. Result: False")
return meta

View File

@@ -36,7 +36,7 @@ class HaRules:
"""
@staticmethod
def get_ha_rules(proxmox_api: any) -> Dict[str, Any]:
def get_ha_rules(proxmox_api: any, meta: dict) -> Dict[str, Any]:
"""
Retrieve all HA rules from a Proxmox cluster.
@@ -46,15 +46,23 @@ class HaRules:
descriptive format (affinity or anti-affinity).
Args:
proxmox_api (any): Proxmox API client instance.
proxmox_api (any): Proxmox API client instance.
meta (dict): The metadata dictionary containing cluster information.
Returns:
Dict[str, Any]: Dictionary with a top-level "ha_rules" key mapping rule id
to {"rule": <rule_id>, "type": <affinity_type>, "members": [<resource_ids>...]}.
Dict[str, Any]: Dictionary with a top-level "ha_rules" key mapping rule id
to {"rule": <rule_id>, "type": <affinity_type>, "members": [<resource_ids>...]}.
"""
logger.debug("Starting: get_ha_rules.")
ha_rules = {"ha_rules": {}}
# If any node is non PVE 9, skip fetching HA rules as they are unsupported
if meta["meta"]["cluster_non_pve9"]:
logger.debug("Skipping HA rule retrieval as non Proxmox VE 9 systems detected.")
return ha_rules
else:
logger.debug("Cluster running Proxmox VE 9 or newer, proceeding with HA rule retrieval.")
for rule in proxmox_api.cluster.ha.rules.get():
# Skip disabled rules (disable key exists AND is truthy)