Skip to content

logicalvolumegetter: add storcli2 logical volume getter#61

Merged
g-carre merged 2 commits into
mainfrom
feature/storcli2-logical-volume-getter
Jun 16, 2026
Merged

logicalvolumegetter: add storcli2 logical volume getter#61
g-carre merged 2 commits into
mainfrom
feature/storcli2-logical-volume-getter

Conversation

@ezekiel-alexrod

Copy link
Copy Markdown
Contributor

What

Implements ports.LogicalVolumesGetter for storcli2 / perccli2 (logicalvolumegetter/storcli2.go), mirroring the ssacli getter and the megaraid v1 virtual-drive parsing.

How

  • LogicalVolumes(ctrl) → a single /cN/vall show all; LogicalVolume(meta)/cN/vM show all, with a not-found guard on an empty list (an out-of-range VD is a command-level failure payload surfaced by storcli2.Decode).
  • Each Virtual Drives entry maps to a LogicalVolume:
    • ID = the VD half of the DG/VD pair; TYPElogicalvolume.RAIDLevelMap.
    • VD state, per the StorCLI2 User Guide v1.1 legend (Rec|OfLn|Pdgd|Dgrd|Optl): Optl → optimal; Dgrd/Pdgd/Rec (recovery) → degraded; OfLn — the documented terminal state — → failed. storcli1's Fail is kept as a defensive guard; unknown states soft-fail to LVStatusUnknown so newer firmware does not break inventory.
    • CurrentCache parsed as comma-separated tokens (e.g. NR,WB) — unlike storcli1's concatenated form — with unknown tokens leaving the corresponding policy unknown.
    • Paths: OS Drive NameDevicePath; SCSI NAA Id/dev/disk/by-id/wwn-0x… permanent path, lowercased because udev links are lowercase hex while the firmware is case-inconsistent across sections (the same SAS address appears as 0x…/0X… depending on the section).
    • Backing drives → PDrivesMetadata keyed by EID:Slt, consistent with the physical-drive getter.
    • Size via utils.ConvertSizeBytes. Error wraps carry the controller ID and the failing DG/VD, matching the physical-drive getter.
  • Zero-VD contract: per the User Guide, showing a nonexistent object reports success, so an absent Virtual Drives section is an empty inventory (the all-JBOD deployment this adapter targets), not an error.
  • One implementation serves both binaries via an injected commandrunner.CommandRunner. Section structs live in the getter file and consume the shared storcli2.Decode + utils.UnmarshalToSlice.

Tests

Table-driven storcli2_test.go against real server captures from a MegaRAID 9660-16i (24-VD inventory, single VDs, invalid-VD failure payload with Invalid VD number). Cases: full inventory (first VD asserted field-by-field), single VD (nominal / invalid), empty-list and absent-section guards, empty zero-VD inventory, and unit tables for VD-state mapping (including OfLn/Ofln/Rec), cache-token parsing, DG/VD parsing and permanent-path building (including the lowercase normalization).

Implement ports.LogicalVolumesGetter for storcli2 / perccli2, mirroring the
ssacli getter and the megaraid v1 virtual-drive parsing. LogicalVolumes()
reads every virtual drive from a single "/cN/vall show all" call;
LogicalVolume() reads one via its "/cN/vM" selector, with a not-found guard on
an empty list (an out-of-range VD is a command-level failure payload surfaced
by storcli2.Decode).

Each "Virtual Drives" entry maps to a LogicalVolume: the ID is the VD half of
the "DG/VD" pair, TYPE feeds logicalvolume.RAIDLevelMap, and size goes through
utils.ConvertSizeBytes. The VD state mapping follows the StorCLI2 User Guide
v1.1 legend (Rec/OfLn/Pdgd/Dgrd/Optl): Optl is optimal, Dgrd, Pdgd and Rec
(recovery) are degraded, and OfLn — the documented terminal state — is failed;
storcli1's "Fail" is kept as a defensive guard and unknown states soft-fail to
LVStatusUnknown so newer firmware does not break inventory. Per the same
guide, showing a nonexistent object reports success, so an absent "Virtual
Drives" section is an empty inventory (the zero-VD, all-JBOD deployment this
adapter targets), not an error. CurrentCache is parsed as comma-separated
tokens (e.g. "NR,WB") — unlike storcli1's concatenated form — with unknown
tokens leaving the corresponding policy unknown. Paths come from the VD
properties: "OS Drive Name" is the device path and "SCSI NAA Id" forms the
/dev/disk/by-id/wwn-0x permanent path, lowercased because udev links are
lowercase hex while the firmware is case-inconsistent across sections.
Backing drives become PDrivesMetadata entries keyed by "EID:Slt", consistent
with the physical-drive getter. Verified against a live MegaRAID 9660-16i
(24-VD fixture set).

One implementation serves both binaries through the injected
commandrunner.CommandRunner. Section structs live in the getter file and
consume the shared storcli2.Decode + utils.UnmarshalToSlice.
@ezekiel-alexrod ezekiel-alexrod requested a review from a team as a code owner June 12, 2026 14:24

return arguments.Get(0).([]byte), arguments.Error(1)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This MockCommandRunner duplicates the one in mock_test.go (which lives in package logicalvolumegetter_test). The internal package is needed here for testing unexported helpers, so the duplication is structurally unavoidable without refactoring mock_test.go to also be in package logicalvolumegetter — which would break the existing ssacli/mdadm tests. Noting it as tech debt rather than a blocker since physicaldrivegetter has the same pattern.

— Claude Code

@claude

claude Bot commented Jun 15, 2026

Copy link
Copy Markdown

LGTM — clean implementation that follows existing adapter patterns well.

- storcli2_test.go:22-28 — duplicate MockCommandRunner (tech debt note, not blocking; matches physicaldrivegetter pattern)

The code correctly implements the LogicalVolumesGetter port, reuses shared storcli2.Decode/utils.UnmarshalToSlice infra, handles edge cases (empty inventory, absent sections, case-insensitive states, unknown firmware states), and has comprehensive table-driven tests with real fixture data. Error wrapping, hexagonal boundaries, and CLI output parsing all look correct.

Review by Claude Code

@g-carre g-carre left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@g-carre g-carre merged commit eee9880 into main Jun 16, 2026
7 checks passed
@g-carre g-carre deleted the feature/storcli2-logical-volume-getter branch June 16, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants