# `Hyper.Vm`
[🔗](https://github.com/harmont-dev/hyper/blob/main/lib/hyper/vm.ex#L1)

A microVM handle (its controller pid) and cluster-wide fork operations.

# `source`

```elixir
@type source() :: %{
  :kernel_image_path =&gt; Path.t(),
  :root_drive_path =&gt; Path.t(),
  :vm_id =&gt; Hyper.Vm.Id.t(),
  optional(:boot_args) =&gt; String.t()
}
```

What a VM boots from: explicit, already-jail-visible artifact paths for a cold
boot (kernel + root drive). `boot_args` defaults to a standard serial-console
cmdline when omitted. `vm_id` is required — networking is mandatory and
`BootSpec.resolve/2` derives the guest NIC (`ip=` cmdline + MAC) from it.

# `t`

```elixir
@type t() :: pid()
```

# `fast_fork`

```elixir
@spec fast_fork(t()) :: {:ok, t()} | {:error, term()}
```

Attempt to create a fast fork of this VM.

A fast fork is guaranteed to co-locate on the same `Hyper.Node`. If the node does not have
sufficient runtime resources (out-of-memory, out-of-cpu), then this function will gracefully
error.

If you want to, instead, have logic which falls back to a slow fork, ie. one which snapshots
the state of the VM, transferring it to another node, and then spawning the VM there, then you
should see `Hyper.Vm.fork/1`.

# `fork`

```elixir
@spec fork(t()) :: {:ok, t()} | {:error, term()}
```

Fork this VM, colocating on its own node when it fits (`fast_fork/1`). When
the local node refuses admission, the parent's disk state is published as a
new immutable delta layer and the child is scheduled cluster-wide, preferring
nodes that already hold the image's layers. Never refuses for lack of *local*
resources; can still error on faults (unknown VM, unreachable node, storage
errors) or a cluster-wide `:no_capacity` or `:exhausted`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
