defmodule ProxmoxAgent.Collectors.Storage do @moduledoc "Collects Proxmox storage summary via pvesh." @spec collect(keyword()) :: %{storages: [map()], errors: [map()]} def collect(opts \\ []) do runner = Keyword.get(opts, :runner, &ProxmoxAgent.Shell.run/2) node = Keyword.fetch!(opts, :node) case runner.("pvesh", ["get", "/nodes/#{node}/storage", "--output-format", "json"]) do {:ok, body} -> case Jason.decode(body) do {:ok, list} when is_list(list) -> %{storages: Enum.map(list, &normalize/1), errors: []} {:error, e} -> %{storages: [], errors: [%{tag: "decode", message: Exception.message(e)}]} end {:error, reason} -> %{storages: [], errors: [%{tag: "pvesh", message: inspect(reason)}]} end end defp normalize(entry) do %{ name: entry["storage"], type: entry["type"], content: entry["content"], active: entry["active"] == 1, enabled: entry["enabled"] == 1, used_bytes: entry["used"] || 0, total_bytes: entry["total"] || 0, avail_bytes: entry["avail"] || 0, used_fraction: entry["used_fraction"] || 0.0 } end end