defmodule ServerWeb.VmSearchLive do
use ServerWeb, :live_view
alias Server.{Hosts, Metrics}
@impl true
def mount(_params, _session, socket) do
if connected?(socket), do: Phoenix.PubSub.subscribe(Server.PubSub, "metrics")
{:ok, socket |> assign(q: "", vms: load_vms(), page_title: "VM Search")}
end
@impl true
def handle_info({:metric_inserted, _, _}, socket) do
{:noreply, assign(socket, :vms, load_vms())}
end
@impl true
def handle_event("search", %{"q" => q}, socket) do
{:noreply, assign(socket, :q, q)}
end
defp load_vms do
for host <- Hosts.list_all(),
runtime_sample = Metrics.latest_sample(host.id, "fast"),
vm <- get_in(runtime_sample && runtime_sample.payload, ["vms_runtime", "vms"]) || [],
into: [] do
detail_sample = Metrics.latest_sample(host.id, "medium")
detail_vms = get_in(detail_sample && detail_sample.payload, ["vms_detail", "vms"]) || []
detail_vm = Enum.find(detail_vms, &(&1["vmid"] == vm["vmid"])) || %{}
ips = detail_vm["ips"] || []
%{
vmid: vm["vmid"],
name: vm["name"],
type: vm["type"],
status: vm["status"],
host_name: host.name,
ips: ips
}
end
end
defp filter(vms, ""), do: vms
defp filter(vms, q) do
q = String.downcase(q)
Enum.filter(vms, fn vm ->
String.contains?(String.downcase(vm.name || ""), q) or
Enum.any?(vm.ips, &String.contains?(&1, q))
end)
end
@impl true
def render(assigns) do
~H"""
| VMID | Name | Host | Type | Status | IPs |
|---|---|---|---|---|---|
| {vm.vmid} | {vm.name} | <.link navigate={~p"/hosts/#{vm.host_name}"}>{vm.host_name} | {vm.type} | {vm.status} | {Enum.join(vm.ips, ", ")} |