Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions plugins/filter/cluster_colima.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,26 +67,34 @@ def _number(amount: Decimal) -> int | float:


def cluster_colima_memory(memory_gib: Any, host_memory_mb: Any, reserved_gib: Any, host_reserve_gib: Any, guest_baseline_gib: Any, runner_limit_gib: Any) -> dict[str, Any]:
"""Work out the memory a Colima node VM is to have: the value set, or what the host can spare, never less than a node needs to run one runner.
"""Work out the memory a Colima node VM is to have: the value set, within what the host can spare when a reserve is set, or what the host can spare, never less than a node needs to run one runner.

:param memory_gib: github_runner_cluster_colima_memory_gib: the VM's memory in GiB, which wins when set. :param host_memory_mb: ansible_facts['memtotal_mb'], the host's memory in MiB, needed only to derive. :param reserved_gib: github_runner_cluster_colima_memory_reserved_gib: the GiB the host's other workloads need; empty derives nothing. :param host_reserve_gib: github_runner_cluster_colima_memory_host_reserve_gib: the GiB kept for the host's operating system. :param guest_baseline_gib: github_runner_cluster_colima_guest_baseline_gib: the GiB the node VM uses with no runner pod on it. :param runner_limit_gib: github_runner_cluster_colima_runner_memory_limit_gib: one runner pod's memory limit in GiB.
:returns: ``{"memory_gib": int | None, "source": "set" | "derived" | "none", "available_gib": <the host's memory less both reserves, or None>, "floor_gib": <the guest baseline and one runner's limit rounded up to a whole GiB, or None>, "clamped": bool}``. A derived memory is the available memory rounded down to a whole GiB, since `colima start --memory` takes whole GiB and rounding up would take memory the reserves keep; below the floor it is the floor, with ``clamped`` true. ``memory_gib`` None keeps the profile's own.
:raises AnsibleFilterError: if a value is set and is not a number of the kind its variable takes, or a derivation lacks the runner's limit or the host's memory.
:param memory_gib: github_runner_cluster_colima_memory_gib: the VM's memory in GiB, which wins when set. :param host_memory_mb: ansible_facts['memtotal_mb'], the host's memory in MiB, needed only when a reserve is set. :param reserved_gib: github_runner_cluster_colima_memory_reserved_gib: the GiB the host's other workloads need; set, it bounds a memory set explicitly and derives one otherwise; empty, it does neither. :param host_reserve_gib: github_runner_cluster_colima_memory_host_reserve_gib: the GiB kept for the host's operating system. :param guest_baseline_gib: github_runner_cluster_colima_guest_baseline_gib: the GiB the node VM uses with no runner pod on it. :param runner_limit_gib: github_runner_cluster_colima_runner_memory_limit_gib: one runner pod's memory limit in GiB.
:returns: ``{"memory_gib": int | None, "source": "set" | "derived" | "none", "available_gib": <the host's memory less both reserves, or None without a reserve>, "floor_gib": <the guest baseline and one runner's limit rounded up to a whole GiB, or None>, "clamped": bool}``. A derived memory is the available memory rounded down to a whole GiB, since `colima start --memory` takes whole GiB and rounding up would take memory the reserves keep; below the floor it is the floor, with ``clamped`` true. ``memory_gib`` None keeps the profile's own.
:raises AnsibleFilterError: if a value is set and is not a number of the kind its variable takes, a reserve is set without the host's memory, a derivation lacks the runner's limit, or a memory set explicitly is more than the host can spare (the budget is a safety limit, so a workload whose reserve grows can never leave the VM larger than the host affords).
"""
explicit = _size(MEMORY_VARIABLE, memory_gib)
reserved = _amount(RESERVED_VARIABLE, reserved_gib)
if explicit is not None:
return {"memory_gib": explicit, "source": "set", "available_gib": None, "floor_gib": None, "clamped": False}
if reserved is None:
return {"memory_gib": None, "source": "none", "available_gib": None, "floor_gib": None, "clamped": False}
source = "none" if explicit is None else "set"
return {"memory_gib": explicit, "source": source, "available_gib": None, "floor_gib": None, "clamped": False}
host_reserve = _needed(HOST_RESERVE_VARIABLE, host_reserve_gib)
if isinstance(host_memory_mb, bool) or not isinstance(host_memory_mb, (int, str)) or not WHOLE_NUMBER.match(str(host_memory_mb)):
raise AnsibleFilterError(f"{HOST_MEMORY_FACT} must give the host's memory in MiB to size the Colima VM within {RESERVED_VARIABLE}, not {host_memory_mb!r}.")
host = Decimal(int(host_memory_mb)) / MIB_PER_GIB
available = host - reserved - host_reserve
if explicit is not None:
if explicit > available:
raise AnsibleFilterError(
f"{MEMORY_VARIABLE} {explicit} is more than the {_number(available)} GiB this host can spare: its {_number(host)} GiB less "
f"{_number(reserved)} GiB for its other workloads ({RESERVED_VARIABLE}) and {_number(host_reserve)} GiB for its operating system "
f"({HOST_RESERVE_VARIABLE}). Lower the memory, or the reserve if the workloads need less."
)
return {"memory_gib": explicit, "source": "set", "available_gib": _number(available), "floor_gib": None, "clamped": False}
baseline = _needed(BASELINE_VARIABLE, guest_baseline_gib)
runner = _needed(RUNNER_VARIABLE, runner_limit_gib)
if runner == 0:
raise AnsibleFilterError(f"{RUNNER_VARIABLE} must be more than zero: a node VM is sized to run at least one runner pod.")
if isinstance(host_memory_mb, bool) or not isinstance(host_memory_mb, (int, str)) or not WHOLE_NUMBER.match(str(host_memory_mb)):
raise AnsibleFilterError(f"{HOST_MEMORY_FACT} must give the host's memory in MiB to derive the Colima VM's memory, not {host_memory_mb!r}.")
available = Decimal(int(host_memory_mb)) / MIB_PER_GIB - reserved - host_reserve
floor = int((baseline + runner).to_integral_value(rounding=ROUND_CEILING))
derived = int(available.to_integral_value(rounding=ROUND_FLOOR))
return {"memory_gib": max(derived, floor), "source": "derived", "available_gib": _number(available), "floor_gib": floor, "clamped": derived < floor}
Expand Down
Loading
Loading