feat(agent): enrich zpool summary with type, scan state, vdev list
This commit is contained in:
parent
a4f4d3ca51
commit
e763ea96bd
3 changed files with 61 additions and 5 deletions
|
|
@ -4,6 +4,15 @@ defmodule ProxmoxAgent.Collectors.Zfs do
|
|||
Delegates shelling out to an injectable runner so tests can supply fixtures.
|
||||
"""
|
||||
|
||||
@type vdev_summary :: %{
|
||||
name: String.t(),
|
||||
type: String.t(),
|
||||
state: String.t(),
|
||||
read_errors: non_neg_integer(),
|
||||
write_errors: non_neg_integer(),
|
||||
checksum_errors: non_neg_integer()
|
||||
}
|
||||
|
||||
@type pool_summary :: %{
|
||||
name: String.t(),
|
||||
health: String.t(),
|
||||
|
|
@ -15,7 +24,11 @@ defmodule ProxmoxAgent.Collectors.Zfs do
|
|||
error_count: non_neg_integer(),
|
||||
vdev_count: non_neg_integer(),
|
||||
degraded_vdev_count: non_neg_integer(),
|
||||
last_scrub_end: String.t() | nil
|
||||
pool_type: String.t(),
|
||||
scan_function: String.t() | nil,
|
||||
scan_state: String.t() | nil,
|
||||
last_scrub_end: String.t() | nil,
|
||||
vdevs: [vdev_summary()]
|
||||
}
|
||||
|
||||
@spec collect_pools(keyword()) :: %{pools: [pool_summary()], errors: [map()]}
|
||||
|
|
@ -71,7 +84,8 @@ defmodule ProxmoxAgent.Collectors.Zfs do
|
|||
defp merge_pools(%{"pools" => list_pools}, %{"pools" => status_pools}) do
|
||||
Enum.map(list_pools, fn {name, list_info} ->
|
||||
status_info = Map.get(status_pools, name, %{})
|
||||
vdevs = Map.get(status_info, "vdevs", %{}) |> Map.values()
|
||||
raw_vdevs = Map.get(status_info, "vdevs", %{}) |> Map.values()
|
||||
vdevs = Enum.map(raw_vdevs, &vdev_summary/1)
|
||||
|
||||
%{
|
||||
name: name,
|
||||
|
|
@ -83,12 +97,45 @@ defmodule ProxmoxAgent.Collectors.Zfs do
|
|||
capacity_percent: Map.get(list_info, "cap", 0),
|
||||
error_count: to_int(Map.get(status_info, "error_count", "0")),
|
||||
vdev_count: length(vdevs),
|
||||
degraded_vdev_count: Enum.count(vdevs, &(&1["state"] != "ONLINE")),
|
||||
last_scrub_end: get_in(status_info, ["scan", "end_time"])
|
||||
degraded_vdev_count: Enum.count(vdevs, &(&1.state != "ONLINE")),
|
||||
pool_type: derive_pool_type(vdevs),
|
||||
scan_function: get_in(status_info, ["scan", "function"]),
|
||||
scan_state: get_in(status_info, ["scan", "state"]),
|
||||
last_scrub_end: get_in(status_info, ["scan", "end_time"]),
|
||||
vdevs: vdevs
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
defp vdev_summary(v) do
|
||||
%{
|
||||
name: Map.get(v, "name"),
|
||||
type: Map.get(v, "vdev_type"),
|
||||
state: Map.get(v, "state"),
|
||||
read_errors: to_int(Map.get(v, "read_errors", "0")),
|
||||
write_errors: to_int(Map.get(v, "write_errors", "0")),
|
||||
checksum_errors: to_int(Map.get(v, "checksum_errors", "0"))
|
||||
}
|
||||
end
|
||||
|
||||
@data_vdev_types ~w(mirror raidz1 raidz2 raidz3 disk)
|
||||
@special_vdev_types ~w(log cache spare dedup special)
|
||||
|
||||
defp derive_pool_type(vdevs) do
|
||||
data_types =
|
||||
vdevs
|
||||
|> Enum.map(& &1.type)
|
||||
|> Enum.reject(&(&1 in @special_vdev_types))
|
||||
|> Enum.uniq()
|
||||
|
||||
case data_types do
|
||||
[] -> "unknown"
|
||||
["disk"] -> "stripe"
|
||||
[t] when t in @data_vdev_types -> t
|
||||
_ -> "mixed"
|
||||
end
|
||||
end
|
||||
|
||||
defp summarize_datasets(nil), do: []
|
||||
|
||||
defp summarize_datasets(%{"datasets" => datasets}) do
|
||||
|
|
|
|||
2
agent/test/fixtures/zfs/zpool_status.json
vendored
2
agent/test/fixtures/zfs/zpool_status.json
vendored
|
|
@ -26,7 +26,7 @@
|
|||
"state": "DEGRADED",
|
||||
"scan": {
|
||||
"function": "scrub",
|
||||
"state": "FINISHED",
|
||||
"state": "SCANNING",
|
||||
"end_time": "Tue Mar 01 08:00:00 2026"
|
||||
},
|
||||
"error_count": "2",
|
||||
|
|
|
|||
|
|
@ -32,10 +32,19 @@ defmodule ProxmoxAgent.Collectors.ZfsTest do
|
|||
assert rpool.size_bytes == 500_000_000_000
|
||||
assert rpool.error_count == 0
|
||||
assert rpool.degraded_vdev_count == 0
|
||||
assert rpool.pool_type == "mirror"
|
||||
assert rpool.scan_function == "scrub"
|
||||
assert rpool.scan_state == "FINISHED"
|
||||
assert [%{name: "mirror-0", type: "mirror", state: "ONLINE",
|
||||
read_errors: 0, write_errors: 0, checksum_errors: 0}] = rpool.vdevs
|
||||
|
||||
assert tank.health == "DEGRADED"
|
||||
assert tank.error_count == 2
|
||||
assert tank.degraded_vdev_count == 1
|
||||
assert tank.pool_type == "raidz2"
|
||||
assert tank.scan_state == "SCANNING"
|
||||
assert [%{name: "raidz2-0", type: "raidz2", state: "DEGRADED",
|
||||
checksum_errors: 2}] = tank.vdevs
|
||||
end
|
||||
|
||||
test "populates errors list when zpool fails" do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue