# `Hyper.Node.FireVMM.Client`
[🔗](https://github.com/harmont-dev/hyper/blob/main/lib/hyper/node/fire_vmm/client.ex#L1)

Per-microVM facade over the generated Firecracker API
(`Hyper.Firecracker.Api.Operations`). One GenServer per VM, registered
cluster-wide via `Hyper.Cluster.Routing.via({vm_id, :client})`. It serializes
every request through `handle_call` (Firecracker's API server is
single-threaded).

The VM's API socket is derived from `vm_id` alone via
`Hyper.Node.FireVMM.Jailer.host_socket/1` (the same function the controller
uses), so the client needs no socket threaded in and the two cannot disagree.
A `:socket_path` override is accepted for tests/stand-ins.

Call any generated operation through `run/2`, passing a 1-arity closure that
receives the per-call opts (carrying `:socket_path`) to forward as the
operation's trailing `opts` argument:

    alias Hyper.Firecracker.Api.Operations

    Client.run(Client.via(vm_id), &Operations.describe_instance/1)

    Client.run(Client.via(vm_id), fn opts ->
      Operations.put_guest_boot_source(%Hyper.Firecracker.Api.BootSource{
        kernel_image_path: "/vmlinux"
      }, opts)
    end)

The closure's return value (`:ok` / `{:ok, struct}` / `{:error, _}` from
`Hyper.Firecracker.Api.Transport`) is returned to the caller unchanged.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `run`

```elixir
@spec run(GenServer.server(), (keyword() -&gt; result)) :: result when result: var
```

Run a generated operation against this VM's daemon, serialized.

# `start_link`

```elixir
@spec start_link(Hyper.Node.FireVMM.Client.Opts.t()) :: GenServer.on_start()
```

# `via`

```elixir
@spec via(Hyper.Vm.Id.t()) :: GenServer.name()
```

---

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