Skip to content

Commit 636763f

Browse files
committed
Adjust the integration of node resource reservation
- Renamed to set_node_resource_reservation - Immediately apply the values as maxmem for a node - Avoid recalculating percentage values - Simplyfied code
1 parent 89ad425 commit 636763f

File tree

2 files changed

+46
-69
lines changed

2 files changed

+46
-69
lines changed

proxlb/models/nodes.py

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def get_nodes(proxmox_api: any, proxlb_config: Dict[str, Any]) -> Dict[str, Any]
7878
nodes["nodes"][node["node"]]["cpu_pressure_some_spikes_percent"] = Nodes.get_node_rrd_data(proxmox_api, node["node"], "cpu", "some", spikes=True)
7979
nodes["nodes"][node["node"]]["cpu_pressure_full_spikes_percent"] = Nodes.get_node_rrd_data(proxmox_api, node["node"], "cpu", "full", spikes=True)
8080
nodes["nodes"][node["node"]]["cpu_pressure_hot"] = False
81-
nodes["nodes"][node["node"]]["memory_total"] = node["maxmem"]
81+
nodes["nodes"][node["node"]]["memory_total"] = Nodes.set_node_resource_reservation(node["node"], node["maxmem"], proxlb_config, "memory")
8282
nodes["nodes"][node["node"]]["memory_assigned"] = 0
8383
nodes["nodes"][node["node"]]["memory_used"] = node["mem"]
8484
nodes["nodes"][node["node"]]["memory_free"] = node["maxmem"] - node["mem"]
@@ -103,7 +103,6 @@ def get_nodes(proxmox_api: any, proxlb_config: Dict[str, Any]) -> Dict[str, Any]
103103
nodes["nodes"][node["node"]]["disk_pressure_full_spikes_percent"] = Nodes.get_node_rrd_data(proxmox_api, node["node"], "disk", "full", spikes=True)
104104
nodes["nodes"][node["node"]]["disk_pressure_hot"] = False
105105

106-
Nodes.apply_resource_reservation(nodes["nodes"][node["node"]]["name"], proxlb_config, nodes["nodes"][node["node"]])
107106
# Evaluate if node should be set to maintenance mode
108107
if Nodes.set_node_maintenance(proxmox_api, proxlb_config, node["node"]):
109108
nodes["nodes"][node["node"]]["maintenance"] = True
@@ -257,51 +256,56 @@ def get_node_pve_version(proxmox_api, node_name: str) -> float:
257256
return version["version"]
258257

259258
@staticmethod
260-
def apply_resource_reservation(node_name, proxlb_config: Dict[str, Any], node_data: Dict[str, Any]) -> None:
259+
def set_node_resource_reservation(node_name, resource_value, proxlb_config, resource_type) -> int:
261260
"""
262-
Check if there is a a configured resource reservation for the current nodes and apply it as needed.
261+
Check if there is a configured resource reservation for the current node and apply it as needed.
263262
Checks for a node specific config first, then if there is any configured default and if neither then nothing is reserved.
264-
Reservations are applied by directly modifying the data gathered from the nodes.
263+
Reservations are applied by directly modifying the resource value.
265264
266265
Args:
267-
node_name: (str) the name of the node
268-
proxlb_config (Dict[str, Any]): A dictionary containing the ProxLB configuration.
269-
node_data: (Dict[str, Any]): Dict containing the current nodes data
270-
Returns: none
266+
node_name (str): The name of the node.
267+
resource_value (int): The total resource value in bytes.
268+
proxlb_config (Dict[str, Any]): A dictionary containing the ProxLB configuration.
269+
resource_type (str): The type of resource ('memory', 'disk', etc.).
270+
271+
Returns:
272+
int: The resource value after applying any configured reservations.
271273
"""
272274
logger.debug(f"Starting: apply_resource_reservation")
275+
273276
balancing_cfg = proxlb_config.get("balancing", {})
274277
reserve_cfg = balancing_cfg.get("node_resource_reserve", {})
275-
reserved_memory_gb_node = reserve_cfg.get(node_name, {}).get("memory")
276-
reserved_memory_gb_default = reserve_cfg.get("defaults", {}).get("memory", 0)
277-
278-
# Make sure the reservation is a numeric value - check for both, default and node specific
279-
if not isinstance(reserved_memory_gb_default, (int, float)):
280-
if reserved_memory_gb_default is not None:
281-
logger.info("Invalid default memory reservation: Found a string while expecting a numeric value - skipping default reservation")
282-
reserved_memory_gb_default = 0
283-
284-
if not isinstance(reserved_memory_gb_node, (int, float)):
285-
if reserved_memory_gb_node is not None:
286-
logger.info(f"Invalid memory reservation: Found a string while expecting a numeric value - applying current default of {reserved_memory_gb_default} Bytes")
287-
reserved_memory_gb_node = reserved_memory_gb_default
288-
289-
# Make sure the reservation is positive
290-
if reserved_memory_gb_node < 0:
291-
logger.info(f"{nodes['nodes'][node['node']]['name']}: Invalid assigned memory reservation, applying defaults")
292-
reserved_memory_gb_node = reserved_memory_gb_default
293-
294-
# Convert the reservation from GB to Bytes, get the current nodes physical memory
295-
reserved_memory_node = int(round(reserved_memory_gb_node * 1024 ** 3))
296-
total_mem = node_data.get("memory_total")
297-
298-
# Check if the reservation doesnt exceed the nodes total memory
299-
if reserved_memory_node > total_mem:
300-
logger.debug(f"Reservation of {reserved_memory_node} Bytes exceeds available memory of {total_mem} Bytes- skipping reservation")
301-
reserved_memory_node = 0
302-
reserved_memory_gb_node = 0
303-
304-
logger.debug(f"Reserved Memory: {reserved_memory_gb_node} GB ({reserved_memory_node} Bytes)")
305-
node_data["memory_total"] -= reserved_memory_node
306-
Helper.update_node_resource_percentages(node_data)
307-
logger.debug(f"Finished: apply_resource_reservation")
278+
node_resource_reservation = reserve_cfg.get(node_name, {}).get(resource_type, 0)
279+
default_resource_reservation = reserve_cfg.get("defaults", {}).get(resource_type, 0)
280+
281+
if reserve_cfg.get("defaults", None):
282+
logger.debug(f"Applying resource reservation from config.")
283+
284+
# Ensure reservations are numeric values
285+
node_resource_reservation = node_resource_reservation if isinstance(node_resource_reservation, (int, float)) else 0
286+
default_resource_reservation = default_resource_reservation if isinstance(default_resource_reservation, (int, float)) else 0
287+
288+
# Apply node specific reservation if set
289+
if node_resource_reservation > 0:
290+
if resource_value < (node_resource_reservation * 1024 ** 3):
291+
logger.critical(f"Configured resource reservation for node {node_name} of type {resource_type} with {node_resource_reservation} GB is higher than available resource value {resource_value / (1024 ** 3):.2f} GB. Not applying...")
292+
return resource_value
293+
else:
294+
logger.debug(f"Applying node specific reservation for {node_name} of type {resource_type} with {node_resource_reservation} GB")
295+
resource_value -= (node_resource_reservation * 1024 ** 3)
296+
return resource_value
297+
298+
# Apply default reservation if set and no node specific reservation has been performed
299+
elif default_resource_reservation > 0:
300+
if resource_value < (default_resource_reservation * 1024 ** 3):
301+
logger.critical(f"Configured default reservation for node {node_name} of type {resource_type} with {default_resource_reservation} GB is higher than available resource value {resource_value / (1024 ** 3):.2f} GB. Not applying...")
302+
return resource_value
303+
else:
304+
logger.debug(f"Applying default reservation for {node_name} of type {resource_type} with {default_resource_reservation} GB")
305+
resource_value -= (default_resource_reservation * 1024 ** 3)
306+
return resource_value
307+
308+
else:
309+
logger.debug(f"No default or node specific resource reservation for node {node_name} found. Skipping...")
310+
logger.debug(f"Finished: apply_resource_reservation")
311+
return resource_value

proxlb/utils/helper.py

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -335,30 +335,3 @@ def tcp_connect_test(addr_family: int, host: str, port: int, timeout: int) -> tu
335335
return (rc == 0, rc if rc != 0 else None)
336336
finally:
337337
test_socket.close()
338-
339-
@staticmethod
340-
def update_node_resource_percentages(node_data: Dict[str, any]) -> None:
341-
"""
342-
This function updates the percentages of the node's resources in its respective dict
343-
Args:
344-
node_data: (Dict[str, any]) dict containing the nodes data to be updated
345-
Returns: none
346-
"""
347-
logger.debug(f"Starting: Update resource percentages")
348-
logger.debug(f"node data: {node_data}")
349-
# memory
350-
node_data["memory_assigned_percent"] = node_data["memory_assigned"] / node_data["memory_total"] * 100
351-
node_data["memory_free_percent"] = node_data["memory_free"] / node_data["memory_total"] * 100
352-
node_data["memory_used_percent"] = node_data["memory_used"] / node_data["memory_total"] * 100
353-
# cpu
354-
node_data["cpu_assigned_percent"] = node_data["cpu_assigned"] / node_data["cpu_total"] * 100
355-
node_data["cpu_free_percent"] = node_data["cpu_free"] / node_data["cpu_total"] * 100
356-
node_data["cpu_used_percent"] = node_data["cpu_used"] / node_data["cpu_total"] * 100
357-
# disk
358-
node_data["disk_assigned_percent"] = node_data["disk_assigned"] / node_data["disk_total"] * 100
359-
node_data["disk_free_percent"] = node_data["disk_free"] / node_data["disk_total"] * 100
360-
node_data["disk_used_percent"] = node_data["disk_used"] / node_data["disk_total"] * 100
361-
362-
logger.debug(f"node data: {node_data}")
363-
logger.debug(f"End: Update resource percentages")
364-
return

0 commit comments

Comments
 (0)