Picks the node to run a VM on. The first pass reads the gossip-replicated
Hyper.Node.Budget.NodeStates (Hyper.Cluster.Budget.all_states/0), drops
nodes that cannot fit the spec, and ranks survivors by how many bytes of the
VM's image layers they already have mounted (colo(N, VM) = sum of |L| over
shared mounted layers). The result is an ordered candidate list; the chosen
node confirms authoritatively via Hyper.Node.Budget.admit/2 (see place/3).
All filtering is best-effort on a possibly-stale snapshot: a node that no longer fits simply refuses at confirmation time.
Summary
Functions
Fitting nodes for spec, most colocated bytes first.
Bytes of layers already mounted on state's node.
Place spec on the best confirming node.
Place and boot spec somewhere in the cluster.
Types
@type layer_sizes() :: [{Hyper.Layer.id(), Unit.Information.t()}]
Functions
@spec candidates(Hyper.Vm.Instance.Spec.t(), layer_sizes()) :: [node()]
Fitting nodes for spec, most colocated bytes first.
@spec colocation_score(Hyper.Node.Budget.NodeState.t(), layer_sizes()) :: non_neg_integer()
Bytes of layers already mounted on state's node.
@spec place(Hyper.Vm.Instance.Spec.t(), layer_sizes(), (node() -> {:ok, term()} | {:error, term()})) :: {:ok, {node(), term()}} | {:error, :no_capacity}
Place spec on the best confirming node.
Walks candidates/2 in rank order, calling attempt on each until one returns
{:ok, result} (the authoritative confirmation, typically a node running
Hyper.Node.try_run/3 over :erpc). {:error, :no_capacity} if all refuse.
@spec run( Hyper.Vm.Instance.Spec.t(), layer_sizes(), (-> {:ok, pid()} | {:error, term()}), (pid() -> :ok) ) :: {:ok, {node(), pid()}} | {:error, :no_capacity}
Place and boot spec somewhere in the cluster.
Confirms each candidate by RPC-ing Hyper.Node.try_run/3 on it; the first node
to boot the VM and reserve its budget wins. start_fun/stop_fun describe how
to boot/tear down the VM on the target node.