fix(calculations): Add safety guard to avoid overprovisioning of nodes by memory.

Fixes: #275
This commit is contained in:
gyptazy
2025-12-02 09:59:51 +01:00
parent 490fb55ee1
commit 3d9f0eb85e
2 changed files with 43 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
fixed:
- Fixed missing overprovisioning safety guard to avoid node overprovisioning (@gyptazy). [#275]

View File

@@ -387,6 +387,10 @@ class Calculations:
for guest_name in proxlb_data["groups"]["affinity"][group_name]["guests"]:
mode = proxlb_data["meta"]["balancing"].get("mode", "used")
if not Calculations.validate_node_resources(proxlb_data, guest_name):
logger.warning(f"Skipping relocation of guest {guest_name} due to insufficient resources on target node {proxlb_data['meta']['balancing']['balance_next_node']}. This might affect affinity group {group_name}.")
continue
if mode == 'psi':
logger.debug(f"Evaluating guest relocation based on {mode} mode.")
method = proxlb_data["meta"]["balancing"].get("method", "memory")
@@ -707,3 +711,40 @@ class Calculations:
return False
return True
@staticmethod
def validate_node_resources(proxlb_data: Dict[str, Any], guest_name: str) -> bool:
"""
Validate that the target node has sufficient resources to host the specified guest.
This function checks if the target node, determined by the balancing logic,
has enough CPU, memory, and disk resources available to accommodate the guest.
Args:
proxlb_data (Dict[str, Any]): A dictionary containing the complete ProxLB state including:
- "nodes": Dictionary with node resource information
- "guests": Dictionary with guest resource requirements
- "meta": Dictionary with balancing information including target node
guest_name (str): The name of the guest to validate resources for
Returns:
bool: True if the target node has sufficient resources, False otherwise
"""
logger.debug("Starting: validate_node_resources.")
node_target = proxlb_data["meta"]["balancing"]["balance_next_node"]
node_memory_free = proxlb_data["nodes"][node_target]["memory_free"]
node_cpu_free = proxlb_data["nodes"][node_target]["cpu_free"]
node_disk_free = proxlb_data["nodes"][node_target]["disk_free"]
guest_memory_required = proxlb_data["guests"][guest_name]["memory_used"]
guest_cpu_required = proxlb_data["guests"][guest_name]["cpu_used"]
guest_disk_required = proxlb_data["guests"][guest_name]["disk_used"]
if guest_memory_required < node_memory_free:
logger.debug(f"Node '{node_target}' has sufficient resources for guest '{guest_name}'.")
logger.debug("Finished: validate_node_resources.")
return True
else:
logger.debug(f"Node '{node_target}' lacks sufficient resources for guest '{guest_name}'.")
logger.debug("Finished: validate_node_resources.")
return False